OSDN Git Service

Merging r338554:
[android-x86/external-llvm.git] / 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       [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
4644                           (i32 imm:$cond), NZCV))]> {
4645     let Inst{23-22} = 0b11;
4646     let Predicates = [HasFullFP16];
4647   }
4648
4649   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4650       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4651                           (i32 imm:$cond), NZCV))]> {
4652     let Inst{23-22} = 0b00;
4653   }
4654
4655   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4656       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4657                           (i32 imm:$cond), NZCV))]> {
4658     let Inst{23-22} = 0b01;
4659   }
4660 }
4661
4662 //---
4663 // Floating point conditional select
4664 //---
4665
4666 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4667     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4668          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4669          [(set regtype:$Rd,
4670                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4671                           (i32 imm:$cond), NZCV))]>,
4672       Sched<[WriteF]> {
4673   bits<5> Rd;
4674   bits<5> Rn;
4675   bits<5> Rm;
4676   bits<4> cond;
4677
4678   let Inst{31-24} = 0b00011110;
4679   let Inst{21}    = 1;
4680   let Inst{20-16} = Rm;
4681   let Inst{15-12} = cond;
4682   let Inst{11-10} = 0b11;
4683   let Inst{9-5}   = Rn;
4684   let Inst{4-0}   = Rd;
4685 }
4686
4687 multiclass FPCondSelect<string asm> {
4688   let Uses = [NZCV] in {
4689   def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4690     let Inst{23-22} = 0b11;
4691     let Predicates = [HasFullFP16];
4692   }
4693
4694   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4695     let Inst{23-22} = 0b00;
4696   }
4697
4698   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4699     let Inst{23-22} = 0b01;
4700   }
4701   } // Uses = [NZCV]
4702 }
4703
4704 //---
4705 // Floating move immediate
4706 //---
4707
4708 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4709   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4710       [(set regtype:$Rd, fpimmtype:$imm)]>,
4711     Sched<[WriteFImm]> {
4712   bits<5> Rd;
4713   bits<8> imm;
4714   let Inst{31-24} = 0b00011110;
4715   let Inst{21}    = 1;
4716   let Inst{20-13} = imm;
4717   let Inst{12-5}  = 0b10000000;
4718   let Inst{4-0}   = Rd;
4719 }
4720
4721 multiclass FPMoveImmediate<string asm> {
4722   def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4723     let Inst{23-22} = 0b11;
4724     let Predicates = [HasFullFP16];
4725   }
4726
4727   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4728     let Inst{23-22} = 0b00;
4729   }
4730
4731   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4732     let Inst{23-22} = 0b01;
4733   }
4734 }
4735 } // end of 'let Predicates = [HasFPARMv8]'
4736
4737 //----------------------------------------------------------------------------
4738 // AdvSIMD
4739 //----------------------------------------------------------------------------
4740
4741 let Predicates = [HasNEON] in {
4742
4743 //----------------------------------------------------------------------------
4744 // AdvSIMD three register vector instructions
4745 //----------------------------------------------------------------------------
4746
4747 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4748 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4749                         RegisterOperand regtype, string asm, string kind,
4750                         list<dag> pattern>
4751   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4752       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4753       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4754     Sched<[WriteV]> {
4755   bits<5> Rd;
4756   bits<5> Rn;
4757   bits<5> Rm;
4758   let Inst{31}    = 0;
4759   let Inst{30}    = Q;
4760   let Inst{29}    = U;
4761   let Inst{28-24} = 0b01110;
4762   let Inst{23-21} = size;
4763   let Inst{20-16} = Rm;
4764   let Inst{15-11} = opcode;
4765   let Inst{10}    = 1;
4766   let Inst{9-5}   = Rn;
4767   let Inst{4-0}   = Rd;
4768 }
4769
4770 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4771 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
4772                         RegisterOperand regtype, string asm, string kind,
4773                         list<dag> pattern>
4774   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4775       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4776       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4777     Sched<[WriteV]> {
4778   bits<5> Rd;
4779   bits<5> Rn;
4780   bits<5> Rm;
4781   let Inst{31}    = 0;
4782   let Inst{30}    = Q;
4783   let Inst{29}    = U;
4784   let Inst{28-24} = 0b01110;
4785   let Inst{23-21} = size;
4786   let Inst{20-16} = Rm;
4787   let Inst{15-11} = opcode;
4788   let Inst{10}    = 1;
4789   let Inst{9-5}   = Rn;
4790   let Inst{4-0}   = Rd;
4791 }
4792
4793 class BaseSIMDThreeSameVectorDot<bit Q, bit U, string asm, string kind1,
4794                                  string kind2, RegisterOperand RegType,
4795                                  ValueType AccumType, ValueType InputType,
4796                                  SDPatternOperator OpNode> :
4797         BaseSIMDThreeSameVectorTied<Q, U, 0b100, 0b10010, RegType, asm, kind1,
4798         [(set (AccumType RegType:$dst),
4799               (OpNode (AccumType RegType:$Rd),
4800                       (InputType RegType:$Rn),
4801                       (InputType RegType:$Rm)))]> {
4802   let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
4803 }
4804
4805 multiclass SIMDThreeSameVectorDot<bit U, string asm, SDPatternOperator OpNode> {
4806   def v8i8  : BaseSIMDThreeSameVectorDot<0, U, asm, ".2s", ".8b", V64,
4807                                          v2i32, v8i8, OpNode>;
4808   def v16i8 : BaseSIMDThreeSameVectorDot<1, U, asm, ".4s", ".16b", V128,
4809                                          v4i32, v16i8, OpNode>;
4810 }
4811
4812 // All operand sizes distinguished in the encoding.
4813 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4814                                SDPatternOperator OpNode> {
4815   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4816                                       asm, ".8b",
4817          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4818   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4819                                       asm, ".16b",
4820          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4821   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4822                                       asm, ".4h",
4823          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4824   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4825                                       asm, ".8h",
4826          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4827   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4828                                       asm, ".2s",
4829          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4830   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4831                                       asm, ".4s",
4832          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4833   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
4834                                       asm, ".2d",
4835          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4836 }
4837
4838 // As above, but D sized elements unsupported.
4839 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4840                                   SDPatternOperator OpNode> {
4841   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4842                                       asm, ".8b",
4843         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4844   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4845                                       asm, ".16b",
4846         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4847   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4848                                       asm, ".4h",
4849         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4850   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4851                                       asm, ".8h",
4852         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4853   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4854                                       asm, ".2s",
4855         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4856   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4857                                       asm, ".4s",
4858         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4859 }
4860
4861 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4862                                   SDPatternOperator OpNode> {
4863   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
4864                                       asm, ".8b",
4865       [(set (v8i8 V64:$dst),
4866             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4867   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
4868                                       asm, ".16b",
4869       [(set (v16i8 V128:$dst),
4870             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4871   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
4872                                       asm, ".4h",
4873       [(set (v4i16 V64:$dst),
4874             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4875   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
4876                                       asm, ".8h",
4877       [(set (v8i16 V128:$dst),
4878             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4879   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
4880                                       asm, ".2s",
4881       [(set (v2i32 V64:$dst),
4882             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4883   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
4884                                       asm, ".4s",
4885       [(set (v4i32 V128:$dst),
4886             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4887 }
4888
4889 // As above, but only B sized elements supported.
4890 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4891                                 SDPatternOperator OpNode> {
4892   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4893                                       asm, ".8b",
4894     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4895   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4896                                       asm, ".16b",
4897     [(set (v16i8 V128:$Rd),
4898           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4899 }
4900
4901 // As above, but only floating point elements supported.
4902 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
4903                                  string asm, SDPatternOperator OpNode> {
4904   let Predicates = [HasNEON, HasFullFP16] in {
4905   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4906                                       asm, ".4h",
4907         [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4908   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4909                                       asm, ".8h",
4910         [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4911   } // Predicates = [HasNEON, HasFullFP16]
4912   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4913                                       asm, ".2s",
4914         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4915   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4916                                       asm, ".4s",
4917         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4918   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4919                                       asm, ".2d",
4920         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4921 }
4922
4923 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
4924                                     string asm,
4925                                     SDPatternOperator OpNode> {
4926   let Predicates = [HasNEON, HasFullFP16] in {
4927   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4928                                       asm, ".4h",
4929         [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4930   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4931                                       asm, ".8h",
4932         [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4933   } // Predicates = [HasNEON, HasFullFP16]
4934   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4935                                       asm, ".2s",
4936         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4937   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4938                                       asm, ".4s",
4939         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4940   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4941                                       asm, ".2d",
4942         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4943 }
4944
4945 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
4946                                  string asm, SDPatternOperator OpNode> {
4947   let Predicates = [HasNEON, HasFullFP16] in {
4948   def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
4949                                       asm, ".4h",
4950      [(set (v4f16 V64:$dst),
4951            (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4952   def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
4953                                       asm, ".8h",
4954      [(set (v8f16 V128:$dst),
4955            (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4956   } // Predicates = [HasNEON, HasFullFP16]
4957   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
4958                                       asm, ".2s",
4959      [(set (v2f32 V64:$dst),
4960            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4961   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
4962                                       asm, ".4s",
4963      [(set (v4f32 V128:$dst),
4964            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4965   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
4966                                       asm, ".2d",
4967      [(set (v2f64 V128:$dst),
4968            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4969 }
4970
4971 // As above, but D and B sized elements unsupported.
4972 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4973                                 SDPatternOperator OpNode> {
4974   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4975                                       asm, ".4h",
4976         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4977   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4978                                       asm, ".8h",
4979         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4980   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4981                                       asm, ".2s",
4982         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4983   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4984                                       asm, ".4s",
4985         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4986 }
4987
4988 // Logical three vector ops share opcode bits, and only use B sized elements.
4989 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4990                                   SDPatternOperator OpNode = null_frag> {
4991   def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
4992                                      asm, ".8b",
4993                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4994   def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
4995                                      asm, ".16b",
4996                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4997
4998   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4999           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5000   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5001           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5002   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5003           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5004
5005   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5006       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5007   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5008       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5009   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5010       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5011 }
5012
5013 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5014                                   string asm, SDPatternOperator OpNode> {
5015   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5016                                      asm, ".8b",
5017              [(set (v8i8 V64:$dst),
5018                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5019   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5020                                      asm, ".16b",
5021              [(set (v16i8 V128:$dst),
5022                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5023                            (v16i8 V128:$Rm)))]>;
5024
5025   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5026                            (v4i16 V64:$RHS))),
5027           (!cast<Instruction>(NAME#"v8i8")
5028             V64:$LHS, V64:$MHS, V64:$RHS)>;
5029   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5030                            (v2i32 V64:$RHS))),
5031           (!cast<Instruction>(NAME#"v8i8")
5032             V64:$LHS, V64:$MHS, V64:$RHS)>;
5033   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5034                            (v1i64 V64:$RHS))),
5035           (!cast<Instruction>(NAME#"v8i8")
5036             V64:$LHS, V64:$MHS, V64:$RHS)>;
5037
5038   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5039                            (v8i16 V128:$RHS))),
5040       (!cast<Instruction>(NAME#"v16i8")
5041         V128:$LHS, V128:$MHS, V128:$RHS)>;
5042   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5043                            (v4i32 V128:$RHS))),
5044       (!cast<Instruction>(NAME#"v16i8")
5045         V128:$LHS, V128:$MHS, V128:$RHS)>;
5046   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5047                            (v2i64 V128:$RHS))),
5048       (!cast<Instruction>(NAME#"v16i8")
5049         V128:$LHS, V128:$MHS, V128:$RHS)>;
5050 }
5051
5052
5053 //----------------------------------------------------------------------------
5054 // AdvSIMD two register vector instructions.
5055 //----------------------------------------------------------------------------
5056
5057 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5058 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5059                             bits<2> size2, RegisterOperand regtype, string asm,
5060                             string dstkind, string srckind, list<dag> pattern>
5061   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5062       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5063       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5064     Sched<[WriteV]> {
5065   bits<5> Rd;
5066   bits<5> Rn;
5067   let Inst{31}    = 0;
5068   let Inst{30}    = Q;
5069   let Inst{29}    = U;
5070   let Inst{28-24} = 0b01110;
5071   let Inst{23-22} = size;
5072   let Inst{21} = 0b1;
5073   let Inst{20-19} = size2;
5074   let Inst{18-17} = 0b00;
5075   let Inst{16-12} = opcode;
5076   let Inst{11-10} = 0b10;
5077   let Inst{9-5}   = Rn;
5078   let Inst{4-0}   = Rd;
5079 }
5080
5081 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5082 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5083                                 bits<2> size2, RegisterOperand regtype,
5084                                 string asm, string dstkind, string srckind,
5085                                 list<dag> pattern>
5086   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5087       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5088       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5089     Sched<[WriteV]> {
5090   bits<5> Rd;
5091   bits<5> Rn;
5092   let Inst{31}    = 0;
5093   let Inst{30}    = Q;
5094   let Inst{29}    = U;
5095   let Inst{28-24} = 0b01110;
5096   let Inst{23-22} = size;
5097   let Inst{21} = 0b1;
5098   let Inst{20-19} = size2;
5099   let Inst{18-17} = 0b00;
5100   let Inst{16-12} = opcode;
5101   let Inst{11-10} = 0b10;
5102   let Inst{9-5}   = Rn;
5103   let Inst{4-0}   = Rd;
5104 }
5105
5106 // Supports B, H, and S element sizes.
5107 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5108                             SDPatternOperator OpNode> {
5109   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5110                                       asm, ".8b", ".8b",
5111                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5112   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5113                                       asm, ".16b", ".16b",
5114                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5115   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5116                                       asm, ".4h", ".4h",
5117                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5118   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5119                                       asm, ".8h", ".8h",
5120                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5121   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5122                                       asm, ".2s", ".2s",
5123                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5124   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5125                                       asm, ".4s", ".4s",
5126                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5127 }
5128
5129 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5130                             RegisterOperand regtype, string asm, string dstkind,
5131                             string srckind, string amount>
5132   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5133       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5134       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5135     Sched<[WriteV]> {
5136   bits<5> Rd;
5137   bits<5> Rn;
5138   let Inst{31}    = 0;
5139   let Inst{30}    = Q;
5140   let Inst{29-24} = 0b101110;
5141   let Inst{23-22} = size;
5142   let Inst{21-10} = 0b100001001110;
5143   let Inst{9-5}   = Rn;
5144   let Inst{4-0}   = Rd;
5145 }
5146
5147 multiclass SIMDVectorLShiftLongBySizeBHS {
5148   let hasSideEffects = 0 in {
5149   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5150                                              "shll", ".8h",  ".8b", "8">;
5151   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5152                                              "shll2", ".8h", ".16b", "8">;
5153   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5154                                              "shll", ".4s",  ".4h", "16">;
5155   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5156                                              "shll2", ".4s", ".8h", "16">;
5157   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5158                                              "shll", ".2d",  ".2s", "32">;
5159   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5160                                              "shll2", ".2d", ".4s", "32">;
5161   }
5162 }
5163
5164 // Supports all element sizes.
5165 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5166                              SDPatternOperator OpNode> {
5167   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5168                                       asm, ".4h", ".8b",
5169                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5170   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5171                                       asm, ".8h", ".16b",
5172                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5173   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5174                                       asm, ".2s", ".4h",
5175                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5176   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5177                                       asm, ".4s", ".8h",
5178                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5179   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5180                                       asm, ".1d", ".2s",
5181                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5182   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5183                                       asm, ".2d", ".4s",
5184                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5185 }
5186
5187 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5188                                  SDPatternOperator OpNode> {
5189   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5190                                           asm, ".4h", ".8b",
5191       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5192                                       (v8i8 V64:$Rn)))]>;
5193   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5194                                           asm, ".8h", ".16b",
5195       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5196                                       (v16i8 V128:$Rn)))]>;
5197   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5198                                           asm, ".2s", ".4h",
5199       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5200                                       (v4i16 V64:$Rn)))]>;
5201   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5202                                           asm, ".4s", ".8h",
5203       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5204                                       (v8i16 V128:$Rn)))]>;
5205   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5206                                           asm, ".1d", ".2s",
5207       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5208                                       (v2i32 V64:$Rn)))]>;
5209   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5210                                           asm, ".2d", ".4s",
5211       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5212                                       (v4i32 V128:$Rn)))]>;
5213 }
5214
5215 // Supports all element sizes, except 1xD.
5216 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5217                                   SDPatternOperator OpNode> {
5218   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5219                                     asm, ".8b", ".8b",
5220     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5221   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5222                                     asm, ".16b", ".16b",
5223     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5224   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5225                                     asm, ".4h", ".4h",
5226     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5227   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5228                                     asm, ".8h", ".8h",
5229     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5230   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5231                                     asm, ".2s", ".2s",
5232     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5233   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5234                                     asm, ".4s", ".4s",
5235     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5236   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5237                                     asm, ".2d", ".2d",
5238     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5239 }
5240
5241 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5242                              SDPatternOperator OpNode = null_frag> {
5243   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5244                                 asm, ".8b", ".8b",
5245     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5246   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5247                                 asm, ".16b", ".16b",
5248     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5249   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5250                                 asm, ".4h", ".4h",
5251     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5252   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5253                                 asm, ".8h", ".8h",
5254     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5255   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5256                                 asm, ".2s", ".2s",
5257     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5258   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5259                                 asm, ".4s", ".4s",
5260     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5261   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5262                                 asm, ".2d", ".2d",
5263     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5264 }
5265
5266
5267 // Supports only B element sizes.
5268 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5269                           SDPatternOperator OpNode> {
5270   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5271                                 asm, ".8b", ".8b",
5272                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5273   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5274                                 asm, ".16b", ".16b",
5275                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5276
5277 }
5278
5279 // Supports only B and H element sizes.
5280 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5281                                 SDPatternOperator OpNode> {
5282   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5283                                 asm, ".8b", ".8b",
5284                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5285   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5286                                 asm, ".16b", ".16b",
5287                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5288   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5289                                 asm, ".4h", ".4h",
5290                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5291   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5292                                 asm, ".8h", ".8h",
5293                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5294 }
5295
5296 // Supports only S and D element sizes, uses high bit of the size field
5297 // as an extra opcode bit.
5298 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5299                            SDPatternOperator OpNode> {
5300   let Predicates = [HasNEON, HasFullFP16] in {
5301   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5302                                 asm, ".4h", ".4h",
5303                           [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5304   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5305                                 asm, ".8h", ".8h",
5306                           [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5307   } // Predicates = [HasNEON, HasFullFP16]
5308   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5309                                 asm, ".2s", ".2s",
5310                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5311   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5312                                 asm, ".4s", ".4s",
5313                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5314   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5315                                 asm, ".2d", ".2d",
5316                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5317 }
5318
5319 // Supports only S element size.
5320 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5321                            SDPatternOperator OpNode> {
5322   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5323                                 asm, ".2s", ".2s",
5324                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5325   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5326                                 asm, ".4s", ".4s",
5327                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5328 }
5329
5330
5331 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5332                            SDPatternOperator OpNode> {
5333   let Predicates = [HasNEON, HasFullFP16] in {
5334   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5335                                 asm, ".4h", ".4h",
5336                           [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5337   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5338                                 asm, ".8h", ".8h",
5339                           [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5340   } // Predicates = [HasNEON, HasFullFP16]
5341   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5342                                 asm, ".2s", ".2s",
5343                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5344   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5345                                 asm, ".4s", ".4s",
5346                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5347   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5348                                 asm, ".2d", ".2d",
5349                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5350 }
5351
5352 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5353                            SDPatternOperator OpNode> {
5354   let Predicates = [HasNEON, HasFullFP16] in {
5355   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5356                                 asm, ".4h", ".4h",
5357                           [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5358   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5359                                 asm, ".8h", ".8h",
5360                           [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5361   } // Predicates = [HasNEON, HasFullFP16]
5362   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5363                                 asm, ".2s", ".2s",
5364                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5365   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5366                                 asm, ".4s", ".4s",
5367                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5368   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5369                                 asm, ".2d", ".2d",
5370                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5371 }
5372
5373
5374 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5375                            RegisterOperand inreg, RegisterOperand outreg,
5376                            string asm, string outkind, string inkind,
5377                            list<dag> pattern>
5378   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5379       "{\t$Rd" # outkind # ", $Rn" # inkind #
5380       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5381     Sched<[WriteV]> {
5382   bits<5> Rd;
5383   bits<5> Rn;
5384   let Inst{31}    = 0;
5385   let Inst{30}    = Q;
5386   let Inst{29}    = U;
5387   let Inst{28-24} = 0b01110;
5388   let Inst{23-22} = size;
5389   let Inst{21-17} = 0b10000;
5390   let Inst{16-12} = opcode;
5391   let Inst{11-10} = 0b10;
5392   let Inst{9-5}   = Rn;
5393   let Inst{4-0}   = Rd;
5394 }
5395
5396 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5397                            RegisterOperand inreg, RegisterOperand outreg,
5398                            string asm, string outkind, string inkind,
5399                            list<dag> pattern>
5400   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5401       "{\t$Rd" # outkind # ", $Rn" # inkind #
5402       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5403     Sched<[WriteV]> {
5404   bits<5> Rd;
5405   bits<5> Rn;
5406   let Inst{31}    = 0;
5407   let Inst{30}    = Q;
5408   let Inst{29}    = U;
5409   let Inst{28-24} = 0b01110;
5410   let Inst{23-22} = size;
5411   let Inst{21-17} = 0b10000;
5412   let Inst{16-12} = opcode;
5413   let Inst{11-10} = 0b10;
5414   let Inst{9-5}   = Rn;
5415   let Inst{4-0}   = Rd;
5416 }
5417
5418 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
5419                               SDPatternOperator OpNode> {
5420   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
5421                                       asm, ".8b", ".8h",
5422         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5423   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
5424                                       asm#"2", ".16b", ".8h", []>;
5425   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
5426                                       asm, ".4h", ".4s",
5427         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5428   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
5429                                       asm#"2", ".8h", ".4s", []>;
5430   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
5431                                       asm, ".2s", ".2d",
5432         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5433   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
5434                                       asm#"2", ".4s", ".2d", []>;
5435
5436   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
5437             (!cast<Instruction>(NAME # "v16i8")
5438                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5439   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
5440             (!cast<Instruction>(NAME # "v8i16")
5441                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5442   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
5443             (!cast<Instruction>(NAME # "v4i32")
5444                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5445 }
5446
5447 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
5448                            bits<5> opcode, RegisterOperand regtype, string asm,
5449                            string kind, string zero, ValueType dty,
5450                            ValueType sty, SDNode OpNode>
5451   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5452       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5453       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5454       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5455     Sched<[WriteV]> {
5456   bits<5> Rd;
5457   bits<5> Rn;
5458   let Inst{31}    = 0;
5459   let Inst{30}    = Q;
5460   let Inst{29}    = U;
5461   let Inst{28-24} = 0b01110;
5462   let Inst{23-22} = size;
5463   let Inst{21} = 0b1;
5464   let Inst{20-19} = size2;
5465   let Inst{18-17} = 0b00;
5466   let Inst{16-12} = opcode;
5467   let Inst{11-10} = 0b10;
5468   let Inst{9-5}   = Rn;
5469   let Inst{4-0}   = Rd;
5470 }
5471
5472 // Comparisons support all element sizes, except 1xD.
5473 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5474                             SDNode OpNode> {
5475   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5476                                      asm, ".8b", "0",
5477                                      v8i8, v8i8, OpNode>;
5478   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5479                                      asm, ".16b", "0",
5480                                      v16i8, v16i8, OpNode>;
5481   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5482                                      asm, ".4h", "0",
5483                                      v4i16, v4i16, OpNode>;
5484   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5485                                      asm, ".8h", "0",
5486                                      v8i16, v8i16, OpNode>;
5487   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5488                                      asm, ".2s", "0",
5489                                      v2i32, v2i32, OpNode>;
5490   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5491                                      asm, ".4s", "0",
5492                                      v4i32, v4i32, OpNode>;
5493   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5494                                      asm, ".2d", "0",
5495                                      v2i64, v2i64, OpNode>;
5496 }
5497
5498 // FP Comparisons support only S and D element sizes (and H for v8.2a).
5499 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5500                               string asm, SDNode OpNode> {
5501
5502   let Predicates = [HasNEON, HasFullFP16] in {
5503   def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5504                                      asm, ".4h", "0.0",
5505                                      v4i16, v4f16, OpNode>;
5506   def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5507                                      asm, ".8h", "0.0",
5508                                      v8i16, v8f16, OpNode>;
5509   } // Predicates = [HasNEON, HasFullFP16]
5510   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5511                                      asm, ".2s", "0.0",
5512                                      v2i32, v2f32, OpNode>;
5513   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5514                                      asm, ".4s", "0.0",
5515                                      v4i32, v4f32, OpNode>;
5516   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5517                                      asm, ".2d", "0.0",
5518                                      v2i64, v2f64, OpNode>;
5519
5520   let Predicates = [HasNEON, HasFullFP16] in {
5521   def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5522                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5523   def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5524                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5525   }
5526   def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5527                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5528   def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5529                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5530   def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5531                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5532   let Predicates = [HasNEON, HasFullFP16] in {
5533   def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5534                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5535   def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5536                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5537   }
5538   def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5539                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5540   def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5541                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5542   def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5543                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5544 }
5545
5546 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5547 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5548                              RegisterOperand outtype, RegisterOperand intype,
5549                              string asm, string VdTy, string VnTy,
5550                              list<dag> pattern>
5551   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5552       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5553     Sched<[WriteV]> {
5554   bits<5> Rd;
5555   bits<5> Rn;
5556   let Inst{31}    = 0;
5557   let Inst{30}    = Q;
5558   let Inst{29}    = U;
5559   let Inst{28-24} = 0b01110;
5560   let Inst{23-22} = size;
5561   let Inst{21-17} = 0b10000;
5562   let Inst{16-12} = opcode;
5563   let Inst{11-10} = 0b10;
5564   let Inst{9-5}   = Rn;
5565   let Inst{4-0}   = Rd;
5566 }
5567
5568 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5569                              RegisterOperand outtype, RegisterOperand intype,
5570                              string asm, string VdTy, string VnTy,
5571                              list<dag> pattern>
5572   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5573       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5574     Sched<[WriteV]> {
5575   bits<5> Rd;
5576   bits<5> Rn;
5577   let Inst{31}    = 0;
5578   let Inst{30}    = Q;
5579   let Inst{29}    = U;
5580   let Inst{28-24} = 0b01110;
5581   let Inst{23-22} = size;
5582   let Inst{21-17} = 0b10000;
5583   let Inst{16-12} = opcode;
5584   let Inst{11-10} = 0b10;
5585   let Inst{9-5}   = Rn;
5586   let Inst{4-0}   = Rd;
5587 }
5588
5589 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5590   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5591                                     asm, ".4s", ".4h", []>;
5592   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5593                                     asm#"2", ".4s", ".8h", []>;
5594   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5595                                     asm, ".2d", ".2s", []>;
5596   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5597                                     asm#"2", ".2d", ".4s", []>;
5598 }
5599
5600 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5601   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5602                                     asm, ".4h", ".4s", []>;
5603   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5604                                     asm#"2", ".8h", ".4s", []>;
5605   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5606                                     asm, ".2s", ".2d", []>;
5607   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5608                                     asm#"2", ".4s", ".2d", []>;
5609 }
5610
5611 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5612                                      Intrinsic OpNode> {
5613   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5614                                      asm, ".2s", ".2d",
5615                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5616   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5617                                     asm#"2", ".4s", ".2d", []>;
5618
5619   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5620             (!cast<Instruction>(NAME # "v4f32")
5621                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5622 }
5623
5624 //----------------------------------------------------------------------------
5625 // AdvSIMD three register different-size vector instructions.
5626 //----------------------------------------------------------------------------
5627
5628 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5629 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5630                       RegisterOperand outtype, RegisterOperand intype1,
5631                       RegisterOperand intype2, string asm,
5632                       string outkind, string inkind1, string inkind2,
5633                       list<dag> pattern>
5634   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5635       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5636       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5637     Sched<[WriteV]> {
5638   bits<5> Rd;
5639   bits<5> Rn;
5640   bits<5> Rm;
5641   let Inst{31}    = 0;
5642   let Inst{30}    = size{0};
5643   let Inst{29}    = U;
5644   let Inst{28-24} = 0b01110;
5645   let Inst{23-22} = size{2-1};
5646   let Inst{21}    = 1;
5647   let Inst{20-16} = Rm;
5648   let Inst{15-12} = opcode;
5649   let Inst{11-10} = 0b00;
5650   let Inst{9-5}   = Rn;
5651   let Inst{4-0}   = Rd;
5652 }
5653
5654 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5655 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5656                       RegisterOperand outtype, RegisterOperand intype1,
5657                       RegisterOperand intype2, string asm,
5658                       string outkind, string inkind1, string inkind2,
5659                       list<dag> pattern>
5660   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5661       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5662       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5663     Sched<[WriteV]> {
5664   bits<5> Rd;
5665   bits<5> Rn;
5666   bits<5> Rm;
5667   let Inst{31}    = 0;
5668   let Inst{30}    = size{0};
5669   let Inst{29}    = U;
5670   let Inst{28-24} = 0b01110;
5671   let Inst{23-22} = size{2-1};
5672   let Inst{21}    = 1;
5673   let Inst{20-16} = Rm;
5674   let Inst{15-12} = opcode;
5675   let Inst{11-10} = 0b00;
5676   let Inst{9-5}   = Rn;
5677   let Inst{4-0}   = Rd;
5678 }
5679
5680 // FIXME: TableGen doesn't know how to deal with expanded types that also
5681 //        change the element count (in this case, placing the results in
5682 //        the high elements of the result register rather than the low
5683 //        elements). Until that's fixed, we can't code-gen those.
5684 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5685                                     Intrinsic IntOp> {
5686   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5687                                                   V64, V128, V128,
5688                                                   asm, ".8b", ".8h", ".8h",
5689      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5690   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5691                                                   V128, V128, V128,
5692                                                   asm#"2", ".16b", ".8h", ".8h",
5693      []>;
5694   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5695                                                   V64, V128, V128,
5696                                                   asm, ".4h", ".4s", ".4s",
5697      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5698   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5699                                                   V128, V128, V128,
5700                                                   asm#"2", ".8h", ".4s", ".4s",
5701      []>;
5702   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5703                                                   V64, V128, V128,
5704                                                   asm, ".2s", ".2d", ".2d",
5705      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5706   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5707                                                   V128, V128, V128,
5708                                                   asm#"2", ".4s", ".2d", ".2d",
5709      []>;
5710
5711
5712   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5713   // a version attached to an instruction.
5714   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5715                                                    (v8i16 V128:$Rm))),
5716             (!cast<Instruction>(NAME # "v8i16_v16i8")
5717                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5718                 V128:$Rn, V128:$Rm)>;
5719   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5720                                                     (v4i32 V128:$Rm))),
5721             (!cast<Instruction>(NAME # "v4i32_v8i16")
5722                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5723                 V128:$Rn, V128:$Rm)>;
5724   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5725                                                     (v2i64 V128:$Rm))),
5726             (!cast<Instruction>(NAME # "v2i64_v4i32")
5727                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5728                 V128:$Rn, V128:$Rm)>;
5729 }
5730
5731 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5732                                       Intrinsic IntOp> {
5733   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5734                                             V128, V64, V64,
5735                                             asm, ".8h", ".8b", ".8b",
5736       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5737   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5738                                             V128, V128, V128,
5739                                             asm#"2", ".8h", ".16b", ".16b", []>;
5740   let Predicates = [HasAES] in {
5741     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5742                                               V128, V64, V64,
5743                                               asm, ".1q", ".1d", ".1d", []>;
5744     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5745                                               V128, V128, V128,
5746                                               asm#"2", ".1q", ".2d", ".2d", []>;
5747   }
5748
5749   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5750                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
5751       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5752 }
5753
5754 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5755                                  SDPatternOperator OpNode> {
5756   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5757                                                   V128, V64, V64,
5758                                                   asm, ".4s", ".4h", ".4h",
5759       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5760   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5761                                                   V128, V128, V128,
5762                                                   asm#"2", ".4s", ".8h", ".8h",
5763       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5764                                       (extract_high_v8i16 V128:$Rm)))]>;
5765   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5766                                                   V128, V64, V64,
5767                                                   asm, ".2d", ".2s", ".2s",
5768       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5769   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5770                                                   V128, V128, V128,
5771                                                   asm#"2", ".2d", ".4s", ".4s",
5772       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5773                                       (extract_high_v4i32 V128:$Rm)))]>;
5774 }
5775
5776 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5777                                   SDPatternOperator OpNode = null_frag> {
5778   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5779                                                   V128, V64, V64,
5780                                                   asm, ".8h", ".8b", ".8b",
5781       [(set (v8i16 V128:$Rd),
5782             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5783   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5784                                                  V128, V128, V128,
5785                                                  asm#"2", ".8h", ".16b", ".16b",
5786       [(set (v8i16 V128:$Rd),
5787             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5788                                 (extract_high_v16i8 V128:$Rm)))))]>;
5789   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5790                                                   V128, V64, V64,
5791                                                   asm, ".4s", ".4h", ".4h",
5792       [(set (v4i32 V128:$Rd),
5793             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5794   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5795                                                   V128, V128, V128,
5796                                                   asm#"2", ".4s", ".8h", ".8h",
5797       [(set (v4i32 V128:$Rd),
5798             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5799                                   (extract_high_v8i16 V128:$Rm)))))]>;
5800   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5801                                                   V128, V64, V64,
5802                                                   asm, ".2d", ".2s", ".2s",
5803       [(set (v2i64 V128:$Rd),
5804             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5805   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5806                                                   V128, V128, V128,
5807                                                   asm#"2", ".2d", ".4s", ".4s",
5808       [(set (v2i64 V128:$Rd),
5809             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5810                                  (extract_high_v4i32 V128:$Rm)))))]>;
5811 }
5812
5813 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5814                                           string asm,
5815                                           SDPatternOperator OpNode> {
5816   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5817                                                   V128, V64, V64,
5818                                                   asm, ".8h", ".8b", ".8b",
5819     [(set (v8i16 V128:$dst),
5820           (add (v8i16 V128:$Rd),
5821                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5822   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5823                                                  V128, V128, V128,
5824                                                  asm#"2", ".8h", ".16b", ".16b",
5825     [(set (v8i16 V128:$dst),
5826           (add (v8i16 V128:$Rd),
5827                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5828                                    (extract_high_v16i8 V128:$Rm))))))]>;
5829   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5830                                                   V128, V64, V64,
5831                                                   asm, ".4s", ".4h", ".4h",
5832     [(set (v4i32 V128:$dst),
5833           (add (v4i32 V128:$Rd),
5834                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5835   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5836                                                   V128, V128, V128,
5837                                                   asm#"2", ".4s", ".8h", ".8h",
5838     [(set (v4i32 V128:$dst),
5839           (add (v4i32 V128:$Rd),
5840                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5841                                     (extract_high_v8i16 V128:$Rm))))))]>;
5842   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5843                                                   V128, V64, V64,
5844                                                   asm, ".2d", ".2s", ".2s",
5845     [(set (v2i64 V128:$dst),
5846           (add (v2i64 V128:$Rd),
5847                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5848   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5849                                                   V128, V128, V128,
5850                                                   asm#"2", ".2d", ".4s", ".4s",
5851     [(set (v2i64 V128:$dst),
5852           (add (v2i64 V128:$Rd),
5853                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5854                                     (extract_high_v4i32 V128:$Rm))))))]>;
5855 }
5856
5857 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5858                                   SDPatternOperator OpNode = null_frag> {
5859   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5860                                                   V128, V64, V64,
5861                                                   asm, ".8h", ".8b", ".8b",
5862       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5863   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5864                                                  V128, V128, V128,
5865                                                  asm#"2", ".8h", ".16b", ".16b",
5866       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5867                                       (extract_high_v16i8 V128:$Rm)))]>;
5868   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5869                                                   V128, V64, V64,
5870                                                   asm, ".4s", ".4h", ".4h",
5871       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5872   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5873                                                   V128, V128, V128,
5874                                                   asm#"2", ".4s", ".8h", ".8h",
5875       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5876                                       (extract_high_v8i16 V128:$Rm)))]>;
5877   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5878                                                   V128, V64, V64,
5879                                                   asm, ".2d", ".2s", ".2s",
5880       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5881   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5882                                                   V128, V128, V128,
5883                                                   asm#"2", ".2d", ".4s", ".4s",
5884       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5885                                       (extract_high_v4i32 V128:$Rm)))]>;
5886 }
5887
5888 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5889                                       string asm,
5890                                       SDPatternOperator OpNode> {
5891   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5892                                                   V128, V64, V64,
5893                                                   asm, ".8h", ".8b", ".8b",
5894     [(set (v8i16 V128:$dst),
5895           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5896   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5897                                                  V128, V128, V128,
5898                                                  asm#"2", ".8h", ".16b", ".16b",
5899     [(set (v8i16 V128:$dst),
5900           (OpNode (v8i16 V128:$Rd),
5901                   (extract_high_v16i8 V128:$Rn),
5902                   (extract_high_v16i8 V128:$Rm)))]>;
5903   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5904                                                   V128, V64, V64,
5905                                                   asm, ".4s", ".4h", ".4h",
5906     [(set (v4i32 V128:$dst),
5907           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5908   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5909                                                   V128, V128, V128,
5910                                                   asm#"2", ".4s", ".8h", ".8h",
5911     [(set (v4i32 V128:$dst),
5912           (OpNode (v4i32 V128:$Rd),
5913                   (extract_high_v8i16 V128:$Rn),
5914                   (extract_high_v8i16 V128:$Rm)))]>;
5915   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5916                                                   V128, V64, V64,
5917                                                   asm, ".2d", ".2s", ".2s",
5918     [(set (v2i64 V128:$dst),
5919           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5920   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5921                                                   V128, V128, V128,
5922                                                   asm#"2", ".2d", ".4s", ".4s",
5923     [(set (v2i64 V128:$dst),
5924           (OpNode (v2i64 V128:$Rd),
5925                   (extract_high_v4i32 V128:$Rn),
5926                   (extract_high_v4i32 V128:$Rm)))]>;
5927 }
5928
5929 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5930                                            SDPatternOperator Accum> {
5931   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5932                                                   V128, V64, V64,
5933                                                   asm, ".4s", ".4h", ".4h",
5934     [(set (v4i32 V128:$dst),
5935           (Accum (v4i32 V128:$Rd),
5936                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5937                                                 (v4i16 V64:$Rm)))))]>;
5938   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5939                                                   V128, V128, V128,
5940                                                   asm#"2", ".4s", ".8h", ".8h",
5941     [(set (v4i32 V128:$dst),
5942           (Accum (v4i32 V128:$Rd),
5943                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5944                                             (extract_high_v8i16 V128:$Rm)))))]>;
5945   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5946                                                   V128, V64, V64,
5947                                                   asm, ".2d", ".2s", ".2s",
5948     [(set (v2i64 V128:$dst),
5949           (Accum (v2i64 V128:$Rd),
5950                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5951                                                 (v2i32 V64:$Rm)))))]>;
5952   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5953                                                   V128, V128, V128,
5954                                                   asm#"2", ".2d", ".4s", ".4s",
5955     [(set (v2i64 V128:$dst),
5956           (Accum (v2i64 V128:$Rd),
5957                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5958                                             (extract_high_v4i32 V128:$Rm)))))]>;
5959 }
5960
5961 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5962                                   SDPatternOperator OpNode> {
5963   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5964                                                   V128, V128, V64,
5965                                                   asm, ".8h", ".8h", ".8b",
5966        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5967   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5968                                                   V128, V128, V128,
5969                                                   asm#"2", ".8h", ".8h", ".16b",
5970        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5971                                        (extract_high_v16i8 V128:$Rm)))]>;
5972   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5973                                                   V128, V128, V64,
5974                                                   asm, ".4s", ".4s", ".4h",
5975        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5976   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5977                                                   V128, V128, V128,
5978                                                   asm#"2", ".4s", ".4s", ".8h",
5979        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5980                                        (extract_high_v8i16 V128:$Rm)))]>;
5981   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5982                                                   V128, V128, V64,
5983                                                   asm, ".2d", ".2d", ".2s",
5984        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5985   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5986                                                   V128, V128, V128,
5987                                                   asm#"2", ".2d", ".2d", ".4s",
5988        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5989                                        (extract_high_v4i32 V128:$Rm)))]>;
5990 }
5991
5992 //----------------------------------------------------------------------------
5993 // AdvSIMD bitwise extract from vector
5994 //----------------------------------------------------------------------------
5995
5996 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5997                              string asm, string kind>
5998   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5999       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6000       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6001       [(set (vty regtype:$Rd),
6002             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6003     Sched<[WriteV]> {
6004   bits<5> Rd;
6005   bits<5> Rn;
6006   bits<5> Rm;
6007   bits<4> imm;
6008   let Inst{31}    = 0;
6009   let Inst{30}    = size;
6010   let Inst{29-21} = 0b101110000;
6011   let Inst{20-16} = Rm;
6012   let Inst{15}    = 0;
6013   let Inst{14-11} = imm;
6014   let Inst{10}    = 0;
6015   let Inst{9-5}   = Rn;
6016   let Inst{4-0}   = Rd;
6017 }
6018
6019
6020 multiclass SIMDBitwiseExtract<string asm> {
6021   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6022     let imm{3} = 0;
6023   }
6024   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6025 }
6026
6027 //----------------------------------------------------------------------------
6028 // AdvSIMD zip vector
6029 //----------------------------------------------------------------------------
6030
6031 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6032                         string asm, string kind, SDNode OpNode, ValueType valty>
6033   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6034       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6035       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6036       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6037     Sched<[WriteV]> {
6038   bits<5> Rd;
6039   bits<5> Rn;
6040   bits<5> Rm;
6041   let Inst{31}    = 0;
6042   let Inst{30}    = size{0};
6043   let Inst{29-24} = 0b001110;
6044   let Inst{23-22} = size{2-1};
6045   let Inst{21}    = 0;
6046   let Inst{20-16} = Rm;
6047   let Inst{15}    = 0;
6048   let Inst{14-12} = opc;
6049   let Inst{11-10} = 0b10;
6050   let Inst{9-5}   = Rn;
6051   let Inst{4-0}   = Rd;
6052 }
6053
6054 multiclass SIMDZipVector<bits<3>opc, string asm,
6055                          SDNode OpNode> {
6056   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6057       asm, ".8b", OpNode, v8i8>;
6058   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6059       asm, ".16b", OpNode, v16i8>;
6060   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6061       asm, ".4h", OpNode, v4i16>;
6062   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6063       asm, ".8h", OpNode, v8i16>;
6064   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6065       asm, ".2s", OpNode, v2i32>;
6066   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6067       asm, ".4s", OpNode, v4i32>;
6068   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6069       asm, ".2d", OpNode, v2i64>;
6070
6071   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6072         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6073   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6074         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6075   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6076         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6077   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6078         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6079   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6080         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6081 }
6082
6083 //----------------------------------------------------------------------------
6084 // AdvSIMD three register scalar instructions
6085 //----------------------------------------------------------------------------
6086
6087 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6088 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6089                         RegisterClass regtype, string asm,
6090                         list<dag> pattern>
6091   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6092       "\t$Rd, $Rn, $Rm", "", pattern>,
6093     Sched<[WriteV]> {
6094   bits<5> Rd;
6095   bits<5> Rn;
6096   bits<5> Rm;
6097   let Inst{31-30} = 0b01;
6098   let Inst{29}    = U;
6099   let Inst{28-24} = 0b11110;
6100   let Inst{23-21} = size;
6101   let Inst{20-16} = Rm;
6102   let Inst{15-11} = opcode;
6103   let Inst{10}    = 1;
6104   let Inst{9-5}   = Rn;
6105   let Inst{4-0}   = Rd;
6106 }
6107
6108 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6109 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6110                         dag oops, dag iops, string asm,
6111             list<dag> pattern>
6112   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6113     Sched<[WriteV]> {
6114   bits<5> Rd;
6115   bits<5> Rn;
6116   bits<5> Rm;
6117   let Inst{31-30} = 0b01;
6118   let Inst{29}    = U;
6119   let Inst{28-24} = 0b11110;
6120   let Inst{23-22} = size;
6121   let Inst{21}    = R;
6122   let Inst{20-16} = Rm;
6123   let Inst{15-11} = opcode;
6124   let Inst{10}    = 1;
6125   let Inst{9-5}   = Rn;
6126   let Inst{4-0}   = Rd;
6127 }
6128
6129 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6130                             SDPatternOperator OpNode> {
6131   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6132     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6133 }
6134
6135 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6136                                SDPatternOperator OpNode> {
6137   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6138     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6139   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6140   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6141   def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6142
6143   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6144             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6145   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6146             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6147 }
6148
6149 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6150                              SDPatternOperator OpNode> {
6151   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6152                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6153   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6154 }
6155
6156 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6157                                  SDPatternOperator OpNode = null_frag> {
6158   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6159                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6160                                      asm, []>;
6161   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6162                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6163                                      asm, []>;
6164 }
6165
6166 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6167                              SDPatternOperator OpNode = null_frag> {
6168   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6169     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6170       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6171     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6172       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6173     let Predicates = [HasNEON, HasFullFP16] in {
6174     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6175       [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
6176     } // Predicates = [HasNEON, HasFullFP16]
6177   }
6178
6179   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6180             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6181 }
6182
6183 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6184                                 SDPatternOperator OpNode = null_frag> {
6185   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6186     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6187       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6188     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6189       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6190     let Predicates = [HasNEON, HasFullFP16] in {
6191     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6192       []>;
6193     } // Predicates = [HasNEON, HasFullFP16]
6194   }
6195
6196   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6197             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6198 }
6199
6200 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6201               dag oops, dag iops, string asm, string cstr, list<dag> pat>
6202   : I<oops, iops, asm,
6203       "\t$Rd, $Rn, $Rm", cstr, pat>,
6204     Sched<[WriteV]> {
6205   bits<5> Rd;
6206   bits<5> Rn;
6207   bits<5> Rm;
6208   let Inst{31-30} = 0b01;
6209   let Inst{29}    = U;
6210   let Inst{28-24} = 0b11110;
6211   let Inst{23-22} = size;
6212   let Inst{21}    = 1;
6213   let Inst{20-16} = Rm;
6214   let Inst{15-11} = opcode;
6215   let Inst{10}    = 0;
6216   let Inst{9-5}   = Rn;
6217   let Inst{4-0}   = Rd;
6218 }
6219
6220 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6221 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6222                                   SDPatternOperator OpNode = null_frag> {
6223   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6224                                       (outs FPR32:$Rd),
6225                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6226   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6227                                       (outs FPR64:$Rd),
6228                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6229             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6230 }
6231
6232 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6233 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6234                                   SDPatternOperator OpNode = null_frag> {
6235   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6236                                       (outs FPR32:$dst),
6237                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6238                                       asm, "$Rd = $dst", []>;
6239   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6240                                       (outs FPR64:$dst),
6241                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6242                                       asm, "$Rd = $dst",
6243             [(set (i64 FPR64:$dst),
6244                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6245 }
6246
6247 //----------------------------------------------------------------------------
6248 // AdvSIMD two register scalar instructions
6249 //----------------------------------------------------------------------------
6250
6251 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6252 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6253                         RegisterClass regtype, RegisterClass regtype2,
6254                         string asm, list<dag> pat>
6255   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6256       "\t$Rd, $Rn", "", pat>,
6257     Sched<[WriteV]> {
6258   bits<5> Rd;
6259   bits<5> Rn;
6260   let Inst{31-30} = 0b01;
6261   let Inst{29}    = U;
6262   let Inst{28-24} = 0b11110;
6263   let Inst{23-22} = size;
6264   let Inst{21} = 0b1;
6265   let Inst{20-19} = size2;
6266   let Inst{18-17} = 0b00;
6267   let Inst{16-12} = opcode;
6268   let Inst{11-10} = 0b10;
6269   let Inst{9-5}   = Rn;
6270   let Inst{4-0}   = Rd;
6271 }
6272
6273 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6274 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6275                         RegisterClass regtype, RegisterClass regtype2,
6276                         string asm, list<dag> pat>
6277   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6278       "\t$Rd, $Rn", "$Rd = $dst", pat>,
6279     Sched<[WriteV]> {
6280   bits<5> Rd;
6281   bits<5> Rn;
6282   let Inst{31-30} = 0b01;
6283   let Inst{29}    = U;
6284   let Inst{28-24} = 0b11110;
6285   let Inst{23-22} = size;
6286   let Inst{21-17} = 0b10000;
6287   let Inst{16-12} = opcode;
6288   let Inst{11-10} = 0b10;
6289   let Inst{9-5}   = Rn;
6290   let Inst{4-0}   = Rd;
6291 }
6292
6293
6294 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6295 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6296                         RegisterClass regtype, string asm, string zero>
6297   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6298       "\t$Rd, $Rn, #" # zero, "", []>,
6299     Sched<[WriteV]> {
6300   bits<5> Rd;
6301   bits<5> Rn;
6302   let Inst{31-30} = 0b01;
6303   let Inst{29}    = U;
6304   let Inst{28-24} = 0b11110;
6305   let Inst{23-22} = size;
6306   let Inst{21} = 0b1;
6307   let Inst{20-19} = size2;
6308   let Inst{18-17} = 0b00;
6309   let Inst{16-12} = opcode;
6310   let Inst{11-10} = 0b10;
6311   let Inst{9-5}   = Rn;
6312   let Inst{4-0}   = Rd;
6313 }
6314
6315 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6316   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6317      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6318     Sched<[WriteV]> {
6319   bits<5> Rd;
6320   bits<5> Rn;
6321   let Inst{31-17} = 0b011111100110000;
6322   let Inst{16-12} = opcode;
6323   let Inst{11-10} = 0b10;
6324   let Inst{9-5}   = Rn;
6325   let Inst{4-0}   = Rd;
6326 }
6327
6328 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6329                              SDPatternOperator OpNode> {
6330   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6331
6332   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6333             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6334 }
6335
6336 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6337                               SDPatternOperator OpNode> {
6338   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6339   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6340   let Predicates = [HasNEON, HasFullFP16] in {
6341   def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6342   }
6343
6344   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6345                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6346   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6347                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6348   let Predicates = [HasNEON, HasFullFP16] in {
6349   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6350                   (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6351   }
6352
6353   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6354             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6355 }
6356
6357 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6358                           SDPatternOperator OpNode = null_frag> {
6359   def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6360     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6361
6362   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6363             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6364 }
6365
6366 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6367   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6368   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6369   let Predicates = [HasNEON, HasFullFP16] in {
6370   def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6371   }
6372 }
6373
6374 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6375                               SDPatternOperator OpNode> {
6376   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6377                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6378   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6379                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6380   let Predicates = [HasNEON, HasFullFP16] in {
6381   def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6382                                 [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
6383   }
6384 }
6385
6386 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6387                              SDPatternOperator OpNode = null_frag> {
6388   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6389     def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6390            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6391     def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6392            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6393     def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6394     def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6395   }
6396
6397   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6398             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6399 }
6400
6401 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6402                                  Intrinsic OpNode> {
6403   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6404     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6405         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6406     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6407         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
6408     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
6409     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
6410   }
6411
6412   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
6413             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
6414 }
6415
6416
6417
6418 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6419 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
6420                                  SDPatternOperator OpNode = null_frag> {
6421   def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
6422         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6423   def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
6424   def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
6425 }
6426
6427 //----------------------------------------------------------------------------
6428 // AdvSIMD scalar pairwise instructions
6429 //----------------------------------------------------------------------------
6430
6431 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6432 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
6433                         RegisterOperand regtype, RegisterOperand vectype,
6434                         string asm, string kind>
6435   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6436       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
6437     Sched<[WriteV]> {
6438   bits<5> Rd;
6439   bits<5> Rn;
6440   let Inst{31-30} = 0b01;
6441   let Inst{29}    = U;
6442   let Inst{28-24} = 0b11110;
6443   let Inst{23-22} = size;
6444   let Inst{21-17} = 0b11000;
6445   let Inst{16-12} = opcode;
6446   let Inst{11-10} = 0b10;
6447   let Inst{9-5}   = Rn;
6448   let Inst{4-0}   = Rd;
6449 }
6450
6451 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6452   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6453                                       asm, ".2d">;
6454 }
6455
6456 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6457   let Predicates = [HasNEON, HasFullFP16] in {
6458   def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6459                                       asm, ".2h">;
6460   }
6461   def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6462                                       asm, ".2s">;
6463   def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6464                                       asm, ".2d">;
6465 }
6466
6467 //----------------------------------------------------------------------------
6468 // AdvSIMD across lanes instructions
6469 //----------------------------------------------------------------------------
6470
6471 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6472 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6473                           RegisterClass regtype, RegisterOperand vectype,
6474                           string asm, string kind, list<dag> pattern>
6475   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6476       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6477     Sched<[WriteV]> {
6478   bits<5> Rd;
6479   bits<5> Rn;
6480   let Inst{31}    = 0;
6481   let Inst{30}    = Q;
6482   let Inst{29}    = U;
6483   let Inst{28-24} = 0b01110;
6484   let Inst{23-22} = size;
6485   let Inst{21-17} = 0b11000;
6486   let Inst{16-12} = opcode;
6487   let Inst{11-10} = 0b10;
6488   let Inst{9-5}   = Rn;
6489   let Inst{4-0}   = Rd;
6490 }
6491
6492 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6493                               string asm> {
6494   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
6495                                    asm, ".8b", []>;
6496   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
6497                                    asm, ".16b", []>;
6498   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6499                                    asm, ".4h", []>;
6500   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6501                                    asm, ".8h", []>;
6502   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6503                                    asm, ".4s", []>;
6504 }
6505
6506 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6507   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6508                                    asm, ".8b", []>;
6509   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6510                                    asm, ".16b", []>;
6511   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6512                                    asm, ".4h", []>;
6513   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6514                                    asm, ".8h", []>;
6515   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6516                                    asm, ".4s", []>;
6517 }
6518
6519 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6520                             Intrinsic intOp> {
6521   let Predicates = [HasNEON, HasFullFP16] in {
6522   def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6523                                    asm, ".4h",
6524         [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6525   def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6526                                    asm, ".8h",
6527         [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6528   } // Predicates = [HasNEON, HasFullFP16]
6529   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6530                                    asm, ".4s",
6531         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6532 }
6533
6534 //----------------------------------------------------------------------------
6535 // AdvSIMD INS/DUP instructions
6536 //----------------------------------------------------------------------------
6537
6538 // FIXME: There has got to be a better way to factor these. ugh.
6539
6540 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6541                      string operands, string constraints, list<dag> pattern>
6542   : I<outs, ins, asm, operands, constraints, pattern>,
6543     Sched<[WriteV]> {
6544   bits<5> Rd;
6545   bits<5> Rn;
6546   let Inst{31} = 0;
6547   let Inst{30} = Q;
6548   let Inst{29} = op;
6549   let Inst{28-21} = 0b01110000;
6550   let Inst{15} = 0;
6551   let Inst{10} = 1;
6552   let Inst{9-5} = Rn;
6553   let Inst{4-0} = Rd;
6554 }
6555
6556 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6557                       RegisterOperand vecreg, RegisterClass regtype>
6558   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6559                    "{\t$Rd" # size # ", $Rn" #
6560                    "|" # size # "\t$Rd, $Rn}", "",
6561                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6562   let Inst{20-16} = imm5;
6563   let Inst{14-11} = 0b0001;
6564 }
6565
6566 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6567                          ValueType vectype, ValueType insreg,
6568                          RegisterOperand vecreg, Operand idxtype,
6569                          ValueType elttype, SDNode OpNode>
6570   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6571                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6572                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6573                  [(set (vectype vecreg:$Rd),
6574                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6575   let Inst{14-11} = 0b0000;
6576 }
6577
6578 class SIMDDup64FromElement
6579   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6580                        VectorIndexD, i64, AArch64duplane64> {
6581   bits<1> idx;
6582   let Inst{20} = idx;
6583   let Inst{19-16} = 0b1000;
6584 }
6585
6586 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6587                            RegisterOperand vecreg>
6588   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6589                        VectorIndexS, i64, AArch64duplane32> {
6590   bits<2> idx;
6591   let Inst{20-19} = idx;
6592   let Inst{18-16} = 0b100;
6593 }
6594
6595 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6596                            RegisterOperand vecreg>
6597   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6598                        VectorIndexH, i64, AArch64duplane16> {
6599   bits<3> idx;
6600   let Inst{20-18} = idx;
6601   let Inst{17-16} = 0b10;
6602 }
6603
6604 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6605                           RegisterOperand vecreg>
6606   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6607                        VectorIndexB, i64, AArch64duplane8> {
6608   bits<4> idx;
6609   let Inst{20-17} = idx;
6610   let Inst{16} = 1;
6611 }
6612
6613 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6614                   Operand idxtype, string asm, list<dag> pattern>
6615   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6616                    "{\t$Rd, $Rn" # size # "$idx" #
6617                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6618   let Inst{14-11} = imm4;
6619 }
6620
6621 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6622                Operand idxtype>
6623   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6624 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6625                Operand idxtype>
6626   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6627       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6628
6629 class SIMDMovAlias<string asm, string size, Instruction inst,
6630                    RegisterClass regtype, Operand idxtype>
6631     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6632                     "|" # size # "\t$dst, $src$idx}",
6633                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6634
6635 multiclass SMov {
6636   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6637     bits<4> idx;
6638     let Inst{20-17} = idx;
6639     let Inst{16} = 1;
6640   }
6641   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6642     bits<4> idx;
6643     let Inst{20-17} = idx;
6644     let Inst{16} = 1;
6645   }
6646   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6647     bits<3> idx;
6648     let Inst{20-18} = idx;
6649     let Inst{17-16} = 0b10;
6650   }
6651   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6652     bits<3> idx;
6653     let Inst{20-18} = idx;
6654     let Inst{17-16} = 0b10;
6655   }
6656   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6657     bits<2> idx;
6658     let Inst{20-19} = idx;
6659     let Inst{18-16} = 0b100;
6660   }
6661 }
6662
6663 multiclass UMov {
6664   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6665     bits<4> idx;
6666     let Inst{20-17} = idx;
6667     let Inst{16} = 1;
6668   }
6669   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6670     bits<3> idx;
6671     let Inst{20-18} = idx;
6672     let Inst{17-16} = 0b10;
6673   }
6674   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6675     bits<2> idx;
6676     let Inst{20-19} = idx;
6677     let Inst{18-16} = 0b100;
6678   }
6679   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6680     bits<1> idx;
6681     let Inst{20} = idx;
6682     let Inst{19-16} = 0b1000;
6683   }
6684   def : SIMDMovAlias<"mov", ".s",
6685                      !cast<Instruction>(NAME#"vi32"),
6686                      GPR32, VectorIndexS>;
6687   def : SIMDMovAlias<"mov", ".d",
6688                      !cast<Instruction>(NAME#"vi64"),
6689                      GPR64, VectorIndexD>;
6690 }
6691
6692 class SIMDInsFromMain<string size, ValueType vectype,
6693                       RegisterClass regtype, Operand idxtype>
6694   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6695                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6696                    "{\t$Rd" # size # "$idx, $Rn" #
6697                    "|" # size # "\t$Rd$idx, $Rn}",
6698                    "$Rd = $dst",
6699             [(set V128:$dst,
6700               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6701   let Inst{14-11} = 0b0011;
6702 }
6703
6704 class SIMDInsFromElement<string size, ValueType vectype,
6705                          ValueType elttype, Operand idxtype>
6706   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6707                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6708                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6709                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
6710                    "$Rd = $dst",
6711          [(set V128:$dst,
6712                (vector_insert
6713                  (vectype V128:$Rd),
6714                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6715                  idxtype:$idx))]>;
6716
6717 class SIMDInsMainMovAlias<string size, Instruction inst,
6718                           RegisterClass regtype, Operand idxtype>
6719     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6720                         "|" # size #"\t$dst$idx, $src}",
6721                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6722 class SIMDInsElementMovAlias<string size, Instruction inst,
6723                              Operand idxtype>
6724     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6725                       # "|" # size #"\t$dst$idx, $src$idx2}",
6726                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6727
6728
6729 multiclass SIMDIns {
6730   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6731     bits<4> idx;
6732     let Inst{20-17} = idx;
6733     let Inst{16} = 1;
6734   }
6735   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6736     bits<3> idx;
6737     let Inst{20-18} = idx;
6738     let Inst{17-16} = 0b10;
6739   }
6740   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6741     bits<2> idx;
6742     let Inst{20-19} = idx;
6743     let Inst{18-16} = 0b100;
6744   }
6745   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6746     bits<1> idx;
6747     let Inst{20} = idx;
6748     let Inst{19-16} = 0b1000;
6749   }
6750
6751   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6752     bits<4> idx;
6753     bits<4> idx2;
6754     let Inst{20-17} = idx;
6755     let Inst{16} = 1;
6756     let Inst{14-11} = idx2;
6757   }
6758   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6759     bits<3> idx;
6760     bits<3> idx2;
6761     let Inst{20-18} = idx;
6762     let Inst{17-16} = 0b10;
6763     let Inst{14-12} = idx2;
6764     let Inst{11} = {?};
6765   }
6766   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6767     bits<2> idx;
6768     bits<2> idx2;
6769     let Inst{20-19} = idx;
6770     let Inst{18-16} = 0b100;
6771     let Inst{14-13} = idx2;
6772     let Inst{12-11} = {?,?};
6773   }
6774   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6775     bits<1> idx;
6776     bits<1> idx2;
6777     let Inst{20} = idx;
6778     let Inst{19-16} = 0b1000;
6779     let Inst{14} = idx2;
6780     let Inst{13-11} = {?,?,?};
6781   }
6782
6783   // For all forms of the INS instruction, the "mov" mnemonic is the
6784   // preferred alias. Why they didn't just call the instruction "mov" in
6785   // the first place is a very good question indeed...
6786   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6787                          GPR32, VectorIndexB>;
6788   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6789                          GPR32, VectorIndexH>;
6790   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6791                          GPR32, VectorIndexS>;
6792   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6793                          GPR64, VectorIndexD>;
6794
6795   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6796                          VectorIndexB>;
6797   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6798                          VectorIndexH>;
6799   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6800                          VectorIndexS>;
6801   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6802                          VectorIndexD>;
6803 }
6804
6805 //----------------------------------------------------------------------------
6806 // AdvSIMD TBL/TBX
6807 //----------------------------------------------------------------------------
6808
6809 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6810 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6811                           RegisterOperand listtype, string asm, string kind>
6812   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6813        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6814     Sched<[WriteV]> {
6815   bits<5> Vd;
6816   bits<5> Vn;
6817   bits<5> Vm;
6818   let Inst{31}    = 0;
6819   let Inst{30}    = Q;
6820   let Inst{29-21} = 0b001110000;
6821   let Inst{20-16} = Vm;
6822   let Inst{15}    = 0;
6823   let Inst{14-13} = len;
6824   let Inst{12}    = op;
6825   let Inst{11-10} = 0b00;
6826   let Inst{9-5}   = Vn;
6827   let Inst{4-0}   = Vd;
6828 }
6829
6830 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6831 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6832                           RegisterOperand listtype, string asm, string kind>
6833   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6834        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6835     Sched<[WriteV]> {
6836   bits<5> Vd;
6837   bits<5> Vn;
6838   bits<5> Vm;
6839   let Inst{31}    = 0;
6840   let Inst{30}    = Q;
6841   let Inst{29-21} = 0b001110000;
6842   let Inst{20-16} = Vm;
6843   let Inst{15}    = 0;
6844   let Inst{14-13} = len;
6845   let Inst{12}    = op;
6846   let Inst{11-10} = 0b00;
6847   let Inst{9-5}   = Vn;
6848   let Inst{4-0}   = Vd;
6849 }
6850
6851 class SIMDTableLookupAlias<string asm, Instruction inst,
6852                           RegisterOperand vectype, RegisterOperand listtype>
6853     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6854                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6855
6856 multiclass SIMDTableLookup<bit op, string asm> {
6857   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6858                                       asm, ".8b">;
6859   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6860                                       asm, ".8b">;
6861   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6862                                       asm, ".8b">;
6863   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6864                                       asm, ".8b">;
6865   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6866                                       asm, ".16b">;
6867   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6868                                       asm, ".16b">;
6869   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6870                                       asm, ".16b">;
6871   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6872                                       asm, ".16b">;
6873
6874   def : SIMDTableLookupAlias<asm # ".8b",
6875                          !cast<Instruction>(NAME#"v8i8One"),
6876                          V64, VecListOne128>;
6877   def : SIMDTableLookupAlias<asm # ".8b",
6878                          !cast<Instruction>(NAME#"v8i8Two"),
6879                          V64, VecListTwo128>;
6880   def : SIMDTableLookupAlias<asm # ".8b",
6881                          !cast<Instruction>(NAME#"v8i8Three"),
6882                          V64, VecListThree128>;
6883   def : SIMDTableLookupAlias<asm # ".8b",
6884                          !cast<Instruction>(NAME#"v8i8Four"),
6885                          V64, VecListFour128>;
6886   def : SIMDTableLookupAlias<asm # ".16b",
6887                          !cast<Instruction>(NAME#"v16i8One"),
6888                          V128, VecListOne128>;
6889   def : SIMDTableLookupAlias<asm # ".16b",
6890                          !cast<Instruction>(NAME#"v16i8Two"),
6891                          V128, VecListTwo128>;
6892   def : SIMDTableLookupAlias<asm # ".16b",
6893                          !cast<Instruction>(NAME#"v16i8Three"),
6894                          V128, VecListThree128>;
6895   def : SIMDTableLookupAlias<asm # ".16b",
6896                          !cast<Instruction>(NAME#"v16i8Four"),
6897                          V128, VecListFour128>;
6898 }
6899
6900 multiclass SIMDTableLookupTied<bit op, string asm> {
6901   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6902                                       asm, ".8b">;
6903   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6904                                       asm, ".8b">;
6905   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6906                                       asm, ".8b">;
6907   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6908                                       asm, ".8b">;
6909   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6910                                       asm, ".16b">;
6911   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6912                                       asm, ".16b">;
6913   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6914                                       asm, ".16b">;
6915   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6916                                       asm, ".16b">;
6917
6918   def : SIMDTableLookupAlias<asm # ".8b",
6919                          !cast<Instruction>(NAME#"v8i8One"),
6920                          V64, VecListOne128>;
6921   def : SIMDTableLookupAlias<asm # ".8b",
6922                          !cast<Instruction>(NAME#"v8i8Two"),
6923                          V64, VecListTwo128>;
6924   def : SIMDTableLookupAlias<asm # ".8b",
6925                          !cast<Instruction>(NAME#"v8i8Three"),
6926                          V64, VecListThree128>;
6927   def : SIMDTableLookupAlias<asm # ".8b",
6928                          !cast<Instruction>(NAME#"v8i8Four"),
6929                          V64, VecListFour128>;
6930   def : SIMDTableLookupAlias<asm # ".16b",
6931                          !cast<Instruction>(NAME#"v16i8One"),
6932                          V128, VecListOne128>;
6933   def : SIMDTableLookupAlias<asm # ".16b",
6934                          !cast<Instruction>(NAME#"v16i8Two"),
6935                          V128, VecListTwo128>;
6936   def : SIMDTableLookupAlias<asm # ".16b",
6937                          !cast<Instruction>(NAME#"v16i8Three"),
6938                          V128, VecListThree128>;
6939   def : SIMDTableLookupAlias<asm # ".16b",
6940                          !cast<Instruction>(NAME#"v16i8Four"),
6941                          V128, VecListFour128>;
6942 }
6943
6944
6945 //----------------------------------------------------------------------------
6946 // AdvSIMD scalar CPY
6947 //----------------------------------------------------------------------------
6948 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6949 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6950                         string kind, Operand idxtype>
6951   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6952        "{\t$dst, $src" # kind # "$idx" #
6953        "|\t$dst, $src$idx}", "", []>,
6954     Sched<[WriteV]> {
6955   bits<5> dst;
6956   bits<5> src;
6957   let Inst{31-21} = 0b01011110000;
6958   let Inst{15-10} = 0b000001;
6959   let Inst{9-5}   = src;
6960   let Inst{4-0}   = dst;
6961 }
6962
6963 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6964       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6965     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6966                     # "|\t$dst, $src$index}",
6967                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6968
6969
6970 multiclass SIMDScalarCPY<string asm> {
6971   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6972     bits<4> idx;
6973     let Inst{20-17} = idx;
6974     let Inst{16} = 1;
6975   }
6976   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6977     bits<3> idx;
6978     let Inst{20-18} = idx;
6979     let Inst{17-16} = 0b10;
6980   }
6981   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6982     bits<2> idx;
6983     let Inst{20-19} = idx;
6984     let Inst{18-16} = 0b100;
6985   }
6986   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6987     bits<1> idx;
6988     let Inst{20} = idx;
6989     let Inst{19-16} = 0b1000;
6990   }
6991
6992   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6993                                                           VectorIndexD:$idx)))),
6994             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6995
6996   // 'DUP' mnemonic aliases.
6997   def : SIMDScalarCPYAlias<"dup", ".b",
6998                            !cast<Instruction>(NAME#"i8"),
6999                            FPR8, V128, VectorIndexB>;
7000   def : SIMDScalarCPYAlias<"dup", ".h",
7001                            !cast<Instruction>(NAME#"i16"),
7002                            FPR16, V128, VectorIndexH>;
7003   def : SIMDScalarCPYAlias<"dup", ".s",
7004                            !cast<Instruction>(NAME#"i32"),
7005                            FPR32, V128, VectorIndexS>;
7006   def : SIMDScalarCPYAlias<"dup", ".d",
7007                            !cast<Instruction>(NAME#"i64"),
7008                            FPR64, V128, VectorIndexD>;
7009 }
7010
7011 //----------------------------------------------------------------------------
7012 // AdvSIMD modified immediate instructions
7013 //----------------------------------------------------------------------------
7014
7015 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7016                           string asm, string op_string,
7017                           string cstr, list<dag> pattern>
7018   : I<oops, iops, asm, op_string, cstr, pattern>,
7019     Sched<[WriteV]> {
7020   bits<5> Rd;
7021   bits<8> imm8;
7022   let Inst{31}    = 0;
7023   let Inst{30}    = Q;
7024   let Inst{29}    = op;
7025   let Inst{28-19} = 0b0111100000;
7026   let Inst{18-16} = imm8{7-5};
7027   let Inst{11} = op2;
7028   let Inst{10} = 1;
7029   let Inst{9-5}   = imm8{4-0};
7030   let Inst{4-0}   = Rd;
7031 }
7032
7033 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7034                                 Operand immtype, dag opt_shift_iop,
7035                                 string opt_shift, string asm, string kind,
7036                                 list<dag> pattern>
7037   : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7038                         !con((ins immtype:$imm8), opt_shift_iop), asm,
7039                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
7040                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7041                         "", pattern> {
7042   let DecoderMethod = "DecodeModImmInstruction";
7043 }
7044
7045 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7046                                 Operand immtype, dag opt_shift_iop,
7047                                 string opt_shift, string asm, string kind,
7048                                 list<dag> pattern>
7049   : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7050                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7051                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7052                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7053                         "$Rd = $dst", pattern> {
7054   let DecoderMethod = "DecodeModImmTiedInstruction";
7055 }
7056
7057 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7058                                      RegisterOperand vectype, string asm,
7059                                      string kind, list<dag> pattern>
7060   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7061                               (ins logical_vec_shift:$shift),
7062                               "$shift", asm, kind, pattern> {
7063   bits<2> shift;
7064   let Inst{15}    = b15_b12{1};
7065   let Inst{14-13} = shift;
7066   let Inst{12}    = b15_b12{0};
7067 }
7068
7069 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7070                                      RegisterOperand vectype, string asm,
7071                                      string kind, list<dag> pattern>
7072   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7073                               (ins logical_vec_shift:$shift),
7074                               "$shift", asm, kind, pattern> {
7075   bits<2> shift;
7076   let Inst{15}    = b15_b12{1};
7077   let Inst{14-13} = shift;
7078   let Inst{12}    = b15_b12{0};
7079 }
7080
7081
7082 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7083                                          RegisterOperand vectype, string asm,
7084                                          string kind, list<dag> pattern>
7085   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7086                               (ins logical_vec_hw_shift:$shift),
7087                               "$shift", asm, kind, pattern> {
7088   bits<2> shift;
7089   let Inst{15} = b15_b12{1};
7090   let Inst{14} = 0;
7091   let Inst{13} = shift{0};
7092   let Inst{12} = b15_b12{0};
7093 }
7094
7095 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7096                                          RegisterOperand vectype, string asm,
7097                                          string kind, list<dag> pattern>
7098   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7099                               (ins logical_vec_hw_shift:$shift),
7100                               "$shift", asm, kind, pattern> {
7101   bits<2> shift;
7102   let Inst{15} = b15_b12{1};
7103   let Inst{14} = 0;
7104   let Inst{13} = shift{0};
7105   let Inst{12} = b15_b12{0};
7106 }
7107
7108 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7109                                       string asm> {
7110   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7111                                                  asm, ".4h", []>;
7112   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7113                                                  asm, ".8h", []>;
7114
7115   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7116                                              asm, ".2s", []>;
7117   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7118                                              asm, ".4s", []>;
7119 }
7120
7121 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7122                                       bits<2> w_cmode, string asm,
7123                                       SDNode OpNode> {
7124   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7125                                                  asm, ".4h",
7126              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7127                                              imm0_255:$imm8,
7128                                              (i32 imm:$shift)))]>;
7129   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7130                                                  asm, ".8h",
7131              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7132                                               imm0_255:$imm8,
7133                                               (i32 imm:$shift)))]>;
7134
7135   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7136                                              asm, ".2s",
7137              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7138                                              imm0_255:$imm8,
7139                                              (i32 imm:$shift)))]>;
7140   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7141                                              asm, ".4s",
7142              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7143                                               imm0_255:$imm8,
7144                                               (i32 imm:$shift)))]>;
7145 }
7146
7147 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7148                              RegisterOperand vectype, string asm,
7149                              string kind, list<dag> pattern>
7150   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7151                               (ins move_vec_shift:$shift),
7152                               "$shift", asm, kind, pattern> {
7153   bits<1> shift;
7154   let Inst{15-13} = cmode{3-1};
7155   let Inst{12}    = shift;
7156 }
7157
7158 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7159                                    RegisterOperand vectype,
7160                                    Operand imm_type, string asm,
7161                                    string kind, list<dag> pattern>
7162   : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7163                               asm, kind, pattern> {
7164   let Inst{15-12} = cmode;
7165 }
7166
7167 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7168                                    list<dag> pattern>
7169   : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7170                         "\t$Rd, $imm8", "", pattern> {
7171   let Inst{15-12} = cmode;
7172   let DecoderMethod = "DecodeModImmInstruction";
7173 }
7174
7175 //----------------------------------------------------------------------------
7176 // AdvSIMD indexed element
7177 //----------------------------------------------------------------------------
7178
7179 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7180 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7181                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7182                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7183                       string apple_kind, string dst_kind, string lhs_kind,
7184                       string rhs_kind, list<dag> pattern>
7185   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7186       asm,
7187       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7188       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7189     Sched<[WriteV]> {
7190   bits<5> Rd;
7191   bits<5> Rn;
7192   bits<5> Rm;
7193
7194   let Inst{31}    = 0;
7195   let Inst{30}    = Q;
7196   let Inst{29}    = U;
7197   let Inst{28}    = Scalar;
7198   let Inst{27-24} = 0b1111;
7199   let Inst{23-22} = size;
7200   // Bit 21 must be set by the derived class.
7201   let Inst{20-16} = Rm;
7202   let Inst{15-12} = opc;
7203   // Bit 11 must be set by the derived class.
7204   let Inst{10}    = 0;
7205   let Inst{9-5}   = Rn;
7206   let Inst{4-0}   = Rd;
7207 }
7208
7209 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7210 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7211                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7212                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7213                       string apple_kind, string dst_kind, string lhs_kind,
7214                       string rhs_kind, list<dag> pattern>
7215   : I<(outs dst_reg:$dst),
7216       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7217       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7218       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7219     Sched<[WriteV]> {
7220   bits<5> Rd;
7221   bits<5> Rn;
7222   bits<5> Rm;
7223
7224   let Inst{31}    = 0;
7225   let Inst{30}    = Q;
7226   let Inst{29}    = U;
7227   let Inst{28}    = Scalar;
7228   let Inst{27-24} = 0b1111;
7229   let Inst{23-22} = size;
7230   // Bit 21 must be set by the derived class.
7231   let Inst{20-16} = Rm;
7232   let Inst{15-12} = opc;
7233   // Bit 11 must be set by the derived class.
7234   let Inst{10}    = 0;
7235   let Inst{9-5}   = Rn;
7236   let Inst{4-0}   = Rd;
7237 }
7238
7239 // ARMv8.2 Index Dot product instructions
7240 class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, string asm, string dst_kind,
7241                                       string lhs_kind, string rhs_kind,
7242                                       RegisterOperand RegType,
7243                                       ValueType AccumType, ValueType InputType,
7244                                       SDPatternOperator OpNode> :
7245         BaseSIMDIndexedTied<Q, U, 0b0, 0b10, 0b1110, RegType, RegType, V128,
7246                             VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7247         [(set (AccumType RegType:$dst),
7248               (AccumType (OpNode (AccumType RegType:$Rd),
7249                                  (InputType RegType:$Rn),
7250                                  (InputType (bitconvert (AccumType
7251                                     (AArch64duplane32 (v4i32 V128:$Rm),
7252                                         VectorIndexS:$idx)))))))]> {
7253   bits<2> idx;
7254   let Inst{21}    = idx{0};  // L
7255   let Inst{11}    = idx{1};  // H
7256 }
7257
7258 multiclass SIMDThreeSameVectorDotIndex<bit U, string asm,
7259                                        SDPatternOperator OpNode> {
7260   def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, asm, ".2s", ".8b", ".4b", V64,
7261                                               v2i32, v8i8, OpNode>;
7262   def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, asm, ".4s", ".16b", ".4b", V128,
7263                                               v4i32, v16i8, OpNode>;
7264 }
7265
7266 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
7267                          SDPatternOperator OpNode> {
7268   let Predicates = [HasNEON, HasFullFP16] in {
7269   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
7270                                       V64, V64,
7271                                       V128_lo, VectorIndexH,
7272                                       asm, ".4h", ".4h", ".4h", ".h",
7273     [(set (v4f16 V64:$Rd),
7274         (OpNode (v4f16 V64:$Rn),
7275          (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7276     bits<3> idx;
7277     let Inst{11} = idx{2};
7278     let Inst{21} = idx{1};
7279     let Inst{20} = idx{0};
7280   }
7281
7282   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
7283                                       V128, V128,
7284                                       V128_lo, VectorIndexH,
7285                                       asm, ".8h", ".8h", ".8h", ".h",
7286     [(set (v8f16 V128:$Rd),
7287         (OpNode (v8f16 V128:$Rn),
7288          (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7289     bits<3> idx;
7290     let Inst{11} = idx{2};
7291     let Inst{21} = idx{1};
7292     let Inst{20} = idx{0};
7293   }
7294   } // Predicates = [HasNEON, HasFullFP16]
7295
7296   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7297                                       V64, V64,
7298                                       V128, VectorIndexS,
7299                                       asm, ".2s", ".2s", ".2s", ".s",
7300     [(set (v2f32 V64:$Rd),
7301         (OpNode (v2f32 V64:$Rn),
7302          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7303     bits<2> idx;
7304     let Inst{11} = idx{1};
7305     let Inst{21} = idx{0};
7306   }
7307
7308   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7309                                       V128, V128,
7310                                       V128, VectorIndexS,
7311                                       asm, ".4s", ".4s", ".4s", ".s",
7312     [(set (v4f32 V128:$Rd),
7313         (OpNode (v4f32 V128:$Rn),
7314          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7315     bits<2> idx;
7316     let Inst{11} = idx{1};
7317     let Inst{21} = idx{0};
7318   }
7319
7320   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
7321                                       V128, V128,
7322                                       V128, VectorIndexD,
7323                                       asm, ".2d", ".2d", ".2d", ".d",
7324     [(set (v2f64 V128:$Rd),
7325         (OpNode (v2f64 V128:$Rn),
7326          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
7327     bits<1> idx;
7328     let Inst{11} = idx{0};
7329     let Inst{21} = 0;
7330   }
7331
7332   let Predicates = [HasNEON, HasFullFP16] in {
7333   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
7334                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7335                                       asm, ".h", "", "", ".h",
7336     [(set (f16 FPR16Op:$Rd),
7337           (OpNode (f16 FPR16Op:$Rn),
7338                   (f16 (vector_extract (v8f16 V128_lo:$Rm),
7339                                        VectorIndexH:$idx))))]> {
7340     bits<3> idx;
7341     let Inst{11} = idx{2};
7342     let Inst{21} = idx{1};
7343     let Inst{20} = idx{0};
7344   }
7345   } // Predicates = [HasNEON, HasFullFP16]
7346
7347   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7348                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7349                                       asm, ".s", "", "", ".s",
7350     [(set (f32 FPR32Op:$Rd),
7351           (OpNode (f32 FPR32Op:$Rn),
7352                   (f32 (vector_extract (v4f32 V128:$Rm),
7353                                        VectorIndexS:$idx))))]> {
7354     bits<2> idx;
7355     let Inst{11} = idx{1};
7356     let Inst{21} = idx{0};
7357   }
7358
7359   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
7360                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7361                                       asm, ".d", "", "", ".d",
7362     [(set (f64 FPR64Op:$Rd),
7363           (OpNode (f64 FPR64Op:$Rn),
7364                   (f64 (vector_extract (v2f64 V128:$Rm),
7365                                        VectorIndexD:$idx))))]> {
7366     bits<1> idx;
7367     let Inst{11} = idx{0};
7368     let Inst{21} = 0;
7369   }
7370 }
7371
7372 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
7373   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
7374   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7375                            (AArch64duplane32 (v4f32 V128:$Rm),
7376                                            VectorIndexS:$idx))),
7377             (!cast<Instruction>(INST # v2i32_indexed)
7378                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7379   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7380                            (AArch64dup (f32 FPR32Op:$Rm)))),
7381             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
7382                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7383
7384
7385   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
7386   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7387                            (AArch64duplane32 (v4f32 V128:$Rm),
7388                                            VectorIndexS:$idx))),
7389             (!cast<Instruction>(INST # "v4i32_indexed")
7390                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7391   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7392                            (AArch64dup (f32 FPR32Op:$Rm)))),
7393             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
7394                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7395
7396   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
7397   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7398                            (AArch64duplane64 (v2f64 V128:$Rm),
7399                                            VectorIndexD:$idx))),
7400             (!cast<Instruction>(INST # "v2i64_indexed")
7401                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7402   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7403                            (AArch64dup (f64 FPR64Op:$Rm)))),
7404             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
7405                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
7406
7407   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
7408   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7409                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
7410             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7411                 V128:$Rm, VectorIndexS:$idx)>;
7412   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7413                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
7414             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7415                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
7416
7417   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
7418   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
7419                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
7420             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
7421                 V128:$Rm, VectorIndexD:$idx)>;
7422 }
7423
7424 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
7425   let Predicates = [HasNEON, HasFullFP16] in {
7426   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
7427                                           V128_lo, VectorIndexH,
7428                                           asm, ".4h", ".4h", ".4h", ".h", []> {
7429     bits<3> idx;
7430     let Inst{11} = idx{2};
7431     let Inst{21} = idx{1};
7432     let Inst{20} = idx{0};
7433   }
7434
7435   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
7436                                           V128, V128,
7437                                           V128_lo, VectorIndexH,
7438                                           asm, ".8h", ".8h", ".8h", ".h", []> {
7439     bits<3> idx;
7440     let Inst{11} = idx{2};
7441     let Inst{21} = idx{1};
7442     let Inst{20} = idx{0};
7443   }
7444   } // Predicates = [HasNEON, HasFullFP16]
7445
7446   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
7447                                           V128, VectorIndexS,
7448                                           asm, ".2s", ".2s", ".2s", ".s", []> {
7449     bits<2> idx;
7450     let Inst{11} = idx{1};
7451     let Inst{21} = idx{0};
7452   }
7453
7454   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7455                                       V128, V128,
7456                                       V128, VectorIndexS,
7457                                       asm, ".4s", ".4s", ".4s", ".s", []> {
7458     bits<2> idx;
7459     let Inst{11} = idx{1};
7460     let Inst{21} = idx{0};
7461   }
7462
7463   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
7464                                       V128, V128,
7465                                       V128, VectorIndexD,
7466                                       asm, ".2d", ".2d", ".2d", ".d", []> {
7467     bits<1> idx;
7468     let Inst{11} = idx{0};
7469     let Inst{21} = 0;
7470   }
7471
7472   let Predicates = [HasNEON, HasFullFP16] in {
7473   def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
7474                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7475                                       asm, ".h", "", "", ".h", []> {
7476     bits<3> idx;
7477     let Inst{11} = idx{2};
7478     let Inst{21} = idx{1};
7479     let Inst{20} = idx{0};
7480   }
7481   } // Predicates = [HasNEON, HasFullFP16]
7482
7483   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7484                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7485                                       asm, ".s", "", "", ".s", []> {
7486     bits<2> idx;
7487     let Inst{11} = idx{1};
7488     let Inst{21} = idx{0};
7489   }
7490
7491   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7492                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7493                                       asm, ".d", "", "", ".d", []> {
7494     bits<1> idx;
7495     let Inst{11} = idx{0};
7496     let Inst{21} = 0;
7497   }
7498 }
7499
7500 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7501                          SDPatternOperator OpNode> {
7502   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7503                                       V128_lo, VectorIndexH,
7504                                       asm, ".4h", ".4h", ".4h", ".h",
7505     [(set (v4i16 V64:$Rd),
7506         (OpNode (v4i16 V64:$Rn),
7507          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7508     bits<3> idx;
7509     let Inst{11} = idx{2};
7510     let Inst{21} = idx{1};
7511     let Inst{20} = idx{0};
7512   }
7513
7514   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7515                                       V128, V128,
7516                                       V128_lo, VectorIndexH,
7517                                       asm, ".8h", ".8h", ".8h", ".h",
7518     [(set (v8i16 V128:$Rd),
7519        (OpNode (v8i16 V128:$Rn),
7520          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7521     bits<3> idx;
7522     let Inst{11} = idx{2};
7523     let Inst{21} = idx{1};
7524     let Inst{20} = idx{0};
7525   }
7526
7527   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7528                                       V64, V64,
7529                                       V128, VectorIndexS,
7530                                       asm, ".2s", ".2s", ".2s",  ".s",
7531     [(set (v2i32 V64:$Rd),
7532        (OpNode (v2i32 V64:$Rn),
7533           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7534     bits<2> idx;
7535     let Inst{11} = idx{1};
7536     let Inst{21} = idx{0};
7537   }
7538
7539   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7540                                       V128, V128,
7541                                       V128, VectorIndexS,
7542                                       asm, ".4s", ".4s", ".4s", ".s",
7543     [(set (v4i32 V128:$Rd),
7544        (OpNode (v4i32 V128:$Rn),
7545           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7546     bits<2> idx;
7547     let Inst{11} = idx{1};
7548     let Inst{21} = idx{0};
7549   }
7550
7551   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7552                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7553                                       asm, ".h", "", "", ".h", []> {
7554     bits<3> idx;
7555     let Inst{11} = idx{2};
7556     let Inst{21} = idx{1};
7557     let Inst{20} = idx{0};
7558   }
7559
7560   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7561                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7562                                       asm, ".s", "", "", ".s",
7563       [(set (i32 FPR32Op:$Rd),
7564             (OpNode FPR32Op:$Rn,
7565                     (i32 (vector_extract (v4i32 V128:$Rm),
7566                                          VectorIndexS:$idx))))]> {
7567     bits<2> idx;
7568     let Inst{11} = idx{1};
7569     let Inst{21} = idx{0};
7570   }
7571 }
7572
7573 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7574                                SDPatternOperator OpNode> {
7575   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7576                                       V64, V64,
7577                                       V128_lo, VectorIndexH,
7578                                       asm, ".4h", ".4h", ".4h", ".h",
7579     [(set (v4i16 V64:$Rd),
7580         (OpNode (v4i16 V64:$Rn),
7581          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7582     bits<3> idx;
7583     let Inst{11} = idx{2};
7584     let Inst{21} = idx{1};
7585     let Inst{20} = idx{0};
7586   }
7587
7588   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7589                                       V128, V128,
7590                                       V128_lo, VectorIndexH,
7591                                       asm, ".8h", ".8h", ".8h", ".h",
7592     [(set (v8i16 V128:$Rd),
7593        (OpNode (v8i16 V128:$Rn),
7594          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7595     bits<3> idx;
7596     let Inst{11} = idx{2};
7597     let Inst{21} = idx{1};
7598     let Inst{20} = idx{0};
7599   }
7600
7601   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7602                                       V64, V64,
7603                                       V128, VectorIndexS,
7604                                       asm, ".2s", ".2s", ".2s", ".s",
7605     [(set (v2i32 V64:$Rd),
7606        (OpNode (v2i32 V64:$Rn),
7607           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7608     bits<2> idx;
7609     let Inst{11} = idx{1};
7610     let Inst{21} = idx{0};
7611   }
7612
7613   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7614                                       V128, V128,
7615                                       V128, VectorIndexS,
7616                                       asm, ".4s", ".4s", ".4s", ".s",
7617     [(set (v4i32 V128:$Rd),
7618        (OpNode (v4i32 V128:$Rn),
7619           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7620     bits<2> idx;
7621     let Inst{11} = idx{1};
7622     let Inst{21} = idx{0};
7623   }
7624 }
7625
7626 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7627                                    SDPatternOperator OpNode> {
7628   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7629                                           V128_lo, VectorIndexH,
7630                                           asm, ".4h", ".4h", ".4h", ".h",
7631     [(set (v4i16 V64:$dst),
7632         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7633          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7634     bits<3> idx;
7635     let Inst{11} = idx{2};
7636     let Inst{21} = idx{1};
7637     let Inst{20} = idx{0};
7638   }
7639
7640   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7641                                       V128, V128,
7642                                       V128_lo, VectorIndexH,
7643                                       asm, ".8h", ".8h", ".8h", ".h",
7644     [(set (v8i16 V128:$dst),
7645        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7646          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7647     bits<3> idx;
7648     let Inst{11} = idx{2};
7649     let Inst{21} = idx{1};
7650     let Inst{20} = idx{0};
7651   }
7652
7653   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7654                                       V64, V64,
7655                                       V128, VectorIndexS,
7656                                       asm, ".2s", ".2s", ".2s", ".s",
7657     [(set (v2i32 V64:$dst),
7658        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7659           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7660     bits<2> idx;
7661     let Inst{11} = idx{1};
7662     let Inst{21} = idx{0};
7663   }
7664
7665   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7666                                       V128, V128,
7667                                       V128, VectorIndexS,
7668                                       asm, ".4s", ".4s", ".4s", ".s",
7669     [(set (v4i32 V128:$dst),
7670        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7671           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7672     bits<2> idx;
7673     let Inst{11} = idx{1};
7674     let Inst{21} = idx{0};
7675   }
7676 }
7677
7678 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
7679                              SDPatternOperator OpNode> {
7680   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7681                                       V128, V64,
7682                                       V128_lo, VectorIndexH,
7683                                       asm, ".4s", ".4s", ".4h", ".h",
7684     [(set (v4i32 V128:$Rd),
7685         (OpNode (v4i16 V64:$Rn),
7686          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7687     bits<3> idx;
7688     let Inst{11} = idx{2};
7689     let Inst{21} = idx{1};
7690     let Inst{20} = idx{0};
7691   }
7692
7693   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7694                                       V128, V128,
7695                                       V128_lo, VectorIndexH,
7696                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7697     [(set (v4i32 V128:$Rd),
7698           (OpNode (extract_high_v8i16 V128:$Rn),
7699                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7700                                                       VectorIndexH:$idx))))]> {
7701
7702     bits<3> idx;
7703     let Inst{11} = idx{2};
7704     let Inst{21} = idx{1};
7705     let Inst{20} = idx{0};
7706   }
7707
7708   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7709                                       V128, V64,
7710                                       V128, VectorIndexS,
7711                                       asm, ".2d", ".2d", ".2s", ".s",
7712     [(set (v2i64 V128:$Rd),
7713         (OpNode (v2i32 V64:$Rn),
7714          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7715     bits<2> idx;
7716     let Inst{11} = idx{1};
7717     let Inst{21} = idx{0};
7718   }
7719
7720   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7721                                       V128, V128,
7722                                       V128, VectorIndexS,
7723                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7724     [(set (v2i64 V128:$Rd),
7725           (OpNode (extract_high_v4i32 V128:$Rn),
7726                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7727                                                       VectorIndexS:$idx))))]> {
7728     bits<2> idx;
7729     let Inst{11} = idx{1};
7730     let Inst{21} = idx{0};
7731   }
7732
7733   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7734                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7735                                       asm, ".h", "", "", ".h", []> {
7736     bits<3> idx;
7737     let Inst{11} = idx{2};
7738     let Inst{21} = idx{1};
7739     let Inst{20} = idx{0};
7740   }
7741
7742   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7743                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7744                                       asm, ".s", "", "", ".s", []> {
7745     bits<2> idx;
7746     let Inst{11} = idx{1};
7747     let Inst{21} = idx{0};
7748   }
7749 }
7750
7751 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
7752                                        SDPatternOperator Accum> {
7753   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7754                                       V128, V64,
7755                                       V128_lo, VectorIndexH,
7756                                       asm, ".4s", ".4s", ".4h", ".h",
7757     [(set (v4i32 V128:$dst),
7758           (Accum (v4i32 V128:$Rd),
7759                  (v4i32 (int_aarch64_neon_sqdmull
7760                              (v4i16 V64:$Rn),
7761                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7762                                                     VectorIndexH:$idx))))))]> {
7763     bits<3> idx;
7764     let Inst{11} = idx{2};
7765     let Inst{21} = idx{1};
7766     let Inst{20} = idx{0};
7767   }
7768
7769   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
7770   // intermediate EXTRACT_SUBREG would be untyped.
7771   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
7772                 (i32 (vector_extract (v4i32
7773                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7774                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7775                                                     VectorIndexH:$idx)))),
7776                          (i64 0))))),
7777             (EXTRACT_SUBREG
7778                 (!cast<Instruction>(NAME # v4i16_indexed)
7779                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
7780                     V128_lo:$Rm, VectorIndexH:$idx),
7781                 ssub)>;
7782
7783   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7784                                       V128, V128,
7785                                       V128_lo, VectorIndexH,
7786                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7787     [(set (v4i32 V128:$dst),
7788           (Accum (v4i32 V128:$Rd),
7789                  (v4i32 (int_aarch64_neon_sqdmull
7790                             (extract_high_v8i16 V128:$Rn),
7791                             (extract_high_v8i16
7792                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7793                                                 VectorIndexH:$idx))))))]> {
7794     bits<3> idx;
7795     let Inst{11} = idx{2};
7796     let Inst{21} = idx{1};
7797     let Inst{20} = idx{0};
7798   }
7799
7800   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7801                                       V128, V64,
7802                                       V128, VectorIndexS,
7803                                       asm, ".2d", ".2d", ".2s", ".s",
7804     [(set (v2i64 V128:$dst),
7805         (Accum (v2i64 V128:$Rd),
7806                (v2i64 (int_aarch64_neon_sqdmull
7807                           (v2i32 V64:$Rn),
7808                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
7809                                                  VectorIndexS:$idx))))))]> {
7810     bits<2> idx;
7811     let Inst{11} = idx{1};
7812     let Inst{21} = idx{0};
7813   }
7814
7815   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7816                                       V128, V128,
7817                                       V128, VectorIndexS,
7818                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7819     [(set (v2i64 V128:$dst),
7820           (Accum (v2i64 V128:$Rd),
7821                  (v2i64 (int_aarch64_neon_sqdmull
7822                             (extract_high_v4i32 V128:$Rn),
7823                             (extract_high_v4i32
7824                                 (AArch64duplane32 (v4i32 V128:$Rm),
7825                                                 VectorIndexS:$idx))))))]> {
7826     bits<2> idx;
7827     let Inst{11} = idx{1};
7828     let Inst{21} = idx{0};
7829   }
7830
7831   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
7832                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7833                                       asm, ".h", "", "", ".h", []> {
7834     bits<3> idx;
7835     let Inst{11} = idx{2};
7836     let Inst{21} = idx{1};
7837     let Inst{20} = idx{0};
7838   }
7839
7840
7841   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7842                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7843                                       asm, ".s", "", "", ".s",
7844     [(set (i64 FPR64Op:$dst),
7845           (Accum (i64 FPR64Op:$Rd),
7846                  (i64 (int_aarch64_neon_sqdmulls_scalar
7847                             (i32 FPR32Op:$Rn),
7848                             (i32 (vector_extract (v4i32 V128:$Rm),
7849                                                  VectorIndexS:$idx))))))]> {
7850
7851     bits<2> idx;
7852     let Inst{11} = idx{1};
7853     let Inst{21} = idx{0};
7854   }
7855 }
7856
7857 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
7858                                    SDPatternOperator OpNode> {
7859   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7860   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7861                                       V128, V64,
7862                                       V128_lo, VectorIndexH,
7863                                       asm, ".4s", ".4s", ".4h", ".h",
7864     [(set (v4i32 V128:$Rd),
7865         (OpNode (v4i16 V64:$Rn),
7866          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7867     bits<3> idx;
7868     let Inst{11} = idx{2};
7869     let Inst{21} = idx{1};
7870     let Inst{20} = idx{0};
7871   }
7872
7873   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7874                                       V128, V128,
7875                                       V128_lo, VectorIndexH,
7876                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7877     [(set (v4i32 V128:$Rd),
7878           (OpNode (extract_high_v8i16 V128:$Rn),
7879                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7880                                                       VectorIndexH:$idx))))]> {
7881
7882     bits<3> idx;
7883     let Inst{11} = idx{2};
7884     let Inst{21} = idx{1};
7885     let Inst{20} = idx{0};
7886   }
7887
7888   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7889                                       V128, V64,
7890                                       V128, VectorIndexS,
7891                                       asm, ".2d", ".2d", ".2s", ".s",
7892     [(set (v2i64 V128:$Rd),
7893         (OpNode (v2i32 V64:$Rn),
7894          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7895     bits<2> idx;
7896     let Inst{11} = idx{1};
7897     let Inst{21} = idx{0};
7898   }
7899
7900   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7901                                       V128, V128,
7902                                       V128, VectorIndexS,
7903                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7904     [(set (v2i64 V128:$Rd),
7905           (OpNode (extract_high_v4i32 V128:$Rn),
7906                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7907                                                       VectorIndexS:$idx))))]> {
7908     bits<2> idx;
7909     let Inst{11} = idx{1};
7910     let Inst{21} = idx{0};
7911   }
7912   }
7913 }
7914
7915 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7916                                        SDPatternOperator OpNode> {
7917   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7918   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7919                                       V128, V64,
7920                                       V128_lo, VectorIndexH,
7921                                       asm, ".4s", ".4s", ".4h", ".h",
7922     [(set (v4i32 V128:$dst),
7923         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7924          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7925     bits<3> idx;
7926     let Inst{11} = idx{2};
7927     let Inst{21} = idx{1};
7928     let Inst{20} = idx{0};
7929   }
7930
7931   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7932                                       V128, V128,
7933                                       V128_lo, VectorIndexH,
7934                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7935     [(set (v4i32 V128:$dst),
7936           (OpNode (v4i32 V128:$Rd),
7937                   (extract_high_v8i16 V128:$Rn),
7938                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7939                                                       VectorIndexH:$idx))))]> {
7940     bits<3> idx;
7941     let Inst{11} = idx{2};
7942     let Inst{21} = idx{1};
7943     let Inst{20} = idx{0};
7944   }
7945
7946   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7947                                       V128, V64,
7948                                       V128, VectorIndexS,
7949                                       asm, ".2d", ".2d", ".2s", ".s",
7950     [(set (v2i64 V128:$dst),
7951         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7952          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7953     bits<2> idx;
7954     let Inst{11} = idx{1};
7955     let Inst{21} = idx{0};
7956   }
7957
7958   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7959                                       V128, V128,
7960                                       V128, VectorIndexS,
7961                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7962     [(set (v2i64 V128:$dst),
7963           (OpNode (v2i64 V128:$Rd),
7964                   (extract_high_v4i32 V128:$Rn),
7965                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7966                                                       VectorIndexS:$idx))))]> {
7967     bits<2> idx;
7968     let Inst{11} = idx{1};
7969     let Inst{21} = idx{0};
7970   }
7971   }
7972 }
7973
7974 //----------------------------------------------------------------------------
7975 // AdvSIMD scalar shift by immediate
7976 //----------------------------------------------------------------------------
7977
7978 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7979 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7980                      RegisterClass regtype1, RegisterClass regtype2,
7981                      Operand immtype, string asm, list<dag> pattern>
7982   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7983       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7984     Sched<[WriteV]> {
7985   bits<5> Rd;
7986   bits<5> Rn;
7987   bits<7> imm;
7988   let Inst{31-30} = 0b01;
7989   let Inst{29}    = U;
7990   let Inst{28-23} = 0b111110;
7991   let Inst{22-16} = fixed_imm;
7992   let Inst{15-11} = opc;
7993   let Inst{10}    = 1;
7994   let Inst{9-5} = Rn;
7995   let Inst{4-0} = Rd;
7996 }
7997
7998 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7999 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8000                      RegisterClass regtype1, RegisterClass regtype2,
8001                      Operand immtype, string asm, list<dag> pattern>
8002   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8003       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8004     Sched<[WriteV]> {
8005   bits<5> Rd;
8006   bits<5> Rn;
8007   bits<7> imm;
8008   let Inst{31-30} = 0b01;
8009   let Inst{29}    = U;
8010   let Inst{28-23} = 0b111110;
8011   let Inst{22-16} = fixed_imm;
8012   let Inst{15-11} = opc;
8013   let Inst{10}    = 1;
8014   let Inst{9-5} = Rn;
8015   let Inst{4-0} = Rd;
8016 }
8017
8018
8019 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8020   let Predicates = [HasNEON, HasFullFP16] in {
8021   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8022                               FPR16, FPR16, vecshiftR16, asm, []> {
8023     let Inst{19-16} = imm{3-0};
8024   }
8025   } // Predicates = [HasNEON, HasFullFP16]
8026   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8027                               FPR32, FPR32, vecshiftR32, asm, []> {
8028     let Inst{20-16} = imm{4-0};
8029   }
8030   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8031                               FPR64, FPR64, vecshiftR64, asm, []> {
8032     let Inst{21-16} = imm{5-0};
8033   }
8034 }
8035
8036 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8037                              SDPatternOperator OpNode> {
8038   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8039                               FPR64, FPR64, vecshiftR64, asm,
8040   [(set (i64 FPR64:$Rd),
8041      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8042     let Inst{21-16} = imm{5-0};
8043   }
8044
8045   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8046             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8047 }
8048
8049 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8050                                  SDPatternOperator OpNode = null_frag> {
8051   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8052                               FPR64, FPR64, vecshiftR64, asm,
8053   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8054                                                    (i32 vecshiftR64:$imm)))]> {
8055     let Inst{21-16} = imm{5-0};
8056   }
8057
8058   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8059                            (i32 vecshiftR64:$imm))),
8060             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8061                                             vecshiftR64:$imm)>;
8062 }
8063
8064 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8065                              SDPatternOperator OpNode> {
8066   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8067                               FPR64, FPR64, vecshiftL64, asm,
8068     [(set (v1i64 FPR64:$Rd),
8069        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8070     let Inst{21-16} = imm{5-0};
8071   }
8072 }
8073
8074 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8075 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8076   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8077                               FPR64, FPR64, vecshiftL64, asm, []> {
8078     let Inst{21-16} = imm{5-0};
8079   }
8080 }
8081
8082 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8083 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8084                                SDPatternOperator OpNode = null_frag> {
8085   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8086                               FPR8, FPR16, vecshiftR8, asm, []> {
8087     let Inst{18-16} = imm{2-0};
8088   }
8089
8090   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8091                               FPR16, FPR32, vecshiftR16, asm, []> {
8092     let Inst{19-16} = imm{3-0};
8093   }
8094
8095   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8096                               FPR32, FPR64, vecshiftR32, asm,
8097     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8098     let Inst{20-16} = imm{4-0};
8099   }
8100 }
8101
8102 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8103                                 SDPatternOperator OpNode> {
8104   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8105                               FPR8, FPR8, vecshiftL8, asm, []> {
8106     let Inst{18-16} = imm{2-0};
8107   }
8108
8109   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8110                               FPR16, FPR16, vecshiftL16, asm, []> {
8111     let Inst{19-16} = imm{3-0};
8112   }
8113
8114   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8115                               FPR32, FPR32, vecshiftL32, asm,
8116     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8117     let Inst{20-16} = imm{4-0};
8118   }
8119
8120   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8121                               FPR64, FPR64, vecshiftL64, asm,
8122     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8123     let Inst{21-16} = imm{5-0};
8124   }
8125
8126   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8127             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8128 }
8129
8130 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8131   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8132                               FPR8, FPR8, vecshiftR8, asm, []> {
8133     let Inst{18-16} = imm{2-0};
8134   }
8135
8136   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8137                               FPR16, FPR16, vecshiftR16, asm, []> {
8138     let Inst{19-16} = imm{3-0};
8139   }
8140
8141   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8142                               FPR32, FPR32, vecshiftR32, asm, []> {
8143     let Inst{20-16} = imm{4-0};
8144   }
8145
8146   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8147                               FPR64, FPR64, vecshiftR64, asm, []> {
8148     let Inst{21-16} = imm{5-0};
8149   }
8150 }
8151
8152 //----------------------------------------------------------------------------
8153 // AdvSIMD vector x indexed element
8154 //----------------------------------------------------------------------------
8155
8156 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8157 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8158                      RegisterOperand dst_reg, RegisterOperand src_reg,
8159                      Operand immtype,
8160                      string asm, string dst_kind, string src_kind,
8161                      list<dag> pattern>
8162   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
8163       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8164            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
8165     Sched<[WriteV]> {
8166   bits<5> Rd;
8167   bits<5> Rn;
8168   let Inst{31}    = 0;
8169   let Inst{30}    = Q;
8170   let Inst{29}    = U;
8171   let Inst{28-23} = 0b011110;
8172   let Inst{22-16} = fixed_imm;
8173   let Inst{15-11} = opc;
8174   let Inst{10}    = 1;
8175   let Inst{9-5}   = Rn;
8176   let Inst{4-0}   = Rd;
8177 }
8178
8179 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8180 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8181                      RegisterOperand vectype1, RegisterOperand vectype2,
8182                      Operand immtype,
8183                      string asm, string dst_kind, string src_kind,
8184                      list<dag> pattern>
8185   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
8186       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8187            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
8188     Sched<[WriteV]> {
8189   bits<5> Rd;
8190   bits<5> Rn;
8191   let Inst{31}    = 0;
8192   let Inst{30}    = Q;
8193   let Inst{29}    = U;
8194   let Inst{28-23} = 0b011110;
8195   let Inst{22-16} = fixed_imm;
8196   let Inst{15-11} = opc;
8197   let Inst{10}    = 1;
8198   let Inst{9-5}   = Rn;
8199   let Inst{4-0}   = Rd;
8200 }
8201
8202 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
8203                               Intrinsic OpNode> {
8204   let Predicates = [HasNEON, HasFullFP16] in {
8205   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8206                                   V64, V64, vecshiftR16,
8207                                   asm, ".4h", ".4h",
8208       [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
8209     bits<4> imm;
8210     let Inst{19-16} = imm;
8211   }
8212
8213   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8214                                   V128, V128, vecshiftR16,
8215                                   asm, ".8h", ".8h",
8216       [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
8217     bits<4> imm;
8218     let Inst{19-16} = imm;
8219   }
8220   } // Predicates = [HasNEON, HasFullFP16]
8221   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8222                                   V64, V64, vecshiftR32,
8223                                   asm, ".2s", ".2s",
8224       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
8225     bits<5> imm;
8226     let Inst{20-16} = imm;
8227   }
8228
8229   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8230                                   V128, V128, vecshiftR32,
8231                                   asm, ".4s", ".4s",
8232       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
8233     bits<5> imm;
8234     let Inst{20-16} = imm;
8235   }
8236
8237   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8238                                   V128, V128, vecshiftR64,
8239                                   asm, ".2d", ".2d",
8240       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
8241     bits<6> imm;
8242     let Inst{21-16} = imm;
8243   }
8244 }
8245
8246 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
8247                                   Intrinsic OpNode> {
8248   let Predicates = [HasNEON, HasFullFP16] in {
8249   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8250                                   V64, V64, vecshiftR16,
8251                                   asm, ".4h", ".4h",
8252       [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
8253     bits<4> imm;
8254     let Inst{19-16} = imm;
8255   }
8256
8257   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8258                                   V128, V128, vecshiftR16,
8259                                   asm, ".8h", ".8h",
8260       [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
8261     bits<4> imm;
8262     let Inst{19-16} = imm;
8263   }
8264   } // Predicates = [HasNEON, HasFullFP16]
8265
8266   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8267                                   V64, V64, vecshiftR32,
8268                                   asm, ".2s", ".2s",
8269       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
8270     bits<5> imm;
8271     let Inst{20-16} = imm;
8272   }
8273
8274   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8275                                   V128, V128, vecshiftR32,
8276                                   asm, ".4s", ".4s",
8277       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
8278     bits<5> imm;
8279     let Inst{20-16} = imm;
8280   }
8281
8282   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8283                                   V128, V128, vecshiftR64,
8284                                   asm, ".2d", ".2d",
8285       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
8286     bits<6> imm;
8287     let Inst{21-16} = imm;
8288   }
8289 }
8290
8291 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
8292                                      SDPatternOperator OpNode> {
8293   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8294                                   V64, V128, vecshiftR16Narrow,
8295                                   asm, ".8b", ".8h",
8296       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
8297     bits<3> imm;
8298     let Inst{18-16} = imm;
8299   }
8300
8301   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8302                                   V128, V128, vecshiftR16Narrow,
8303                                   asm#"2", ".16b", ".8h", []> {
8304     bits<3> imm;
8305     let Inst{18-16} = imm;
8306     let hasSideEffects = 0;
8307   }
8308
8309   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8310                                   V64, V128, vecshiftR32Narrow,
8311                                   asm, ".4h", ".4s",
8312       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
8313     bits<4> imm;
8314     let Inst{19-16} = imm;
8315   }
8316
8317   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8318                                   V128, V128, vecshiftR32Narrow,
8319                                   asm#"2", ".8h", ".4s", []> {
8320     bits<4> imm;
8321     let Inst{19-16} = imm;
8322     let hasSideEffects = 0;
8323   }
8324
8325   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8326                                   V64, V128, vecshiftR64Narrow,
8327                                   asm, ".2s", ".2d",
8328       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
8329     bits<5> imm;
8330     let Inst{20-16} = imm;
8331   }
8332
8333   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8334                                   V128, V128, vecshiftR64Narrow,
8335                                   asm#"2", ".4s", ".2d", []> {
8336     bits<5> imm;
8337     let Inst{20-16} = imm;
8338     let hasSideEffects = 0;
8339   }
8340
8341   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
8342   // themselves, so put them here instead.
8343
8344   // Patterns involving what's effectively an insert high and a normal
8345   // intrinsic, represented by CONCAT_VECTORS.
8346   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
8347                                                    vecshiftR16Narrow:$imm)),
8348             (!cast<Instruction>(NAME # "v16i8_shift")
8349                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8350                 V128:$Rn, vecshiftR16Narrow:$imm)>;
8351   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
8352                                                      vecshiftR32Narrow:$imm)),
8353             (!cast<Instruction>(NAME # "v8i16_shift")
8354                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8355                 V128:$Rn, vecshiftR32Narrow:$imm)>;
8356   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
8357                                                      vecshiftR64Narrow:$imm)),
8358             (!cast<Instruction>(NAME # "v4i32_shift")
8359                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8360                 V128:$Rn, vecshiftR64Narrow:$imm)>;
8361 }
8362
8363 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
8364                                 SDPatternOperator OpNode> {
8365   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8366                                   V64, V64, vecshiftL8,
8367                                   asm, ".8b", ".8b",
8368                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8369                        (i32 vecshiftL8:$imm)))]> {
8370     bits<3> imm;
8371     let Inst{18-16} = imm;
8372   }
8373
8374   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8375                                   V128, V128, vecshiftL8,
8376                                   asm, ".16b", ".16b",
8377              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8378                    (i32 vecshiftL8:$imm)))]> {
8379     bits<3> imm;
8380     let Inst{18-16} = imm;
8381   }
8382
8383   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8384                                   V64, V64, vecshiftL16,
8385                                   asm, ".4h", ".4h",
8386               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8387                     (i32 vecshiftL16:$imm)))]> {
8388     bits<4> imm;
8389     let Inst{19-16} = imm;
8390   }
8391
8392   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8393                                   V128, V128, vecshiftL16,
8394                                   asm, ".8h", ".8h",
8395             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8396                   (i32 vecshiftL16:$imm)))]> {
8397     bits<4> imm;
8398     let Inst{19-16} = imm;
8399   }
8400
8401   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8402                                   V64, V64, vecshiftL32,
8403                                   asm, ".2s", ".2s",
8404               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8405                     (i32 vecshiftL32:$imm)))]> {
8406     bits<5> imm;
8407     let Inst{20-16} = imm;
8408   }
8409
8410   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8411                                   V128, V128, vecshiftL32,
8412                                   asm, ".4s", ".4s",
8413             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8414                   (i32 vecshiftL32:$imm)))]> {
8415     bits<5> imm;
8416     let Inst{20-16} = imm;
8417   }
8418
8419   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8420                                   V128, V128, vecshiftL64,
8421                                   asm, ".2d", ".2d",
8422             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8423                   (i32 vecshiftL64:$imm)))]> {
8424     bits<6> imm;
8425     let Inst{21-16} = imm;
8426   }
8427 }
8428
8429 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
8430                                 SDPatternOperator OpNode> {
8431   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8432                                   V64, V64, vecshiftR8,
8433                                   asm, ".8b", ".8b",
8434                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8435                        (i32 vecshiftR8:$imm)))]> {
8436     bits<3> imm;
8437     let Inst{18-16} = imm;
8438   }
8439
8440   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8441                                   V128, V128, vecshiftR8,
8442                                   asm, ".16b", ".16b",
8443              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8444                    (i32 vecshiftR8:$imm)))]> {
8445     bits<3> imm;
8446     let Inst{18-16} = imm;
8447   }
8448
8449   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8450                                   V64, V64, vecshiftR16,
8451                                   asm, ".4h", ".4h",
8452               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8453                     (i32 vecshiftR16:$imm)))]> {
8454     bits<4> imm;
8455     let Inst{19-16} = imm;
8456   }
8457
8458   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8459                                   V128, V128, vecshiftR16,
8460                                   asm, ".8h", ".8h",
8461             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8462                   (i32 vecshiftR16:$imm)))]> {
8463     bits<4> imm;
8464     let Inst{19-16} = imm;
8465   }
8466
8467   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8468                                   V64, V64, vecshiftR32,
8469                                   asm, ".2s", ".2s",
8470               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8471                     (i32 vecshiftR32:$imm)))]> {
8472     bits<5> imm;
8473     let Inst{20-16} = imm;
8474   }
8475
8476   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8477                                   V128, V128, vecshiftR32,
8478                                   asm, ".4s", ".4s",
8479             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8480                   (i32 vecshiftR32:$imm)))]> {
8481     bits<5> imm;
8482     let Inst{20-16} = imm;
8483   }
8484
8485   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8486                                   V128, V128, vecshiftR64,
8487                                   asm, ".2d", ".2d",
8488             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8489                   (i32 vecshiftR64:$imm)))]> {
8490     bits<6> imm;
8491     let Inst{21-16} = imm;
8492   }
8493 }
8494
8495 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8496 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8497                                     SDPatternOperator OpNode = null_frag> {
8498   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8499                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
8500                  [(set (v8i8 V64:$dst),
8501                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8502                            (i32 vecshiftR8:$imm)))]> {
8503     bits<3> imm;
8504     let Inst{18-16} = imm;
8505   }
8506
8507   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8508                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
8509              [(set (v16i8 V128:$dst),
8510                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8511                        (i32 vecshiftR8:$imm)))]> {
8512     bits<3> imm;
8513     let Inst{18-16} = imm;
8514   }
8515
8516   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8517                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
8518               [(set (v4i16 V64:$dst),
8519                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8520                         (i32 vecshiftR16:$imm)))]> {
8521     bits<4> imm;
8522     let Inst{19-16} = imm;
8523   }
8524
8525   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8526                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
8527             [(set (v8i16 V128:$dst),
8528               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8529                       (i32 vecshiftR16:$imm)))]> {
8530     bits<4> imm;
8531     let Inst{19-16} = imm;
8532   }
8533
8534   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8535                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
8536               [(set (v2i32 V64:$dst),
8537                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8538                         (i32 vecshiftR32:$imm)))]> {
8539     bits<5> imm;
8540     let Inst{20-16} = imm;
8541   }
8542
8543   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8544                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
8545             [(set (v4i32 V128:$dst),
8546               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8547                       (i32 vecshiftR32:$imm)))]> {
8548     bits<5> imm;
8549     let Inst{20-16} = imm;
8550   }
8551
8552   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8553                                   V128, V128, vecshiftR64,
8554                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8555               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8556                       (i32 vecshiftR64:$imm)))]> {
8557     bits<6> imm;
8558     let Inst{21-16} = imm;
8559   }
8560 }
8561
8562 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8563                                     SDPatternOperator OpNode = null_frag> {
8564   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8565                                   V64, V64, vecshiftL8,
8566                                   asm, ".8b", ".8b",
8567                     [(set (v8i8 V64:$dst),
8568                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8569                                   (i32 vecshiftL8:$imm)))]> {
8570     bits<3> imm;
8571     let Inst{18-16} = imm;
8572   }
8573
8574   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8575                                   V128, V128, vecshiftL8,
8576                                   asm, ".16b", ".16b",
8577                     [(set (v16i8 V128:$dst),
8578                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8579                                   (i32 vecshiftL8:$imm)))]> {
8580     bits<3> imm;
8581     let Inst{18-16} = imm;
8582   }
8583
8584   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8585                                   V64, V64, vecshiftL16,
8586                                   asm, ".4h", ".4h",
8587                     [(set (v4i16 V64:$dst),
8588                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8589                                    (i32 vecshiftL16:$imm)))]> {
8590     bits<4> imm;
8591     let Inst{19-16} = imm;
8592   }
8593
8594   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8595                                   V128, V128, vecshiftL16,
8596                                   asm, ".8h", ".8h",
8597                     [(set (v8i16 V128:$dst),
8598                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8599                                   (i32 vecshiftL16:$imm)))]> {
8600     bits<4> imm;
8601     let Inst{19-16} = imm;
8602   }
8603
8604   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8605                                   V64, V64, vecshiftL32,
8606                                   asm, ".2s", ".2s",
8607                     [(set (v2i32 V64:$dst),
8608                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8609                                   (i32 vecshiftL32:$imm)))]> {
8610     bits<5> imm;
8611     let Inst{20-16} = imm;
8612   }
8613
8614   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8615                                   V128, V128, vecshiftL32,
8616                                   asm, ".4s", ".4s",
8617                     [(set (v4i32 V128:$dst),
8618                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8619                                   (i32 vecshiftL32:$imm)))]> {
8620     bits<5> imm;
8621     let Inst{20-16} = imm;
8622   }
8623
8624   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8625                                   V128, V128, vecshiftL64,
8626                                   asm, ".2d", ".2d",
8627                     [(set (v2i64 V128:$dst),
8628                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8629                                   (i32 vecshiftL64:$imm)))]> {
8630     bits<6> imm;
8631     let Inst{21-16} = imm;
8632   }
8633 }
8634
8635 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8636                                    SDPatternOperator OpNode> {
8637   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8638                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
8639       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8640     bits<3> imm;
8641     let Inst{18-16} = imm;
8642   }
8643
8644   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8645                                   V128, V128, vecshiftL8,
8646                                   asm#"2", ".8h", ".16b",
8647       [(set (v8i16 V128:$Rd),
8648             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8649     bits<3> imm;
8650     let Inst{18-16} = imm;
8651   }
8652
8653   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8654                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
8655       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8656     bits<4> imm;
8657     let Inst{19-16} = imm;
8658   }
8659
8660   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8661                                   V128, V128, vecshiftL16,
8662                                   asm#"2", ".4s", ".8h",
8663       [(set (v4i32 V128:$Rd),
8664             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8665
8666     bits<4> imm;
8667     let Inst{19-16} = imm;
8668   }
8669
8670   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8671                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
8672       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8673     bits<5> imm;
8674     let Inst{20-16} = imm;
8675   }
8676
8677   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8678                                   V128, V128, vecshiftL32,
8679                                   asm#"2", ".2d", ".4s",
8680       [(set (v2i64 V128:$Rd),
8681             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
8682     bits<5> imm;
8683     let Inst{20-16} = imm;
8684   }
8685 }
8686
8687
8688 //---
8689 // Vector load/store
8690 //---
8691 // SIMD ldX/stX no-index memory references don't allow the optional
8692 // ", #0" constant and handle post-indexing explicitly, so we use
8693 // a more specialized parse method for them. Otherwise, it's the same as
8694 // the general GPR64sp handling.
8695
8696 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
8697                    string asm, dag oops, dag iops, list<dag> pattern>
8698   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
8699   bits<5> Vt;
8700   bits<5> Rn;
8701   let Inst{31} = 0;
8702   let Inst{30} = Q;
8703   let Inst{29-23} = 0b0011000;
8704   let Inst{22} = L;
8705   let Inst{21-16} = 0b000000;
8706   let Inst{15-12} = opcode;
8707   let Inst{11-10} = size;
8708   let Inst{9-5} = Rn;
8709   let Inst{4-0} = Vt;
8710 }
8711
8712 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
8713                        string asm, dag oops, dag iops>
8714   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
8715   bits<5> Vt;
8716   bits<5> Rn;
8717   bits<5> Xm;
8718   let Inst{31} = 0;
8719   let Inst{30} = Q;
8720   let Inst{29-23} = 0b0011001;
8721   let Inst{22} = L;
8722   let Inst{21} = 0;
8723   let Inst{20-16} = Xm;
8724   let Inst{15-12} = opcode;
8725   let Inst{11-10} = size;
8726   let Inst{9-5} = Rn;
8727   let Inst{4-0} = Vt;
8728 }
8729
8730 // The immediate form of AdvSIMD post-indexed addressing is encoded with
8731 // register post-index addressing from the zero register.
8732 multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
8733                            int Offset, int Size> {
8734   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8735   //      "ld1\t$Vt, [$Rn], #16"
8736   // may get mapped to
8737   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8738   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8739                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8740                       GPR64sp:$Rn,
8741                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8742                       XZR), 1>;
8743
8744   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8745   //      "ld1.8b\t$Vt, [$Rn], #16"
8746   // may get mapped to
8747   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8748   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8749                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8750                       GPR64sp:$Rn,
8751                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8752                       XZR), 0>;
8753
8754   // E.g. "ld1.8b { v0, v1 }, [x1]"
8755   //      "ld1\t$Vt, [$Rn]"
8756   // may get mapped to
8757   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
8758   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8759                   (!cast<Instruction>(BaseName # Count # "v" # layout)
8760                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8761                       GPR64sp:$Rn), 0>;
8762
8763   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
8764   //      "ld1\t$Vt, [$Rn], $Xm"
8765   // may get mapped to
8766   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
8767   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8768                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8769                       GPR64sp:$Rn,
8770                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8771                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8772 }
8773
8774 multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
8775                        int Offset128, int Offset64, bits<4> opcode> {
8776   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8777     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
8778                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
8779                            (ins GPR64sp:$Rn), []>;
8780     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
8781                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
8782                            (ins GPR64sp:$Rn), []>;
8783     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
8784                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
8785                            (ins GPR64sp:$Rn), []>;
8786     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
8787                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
8788                            (ins GPR64sp:$Rn), []>;
8789     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
8790                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
8791                            (ins GPR64sp:$Rn), []>;
8792     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
8793                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
8794                            (ins GPR64sp:$Rn), []>;
8795     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
8796                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
8797                            (ins GPR64sp:$Rn), []>;
8798
8799
8800     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
8801                        (outs GPR64sp:$wback,
8802                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
8803                        (ins GPR64sp:$Rn,
8804                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8805     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
8806                        (outs GPR64sp:$wback,
8807                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
8808                        (ins GPR64sp:$Rn,
8809                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8810     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
8811                        (outs GPR64sp:$wback,
8812                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
8813                        (ins GPR64sp:$Rn,
8814                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8815     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
8816                        (outs GPR64sp:$wback,
8817                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
8818                        (ins GPR64sp:$Rn,
8819                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8820     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
8821                        (outs GPR64sp:$wback,
8822                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
8823                        (ins GPR64sp:$Rn,
8824                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8825     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
8826                        (outs GPR64sp:$wback,
8827                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
8828                        (ins GPR64sp:$Rn,
8829                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8830     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
8831                        (outs GPR64sp:$wback,
8832                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
8833                        (ins GPR64sp:$Rn,
8834                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8835   }
8836
8837   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
8838   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
8839   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
8840   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
8841   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
8842   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
8843   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
8844 }
8845
8846 // Only ld1/st1 has a v1d version.
8847 multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
8848                        int Offset128, int Offset64, bits<4> opcode> {
8849   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
8850     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
8851                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8852                                  GPR64sp:$Rn), []>;
8853     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
8854                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8855                                 GPR64sp:$Rn), []>;
8856     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
8857                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8858                                 GPR64sp:$Rn), []>;
8859     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
8860                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8861                                 GPR64sp:$Rn), []>;
8862     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
8863                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8864                                 GPR64sp:$Rn), []>;
8865     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
8866                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8867                                 GPR64sp:$Rn), []>;
8868     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
8869                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8870                                 GPR64sp:$Rn), []>;
8871
8872     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
8873                        (outs GPR64sp:$wback),
8874                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8875                             GPR64sp:$Rn,
8876                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8877     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
8878                        (outs GPR64sp:$wback),
8879                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8880                             GPR64sp:$Rn,
8881                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8882     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
8883                        (outs GPR64sp:$wback),
8884                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8885                             GPR64sp:$Rn,
8886                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8887     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
8888                        (outs GPR64sp:$wback),
8889                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8890                             GPR64sp:$Rn,
8891                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8892     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
8893                        (outs GPR64sp:$wback),
8894                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8895                             GPR64sp:$Rn,
8896                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8897     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
8898                        (outs GPR64sp:$wback),
8899                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8900                             GPR64sp:$Rn,
8901                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8902     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
8903                        (outs GPR64sp:$wback),
8904                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8905                             GPR64sp:$Rn,
8906                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8907   }
8908
8909   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
8910   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
8911   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
8912   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
8913   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
8914   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
8915   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
8916 }
8917
8918 multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
8919                        int Offset128, int Offset64, bits<4> opcode>
8920   : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
8921
8922   // LD1 instructions have extra "1d" variants.
8923   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8924     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8925                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8926                            (ins GPR64sp:$Rn), []>;
8927
8928     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8929                        (outs GPR64sp:$wback,
8930                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
8931                        (ins GPR64sp:$Rn,
8932                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8933   }
8934
8935   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
8936 }
8937
8938 multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
8939                        int Offset128, int Offset64, bits<4> opcode>
8940   : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
8941
8942   // ST1 instructions have extra "1d" variants.
8943   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8944     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8945                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8946                                 GPR64sp:$Rn), []>;
8947
8948     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8949                        (outs GPR64sp:$wback),
8950                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8951                             GPR64sp:$Rn,
8952                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8953   }
8954
8955   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
8956 }
8957
8958 multiclass SIMDLd1Multiple<string asm> {
8959   defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
8960   defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
8961   defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
8962   defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
8963 }
8964
8965 multiclass SIMDSt1Multiple<string asm> {
8966   defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
8967   defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
8968   defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
8969   defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
8970 }
8971
8972 multiclass SIMDLd2Multiple<string asm> {
8973   defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
8974 }
8975
8976 multiclass SIMDSt2Multiple<string asm> {
8977   defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
8978 }
8979
8980 multiclass SIMDLd3Multiple<string asm> {
8981   defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
8982 }
8983
8984 multiclass SIMDSt3Multiple<string asm> {
8985   defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
8986 }
8987
8988 multiclass SIMDLd4Multiple<string asm> {
8989   defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
8990 }
8991
8992 multiclass SIMDSt4Multiple<string asm> {
8993   defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
8994 }
8995
8996 //---
8997 // AdvSIMD Load/store single-element
8998 //---
8999
9000 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9001                          string asm, string operands, string cst,
9002                          dag oops, dag iops, list<dag> pattern>
9003   : I<oops, iops, asm, operands, cst, pattern> {
9004   bits<5> Vt;
9005   bits<5> Rn;
9006   let Inst{31} = 0;
9007   let Inst{29-24} = 0b001101;
9008   let Inst{22} = L;
9009   let Inst{21} = R;
9010   let Inst{15-13} = opcode;
9011   let Inst{9-5} = Rn;
9012   let Inst{4-0} = Vt;
9013 }
9014
9015 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9016                          string asm, string operands, string cst,
9017                          dag oops, dag iops, list<dag> pattern>
9018   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9019   bits<5> Vt;
9020   bits<5> Rn;
9021   let Inst{31} = 0;
9022   let Inst{29-24} = 0b001101;
9023   let Inst{22} = L;
9024   let Inst{21} = R;
9025   let Inst{15-13} = opcode;
9026   let Inst{9-5} = Rn;
9027   let Inst{4-0} = Vt;
9028 }
9029
9030
9031 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9032 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9033                   DAGOperand listtype>
9034   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9035                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
9036                        []> {
9037   let Inst{30} = Q;
9038   let Inst{23} = 0;
9039   let Inst{20-16} = 0b00000;
9040   let Inst{12} = S;
9041   let Inst{11-10} = size;
9042 }
9043 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9044 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9045                       string asm, DAGOperand listtype, DAGOperand GPR64pi>
9046   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9047                        "$Rn = $wback",
9048                        (outs GPR64sp:$wback, listtype:$Vt),
9049                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9050   bits<5> Xm;
9051   let Inst{30} = Q;
9052   let Inst{23} = 1;
9053   let Inst{20-16} = Xm;
9054   let Inst{12} = S;
9055   let Inst{11-10} = size;
9056 }
9057
9058 multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9059                           int Offset, int Size> {
9060   // E.g. "ld1r { v0.8b }, [x1], #1"
9061   //      "ld1r.8b\t$Vt, [$Rn], #1"
9062   // may get mapped to
9063   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9064   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9065                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9066                       GPR64sp:$Rn,
9067                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9068                       XZR), 1>;
9069
9070   // E.g. "ld1r.8b { v0 }, [x1], #1"
9071   //      "ld1r.8b\t$Vt, [$Rn], #1"
9072   // may get mapped to
9073   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9074   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9075                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9076                       GPR64sp:$Rn,
9077                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9078                       XZR), 0>;
9079
9080   // E.g. "ld1r.8b { v0 }, [x1]"
9081   //      "ld1r.8b\t$Vt, [$Rn]"
9082   // may get mapped to
9083   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9084   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9085                   (!cast<Instruction>(BaseName # "v" # layout)
9086                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9087                       GPR64sp:$Rn), 0>;
9088
9089   // E.g. "ld1r.8b { v0 }, [x1], x2"
9090   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9091   // may get mapped to
9092   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9093   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9094                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9095                       GPR64sp:$Rn,
9096                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9097                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9098 }
9099
9100 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9101   int Offset1, int Offset2, int Offset4, int Offset8> {
9102   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9103                         !cast<DAGOperand>("VecList" # Count # "8b")>;
9104   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9105                         !cast<DAGOperand>("VecList" # Count #"16b")>;
9106   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9107                         !cast<DAGOperand>("VecList" # Count #"4h")>;
9108   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9109                         !cast<DAGOperand>("VecList" # Count #"8h")>;
9110   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9111                         !cast<DAGOperand>("VecList" # Count #"2s")>;
9112   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9113                         !cast<DAGOperand>("VecList" # Count #"4s")>;
9114   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9115                         !cast<DAGOperand>("VecList" # Count #"1d")>;
9116   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9117                         !cast<DAGOperand>("VecList" # Count #"2d")>;
9118
9119   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9120                                  !cast<DAGOperand>("VecList" # Count # "8b"),
9121                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9122   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9123                                  !cast<DAGOperand>("VecList" # Count # "16b"),
9124                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9125   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9126                                  !cast<DAGOperand>("VecList" # Count # "4h"),
9127                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9128   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9129                                  !cast<DAGOperand>("VecList" # Count # "8h"),
9130                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9131   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9132                                  !cast<DAGOperand>("VecList" # Count # "2s"),
9133                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9134   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9135                                  !cast<DAGOperand>("VecList" # Count # "4s"),
9136                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9137   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9138                                  !cast<DAGOperand>("VecList" # Count # "1d"),
9139                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9140   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9141                                  !cast<DAGOperand>("VecList" # Count # "2d"),
9142                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9143
9144   defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
9145   defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9146   defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
9147   defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
9148   defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
9149   defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
9150   defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
9151   defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
9152 }
9153
9154 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9155                       dag oops, dag iops, list<dag> pattern>
9156   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9157                        pattern> {
9158   // idx encoded in Q:S:size fields.
9159   bits<4> idx;
9160   let Inst{30} = idx{3};
9161   let Inst{23} = 0;
9162   let Inst{20-16} = 0b00000;
9163   let Inst{12} = idx{2};
9164   let Inst{11-10} = idx{1-0};
9165 }
9166 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
9167                       dag oops, dag iops, list<dag> pattern>
9168   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9169                            oops, iops, pattern> {
9170   // idx encoded in Q:S:size fields.
9171   bits<4> idx;
9172   let Inst{30} = idx{3};
9173   let Inst{23} = 0;
9174   let Inst{20-16} = 0b00000;
9175   let Inst{12} = idx{2};
9176   let Inst{11-10} = idx{1-0};
9177 }
9178 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
9179                           dag oops, dag iops>
9180   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9181                        "$Rn = $wback", oops, iops, []> {
9182   // idx encoded in Q:S:size fields.
9183   bits<4> idx;
9184   bits<5> Xm;
9185   let Inst{30} = idx{3};
9186   let Inst{23} = 1;
9187   let Inst{20-16} = Xm;
9188   let Inst{12} = idx{2};
9189   let Inst{11-10} = idx{1-0};
9190 }
9191 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
9192                           dag oops, dag iops>
9193   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9194                            "$Rn = $wback", oops, iops, []> {
9195   // idx encoded in Q:S:size fields.
9196   bits<4> idx;
9197   bits<5> Xm;
9198   let Inst{30} = idx{3};
9199   let Inst{23} = 1;
9200   let Inst{20-16} = Xm;
9201   let Inst{12} = idx{2};
9202   let Inst{11-10} = idx{1-0};
9203 }
9204
9205 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
9206                       dag oops, dag iops, list<dag> pattern>
9207   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9208                        pattern> {
9209   // idx encoded in Q:S:size<1> fields.
9210   bits<3> idx;
9211   let Inst{30} = idx{2};
9212   let Inst{23} = 0;
9213   let Inst{20-16} = 0b00000;
9214   let Inst{12} = idx{1};
9215   let Inst{11} = idx{0};
9216   let Inst{10} = size;
9217 }
9218 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
9219                       dag oops, dag iops, list<dag> pattern>
9220   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9221                            oops, iops, pattern> {
9222   // idx encoded in Q:S:size<1> fields.
9223   bits<3> idx;
9224   let Inst{30} = idx{2};
9225   let Inst{23} = 0;
9226   let Inst{20-16} = 0b00000;
9227   let Inst{12} = idx{1};
9228   let Inst{11} = idx{0};
9229   let Inst{10} = size;
9230 }
9231
9232 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9233                           dag oops, dag iops>
9234   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9235                        "$Rn = $wback", oops, iops, []> {
9236   // idx encoded in Q:S:size<1> fields.
9237   bits<3> idx;
9238   bits<5> Xm;
9239   let Inst{30} = idx{2};
9240   let Inst{23} = 1;
9241   let Inst{20-16} = Xm;
9242   let Inst{12} = idx{1};
9243   let Inst{11} = idx{0};
9244   let Inst{10} = size;
9245 }
9246 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9247                           dag oops, dag iops>
9248   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9249                            "$Rn = $wback", oops, iops, []> {
9250   // idx encoded in Q:S:size<1> fields.
9251   bits<3> idx;
9252   bits<5> Xm;
9253   let Inst{30} = idx{2};
9254   let Inst{23} = 1;
9255   let Inst{20-16} = Xm;
9256   let Inst{12} = idx{1};
9257   let Inst{11} = idx{0};
9258   let Inst{10} = size;
9259 }
9260 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9261                       dag oops, dag iops, list<dag> pattern>
9262   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9263                        pattern> {
9264   // idx encoded in Q:S fields.
9265   bits<2> idx;
9266   let Inst{30} = idx{1};
9267   let Inst{23} = 0;
9268   let Inst{20-16} = 0b00000;
9269   let Inst{12} = idx{0};
9270   let Inst{11-10} = size;
9271 }
9272 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9273                       dag oops, dag iops, list<dag> pattern>
9274   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9275                            oops, iops, pattern> {
9276   // idx encoded in Q:S fields.
9277   bits<2> idx;
9278   let Inst{30} = idx{1};
9279   let Inst{23} = 0;
9280   let Inst{20-16} = 0b00000;
9281   let Inst{12} = idx{0};
9282   let Inst{11-10} = size;
9283 }
9284 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
9285                           string asm, dag oops, dag iops>
9286   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9287                        "$Rn = $wback", oops, iops, []> {
9288   // idx encoded in Q:S fields.
9289   bits<2> idx;
9290   bits<5> Xm;
9291   let Inst{30} = idx{1};
9292   let Inst{23} = 1;
9293   let Inst{20-16} = Xm;
9294   let Inst{12} = idx{0};
9295   let Inst{11-10} = size;
9296 }
9297 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9298                           string asm, dag oops, dag iops>
9299   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9300                            "$Rn = $wback", oops, iops, []> {
9301   // idx encoded in Q:S fields.
9302   bits<2> idx;
9303   bits<5> Xm;
9304   let Inst{30} = idx{1};
9305   let Inst{23} = 1;
9306   let Inst{20-16} = Xm;
9307   let Inst{12} = idx{0};
9308   let Inst{11-10} = size;
9309 }
9310 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9311                       dag oops, dag iops, list<dag> pattern>
9312   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9313                        pattern> {
9314   // idx encoded in Q field.
9315   bits<1> idx;
9316   let Inst{30} = idx;
9317   let Inst{23} = 0;
9318   let Inst{20-16} = 0b00000;
9319   let Inst{12} = 0;
9320   let Inst{11-10} = size;
9321 }
9322 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9323                       dag oops, dag iops, list<dag> pattern>
9324   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9325                            oops, iops, pattern> {
9326   // idx encoded in Q field.
9327   bits<1> idx;
9328   let Inst{30} = idx;
9329   let Inst{23} = 0;
9330   let Inst{20-16} = 0b00000;
9331   let Inst{12} = 0;
9332   let Inst{11-10} = size;
9333 }
9334 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
9335                           string asm, dag oops, dag iops>
9336   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9337                        "$Rn = $wback", oops, iops, []> {
9338   // idx encoded in Q field.
9339   bits<1> idx;
9340   bits<5> Xm;
9341   let Inst{30} = idx;
9342   let Inst{23} = 1;
9343   let Inst{20-16} = Xm;
9344   let Inst{12} = 0;
9345   let Inst{11-10} = size;
9346 }
9347 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9348                           string asm, dag oops, dag iops>
9349   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9350                            "$Rn = $wback", oops, iops, []> {
9351   // idx encoded in Q field.
9352   bits<1> idx;
9353   bits<5> Xm;
9354   let Inst{30} = idx;
9355   let Inst{23} = 1;
9356   let Inst{20-16} = Xm;
9357   let Inst{12} = 0;
9358   let Inst{11-10} = size;
9359 }
9360
9361 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9362 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
9363                          RegisterOperand listtype,
9364                          RegisterOperand GPR64pi> {
9365   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
9366                            (outs listtype:$dst),
9367                            (ins listtype:$Vt, VectorIndexB:$idx,
9368                                 GPR64sp:$Rn), []>;
9369
9370   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
9371                             (outs GPR64sp:$wback, listtype:$dst),
9372                             (ins listtype:$Vt, VectorIndexB:$idx,
9373                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9374 }
9375 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9376 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
9377                          RegisterOperand listtype,
9378                          RegisterOperand GPR64pi> {
9379   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
9380                             (outs listtype:$dst),
9381                             (ins listtype:$Vt, VectorIndexH:$idx,
9382                                  GPR64sp:$Rn), []>;
9383
9384   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
9385                             (outs GPR64sp:$wback, listtype:$dst),
9386                             (ins listtype:$Vt, VectorIndexH:$idx,
9387                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9388 }
9389 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9390 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
9391                          RegisterOperand listtype,
9392                          RegisterOperand GPR64pi> {
9393   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
9394                             (outs listtype:$dst),
9395                             (ins listtype:$Vt, VectorIndexS:$idx,
9396                                  GPR64sp:$Rn), []>;
9397
9398   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
9399                             (outs GPR64sp:$wback, listtype:$dst),
9400                             (ins listtype:$Vt, VectorIndexS:$idx,
9401                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9402 }
9403 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9404 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
9405                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9406   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
9407                             (outs listtype:$dst),
9408                             (ins listtype:$Vt, VectorIndexD:$idx,
9409                                  GPR64sp:$Rn), []>;
9410
9411   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
9412                             (outs GPR64sp:$wback, listtype:$dst),
9413                             (ins listtype:$Vt, VectorIndexD:$idx,
9414                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9415 }
9416 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9417 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
9418                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9419   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
9420                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
9421                                         GPR64sp:$Rn), []>;
9422
9423   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
9424                                     (outs GPR64sp:$wback),
9425                                     (ins listtype:$Vt, VectorIndexB:$idx,
9426                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
9427 }
9428 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9429 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
9430                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9431   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
9432                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
9433                                          GPR64sp:$Rn), []>;
9434
9435   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
9436                             (outs GPR64sp:$wback),
9437                             (ins listtype:$Vt, VectorIndexH:$idx,
9438                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9439 }
9440 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9441 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
9442                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9443   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
9444                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
9445                                          GPR64sp:$Rn), []>;
9446
9447   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
9448                             (outs GPR64sp:$wback),
9449                             (ins listtype:$Vt, VectorIndexS:$idx,
9450                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9451 }
9452 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9453 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
9454                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9455   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
9456                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
9457                                          GPR64sp:$Rn), []>;
9458
9459   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
9460                             (outs GPR64sp:$wback),
9461                             (ins listtype:$Vt, VectorIndexD:$idx,
9462                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9463 }
9464
9465 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
9466                                  string Count, int Offset, Operand idxtype> {
9467   // E.g. "ld1 { v0.8b }[0], [x1], #1"
9468   //      "ld1\t$Vt, [$Rn], #1"
9469   // may get mapped to
9470   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9471   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
9472                   (!cast<Instruction>(NAME # Type  # "_POST")
9473                       GPR64sp:$Rn,
9474                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9475                       idxtype:$idx, XZR), 1>;
9476
9477   // E.g. "ld1.8b { v0 }[0], [x1], #1"
9478   //      "ld1.8b\t$Vt, [$Rn], #1"
9479   // may get mapped to
9480   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9481   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9482                   (!cast<Instruction>(NAME # Type # "_POST")
9483                       GPR64sp:$Rn,
9484                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9485                       idxtype:$idx, XZR), 0>;
9486
9487   // E.g. "ld1.8b { v0 }[0], [x1]"
9488   //      "ld1.8b\t$Vt, [$Rn]"
9489   // may get mapped to
9490   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9491   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9492                       (!cast<Instruction>(NAME # Type)
9493                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9494                          idxtype:$idx, GPR64sp:$Rn), 0>;
9495
9496   // E.g. "ld1.8b { v0 }[0], [x1], x2"
9497   //      "ld1.8b\t$Vt, [$Rn], $Xm"
9498   // may get mapped to
9499   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9500   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9501                       (!cast<Instruction>(NAME # Type # "_POST")
9502                          GPR64sp:$Rn,
9503                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9504                          idxtype:$idx,
9505                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9506 }
9507
9508 multiclass SIMDLdSt1SingleAliases<string asm> {
9509   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
9510   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9511   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9512   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9513 }
9514
9515 multiclass SIMDLdSt2SingleAliases<string asm> {
9516   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
9517   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
9518   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
9519   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9520 }
9521
9522 multiclass SIMDLdSt3SingleAliases<string asm> {
9523   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
9524   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
9525   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9526   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9527 }
9528
9529 multiclass SIMDLdSt4SingleAliases<string asm> {
9530   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
9531   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
9532   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9533   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9534 }
9535 } // end of 'let Predicates = [HasNEON]'
9536
9537 //----------------------------------------------------------------------------
9538 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9539 //----------------------------------------------------------------------------
9540
9541 let Predicates = [HasNEON, HasRDM] in {
9542
9543 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9544                                     RegisterOperand regtype, string asm,
9545                                     string kind, list<dag> pattern>
9546   : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9547                                 pattern> {
9548 }
9549 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9550                                              SDPatternOperator Accum> {
9551   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9552     [(set (v4i16 V64:$dst),
9553           (Accum (v4i16 V64:$Rd),
9554                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9555                                                    (v4i16 V64:$Rm)))))]>;
9556   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9557     [(set (v8i16 V128:$dst),
9558           (Accum (v8i16 V128:$Rd),
9559                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9560                                                    (v8i16 V128:$Rm)))))]>;
9561   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9562     [(set (v2i32 V64:$dst),
9563           (Accum (v2i32 V64:$Rd),
9564                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9565                                                    (v2i32 V64:$Rm)))))]>;
9566   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9567     [(set (v4i32 V128:$dst),
9568           (Accum (v4i32 V128:$Rd),
9569                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9570                                                    (v4i32 V128:$Rm)))))]>;
9571 }
9572
9573 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9574                                      SDPatternOperator Accum> {
9575   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9576                                           V64, V64, V128_lo, VectorIndexH,
9577                                           asm, ".4h", ".4h", ".4h", ".h",
9578     [(set (v4i16 V64:$dst),
9579           (Accum (v4i16 V64:$Rd),
9580                  (v4i16 (int_aarch64_neon_sqrdmulh
9581                           (v4i16 V64:$Rn),
9582                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9583                                                     VectorIndexH:$idx))))))]> {
9584     bits<3> idx;
9585     let Inst{11} = idx{2};
9586     let Inst{21} = idx{1};
9587     let Inst{20} = idx{0};
9588   }
9589
9590   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9591                                           V128, V128, V128_lo, VectorIndexH,
9592                                           asm, ".8h", ".8h", ".8h", ".h",
9593     [(set (v8i16 V128:$dst),
9594           (Accum (v8i16 V128:$Rd),
9595                  (v8i16 (int_aarch64_neon_sqrdmulh
9596                           (v8i16 V128:$Rn),
9597                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9598                                                    VectorIndexH:$idx))))))]> {
9599     bits<3> idx;
9600     let Inst{11} = idx{2};
9601     let Inst{21} = idx{1};
9602     let Inst{20} = idx{0};
9603   }
9604
9605   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9606                                           V64, V64, V128, VectorIndexS,
9607                                           asm, ".2s", ".2s", ".2s", ".s",
9608     [(set (v2i32 V64:$dst),
9609         (Accum (v2i32 V64:$Rd),
9610                (v2i32 (int_aarch64_neon_sqrdmulh
9611                         (v2i32 V64:$Rn),
9612                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9613                                                  VectorIndexS:$idx))))))]> {
9614     bits<2> idx;
9615     let Inst{11} = idx{1};
9616     let Inst{21} = idx{0};
9617   }
9618
9619   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9620   // an intermediate EXTRACT_SUBREG would be untyped.
9621   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
9622   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9623   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9624                        (i32 (vector_extract
9625                                (v4i32 (insert_subvector
9626                                        (undef),
9627                                         (v2i32 (int_aarch64_neon_sqrdmulh
9628                                                  (v2i32 V64:$Rn),
9629                                                  (v2i32 (AArch64duplane32
9630                                                           (v4i32 V128:$Rm),
9631                                                           VectorIndexS:$idx)))),
9632                                       (i32 0))),
9633                                (i64 0))))),
9634             (EXTRACT_SUBREG
9635                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9636                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
9637                                                 FPR32Op:$Rd,
9638                                                 ssub)),
9639                           V64:$Rn,
9640                           V128:$Rm,
9641                           VectorIndexS:$idx)),
9642                 ssub)>;
9643
9644   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9645                                           V128, V128, V128, VectorIndexS,
9646                                           asm, ".4s", ".4s", ".4s", ".s",
9647     [(set (v4i32 V128:$dst),
9648           (Accum (v4i32 V128:$Rd),
9649                  (v4i32 (int_aarch64_neon_sqrdmulh
9650                           (v4i32 V128:$Rn),
9651                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9652                                                    VectorIndexS:$idx))))))]> {
9653     bits<2> idx;
9654     let Inst{11} = idx{1};
9655     let Inst{21} = idx{0};
9656   }
9657
9658   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9659   // an intermediate EXTRACT_SUBREG would be untyped.
9660   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9661                         (i32 (vector_extract
9662                                (v4i32 (int_aarch64_neon_sqrdmulh
9663                                         (v4i32 V128:$Rn),
9664                                         (v4i32 (AArch64duplane32
9665                                                  (v4i32 V128:$Rm),
9666                                                  VectorIndexS:$idx)))),
9667                                (i64 0))))),
9668             (EXTRACT_SUBREG
9669                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9670                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
9671                                                FPR32Op:$Rd,
9672                                                ssub)),
9673                          V128:$Rn,
9674                          V128:$Rm,
9675                          VectorIndexS:$idx)),
9676                 ssub)>;
9677
9678   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9679                                         FPR16Op, FPR16Op, V128_lo,
9680                                         VectorIndexH, asm, ".h", "", "", ".h",
9681                                         []> {
9682     bits<3> idx;
9683     let Inst{11} = idx{2};
9684     let Inst{21} = idx{1};
9685     let Inst{20} = idx{0};
9686   }
9687
9688   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9689                                         FPR32Op, FPR32Op, V128, VectorIndexS,
9690                                         asm, ".s", "", "", ".s",
9691     [(set (i32 FPR32Op:$dst),
9692           (Accum (i32 FPR32Op:$Rd),
9693                  (i32 (int_aarch64_neon_sqrdmulh
9694                         (i32 FPR32Op:$Rn),
9695                         (i32 (vector_extract (v4i32 V128:$Rm),
9696                                              VectorIndexS:$idx))))))]> {
9697     bits<2> idx;
9698     let Inst{11} = idx{1};
9699     let Inst{21} = idx{0};
9700   }
9701 }
9702 } // let Predicates = [HasNeon, HasRDM]
9703
9704 //----------------------------------------------------------------------------
9705 // ARMv8.3 Complex ADD/MLA instructions
9706 //----------------------------------------------------------------------------
9707
9708 class ComplexRotationOperand<int Angle, int Remainder, string Type>
9709   : AsmOperandClass {
9710   let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
9711   let DiagnosticType = "InvalidComplexRotation" # Type;
9712   let Name = "ComplexRotation" # Type;
9713 }
9714 def complexrotateop : Operand<i32> {
9715   let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
9716   let PrintMethod = "printComplexRotationOp<90, 0>";
9717 }
9718 def complexrotateopodd : Operand<i32> {
9719   let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
9720   let PrintMethod = "printComplexRotationOp<180, 90>";
9721 }
9722
9723 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9724 class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
9725                                      RegisterOperand regtype, Operand rottype,
9726                                      string asm, string kind, list<dag> pattern>
9727   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
9728       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
9729       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
9730     Sched<[WriteV]> {
9731   bits<5> Rd;
9732   bits<5> Rn;
9733   bits<5> Rm;
9734   bits<1> rot;
9735   let Inst{31}    = 0;
9736   let Inst{30}    = Q;
9737   let Inst{29}    = U;
9738   let Inst{28-24} = 0b01110;
9739   let Inst{23-22} = size;
9740   let Inst{21}    = 0;
9741   let Inst{20-16} = Rm;
9742   let Inst{15-13} = opcode;
9743   // Non-tied version (FCADD) only has one rotation bit
9744   let Inst{12}    = rot;
9745   let Inst{11}    = 0;
9746   let Inst{10}    = 1;
9747   let Inst{9-5}   = Rn;
9748   let Inst{4-0}   = Rd;
9749 }
9750
9751 multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
9752                                           string asm, SDPatternOperator OpNode>{
9753   let Predicates = [HasV8_3a, HasNEON, HasFullFP16] in {
9754   def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
9755               asm, ".4h",
9756               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
9757                                               (v4f16 V64:$Rn),
9758                                               (v4f16 V64:$Rm),
9759                                               (rottype i32:$rot)))]>;
9760
9761   def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
9762               asm, ".8h",
9763               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
9764                                                (v8f16 V128:$Rn),
9765                                                (v8f16 V128:$Rm),
9766                                                (rottype i32:$rot)))]>;
9767   }
9768
9769   let Predicates = [HasV8_3a, HasNEON] in {
9770   def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
9771               asm, ".2s",
9772               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
9773                                               (v2f32 V64:$Rn),
9774                                               (v2f32 V64:$Rm),
9775                                               (rottype i32:$rot)))]>;
9776
9777   def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
9778               asm, ".4s",
9779               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
9780                                                (v4f32 V128:$Rn),
9781                                                (v4f32 V128:$Rm),
9782                                                (rottype i32:$rot)))]>;
9783
9784   def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
9785               asm, ".2d",
9786               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
9787                                                (v2f64 V128:$Rn),
9788                                                (v2f64 V128:$Rm),
9789                                                (rottype i32:$rot)))]>;
9790   }
9791 }
9792
9793 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9794 class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
9795                                          bits<3> opcode,
9796                                          RegisterOperand regtype,
9797                                          Operand rottype, string asm,
9798                                          string kind, list<dag> pattern>
9799   : I<(outs regtype:$dst),
9800       (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
9801       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
9802       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
9803     Sched<[WriteV]> {
9804   bits<5> Rd;
9805   bits<5> Rn;
9806   bits<5> Rm;
9807   bits<2> rot;
9808   let Inst{31}    = 0;
9809   let Inst{30}    = Q;
9810   let Inst{29}    = U;
9811   let Inst{28-24} = 0b01110;
9812   let Inst{23-22} = size;
9813   let Inst{21}    = 0;
9814   let Inst{20-16} = Rm;
9815   let Inst{15-13} = opcode;
9816   let Inst{12-11} = rot;
9817   let Inst{10}    = 1;
9818   let Inst{9-5}   = Rn;
9819   let Inst{4-0}   = Rd;
9820 }
9821
9822 multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
9823                                              Operand rottype, string asm,
9824                                              SDPatternOperator OpNode> {
9825   let Predicates = [HasV8_3a, HasNEON, HasFullFP16] in {
9826   def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
9827               rottype, asm, ".4h",
9828               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
9829                                               (v4f16 V64:$Rn),
9830                                               (v4f16 V64:$Rm),
9831                                               (rottype i32:$rot)))]>;
9832
9833   def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
9834               rottype, asm, ".8h",
9835               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
9836                                                (v8f16 V128:$Rn),
9837                                                (v8f16 V128:$Rm),
9838                                                (rottype i32:$rot)))]>;
9839   }
9840
9841   let Predicates = [HasV8_3a, HasNEON] in {
9842   def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
9843               rottype, asm, ".2s",
9844               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
9845                                               (v2f32 V64:$Rn),
9846                                               (v2f32 V64:$Rm),
9847                                               (rottype i32:$rot)))]>;
9848
9849   def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
9850               rottype, asm, ".4s",
9851               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
9852                                                (v4f32 V128:$Rn),
9853                                                (v4f32 V128:$Rm),
9854                                                (rottype i32:$rot)))]>;
9855
9856   def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
9857               rottype, asm, ".2d",
9858               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
9859                                                (v2f64 V128:$Rn),
9860                                                (v2f64 V128:$Rm),
9861                                                (rottype i32:$rot)))]>;
9862   }
9863 }
9864
9865 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9866 class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
9867                                  bit opc1, bit opc2, RegisterOperand dst_reg,
9868                                  RegisterOperand lhs_reg,
9869                                  RegisterOperand rhs_reg, Operand vec_idx,
9870                                  Operand rottype, string asm, string apple_kind,
9871                                  string dst_kind, string lhs_kind,
9872                                  string rhs_kind, list<dag> pattern>
9873   : I<(outs dst_reg:$dst),
9874       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
9875       asm,
9876       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
9877       "$idx, $rot" # "|" # apple_kind #
9878       "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
9879     Sched<[WriteV]> {
9880   bits<5> Rd;
9881   bits<5> Rn;
9882   bits<5> Rm;
9883   bits<2> rot;
9884
9885   let Inst{31}    = 0;
9886   let Inst{30}    = Q;
9887   let Inst{29}    = U;
9888   let Inst{28}    = Scalar;
9889   let Inst{27-24} = 0b1111;
9890   let Inst{23-22} = size;
9891   // Bit 21 must be set by the derived class.
9892   let Inst{20-16} = Rm;
9893   let Inst{15}    = opc1;
9894   let Inst{14-13} = rot;
9895   let Inst{12}    = opc2;
9896   // Bit 11 must be set by the derived class.
9897   let Inst{10}    = 0;
9898   let Inst{9-5}   = Rn;
9899   let Inst{4-0}   = Rd;
9900 }
9901
9902 // The complex instructions index by pairs of elements, so the VectorIndexes
9903 // don't match the lane types, and the index bits are different to the other
9904 // classes.
9905 multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
9906                                      string asm, SDPatternOperator OpNode> {
9907   let Predicates = [HasV8_3a,HasNEON,HasFullFP16] in {
9908   def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
9909                       V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
9910                       ".4h", ".h", []> {
9911     bits<1> idx;
9912     let Inst{11} = 0;
9913     let Inst{21} = idx{0};
9914   }
9915
9916   def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
9917                       V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
9918                       ".8h", ".8h", ".h", []> {
9919     bits<2> idx;
9920     let Inst{11} = idx{1};
9921     let Inst{21} = idx{0};
9922   }
9923   } // Predicates = [HasV8_3a,HasNEON,HasFullFP16]
9924
9925   let Predicates = [HasV8_3a,HasNEON] in {
9926   def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
9927                       V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
9928                       ".4s", ".4s", ".s", []> {
9929     bits<1> idx;
9930     let Inst{11} = idx{0};
9931     let Inst{21} = 0;
9932   }
9933   } // Predicates = [HasV8_3a,HasNEON]
9934 }
9935
9936 //----------------------------------------------------------------------------
9937 // Crypto extensions
9938 //----------------------------------------------------------------------------
9939
9940 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9941 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
9942               list<dag> pat>
9943   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
9944     Sched<[WriteV]>{
9945   bits<5> Rd;
9946   bits<5> Rn;
9947   let Inst{31-16} = 0b0100111000101000;
9948   let Inst{15-12} = opc;
9949   let Inst{11-10} = 0b10;
9950   let Inst{9-5}   = Rn;
9951   let Inst{4-0}   = Rd;
9952 }
9953
9954 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
9955   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
9956             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
9957
9958 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
9959   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
9960             "$Rd = $dst",
9961             [(set (v16i8 V128:$dst),
9962                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
9963
9964 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9965 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
9966                      dag oops, dag iops, list<dag> pat>
9967   : I<oops, iops, asm,
9968       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
9969       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
9970     Sched<[WriteV]>{
9971   bits<5> Rd;
9972   bits<5> Rn;
9973   bits<5> Rm;
9974   let Inst{31-21} = 0b01011110000;
9975   let Inst{20-16} = Rm;
9976   let Inst{15}    = 0;
9977   let Inst{14-12} = opc;
9978   let Inst{11-10} = 0b00;
9979   let Inst{9-5}   = Rn;
9980   let Inst{4-0}   = Rd;
9981 }
9982
9983 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
9984   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9985                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
9986                    [(set (v4i32 FPR128:$dst),
9987                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
9988                                  (v4i32 V128:$Rm)))]>;
9989
9990 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
9991   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
9992                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
9993                    [(set (v4i32 V128:$dst),
9994                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9995                                  (v4i32 V128:$Rm)))]>;
9996
9997 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
9998   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9999                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10000                    [(set (v4i32 FPR128:$dst),
10001                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10002                                  (v4i32 V128:$Rm)))]>;
10003
10004 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10005 class SHA2OpInst<bits<4> opc, string asm, string kind,
10006                  string cstr, dag oops, dag iops,
10007                  list<dag> pat>
10008   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10009                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10010     Sched<[WriteV]>{
10011   bits<5> Rd;
10012   bits<5> Rn;
10013   let Inst{31-16} = 0b0101111000101000;
10014   let Inst{15-12} = opc;
10015   let Inst{11-10} = 0b10;
10016   let Inst{9-5}   = Rn;
10017   let Inst{4-0}   = Rd;
10018 }
10019
10020 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10021   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10022                (ins V128:$Rd, V128:$Rn),
10023                [(set (v4i32 V128:$dst),
10024                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10025
10026 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10027   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10028                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10029
10030 // Armv8.2-A Crypto extensions
10031 class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10032                     list<dag> pattern>
10033   : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10034   bits<5> Vd;
10035   bits<5> Vn;
10036   let Inst{31-25} = 0b1100111;
10037   let Inst{9-5}   = Vn;
10038   let Inst{4-0}   = Vd;
10039 }
10040
10041 class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10042   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10043                   "$Vm = $Vd", []> {
10044   let Inst{31-25} = 0b1100111;
10045   let Inst{24-21} = 0b0110;
10046   let Inst{20-15} = 0b000001;
10047   let Inst{14}    = op0;
10048   let Inst{13-12} = 0b00;
10049   let Inst{11-10} = op1;
10050 }
10051 class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10052   : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d}">;
10053 class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10054   : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s}">;
10055
10056 class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10057                 string asmops, string cst>
10058   : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10059   bits<5> Vm;
10060   let Inst{24-21} = 0b0011;
10061   let Inst{20-16} = Vm;
10062   let Inst{15}    = 0b1;
10063   let Inst{14}    = op0;
10064   let Inst{13-12} = 0b00;
10065   let Inst{11-10} = op1;
10066 }
10067 class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10068   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10069               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "">;
10070 class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10071   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10072               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "$Vd = $Vdst">;
10073 class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10074   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10075               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "">;
10076 class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10077   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10078               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "$Vd = $Vdst">;
10079 class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10080   : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10081               asm, "{\t$Vd, $Vn, $Vm.2d}", "$Vd = $Vdst">;
10082
10083 class CryptoRRRR<bits<2>op0, string asm, string asmops>
10084   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10085                   asmops, "", []> {
10086   bits<5> Vm;
10087   bits<5> Va;
10088   let Inst{24-23} = 0b00;
10089   let Inst{22-21} = op0;
10090   let Inst{20-16} = Vm;
10091   let Inst{15}    = 0b0;
10092   let Inst{14-10} = Va;
10093 }
10094 class CryptoRRRR_16B<bits<2>op0, string asm>
10095  : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b}"> {
10096 }
10097 class CryptoRRRR_4S<bits<2>op0, string asm>
10098  : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s}"> {
10099 }
10100
10101 class CryptoRRRi6<string asm>
10102   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10103                   "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm}", "", []> {
10104   bits<6> imm;
10105   bits<5> Vm;
10106   let Inst{24-21} = 0b0100;
10107   let Inst{20-16} = Vm;
10108   let Inst{15-10} = imm;
10109   let Inst{9-5}   = Vn;
10110   let Inst{4-0}   = Vd;
10111 }
10112
10113 class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10114   : BaseCryptoV82<(outs V128:$Vdst),
10115                   (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10116                   asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm}", "$Vd = $Vdst", []> {
10117   bits<2> imm;
10118   bits<5> Vm;
10119   let Inst{24-21} = 0b0010;
10120   let Inst{20-16} = Vm;
10121   let Inst{15}    = 0b1;
10122   let Inst{14}    = op0;
10123   let Inst{13-12} = imm;
10124   let Inst{11-10} = op1;
10125 }
10126
10127 //----------------------------------------------------------------------------
10128 // v8.1 atomic instructions extension:
10129 // * CAS
10130 // * CASP
10131 // * SWP
10132 // * LDOPregister<OP>, and aliases STOPregister<OP>
10133
10134 // Instruction encodings:
10135 //
10136 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
10137 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
10138 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
10139 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
10140 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
10141 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
10142
10143 // Instruction syntax:
10144 //
10145 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10146 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10147 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10148 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
10149 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10150 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
10151 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10152 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
10153 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
10154 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
10155
10156 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10157 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
10158                       string cstr, list<dag> pattern>
10159       : I<oops, iops, asm, operands, cstr, pattern> {
10160   bits<2> Sz;
10161   bit NP;
10162   bit Acq;
10163   bit Rel;
10164   bits<5> Rs;
10165   bits<5> Rn;
10166   bits<5> Rt;
10167   let Inst{31-30} = Sz;
10168   let Inst{29-24} = 0b001000;
10169   let Inst{23} = NP;
10170   let Inst{22} = Acq;
10171   let Inst{21} = 0b1;
10172   let Inst{20-16} = Rs;
10173   let Inst{15} = Rel;
10174   let Inst{14-10} = 0b11111;
10175   let Inst{9-5} = Rn;
10176   let Inst{4-0} = Rt;
10177   let Predicates = [HasLSE];
10178 }
10179
10180 class BaseCAS<string order, string size, RegisterClass RC>
10181       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10182                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
10183                         "$out = $Rs",[]>,
10184         Sched<[WriteAtomic]> {
10185   let NP = 1;
10186 }
10187
10188 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
10189   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
10190   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
10191   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
10192   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
10193 }
10194
10195 class BaseCASP<string order, string size, RegisterOperand RC>
10196       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10197                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
10198                         "$out = $Rs",[]>,
10199         Sched<[WriteAtomic]> {
10200   let NP = 0;
10201 }
10202
10203 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
10204   let Sz = 0b00, Acq = Acq, Rel = Rel in
10205     def W : BaseCASP<order, "", WSeqPairClassOperand>;
10206   let Sz = 0b01, Acq = Acq, Rel = Rel in
10207     def X : BaseCASP<order, "", XSeqPairClassOperand>;
10208 }
10209
10210 let Predicates = [HasLSE] in
10211 class BaseSWP<string order, string size, RegisterClass RC>
10212       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
10213           "\t$Rs, $Rt, [$Rn]","",[]>,
10214         Sched<[WriteAtomic]> {
10215   bits<2> Sz;
10216   bit Acq;
10217   bit Rel;
10218   bits<5> Rs;
10219   bits<3> opc = 0b000;
10220   bits<5> Rn;
10221   bits<5> Rt;
10222   let Inst{31-30} = Sz;
10223   let Inst{29-24} = 0b111000;
10224   let Inst{23} = Acq;
10225   let Inst{22} = Rel;
10226   let Inst{21} = 0b1;
10227   let Inst{20-16} = Rs;
10228   let Inst{15} = 0b1;
10229   let Inst{14-12} = opc;
10230   let Inst{11-10} = 0b00;
10231   let Inst{9-5} = Rn;
10232   let Inst{4-0} = Rt;
10233   let Predicates = [HasLSE];
10234 }
10235
10236 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
10237   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
10238   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
10239   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
10240   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
10241 }
10242
10243 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10244 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
10245       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
10246           "\t$Rs, $Rt, [$Rn]","",[]>,
10247         Sched<[WriteAtomic]> {
10248   bits<2> Sz;
10249   bit Acq;
10250   bit Rel;
10251   bits<5> Rs;
10252   bits<3> opc;
10253   bits<5> Rn;
10254   bits<5> Rt;
10255   let Inst{31-30} = Sz;
10256   let Inst{29-24} = 0b111000;
10257   let Inst{23} = Acq;
10258   let Inst{22} = Rel;
10259   let Inst{21} = 0b1;
10260   let Inst{20-16} = Rs;
10261   let Inst{15} = 0b0;
10262   let Inst{14-12} = opc;
10263   let Inst{11-10} = 0b00;
10264   let Inst{9-5} = Rn;
10265   let Inst{4-0} = Rt;
10266   let Predicates = [HasLSE];
10267 }
10268
10269 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
10270                         string order> {
10271   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
10272     def B : BaseLDOPregister<op, order, "b", GPR32>;
10273   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
10274     def H : BaseLDOPregister<op, order, "h", GPR32>;
10275   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
10276     def W : BaseLDOPregister<op, order, "", GPR32>;
10277   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
10278     def X : BaseLDOPregister<op, order, "", GPR64>;
10279 }
10280
10281 // Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
10282 // complex DAG for DstRHS.
10283 let Predicates = [HasLSE] in
10284 multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
10285                                          string size, dag SrcRHS, dag DstRHS> {
10286   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
10287             (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
10288   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
10289             (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
10290   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
10291             (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
10292   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
10293             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10294   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
10295             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10296 }
10297
10298 multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
10299                                      string size, dag RHS> {
10300   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
10301 }
10302
10303 multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
10304                                          string size, dag LHS, dag RHS> {
10305   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
10306 }
10307
10308 multiclass LDOPregister_patterns<string inst, string op> {
10309   defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
10310   defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
10311   defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
10312   defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
10313 }
10314
10315 multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
10316   defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
10317                         (i64 GPR64:$Rm),
10318                         (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
10319   defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
10320                         (i32 GPR32:$Rm),
10321                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10322   defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
10323                         (i32 GPR32:$Rm),
10324                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10325   defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
10326                         (i32 GPR32:$Rm),
10327                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10328 }
10329
10330 let Predicates = [HasLSE] in
10331 multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
10332                                         string size, dag OLD, dag NEW> {
10333   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
10334             (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
10335   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
10336             (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10337   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
10338             (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10339   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
10340             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10341   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
10342             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10343 }
10344
10345 multiclass CASregister_patterns_ord<string inst, string suffix, string op,
10346                                     string size, dag OLD, dag NEW> {
10347   defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
10348 }
10349
10350 multiclass CASregister_patterns<string inst, string op> {
10351   defm : CASregister_patterns_ord<inst, "X", op, "64",
10352                         (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
10353   defm : CASregister_patterns_ord<inst, "W", op, "32",
10354                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10355   defm : CASregister_patterns_ord<inst, "H", op, "16",
10356                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10357   defm : CASregister_patterns_ord<inst, "B", op, "8",
10358                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10359 }
10360
10361 let Predicates = [HasLSE] in
10362 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
10363                         Instruction inst> :
10364       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
10365
10366 multiclass STOPregister<string asm, string instr> {
10367   def : BaseSTOPregister<asm # "lb", GPR32, WZR,
10368                     !cast<Instruction>(instr # "LB")>;
10369   def : BaseSTOPregister<asm # "lh", GPR32, WZR,
10370                     !cast<Instruction>(instr # "LH")>;
10371   def : BaseSTOPregister<asm # "l",  GPR32, WZR,
10372                     !cast<Instruction>(instr # "LW")>;
10373   def : BaseSTOPregister<asm # "l",  GPR64, XZR,
10374                     !cast<Instruction>(instr # "LX")>;
10375   def : BaseSTOPregister<asm # "b",  GPR32, WZR,
10376                     !cast<Instruction>(instr # "B")>;
10377   def : BaseSTOPregister<asm # "h",  GPR32, WZR,
10378                     !cast<Instruction>(instr # "H")>;
10379   def : BaseSTOPregister<asm,        GPR32, WZR,
10380                     !cast<Instruction>(instr # "W")>;
10381   def : BaseSTOPregister<asm,        GPR64, XZR,
10382                     !cast<Instruction>(instr # "X")>;
10383 }
10384
10385 //----------------------------------------------------------------------------
10386 // Allow the size specifier tokens to be upper case, not just lower.
10387 def : TokenAlias<".4B", ".4b">;  // Add dot product
10388 def : TokenAlias<".8B", ".8b">;
10389 def : TokenAlias<".4H", ".4h">;
10390 def : TokenAlias<".2S", ".2s">;
10391 def : TokenAlias<".1D", ".1d">;
10392 def : TokenAlias<".16B", ".16b">;
10393 def : TokenAlias<".8H", ".8h">;
10394 def : TokenAlias<".4S", ".4s">;
10395 def : TokenAlias<".2D", ".2d">;
10396 def : TokenAlias<".1Q", ".1q">;
10397 def : TokenAlias<".2H", ".2h">;
10398 def : TokenAlias<".B", ".b">;
10399 def : TokenAlias<".H", ".h">;
10400 def : TokenAlias<".S", ".s">;
10401 def : TokenAlias<".D", ".d">;
10402 def : TokenAlias<".Q", ".q">;