]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/lib/Target/AArch64/AArch64InstrFormats.td
Merge lldb trunk r338150, and resolve conflicts.
[FreeBSD/FreeBSD.git] / contrib / llvm / lib / Target / AArch64 / AArch64InstrFormats.td
1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 //===----------------------------------------------------------------------===//
11 //  Describe AArch64 instructions format here
12 //
13
14 // Format specifies the encoding used by the instruction.  This is part of the
15 // ad-hoc solution used to emit machine instruction encodings by our machine
16 // code emitter.
17 class Format<bits<2> val> {
18   bits<2> Value = val;
19 }
20
21 def PseudoFrm   : Format<0>;
22 def NormalFrm   : Format<1>; // Do we need any others?
23
24 // AArch64 Instruction Format
25 class AArch64Inst<Format f, string cstr> : Instruction {
26   field bits<32> Inst; // Instruction encoding.
27   // Mask of bits that cause an encoding to be UNPREDICTABLE.
28   // If a bit is set, then if the corresponding bit in the
29   // target encoding differs from its value in the "Inst" field,
30   // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
31   field bits<32> Unpredictable = 0;
32   // SoftFail is the generic name for this field, but we alias it so
33   // as to make it more obvious what it means in ARM-land.
34   field bits<32> SoftFail = Unpredictable;
35   let Namespace   = "AArch64";
36   Format F        = f;
37   bits<2> Form    = F.Value;
38   let Pattern     = [];
39   let Constraints = cstr;
40 }
41
42 class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
43   : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
44
45 // Pseudo instructions (don't have encoding information)
46 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
47     : AArch64Inst<PseudoFrm, cstr> {
48   dag OutOperandList = oops;
49   dag InOperandList  = iops;
50   let Pattern        = pattern;
51   let isCodeGenOnly  = 1;
52 }
53
54 // Real instructions (have encoding information)
55 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
56   let Pattern = pattern;
57   let Size = 4;
58 }
59
60 // Normal instructions
61 class I<dag oops, dag iops, string asm, string operands, string cstr,
62         list<dag> pattern>
63     : EncodedI<cstr, pattern> {
64   dag OutOperandList = oops;
65   dag InOperandList  = iops;
66   let AsmString      = !strconcat(asm, operands);
67 }
68
69 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
70 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
71 class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
72
73 // Helper fragment for an extract of the high portion of a 128-bit vector.
74 def extract_high_v16i8 :
75    UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
76 def extract_high_v8i16 :
77    UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
78 def extract_high_v4i32 :
79    UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
80 def extract_high_v2i64 :
81    UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
82
83 //===----------------------------------------------------------------------===//
84 // Asm Operand Classes.
85 //
86
87 // Shifter operand for arithmetic shifted encodings.
88 def ShifterOperand : AsmOperandClass {
89   let Name = "Shifter";
90 }
91
92 // Shifter operand for mov immediate encodings.
93 def MovImm32ShifterOperand : AsmOperandClass {
94   let SuperClasses = [ShifterOperand];
95   let Name = "MovImm32Shifter";
96   let RenderMethod = "addShifterOperands";
97   let DiagnosticType = "InvalidMovImm32Shift";
98 }
99 def MovImm64ShifterOperand : AsmOperandClass {
100   let SuperClasses = [ShifterOperand];
101   let Name = "MovImm64Shifter";
102   let RenderMethod = "addShifterOperands";
103   let DiagnosticType = "InvalidMovImm64Shift";
104 }
105
106 // Shifter operand for arithmetic register shifted encodings.
107 class ArithmeticShifterOperand<int width> : AsmOperandClass {
108   let SuperClasses = [ShifterOperand];
109   let Name = "ArithmeticShifter" # width;
110   let PredicateMethod = "isArithmeticShifter<" # width # ">";
111   let RenderMethod = "addShifterOperands";
112   let DiagnosticType = "AddSubRegShift" # width;
113 }
114
115 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
116 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
117
118 // Shifter operand for logical register shifted encodings.
119 class LogicalShifterOperand<int width> : AsmOperandClass {
120   let SuperClasses = [ShifterOperand];
121   let Name = "LogicalShifter" # width;
122   let PredicateMethod = "isLogicalShifter<" # width # ">";
123   let RenderMethod = "addShifterOperands";
124   let DiagnosticType = "AddSubRegShift" # width;
125 }
126
127 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
128 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
129
130 // Shifter operand for logical vector 128/64-bit shifted encodings.
131 def LogicalVecShifterOperand : AsmOperandClass {
132   let SuperClasses = [ShifterOperand];
133   let Name = "LogicalVecShifter";
134   let RenderMethod = "addShifterOperands";
135 }
136 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
137   let SuperClasses = [LogicalVecShifterOperand];
138   let Name = "LogicalVecHalfWordShifter";
139   let RenderMethod = "addShifterOperands";
140 }
141
142 // The "MSL" shifter on the vector MOVI instruction.
143 def MoveVecShifterOperand : AsmOperandClass {
144   let SuperClasses = [ShifterOperand];
145   let Name = "MoveVecShifter";
146   let RenderMethod = "addShifterOperands";
147 }
148
149 // Extend operand for arithmetic encodings.
150 def ExtendOperand : AsmOperandClass {
151   let Name = "Extend";
152   let DiagnosticType = "AddSubRegExtendLarge";
153 }
154 def ExtendOperand64 : AsmOperandClass {
155   let SuperClasses = [ExtendOperand];
156   let Name = "Extend64";
157   let DiagnosticType = "AddSubRegExtendSmall";
158 }
159 // 'extend' that's a lsl of a 64-bit register.
160 def ExtendOperandLSL64 : AsmOperandClass {
161   let SuperClasses = [ExtendOperand];
162   let Name = "ExtendLSL64";
163   let RenderMethod = "addExtend64Operands";
164   let DiagnosticType = "AddSubRegExtendLarge";
165 }
166
167 // 8-bit floating-point immediate encodings.
168 def FPImmOperand : AsmOperandClass {
169   let Name = "FPImm";
170   let ParserMethod = "tryParseFPImm<true>";
171   let DiagnosticType = "InvalidFPImm";
172 }
173
174 def CondCode : AsmOperandClass {
175   let Name = "CondCode";
176   let DiagnosticType = "InvalidCondCode";
177 }
178
179 // A 32-bit register pasrsed as 64-bit
180 def GPR32as64Operand : AsmOperandClass {
181   let Name = "GPR32as64";
182   let ParserMethod =
183       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
184 }
185 def GPR32as64 : RegisterOperand<GPR32> {
186   let ParserMatchClass = GPR32as64Operand;
187 }
188
189 // A 64-bit register pasrsed as 32-bit
190 def GPR64as32Operand : AsmOperandClass {
191   let Name = "GPR64as32";
192   let ParserMethod =
193       "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
194 }
195 def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
196   let ParserMatchClass = GPR64as32Operand;
197 }
198
199 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
200 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
201 // are encoded as the eight bit value 'abcdefgh'.
202 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
203
204 class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
205   let Name = "UImm" # Width # "s" # Scale;
206   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
207   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
208   let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
209 }
210
211 class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
212   let Name = "SImm" # Width # "s" # Scale;
213   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
214   let RenderMethod = "addImmScaledOperands<" # Scale # ">";
215   let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
216 }
217
218 //===----------------------------------------------------------------------===//
219 // Operand Definitions.
220 //
221
222 // ADR[P] instruction labels.
223 def AdrpOperand : AsmOperandClass {
224   let Name = "AdrpLabel";
225   let ParserMethod = "tryParseAdrpLabel";
226   let DiagnosticType = "InvalidLabel";
227 }
228 def adrplabel : Operand<i64> {
229   let EncoderMethod = "getAdrLabelOpValue";
230   let PrintMethod = "printAdrpLabel";
231   let ParserMatchClass = AdrpOperand;
232 }
233
234 def AdrOperand : AsmOperandClass {
235   let Name = "AdrLabel";
236   let ParserMethod = "tryParseAdrLabel";
237   let DiagnosticType = "InvalidLabel";
238 }
239 def adrlabel : Operand<i64> {
240   let EncoderMethod = "getAdrLabelOpValue";
241   let ParserMatchClass = AdrOperand;
242 }
243
244 class SImmOperand<int width> : AsmOperandClass {
245   let Name = "SImm" # width;
246   let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
247   let RenderMethod = "addImmOperands";
248   let PredicateMethod = "isSImm<" # width # ">";
249 }
250
251 // Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
252 def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
253 def simm10Scaled : Operand<i64> {
254   let ParserMatchClass = SImm10s8Operand;
255   let DecoderMethod = "DecodeSImm<10>";
256   let PrintMethod = "printImmScale<8>";
257 }
258
259 // uimm6 predicate - True if the immediate is in the range [0, 63].
260 def UImm6Operand : AsmOperandClass {
261   let Name = "UImm6";
262   let DiagnosticType = "InvalidImm0_63";
263 }
264
265 def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
266   let ParserMatchClass = UImm6Operand;
267 }
268
269 def SImm9Operand : SImmOperand<9>;
270 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
271   let ParserMatchClass = SImm9Operand;
272   let DecoderMethod = "DecodeSImm<9>";
273 }
274
275 def SImm8Operand : SImmOperand<8>;
276 def simm8 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 127; }]> {
277   let ParserMatchClass = SImm8Operand;
278   let DecoderMethod = "DecodeSImm<8>";
279 }
280
281 def SImm6Operand : SImmOperand<6>;
282 def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
283   let ParserMatchClass = SImm6Operand;
284   let DecoderMethod = "DecodeSImm<6>";
285 }
286
287 def SImm5Operand : SImmOperand<5>;
288 def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
289   let ParserMatchClass = SImm5Operand;
290   let DecoderMethod = "DecodeSImm<5>";
291 }
292
293 def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
294   let ParserMatchClass = SImm5Operand;
295   let DecoderMethod = "DecodeSImm<5>";
296 }
297
298 // simm7sN predicate - True if the immediate is a multiple of N in the range
299 // [-64 * N, 63 * N].
300
301 def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
302 def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
303 def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
304
305 def simm7s4 : Operand<i32> {
306   let ParserMatchClass = SImm7s4Operand;
307   let PrintMethod = "printImmScale<4>";
308 }
309
310 def simm7s8 : Operand<i32> {
311   let ParserMatchClass = SImm7s8Operand;
312   let PrintMethod = "printImmScale<8>";
313 }
314
315 def simm7s16 : Operand<i32> {
316   let ParserMatchClass = SImm7s16Operand;
317   let PrintMethod = "printImmScale<16>";
318 }
319
320 def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
321 def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
322 def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
323 def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
324 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
325
326 // uimm5sN predicate - True if the immediate is a multiple of N in the range
327 // [0 * N, 32 * N].
328 def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
329 def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
330 def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
331
332 def uimm5s2 : Operand<i64>, ImmLeaf<i64,
333                 [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }]> {
334   let ParserMatchClass = UImm5s2Operand;
335   let PrintMethod = "printImmScale<2>";
336 }
337 def uimm5s4 : Operand<i64>, ImmLeaf<i64,
338                 [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }]> {
339   let ParserMatchClass = UImm5s4Operand;
340   let PrintMethod = "printImmScale<4>";
341 }
342 def uimm5s8 : Operand<i64>, ImmLeaf<i64,
343                 [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }]> {
344   let ParserMatchClass = UImm5s8Operand;
345   let PrintMethod = "printImmScale<8>";
346 }
347
348 // uimm6sN predicate - True if the immediate is a multiple of N in the range
349 // [0 * N, 64 * N].
350 def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
351 def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
352 def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
353 def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
354
355 def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
356   let ParserMatchClass = UImm6s1Operand;
357 }
358 def uimm6s2 : Operand<i64>, ImmLeaf<i64,
359 [{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
360   let PrintMethod = "printImmScale<2>";
361   let ParserMatchClass = UImm6s2Operand;
362 }
363 def uimm6s4 : Operand<i64>, ImmLeaf<i64,
364 [{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
365   let PrintMethod = "printImmScale<4>";
366   let ParserMatchClass = UImm6s4Operand;
367 }
368 def uimm6s8 : Operand<i64>, ImmLeaf<i64,
369 [{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
370   let PrintMethod = "printImmScale<8>";
371   let ParserMatchClass = UImm6s8Operand;
372 }
373
374 // simm6sN predicate - True if the immediate is a multiple of N in the range
375 // [-32 * N, 31 * N].
376 def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
377 def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
378   let ParserMatchClass = SImm6s1Operand;
379   let DecoderMethod = "DecodeSImm<6>";
380 }
381
382 // simm4sN predicate - True if the immediate is a multiple of N in the range
383 // [ -8* N, 7 * N].
384 def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
385 def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
386 def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
387 def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
388 def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
389
390 def simm4s1 : Operand<i64>, ImmLeaf<i64,
391 [{ return Imm >=-8  && Imm <= 7; }]> {
392   let ParserMatchClass = SImm4s1Operand;
393   let DecoderMethod = "DecodeSImm<4>";
394 }
395
396 def simm4s2 : Operand<i64>, ImmLeaf<i64,
397 [{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }]> {
398   let PrintMethod = "printImmScale<2>";
399   let ParserMatchClass = SImm4s2Operand;
400   let DecoderMethod = "DecodeSImm<4>";
401 }
402
403 def simm4s3 : Operand<i64>, ImmLeaf<i64,
404 [{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }]> {
405   let PrintMethod = "printImmScale<3>";
406   let ParserMatchClass = SImm4s3Operand;
407   let DecoderMethod = "DecodeSImm<4>";
408 }
409
410 def simm4s4 : Operand<i64>, ImmLeaf<i64,
411 [{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }]> {
412   let PrintMethod = "printImmScale<4>";
413   let ParserMatchClass = SImm4s4Operand;
414   let DecoderMethod = "DecodeSImm<4>";
415 }
416 def simm4s16 : Operand<i64>, ImmLeaf<i64,
417 [{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }]> {
418   let PrintMethod = "printImmScale<16>";
419   let ParserMatchClass = SImm4s16Operand;
420   let DecoderMethod = "DecodeSImm<4>";
421 }
422
423 class AsmImmRange<int Low, int High> : AsmOperandClass {
424   let Name = "Imm" # Low # "_" # High;
425   let DiagnosticType = "InvalidImm" # Low # "_" # High;
426   let RenderMethod = "addImmOperands";
427   let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
428 }
429
430 def Imm1_8Operand : AsmImmRange<1, 8>;
431 def Imm1_16Operand : AsmImmRange<1, 16>;
432 def Imm1_32Operand : AsmImmRange<1, 32>;
433 def Imm1_64Operand : AsmImmRange<1, 64>;
434
435 class BranchTarget<int N> : AsmOperandClass {
436   let Name = "BranchTarget" # N;
437   let DiagnosticType = "InvalidLabel";
438   let PredicateMethod = "isBranchTarget<" # N # ">";
439 }
440
441 class PCRelLabel<int N> : BranchTarget<N> {
442   let Name = "PCRelLabel" # N;
443 }
444
445 def BranchTarget14Operand : BranchTarget<14>;
446 def BranchTarget26Operand : BranchTarget<26>;
447 def PCRelLabel19Operand   : PCRelLabel<19>;
448
449 def MovZSymbolG3AsmOperand : AsmOperandClass {
450   let Name = "MovZSymbolG3";
451   let RenderMethod = "addImmOperands";
452 }
453
454 def movz_symbol_g3 : Operand<i32> {
455   let ParserMatchClass = MovZSymbolG3AsmOperand;
456 }
457
458 def MovZSymbolG2AsmOperand : AsmOperandClass {
459   let Name = "MovZSymbolG2";
460   let RenderMethod = "addImmOperands";
461 }
462
463 def movz_symbol_g2 : Operand<i32> {
464   let ParserMatchClass = MovZSymbolG2AsmOperand;
465 }
466
467 def MovZSymbolG1AsmOperand : AsmOperandClass {
468   let Name = "MovZSymbolG1";
469   let RenderMethod = "addImmOperands";
470 }
471
472 def movz_symbol_g1 : Operand<i32> {
473   let ParserMatchClass = MovZSymbolG1AsmOperand;
474 }
475
476 def MovZSymbolG0AsmOperand : AsmOperandClass {
477   let Name = "MovZSymbolG0";
478   let RenderMethod = "addImmOperands";
479 }
480
481 def movz_symbol_g0 : Operand<i32> {
482   let ParserMatchClass = MovZSymbolG0AsmOperand;
483 }
484
485 def MovKSymbolG3AsmOperand : AsmOperandClass {
486   let Name = "MovKSymbolG3";
487   let RenderMethod = "addImmOperands";
488 }
489
490 def movk_symbol_g3 : Operand<i32> {
491   let ParserMatchClass = MovKSymbolG3AsmOperand;
492 }
493
494 def MovKSymbolG2AsmOperand : AsmOperandClass {
495   let Name = "MovKSymbolG2";
496   let RenderMethod = "addImmOperands";
497 }
498
499 def movk_symbol_g2 : Operand<i32> {
500   let ParserMatchClass = MovKSymbolG2AsmOperand;
501 }
502
503 def MovKSymbolG1AsmOperand : AsmOperandClass {
504   let Name = "MovKSymbolG1";
505   let RenderMethod = "addImmOperands";
506 }
507
508 def movk_symbol_g1 : Operand<i32> {
509   let ParserMatchClass = MovKSymbolG1AsmOperand;
510 }
511
512 def MovKSymbolG0AsmOperand : AsmOperandClass {
513   let Name = "MovKSymbolG0";
514   let RenderMethod = "addImmOperands";
515 }
516
517 def movk_symbol_g0 : Operand<i32> {
518   let ParserMatchClass = MovKSymbolG0AsmOperand;
519 }
520
521 class fixedpoint_i32<ValueType FloatVT>
522   : Operand<FloatVT>,
523     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
524   let EncoderMethod = "getFixedPointScaleOpValue";
525   let DecoderMethod = "DecodeFixedPointScaleImm32";
526   let ParserMatchClass = Imm1_32Operand;
527 }
528
529 class fixedpoint_i64<ValueType FloatVT>
530   : Operand<FloatVT>,
531     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
532   let EncoderMethod = "getFixedPointScaleOpValue";
533   let DecoderMethod = "DecodeFixedPointScaleImm64";
534   let ParserMatchClass = Imm1_64Operand;
535 }
536
537 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
538 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
539 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
540
541 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
542 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
543 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
544
545 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
546   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
547 }]> {
548   let EncoderMethod = "getVecShiftR8OpValue";
549   let DecoderMethod = "DecodeVecShiftR8Imm";
550   let ParserMatchClass = Imm1_8Operand;
551 }
552 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
553   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
554 }]> {
555   let EncoderMethod = "getVecShiftR16OpValue";
556   let DecoderMethod = "DecodeVecShiftR16Imm";
557   let ParserMatchClass = Imm1_16Operand;
558 }
559 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
560   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
561 }]> {
562   let EncoderMethod = "getVecShiftR16OpValue";
563   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
564   let ParserMatchClass = Imm1_8Operand;
565 }
566 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
567   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
568 }]> {
569   let EncoderMethod = "getVecShiftR32OpValue";
570   let DecoderMethod = "DecodeVecShiftR32Imm";
571   let ParserMatchClass = Imm1_32Operand;
572 }
573 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
574   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
575 }]> {
576   let EncoderMethod = "getVecShiftR32OpValue";
577   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
578   let ParserMatchClass = Imm1_16Operand;
579 }
580 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
581   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
582 }]> {
583   let EncoderMethod = "getVecShiftR64OpValue";
584   let DecoderMethod = "DecodeVecShiftR64Imm";
585   let ParserMatchClass = Imm1_64Operand;
586 }
587 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
588   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
589 }]> {
590   let EncoderMethod = "getVecShiftR64OpValue";
591   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
592   let ParserMatchClass = Imm1_32Operand;
593 }
594
595 def Imm0_1Operand : AsmImmRange<0, 1>;
596 def Imm0_7Operand : AsmImmRange<0, 7>;
597 def Imm0_15Operand : AsmImmRange<0, 15>;
598 def Imm0_31Operand : AsmImmRange<0, 31>;
599 def Imm0_63Operand : AsmImmRange<0, 63>;
600
601 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
602   return (((uint32_t)Imm) < 8);
603 }]> {
604   let EncoderMethod = "getVecShiftL8OpValue";
605   let DecoderMethod = "DecodeVecShiftL8Imm";
606   let ParserMatchClass = Imm0_7Operand;
607 }
608 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
609   return (((uint32_t)Imm) < 16);
610 }]> {
611   let EncoderMethod = "getVecShiftL16OpValue";
612   let DecoderMethod = "DecodeVecShiftL16Imm";
613   let ParserMatchClass = Imm0_15Operand;
614 }
615 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
616   return (((uint32_t)Imm) < 32);
617 }]> {
618   let EncoderMethod = "getVecShiftL32OpValue";
619   let DecoderMethod = "DecodeVecShiftL32Imm";
620   let ParserMatchClass = Imm0_31Operand;
621 }
622 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
623   return (((uint32_t)Imm) < 64);
624 }]> {
625   let EncoderMethod = "getVecShiftL64OpValue";
626   let DecoderMethod = "DecodeVecShiftL64Imm";
627   let ParserMatchClass = Imm0_63Operand;
628 }
629
630
631 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
632 // instructions for splatting repeating bit patterns across the immediate.
633 def logical_imm32_XFORM : SDNodeXForm<imm, [{
634   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
635   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
636 }]>;
637 def logical_imm64_XFORM : SDNodeXForm<imm, [{
638   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
639   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
640 }]>;
641
642 let DiagnosticType = "LogicalSecondSource" in {
643   def LogicalImm32Operand : AsmOperandClass {
644     let Name = "LogicalImm32";
645     let PredicateMethod = "isLogicalImm<int32_t>";
646     let RenderMethod = "addLogicalImmOperands<int32_t>";
647   }
648   def LogicalImm64Operand : AsmOperandClass {
649     let Name = "LogicalImm64";
650     let PredicateMethod = "isLogicalImm<int64_t>";
651     let RenderMethod = "addLogicalImmOperands<int64_t>";
652   }
653   def LogicalImm32NotOperand : AsmOperandClass {
654     let Name = "LogicalImm32Not";
655     let PredicateMethod = "isLogicalImm<int32_t>";
656     let RenderMethod = "addLogicalImmNotOperands<int32_t>";
657   }
658   def LogicalImm64NotOperand : AsmOperandClass {
659     let Name = "LogicalImm64Not";
660     let PredicateMethod = "isLogicalImm<int64_t>";
661     let RenderMethod = "addLogicalImmNotOperands<int64_t>";
662   }
663 }
664 def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
665   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
666 }], logical_imm32_XFORM> {
667   let PrintMethod = "printLogicalImm<int32_t>";
668   let ParserMatchClass = LogicalImm32Operand;
669 }
670 def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
671   return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
672 }], logical_imm64_XFORM> {
673   let PrintMethod = "printLogicalImm<int64_t>";
674   let ParserMatchClass = LogicalImm64Operand;
675 }
676 def logical_imm32_not : Operand<i32> {
677   let ParserMatchClass = LogicalImm32NotOperand;
678 }
679 def logical_imm64_not : Operand<i64> {
680   let ParserMatchClass = LogicalImm64NotOperand;
681 }
682
683 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
684 def Imm0_65535Operand : AsmImmRange<0, 65535>;
685 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
686   return ((uint32_t)Imm) < 65536;
687 }]> {
688   let ParserMatchClass = Imm0_65535Operand;
689   let PrintMethod = "printImmHex";
690 }
691
692 // imm0_255 predicate - True if the immediate is in the range [0,255].
693 def Imm0_255Operand : AsmImmRange<0,255>;
694
695 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
696   return ((uint32_t)Imm) < 256;
697 }]> {
698   let ParserMatchClass = Imm0_255Operand;
699   let PrintMethod = "printImm";
700 }
701
702 // imm0_127 predicate - True if the immediate is in the range [0,127]
703 def Imm0_127Operand : AsmImmRange<0, 127>;
704 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
705   return ((uint32_t)Imm) < 128;
706 }]> {
707   let ParserMatchClass = Imm0_127Operand;
708   let PrintMethod = "printImm";
709 }
710
711 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
712 // for all shift-amounts.
713
714 // imm0_63 predicate - True if the immediate is in the range [0,63]
715 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
716   return ((uint64_t)Imm) < 64;
717 }]> {
718   let ParserMatchClass = Imm0_63Operand;
719 }
720
721 // imm0_31 predicate - True if the immediate is in the range [0,31]
722 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
723   return ((uint64_t)Imm) < 32;
724 }]> {
725   let ParserMatchClass = Imm0_31Operand;
726 }
727
728 // True if the 32-bit immediate is in the range [0,31]
729 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
730   return ((uint64_t)Imm) < 32;
731 }]> {
732   let ParserMatchClass = Imm0_31Operand;
733 }
734
735 // imm0_1 predicate - True if the immediate is in the range [0,1]
736 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
737   return ((uint64_t)Imm) < 2;
738 }]> {
739   let ParserMatchClass = Imm0_1Operand;
740 }
741
742 // imm0_15 predicate - True if the immediate is in the range [0,15]
743 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
744   return ((uint64_t)Imm) < 16;
745 }]> {
746   let ParserMatchClass = Imm0_15Operand;
747 }
748
749 // imm0_7 predicate - True if the immediate is in the range [0,7]
750 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
751   return ((uint64_t)Imm) < 8;
752 }]> {
753   let ParserMatchClass = Imm0_7Operand;
754 }
755
756 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
757 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
758   return ((uint32_t)Imm) < 16;
759 }]> {
760   let ParserMatchClass = Imm0_15Operand;
761 }
762
763 // An arithmetic shifter operand:
764 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
765 //  {5-0} - imm6
766 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
767   let PrintMethod = "printShifter";
768   let ParserMatchClass = !cast<AsmOperandClass>(
769                          "ArithmeticShifterOperand" # width);
770 }
771
772 def arith_shift32 : arith_shift<i32, 32>;
773 def arith_shift64 : arith_shift<i64, 64>;
774
775 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
776     : Operand<Ty>,
777       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
778   let PrintMethod = "printShiftedRegister";
779   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
780 }
781
782 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
783 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
784
785 // An arithmetic shifter operand:
786 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
787 //  {5-0} - imm6
788 class logical_shift<int width> : Operand<i32> {
789   let PrintMethod = "printShifter";
790   let ParserMatchClass = !cast<AsmOperandClass>(
791                          "LogicalShifterOperand" # width);
792 }
793
794 def logical_shift32 : logical_shift<32>;
795 def logical_shift64 : logical_shift<64>;
796
797 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
798     : Operand<Ty>,
799       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
800   let PrintMethod = "printShiftedRegister";
801   let MIOperandInfo = (ops regclass, shiftop);
802 }
803
804 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
805 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
806
807 // A logical vector shifter operand:
808 //  {7-6} - shift type: 00 = lsl
809 //  {5-0} - imm6: #0, #8, #16, or #24
810 def logical_vec_shift : Operand<i32> {
811   let PrintMethod = "printShifter";
812   let EncoderMethod = "getVecShifterOpValue";
813   let ParserMatchClass = LogicalVecShifterOperand;
814 }
815
816 // A logical vector half-word shifter operand:
817 //  {7-6} - shift type: 00 = lsl
818 //  {5-0} - imm6: #0 or #8
819 def logical_vec_hw_shift : Operand<i32> {
820   let PrintMethod = "printShifter";
821   let EncoderMethod = "getVecShifterOpValue";
822   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
823 }
824
825 // A vector move shifter operand:
826 //  {0} - imm1: #8 or #16
827 def move_vec_shift : Operand<i32> {
828   let PrintMethod = "printShifter";
829   let EncoderMethod = "getMoveVecShifterOpValue";
830   let ParserMatchClass = MoveVecShifterOperand;
831 }
832
833 let DiagnosticType = "AddSubSecondSource" in {
834   def AddSubImmOperand : AsmOperandClass {
835     let Name = "AddSubImm";
836     let ParserMethod = "tryParseImmWithOptionalShift";
837     let RenderMethod = "addImmWithOptionalShiftOperands<12>";
838   }
839   def AddSubImmNegOperand : AsmOperandClass {
840     let Name = "AddSubImmNeg";
841     let ParserMethod = "tryParseImmWithOptionalShift";
842     let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
843   }
844 }
845 // An ADD/SUB immediate shifter operand:
846 //  second operand:
847 //  {7-6} - shift type: 00 = lsl
848 //  {5-0} - imm6: #0 or #12
849 class addsub_shifted_imm<ValueType Ty>
850     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
851   let PrintMethod = "printAddSubImm";
852   let EncoderMethod = "getAddSubImmOpValue";
853   let ParserMatchClass = AddSubImmOperand;
854   let MIOperandInfo = (ops i32imm, i32imm);
855 }
856
857 class addsub_shifted_imm_neg<ValueType Ty>
858     : Operand<Ty> {
859   let EncoderMethod = "getAddSubImmOpValue";
860   let ParserMatchClass = AddSubImmNegOperand;
861   let MIOperandInfo = (ops i32imm, i32imm);
862 }
863
864 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
865 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
866 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
867 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
868
869 def gi_addsub_shifted_imm32 :
870     GIComplexOperandMatcher<s32, "selectArithImmed">,
871     GIComplexPatternEquiv<addsub_shifted_imm32>;
872
873 def gi_addsub_shifted_imm64 :
874     GIComplexOperandMatcher<s64, "selectArithImmed">,
875     GIComplexPatternEquiv<addsub_shifted_imm64>;
876
877 class neg_addsub_shifted_imm<ValueType Ty>
878     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
879   let PrintMethod = "printAddSubImm";
880   let EncoderMethod = "getAddSubImmOpValue";
881   let ParserMatchClass = AddSubImmOperand;
882   let MIOperandInfo = (ops i32imm, i32imm);
883 }
884
885 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
886 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
887
888 // An extend operand:
889 //  {5-3} - extend type
890 //  {2-0} - imm3
891 def arith_extend : Operand<i32> {
892   let PrintMethod = "printArithExtend";
893   let ParserMatchClass = ExtendOperand;
894 }
895 def arith_extend64 : Operand<i32> {
896   let PrintMethod = "printArithExtend";
897   let ParserMatchClass = ExtendOperand64;
898 }
899
900 // 'extend' that's a lsl of a 64-bit register.
901 def arith_extendlsl64 : Operand<i32> {
902   let PrintMethod = "printArithExtend";
903   let ParserMatchClass = ExtendOperandLSL64;
904 }
905
906 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
907                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
908   let PrintMethod = "printExtendedRegister";
909   let MIOperandInfo = (ops GPR32, arith_extend);
910 }
911
912 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
913                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
914   let PrintMethod = "printExtendedRegister";
915   let MIOperandInfo = (ops GPR32, arith_extend64);
916 }
917
918 // Floating-point immediate.
919 def fpimm16 : Operand<f16>,
920               FPImmLeaf<f16, [{
921       return AArch64_AM::getFP16Imm(Imm) != -1;
922     }], SDNodeXForm<fpimm, [{
923       APFloat InVal = N->getValueAPF();
924       uint32_t enc = AArch64_AM::getFP16Imm(InVal);
925       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
926     }]>> {
927   let ParserMatchClass = FPImmOperand;
928   let PrintMethod = "printFPImmOperand";
929 }
930 def fpimm32 : Operand<f32>,
931               FPImmLeaf<f32, [{
932       return AArch64_AM::getFP32Imm(Imm) != -1;
933     }], SDNodeXForm<fpimm, [{
934       APFloat InVal = N->getValueAPF();
935       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
936       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
937     }]>> {
938   let ParserMatchClass = FPImmOperand;
939   let PrintMethod = "printFPImmOperand";
940 }
941 def fpimm64 : Operand<f64>,
942               FPImmLeaf<f64, [{
943       return AArch64_AM::getFP64Imm(Imm) != -1;
944     }], SDNodeXForm<fpimm, [{
945       APFloat InVal = N->getValueAPF();
946       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
947       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
948     }]>> {
949   let ParserMatchClass = FPImmOperand;
950   let PrintMethod = "printFPImmOperand";
951 }
952
953 def fpimm8 : Operand<i32> {
954   let ParserMatchClass = FPImmOperand;
955   let PrintMethod = "printFPImmOperand";
956 }
957
958 def fpimm0 : FPImmLeaf<fAny, [{
959   return Imm.isExactlyValue(+0.0);
960 }]>;
961
962 // Vector lane operands
963 class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
964   let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
965   let DiagnosticType = "Invalid" # Name;
966   let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
967   let RenderMethod = "addVectorIndexOperands";
968 }
969
970 class AsmVectorIndexOpnd<AsmOperandClass mc, code pred>
971     : Operand<i64>, ImmLeaf<i64, pred> {
972   let ParserMatchClass = mc;
973   let PrintMethod = "printVectorIndex";
974 }
975
976 def VectorIndex1Operand : AsmVectorIndex<1, 1>;
977 def VectorIndexBOperand : AsmVectorIndex<0, 15>;
978 def VectorIndexHOperand : AsmVectorIndex<0, 7>;
979 def VectorIndexSOperand : AsmVectorIndex<0, 3>;
980 def VectorIndexDOperand : AsmVectorIndex<0, 1>;
981
982 def VectorIndex1 : AsmVectorIndexOpnd<VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
983 def VectorIndexB : AsmVectorIndexOpnd<VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
984 def VectorIndexH : AsmVectorIndexOpnd<VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
985 def VectorIndexS : AsmVectorIndexOpnd<VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
986 def VectorIndexD : AsmVectorIndexOpnd<VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
987
988 def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
989 def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
990 def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
991 def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
992 def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
993
994 def sve_elm_idx_extdup_b
995   : AsmVectorIndexOpnd<SVEVectorIndexExtDupBOperand, [{ return ((uint64_t)Imm) < 64; }]>;
996 def sve_elm_idx_extdup_h
997   : AsmVectorIndexOpnd<SVEVectorIndexExtDupHOperand, [{ return ((uint64_t)Imm) < 32; }]>;
998 def sve_elm_idx_extdup_s
999   : AsmVectorIndexOpnd<SVEVectorIndexExtDupSOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1000 def sve_elm_idx_extdup_d
1001   : AsmVectorIndexOpnd<SVEVectorIndexExtDupDOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1002 def sve_elm_idx_extdup_q
1003   : AsmVectorIndexOpnd<SVEVectorIndexExtDupQOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1004
1005 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
1006 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1007 // are encoded as the eight bit value 'abcdefgh'.
1008 def simdimmtype10 : Operand<i32>,
1009                     FPImmLeaf<f64, [{
1010       return AArch64_AM::isAdvSIMDModImmType10(
1011                  Imm.bitcastToAPInt().getZExtValue());
1012     }], SDNodeXForm<fpimm, [{
1013       APFloat InVal = N->getValueAPF();
1014       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1015                                                            .bitcastToAPInt()
1016                                                            .getZExtValue());
1017       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1018     }]>> {
1019   let ParserMatchClass = SIMDImmType10Operand;
1020   let PrintMethod = "printSIMDType10Operand";
1021 }
1022
1023
1024 //---
1025 // System management
1026 //---
1027
1028 // Base encoding for system instruction operands.
1029 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1030 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1031                   list<dag> pattern = []>
1032     : I<oops, iops, asm, operands, "", pattern> {
1033   let Inst{31-22} = 0b1101010100;
1034   let Inst{21}    = L;
1035 }
1036
1037 // System instructions which do not have an Rt register.
1038 class SimpleSystemI<bit L, dag iops, string asm, string operands,
1039                     list<dag> pattern = []>
1040     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1041   let Inst{4-0} = 0b11111;
1042 }
1043
1044 // System instructions which have an Rt register.
1045 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
1046     : BaseSystemI<L, oops, iops, asm, operands>,
1047       Sched<[WriteSys]> {
1048   bits<5> Rt;
1049   let Inst{4-0} = Rt;
1050 }
1051
1052 // Hint instructions that take both a CRm and a 3-bit immediate.
1053 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1054 // model patterns with sufficiently fine granularity
1055 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1056   class HintI<string mnemonic>
1057       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1058                       [(int_aarch64_hint imm0_127:$imm)]>,
1059         Sched<[WriteHint]> {
1060     bits <7> imm;
1061     let Inst{20-12} = 0b000110010;
1062     let Inst{11-5} = imm;
1063   }
1064
1065 // System instructions taking a single literal operand which encodes into
1066 // CRm. op2 differentiates the opcodes.
1067 def BarrierAsmOperand : AsmOperandClass {
1068   let Name = "Barrier";
1069   let ParserMethod = "tryParseBarrierOperand";
1070 }
1071 def barrier_op : Operand<i32> {
1072   let PrintMethod = "printBarrierOption";
1073   let ParserMatchClass = BarrierAsmOperand;
1074 }
1075 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1076                  list<dag> pattern = []>
1077     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1078       Sched<[WriteBarrier]> {
1079   bits<4> CRm;
1080   let Inst{20-12} = 0b000110011;
1081   let Inst{11-8} = CRm;
1082   let Inst{7-5} = opc;
1083 }
1084
1085 class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1086     : SimpleSystemI<0, (ins), asm, "", pattern>,
1087       Sched<[]> {
1088   bits<4> CRm;
1089   let CRm = 0b0011;
1090   let Inst{31-12} = 0b11010101000000110010;
1091   let Inst{11-8} = CRm;
1092   let Inst{7-5} = op2;
1093   let Inst{4-0} = 0b11111;
1094 }
1095
1096 // MRS/MSR system instructions. These have different operand classes because
1097 // a different subset of registers can be accessed through each instruction.
1098 def MRSSystemRegisterOperand : AsmOperandClass {
1099   let Name = "MRSSystemRegister";
1100   let ParserMethod = "tryParseSysReg";
1101   let DiagnosticType = "MRS";
1102 }
1103 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1104 def mrs_sysreg_op : Operand<i32> {
1105   let ParserMatchClass = MRSSystemRegisterOperand;
1106   let DecoderMethod = "DecodeMRSSystemRegister";
1107   let PrintMethod = "printMRSSystemRegister";
1108 }
1109
1110 def MSRSystemRegisterOperand : AsmOperandClass {
1111   let Name = "MSRSystemRegister";
1112   let ParserMethod = "tryParseSysReg";
1113   let DiagnosticType = "MSR";
1114 }
1115 def msr_sysreg_op : Operand<i32> {
1116   let ParserMatchClass = MSRSystemRegisterOperand;
1117   let DecoderMethod = "DecodeMSRSystemRegister";
1118   let PrintMethod = "printMSRSystemRegister";
1119 }
1120
1121 def PSBHintOperand : AsmOperandClass {
1122   let Name = "PSBHint";
1123   let ParserMethod = "tryParsePSBHint";
1124 }
1125 def psbhint_op : Operand<i32> {
1126   let ParserMatchClass = PSBHintOperand;
1127   let PrintMethod = "printPSBHintOp";
1128   let MCOperandPredicate = [{
1129     // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1130     // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1131     if (!MCOp.isImm())
1132       return false;
1133     return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1134   }];
1135 }
1136
1137 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1138                        "mrs", "\t$Rt, $systemreg"> {
1139   bits<16> systemreg;
1140   let Inst{20-5} = systemreg;
1141 }
1142
1143 // FIXME: Some of these def NZCV, others don't. Best way to model that?
1144 // Explicitly modeling each of the system register as a register class
1145 // would do it, but feels like overkill at this point.
1146 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1147                        "msr", "\t$systemreg, $Rt"> {
1148   bits<16> systemreg;
1149   let Inst{20-5} = systemreg;
1150 }
1151
1152 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1153   let Name = "SystemPStateFieldWithImm0_15";
1154   let ParserMethod = "tryParseSysReg";
1155 }
1156 def pstatefield4_op : Operand<i32> {
1157   let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1158   let PrintMethod = "printSystemPStateField";
1159 }
1160
1161 let Defs = [NZCV] in
1162 class MSRpstateImm0_15
1163   : SimpleSystemI<0, (ins pstatefield4_op:$pstatefield, imm0_15:$imm),
1164                   "msr", "\t$pstatefield, $imm">,
1165     Sched<[WriteSys]> {
1166   bits<6> pstatefield;
1167   bits<4> imm;
1168   let Inst{20-19} = 0b00;
1169   let Inst{18-16} = pstatefield{5-3};
1170   let Inst{15-12} = 0b0100;
1171   let Inst{11-8} = imm;
1172   let Inst{7-5} = pstatefield{2-0};
1173
1174   let DecoderMethod = "DecodeSystemPStateInstruction";
1175   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1176   // Fail the decoder should attempt to decode the instruction as MSRI.
1177   let hasCompleteDecoder = 0;
1178 }
1179
1180 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1181   let Name = "SystemPStateFieldWithImm0_1";
1182   let ParserMethod = "tryParseSysReg";
1183 }
1184 def pstatefield1_op : Operand<i32> {
1185   let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1186   let PrintMethod = "printSystemPStateField";
1187 }
1188
1189 let Defs = [NZCV] in
1190 class MSRpstateImm0_1
1191   : SimpleSystemI<0, (ins pstatefield1_op:$pstatefield, imm0_1:$imm),
1192                   "msr", "\t$pstatefield, $imm">,
1193     Sched<[WriteSys]> {
1194   bits<6> pstatefield;
1195   bit imm;
1196   let Inst{20-19} = 0b00;
1197   let Inst{18-16} = pstatefield{5-3};
1198   let Inst{15-9} = 0b0100000;
1199   let Inst{8} = imm;
1200   let Inst{7-5} = pstatefield{2-0};
1201
1202   let DecoderMethod = "DecodeSystemPStateInstruction";
1203   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1204   // Fail the decoder should attempt to decode the instruction as MSRI.
1205   let hasCompleteDecoder = 0;
1206 }
1207
1208 // SYS and SYSL generic system instructions.
1209 def SysCRAsmOperand : AsmOperandClass {
1210   let Name = "SysCR";
1211   let ParserMethod = "tryParseSysCROperand";
1212 }
1213
1214 def sys_cr_op : Operand<i32> {
1215   let PrintMethod = "printSysCROperand";
1216   let ParserMatchClass = SysCRAsmOperand;
1217 }
1218
1219 class SystemXtI<bit L, string asm>
1220   : RtSystemI<L, (outs),
1221        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1222        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1223   bits<3> op1;
1224   bits<4> Cn;
1225   bits<4> Cm;
1226   bits<3> op2;
1227   let Inst{20-19} = 0b01;
1228   let Inst{18-16} = op1;
1229   let Inst{15-12} = Cn;
1230   let Inst{11-8}  = Cm;
1231   let Inst{7-5}   = op2;
1232 }
1233
1234 class SystemLXtI<bit L, string asm>
1235   : RtSystemI<L, (outs),
1236        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1237        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
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
1250 // Branch (register) instructions:
1251 //
1252 //  case opc of
1253 //    0001 blr
1254 //    0000 br
1255 //    0101 dret
1256 //    0100 eret
1257 //    0010 ret
1258 //    otherwise UNDEFINED
1259 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1260                     string operands, list<dag> pattern>
1261     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1262   let Inst{31-25} = 0b1101011;
1263   let Inst{24-21} = opc;
1264   let Inst{20-16} = 0b11111;
1265   let Inst{15-10} = 0b000000;
1266   let Inst{4-0}   = 0b00000;
1267 }
1268
1269 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1270     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1271   bits<5> Rn;
1272   let Inst{9-5} = Rn;
1273 }
1274
1275 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1276 class SpecialReturn<bits<4> opc, string asm>
1277     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1278   let Inst{9-5} = 0b11111;
1279 }
1280
1281 let mayLoad = 1 in
1282 class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1283   : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1284   Sched<[]> {
1285   bits<5> Rn;
1286   bits<5> Rt;
1287   let Inst{31-30} = sz;
1288   let Inst{29-10} = 0b11100010111111110000;
1289   let Inst{9-5} = Rn;
1290   let Inst{4-0} = Rt;
1291 }
1292
1293 class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1294                list<dag> pattern>
1295   : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1296   let Inst{31-25} = 0b1101011;
1297   let Inst{20-11} = 0b1111100001;
1298   let Inst{10} = M;
1299   let Inst{4-0} = 0b11111;
1300 }
1301
1302 class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1303   : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1304   bits<5> Rn;
1305   bits<5> Rm;
1306   let Inst{24-22} = 0b100;
1307   let Inst{21} = op;
1308   let Inst{9-5} = Rn;
1309   let Inst{4-0} = Rm;
1310 }
1311
1312 class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1313   : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1314   bits<5> Rn;
1315   let Inst{24} = 0;
1316   let Inst{23-21} = opc;
1317   let Inst{9-5} = Rn;
1318 }
1319
1320 class AuthReturn<bits<3> op, bits<1> M, string asm>
1321   : AuthBase<M, (outs), (ins), asm, "", []> {
1322   let Inst{24} = 0;
1323   let Inst{23-21} = op;
1324   let Inst{9-0} = 0b1111111111;
1325 }
1326
1327 let mayLoad = 1 in
1328 class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1329                    string operands, string cstr, Operand opr>
1330   : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1331   bits<10> offset;
1332   bits<5> Rn;
1333   bits<5> Rt;
1334   let Inst{31-24} = 0b11111000;
1335   let Inst{23} = M;
1336   let Inst{22} = offset{9};
1337   let Inst{21} = 1;
1338   let Inst{20-12} = offset{8-0};
1339   let Inst{11} = W;
1340   let Inst{10} = 1;
1341   let Inst{9-5} = Rn;
1342   let Inst{4-0} = Rt;
1343 }
1344
1345 multiclass AuthLoad<bit M, string asm, Operand opr> {
1346   def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1347                                (ins GPR64sp:$Rn, opr:$offset),
1348                                asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1349   def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1350                                (ins GPR64sp:$Rn, opr:$offset),
1351                                asm, "\t$Rt, [$Rn, $offset]!",
1352                                "$Rn = $wback,@earlyclobber $wback", opr>;
1353
1354   def : InstAlias<asm # "\t$Rt, [$Rn]",
1355                   (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1356 }
1357
1358 //---
1359 // Conditional branch instruction.
1360 //---
1361
1362 // Condition code.
1363 // 4-bit immediate. Pretty-printed as <cc>
1364 def ccode : Operand<i32> {
1365   let PrintMethod = "printCondCode";
1366   let ParserMatchClass = CondCode;
1367 }
1368 def inv_ccode : Operand<i32> {
1369   // AL and NV are invalid in the aliases which use inv_ccode
1370   let PrintMethod = "printInverseCondCode";
1371   let ParserMatchClass = CondCode;
1372   let MCOperandPredicate = [{
1373     return MCOp.isImm() &&
1374            MCOp.getImm() != AArch64CC::AL &&
1375            MCOp.getImm() != AArch64CC::NV;
1376   }];
1377 }
1378
1379 // Conditional branch target. 19-bit immediate. The low two bits of the target
1380 // offset are implied zero and so are not part of the immediate.
1381 def am_brcond : Operand<OtherVT> {
1382   let EncoderMethod = "getCondBranchTargetOpValue";
1383   let DecoderMethod = "DecodePCRelLabel19";
1384   let PrintMethod = "printAlignedLabel";
1385   let ParserMatchClass = PCRelLabel19Operand;
1386   let OperandType = "OPERAND_PCREL";
1387 }
1388
1389 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1390                      "b", ".$cond\t$target", "",
1391                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1392                    Sched<[WriteBr]> {
1393   let isBranch = 1;
1394   let isTerminator = 1;
1395   let Uses = [NZCV];
1396
1397   bits<4> cond;
1398   bits<19> target;
1399   let Inst{31-24} = 0b01010100;
1400   let Inst{23-5} = target;
1401   let Inst{4} = 0;
1402   let Inst{3-0} = cond;
1403 }
1404
1405 //---
1406 // Compare-and-branch instructions.
1407 //---
1408 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1409     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1410          asm, "\t$Rt, $target", "",
1411          [(node regtype:$Rt, bb:$target)]>,
1412       Sched<[WriteBr]> {
1413   let isBranch = 1;
1414   let isTerminator = 1;
1415
1416   bits<5> Rt;
1417   bits<19> target;
1418   let Inst{30-25} = 0b011010;
1419   let Inst{24}    = op;
1420   let Inst{23-5}  = target;
1421   let Inst{4-0}   = Rt;
1422 }
1423
1424 multiclass CmpBranch<bit op, string asm, SDNode node> {
1425   def W : BaseCmpBranch<GPR32, op, asm, node> {
1426     let Inst{31} = 0;
1427   }
1428   def X : BaseCmpBranch<GPR64, op, asm, node> {
1429     let Inst{31} = 1;
1430   }
1431 }
1432
1433 //---
1434 // Test-bit-and-branch instructions.
1435 //---
1436 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1437 // the target offset are implied zero and so are not part of the immediate.
1438 def am_tbrcond : Operand<OtherVT> {
1439   let EncoderMethod = "getTestBranchTargetOpValue";
1440   let PrintMethod = "printAlignedLabel";
1441   let ParserMatchClass = BranchTarget14Operand;
1442   let OperandType = "OPERAND_PCREL";
1443 }
1444
1445 // AsmOperand classes to emit (or not) special diagnostics
1446 def TBZImm0_31Operand : AsmOperandClass {
1447   let Name = "TBZImm0_31";
1448   let PredicateMethod = "isImmInRange<0,31>";
1449   let RenderMethod = "addImmOperands";
1450 }
1451 def TBZImm32_63Operand : AsmOperandClass {
1452   let Name = "Imm32_63";
1453   let PredicateMethod = "isImmInRange<32,63>";
1454   let DiagnosticType = "InvalidImm0_63";
1455   let RenderMethod = "addImmOperands";
1456 }
1457
1458 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1459   return (((uint32_t)Imm) < 32);
1460 }]> {
1461   let ParserMatchClass = matcher;
1462 }
1463
1464 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1465 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1466
1467 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1468   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1469 }]> {
1470   let ParserMatchClass = TBZImm32_63Operand;
1471 }
1472
1473 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1474                      bit op, string asm, SDNode node>
1475     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1476        asm, "\t$Rt, $bit_off, $target", "",
1477        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1478       Sched<[WriteBr]> {
1479   let isBranch = 1;
1480   let isTerminator = 1;
1481
1482   bits<5> Rt;
1483   bits<6> bit_off;
1484   bits<14> target;
1485
1486   let Inst{30-25} = 0b011011;
1487   let Inst{24}    = op;
1488   let Inst{23-19} = bit_off{4-0};
1489   let Inst{18-5}  = target;
1490   let Inst{4-0}   = Rt;
1491
1492   let DecoderMethod = "DecodeTestAndBranch";
1493 }
1494
1495 multiclass TestBranch<bit op, string asm, SDNode node> {
1496   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1497     let Inst{31} = 0;
1498   }
1499
1500   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1501     let Inst{31} = 1;
1502   }
1503
1504   // Alias X-reg with 0-31 imm to W-Reg.
1505   def : InstAlias<asm # "\t$Rd, $imm, $target",
1506                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1507                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1508   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1509             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1510             tbz_imm0_31_diag:$imm, bb:$target)>;
1511 }
1512
1513 //---
1514 // Unconditional branch (immediate) instructions.
1515 //---
1516 def am_b_target : Operand<OtherVT> {
1517   let EncoderMethod = "getBranchTargetOpValue";
1518   let PrintMethod = "printAlignedLabel";
1519   let ParserMatchClass = BranchTarget26Operand;
1520   let OperandType = "OPERAND_PCREL";
1521 }
1522 def am_bl_target : Operand<i64> {
1523   let EncoderMethod = "getBranchTargetOpValue";
1524   let PrintMethod = "printAlignedLabel";
1525   let ParserMatchClass = BranchTarget26Operand;
1526   let OperandType = "OPERAND_PCREL";
1527 }
1528
1529 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1530     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1531   bits<26> addr;
1532   let Inst{31}    = op;
1533   let Inst{30-26} = 0b00101;
1534   let Inst{25-0}  = addr;
1535
1536   let DecoderMethod = "DecodeUnconditionalBranch";
1537 }
1538
1539 class BranchImm<bit op, string asm, list<dag> pattern>
1540     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1541 class CallImm<bit op, string asm, list<dag> pattern>
1542     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1543
1544 //---
1545 // Basic one-operand data processing instructions.
1546 //---
1547
1548 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1549 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1550                          SDPatternOperator node>
1551   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1552       [(set regtype:$Rd, (node regtype:$Rn))]>,
1553     Sched<[WriteI, ReadI]> {
1554   bits<5> Rd;
1555   bits<5> Rn;
1556
1557   let Inst{30-13} = 0b101101011000000000;
1558   let Inst{12-10} = opc;
1559   let Inst{9-5}   = Rn;
1560   let Inst{4-0}   = Rd;
1561 }
1562
1563 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1564 multiclass OneOperandData<bits<3> opc, string asm,
1565                           SDPatternOperator node = null_frag> {
1566   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1567     let Inst{31} = 0;
1568   }
1569
1570   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1571     let Inst{31} = 1;
1572   }
1573 }
1574
1575 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1576     : BaseOneOperandData<opc, GPR32, asm, node> {
1577   let Inst{31} = 0;
1578 }
1579
1580 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1581     : BaseOneOperandData<opc, GPR64, asm, node> {
1582   let Inst{31} = 1;
1583 }
1584
1585 class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1586   : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1587       []>,
1588     Sched<[WriteI, ReadI]> {
1589   bits<5> Rd;
1590   bits<5> Rn;
1591   let Inst{31-15} = 0b11011010110000010;
1592   let Inst{14-12} = opcode_prefix;
1593   let Inst{11-10} = opcode;
1594   let Inst{9-5} = Rn;
1595   let Inst{4-0} = Rd;
1596 }
1597
1598 class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1599   : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1600   bits<5> Rd;
1601   let Inst{31-15} = 0b11011010110000010;
1602   let Inst{14-12} = opcode_prefix;
1603   let Inst{11-10} = opcode;
1604   let Inst{9-5} = 0b11111;
1605   let Inst{4-0} = Rd;
1606 }
1607
1608 class SignAuthTwoOperand<bits<4> opc, string asm,
1609                          SDPatternOperator OpNode>
1610   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1611       asm, "\t$Rd, $Rn, $Rm", "",
1612       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1613     Sched<[WriteI, ReadI, ReadI]> {
1614   bits<5> Rd;
1615   bits<5> Rn;
1616   bits<5> Rm;
1617   let Inst{31-21} = 0b10011010110;
1618   let Inst{20-16} = Rm;
1619   let Inst{15-14} = 0b00;
1620   let Inst{13-10} = opc;
1621   let Inst{9-5}   = Rn;
1622   let Inst{4-0}   = Rd;
1623 }
1624
1625 // Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1626 class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1627     : I<(outs), iops, asm, ops, "", []>,
1628       Sched<[WriteI, ReadI, ReadI]> {
1629   let Uses = [NZCV];
1630   bits<5> Rn;
1631   let Inst{31}    = sf;
1632   let Inst{30-15} = 0b0111010000000000;
1633   let Inst{14}    = sz;
1634   let Inst{13-10} = 0b0010;
1635   let Inst{9-5}   = Rn;
1636   let Inst{4-0}   = 0b01101;
1637 }
1638
1639 class FlagRotate<dag iops, string asm, string ops>
1640     : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1641   bits<6> imm;
1642   bits<4> mask;
1643   let Inst{20-15} = imm;
1644   let Inst{13-10} = 0b0001;
1645   let Inst{4}     = 0b0;
1646   let Inst{3-0}   = mask;
1647 }
1648
1649 //---
1650 // Basic two-operand data processing instructions.
1651 //---
1652 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1653                           list<dag> pattern>
1654     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1655         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1656       Sched<[WriteI, ReadI, ReadI]> {
1657   let Uses = [NZCV];
1658   bits<5> Rd;
1659   bits<5> Rn;
1660   bits<5> Rm;
1661   let Inst{30}    = isSub;
1662   let Inst{28-21} = 0b11010000;
1663   let Inst{20-16} = Rm;
1664   let Inst{15-10} = 0;
1665   let Inst{9-5}   = Rn;
1666   let Inst{4-0}   = Rd;
1667 }
1668
1669 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1670                       SDNode OpNode>
1671     : BaseBaseAddSubCarry<isSub, regtype, asm,
1672         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1673
1674 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1675                               SDNode OpNode>
1676     : BaseBaseAddSubCarry<isSub, regtype, asm,
1677         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1678          (implicit NZCV)]> {
1679   let Defs = [NZCV];
1680 }
1681
1682 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1683                        SDNode OpNode, SDNode OpNode_setflags> {
1684   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1685     let Inst{31} = 0;
1686     let Inst{29} = 0;
1687   }
1688   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1689     let Inst{31} = 1;
1690     let Inst{29} = 0;
1691   }
1692
1693   // Sets flags.
1694   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1695                                     OpNode_setflags> {
1696     let Inst{31} = 0;
1697     let Inst{29} = 1;
1698   }
1699   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1700                                     OpNode_setflags> {
1701     let Inst{31} = 1;
1702     let Inst{29} = 1;
1703   }
1704 }
1705
1706 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1707                      SDPatternOperator OpNode>
1708   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1709       asm, "\t$Rd, $Rn, $Rm", "",
1710       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1711   bits<5> Rd;
1712   bits<5> Rn;
1713   bits<5> Rm;
1714   let Inst{30-21} = 0b0011010110;
1715   let Inst{20-16} = Rm;
1716   let Inst{15-14} = 0b00;
1717   let Inst{13-10} = opc;
1718   let Inst{9-5}   = Rn;
1719   let Inst{4-0}   = Rd;
1720 }
1721
1722 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1723               SDPatternOperator OpNode>
1724     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1725   let Inst{10}    = isSigned;
1726 }
1727
1728 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1729   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1730            Sched<[WriteID32, ReadID, ReadID]> {
1731     let Inst{31} = 0;
1732   }
1733   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1734            Sched<[WriteID64, ReadID, ReadID]> {
1735     let Inst{31} = 1;
1736   }
1737 }
1738
1739 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1740                 SDPatternOperator OpNode = null_frag>
1741   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1742     Sched<[WriteIS, ReadI]> {
1743   let Inst{11-10} = shift_type;
1744 }
1745
1746 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1747   def Wr : BaseShift<shift_type, GPR32, asm> {
1748     let Inst{31} = 0;
1749   }
1750
1751   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1752     let Inst{31} = 1;
1753   }
1754
1755   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1756             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1757                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1758
1759   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1760             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1761
1762   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1763             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1764
1765   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1766             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1767 }
1768
1769 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1770     : InstAlias<asm#"\t$dst, $src1, $src2",
1771                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1772
1773 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1774                        RegisterClass addtype, string asm,
1775                        list<dag> pattern>
1776   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1777       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1778   bits<5> Rd;
1779   bits<5> Rn;
1780   bits<5> Rm;
1781   bits<5> Ra;
1782   let Inst{30-24} = 0b0011011;
1783   let Inst{23-21} = opc;
1784   let Inst{20-16} = Rm;
1785   let Inst{15}    = isSub;
1786   let Inst{14-10} = Ra;
1787   let Inst{9-5}   = Rn;
1788   let Inst{4-0}   = Rd;
1789 }
1790
1791 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1792   // MADD/MSUB generation is decided by MachineCombiner.cpp
1793   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1794       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1795       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1796     let Inst{31} = 0;
1797   }
1798
1799   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1800       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1801       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1802     let Inst{31} = 1;
1803   }
1804 }
1805
1806 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1807                    SDNode AccNode, SDNode ExtNode>
1808   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1809     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1810                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1811     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1812   let Inst{31} = 1;
1813 }
1814
1815 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1816   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1817       asm, "\t$Rd, $Rn, $Rm", "",
1818       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1819     Sched<[WriteIM64, ReadIM, ReadIM]> {
1820   bits<5> Rd;
1821   bits<5> Rn;
1822   bits<5> Rm;
1823   let Inst{31-24} = 0b10011011;
1824   let Inst{23-21} = opc;
1825   let Inst{20-16} = Rm;
1826   let Inst{15}    = 0;
1827   let Inst{9-5}   = Rn;
1828   let Inst{4-0}   = Rd;
1829
1830   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1831   // (i.e. all bits 1) but is ignored by the processor.
1832   let PostEncoderMethod = "fixMulHigh";
1833 }
1834
1835 class MulAccumWAlias<string asm, Instruction inst>
1836     : InstAlias<asm#"\t$dst, $src1, $src2",
1837                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1838 class MulAccumXAlias<string asm, Instruction inst>
1839     : InstAlias<asm#"\t$dst, $src1, $src2",
1840                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1841 class WideMulAccumAlias<string asm, Instruction inst>
1842     : InstAlias<asm#"\t$dst, $src1, $src2",
1843                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1844
1845 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1846               SDPatternOperator OpNode, string asm>
1847   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1848       asm, "\t$Rd, $Rn, $Rm", "",
1849       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1850     Sched<[WriteISReg, ReadI, ReadISReg]> {
1851   bits<5> Rd;
1852   bits<5> Rn;
1853   bits<5> Rm;
1854
1855   let Inst{31} = sf;
1856   let Inst{30-21} = 0b0011010110;
1857   let Inst{20-16} = Rm;
1858   let Inst{15-13} = 0b010;
1859   let Inst{12} = C;
1860   let Inst{11-10} = sz;
1861   let Inst{9-5} = Rn;
1862   let Inst{4-0} = Rd;
1863   let Predicates = [HasCRC];
1864 }
1865
1866 //---
1867 // Address generation.
1868 //---
1869
1870 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1871     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1872         pattern>,
1873       Sched<[WriteI]> {
1874   bits<5>  Xd;
1875   bits<21> label;
1876   let Inst{31}    = page;
1877   let Inst{30-29} = label{1-0};
1878   let Inst{28-24} = 0b10000;
1879   let Inst{23-5}  = label{20-2};
1880   let Inst{4-0}   = Xd;
1881
1882   let DecoderMethod = "DecodeAdrInstruction";
1883 }
1884
1885 //---
1886 // Move immediate.
1887 //---
1888
1889 def movimm32_imm : Operand<i32> {
1890   let ParserMatchClass = Imm0_65535Operand;
1891   let EncoderMethod = "getMoveWideImmOpValue";
1892   let PrintMethod = "printImm";
1893 }
1894 def movimm32_shift : Operand<i32> {
1895   let PrintMethod = "printShifter";
1896   let ParserMatchClass = MovImm32ShifterOperand;
1897 }
1898 def movimm64_shift : Operand<i32> {
1899   let PrintMethod = "printShifter";
1900   let ParserMatchClass = MovImm64ShifterOperand;
1901 }
1902
1903 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1904 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1905                         string asm>
1906   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1907        asm, "\t$Rd, $imm$shift", "", []>,
1908     Sched<[WriteImm]> {
1909   bits<5> Rd;
1910   bits<16> imm;
1911   bits<6> shift;
1912   let Inst{30-29} = opc;
1913   let Inst{28-23} = 0b100101;
1914   let Inst{22-21} = shift{5-4};
1915   let Inst{20-5}  = imm;
1916   let Inst{4-0}   = Rd;
1917
1918   let DecoderMethod = "DecodeMoveImmInstruction";
1919 }
1920
1921 multiclass MoveImmediate<bits<2> opc, string asm> {
1922   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1923     let Inst{31} = 0;
1924   }
1925
1926   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1927     let Inst{31} = 1;
1928   }
1929 }
1930
1931 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1932 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1933                           string asm>
1934   : I<(outs regtype:$Rd),
1935       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1936        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1937     Sched<[WriteI, ReadI]> {
1938   bits<5> Rd;
1939   bits<16> imm;
1940   bits<6> shift;
1941   let Inst{30-29} = opc;
1942   let Inst{28-23} = 0b100101;
1943   let Inst{22-21} = shift{5-4};
1944   let Inst{20-5}  = imm;
1945   let Inst{4-0}   = Rd;
1946
1947   let DecoderMethod = "DecodeMoveImmInstruction";
1948 }
1949
1950 multiclass InsertImmediate<bits<2> opc, string asm> {
1951   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1952     let Inst{31} = 0;
1953   }
1954
1955   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1956     let Inst{31} = 1;
1957   }
1958 }
1959
1960 //---
1961 // Add/Subtract
1962 //---
1963
1964 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1965                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1966                     string asm, SDPatternOperator OpNode>
1967     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1968         asm, "\t$Rd, $Rn, $imm", "",
1969         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1970       Sched<[WriteI, ReadI]>  {
1971   bits<5>  Rd;
1972   bits<5>  Rn;
1973   bits<14> imm;
1974   let Inst{30}    = isSub;
1975   let Inst{29}    = setFlags;
1976   let Inst{28-24} = 0b10001;
1977   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1978   let Inst{21-10} = imm{11-0};
1979   let Inst{9-5}   = Rn;
1980   let Inst{4-0}   = Rd;
1981   let DecoderMethod = "DecodeBaseAddSubImm";
1982 }
1983
1984 class BaseAddSubRegPseudo<RegisterClass regtype,
1985                           SDPatternOperator OpNode>
1986     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1987              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1988       Sched<[WriteI, ReadI, ReadI]>;
1989
1990 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1991                      arith_shifted_reg shifted_regtype, string asm,
1992                      SDPatternOperator OpNode>
1993     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1994         asm, "\t$Rd, $Rn, $Rm", "",
1995         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1996       Sched<[WriteISReg, ReadI, ReadISReg]> {
1997   // The operands are in order to match the 'addr' MI operands, so we
1998   // don't need an encoder method and by-name matching. Just use the default
1999   // in-order handling. Since we're using by-order, make sure the names
2000   // do not match.
2001   bits<5> dst;
2002   bits<5> src1;
2003   bits<5> src2;
2004   bits<8> shift;
2005   let Inst{30}    = isSub;
2006   let Inst{29}    = setFlags;
2007   let Inst{28-24} = 0b01011;
2008   let Inst{23-22} = shift{7-6};
2009   let Inst{21}    = 0;
2010   let Inst{20-16} = src2;
2011   let Inst{15-10} = shift{5-0};
2012   let Inst{9-5}   = src1;
2013   let Inst{4-0}   = dst;
2014
2015   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2016 }
2017
2018 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2019                      RegisterClass src1Regtype, Operand src2Regtype,
2020                      string asm, SDPatternOperator OpNode>
2021     : I<(outs dstRegtype:$R1),
2022         (ins src1Regtype:$R2, src2Regtype:$R3),
2023         asm, "\t$R1, $R2, $R3", "",
2024         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2025       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2026   bits<5> Rd;
2027   bits<5> Rn;
2028   bits<5> Rm;
2029   bits<6> ext;
2030   let Inst{30}    = isSub;
2031   let Inst{29}    = setFlags;
2032   let Inst{28-24} = 0b01011;
2033   let Inst{23-21} = 0b001;
2034   let Inst{20-16} = Rm;
2035   let Inst{15-13} = ext{5-3};
2036   let Inst{12-10} = ext{2-0};
2037   let Inst{9-5}   = Rn;
2038   let Inst{4-0}   = Rd;
2039
2040   let DecoderMethod = "DecodeAddSubERegInstruction";
2041 }
2042
2043 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2044 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2045                        RegisterClass src1Regtype, RegisterClass src2Regtype,
2046                        Operand ext_op, string asm>
2047     : I<(outs dstRegtype:$Rd),
2048         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2049         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2050       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2051   bits<5> Rd;
2052   bits<5> Rn;
2053   bits<5> Rm;
2054   bits<6> ext;
2055   let Inst{30}    = isSub;
2056   let Inst{29}    = setFlags;
2057   let Inst{28-24} = 0b01011;
2058   let Inst{23-21} = 0b001;
2059   let Inst{20-16} = Rm;
2060   let Inst{15}    = ext{5};
2061   let Inst{12-10} = ext{2-0};
2062   let Inst{9-5}   = Rn;
2063   let Inst{4-0}   = Rd;
2064
2065   let DecoderMethod = "DecodeAddSubERegInstruction";
2066 }
2067
2068 // Aliases for register+register add/subtract.
2069 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2070                      RegisterClass src1Regtype, RegisterClass src2Regtype,
2071                      int shiftExt>
2072     : InstAlias<asm#"\t$dst, $src1, $src2",
2073                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2074                       shiftExt)>;
2075
2076 multiclass AddSub<bit isSub, string mnemonic, string alias,
2077                   SDPatternOperator OpNode = null_frag> {
2078   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2079   // Add/Subtract immediate
2080   // Increase the weight of the immediate variant to try to match it before
2081   // the extended register variant.
2082   // We used to match the register variant before the immediate when the
2083   // register argument could be implicitly zero-extended.
2084   let AddedComplexity = 6 in
2085   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2086                            mnemonic, OpNode> {
2087     let Inst{31} = 0;
2088   }
2089   let AddedComplexity = 6 in
2090   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2091                            mnemonic, OpNode> {
2092     let Inst{31} = 1;
2093   }
2094
2095   // Add/Subtract register - Only used for CodeGen
2096   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2097   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2098
2099   // Add/Subtract shifted register
2100   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2101                            OpNode> {
2102     let Inst{31} = 0;
2103   }
2104   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2105                            OpNode> {
2106     let Inst{31} = 1;
2107   }
2108   }
2109
2110   // Add/Subtract extended register
2111   let AddedComplexity = 1, hasSideEffects = 0 in {
2112   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2113                            arith_extended_reg32<i32>, mnemonic, OpNode> {
2114     let Inst{31} = 0;
2115   }
2116   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2117                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
2118     let Inst{31} = 1;
2119   }
2120   }
2121
2122   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2123                                arith_extendlsl64, mnemonic> {
2124     // UXTX and SXTX only.
2125     let Inst{14-13} = 0b11;
2126     let Inst{31} = 1;
2127   }
2128
2129   // add Rd, Rb, -imm -> sub Rd, Rn, imm
2130   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2131                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2132                       addsub_shifted_imm32_neg:$imm), 0>;
2133   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2134                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2135                        addsub_shifted_imm64_neg:$imm), 0>;
2136
2137   // Register/register aliases with no shift when SP is not used.
2138   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2139                        GPR32, GPR32, GPR32, 0>;
2140   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2141                        GPR64, GPR64, GPR64, 0>;
2142
2143   // Register/register aliases with no shift when either the destination or
2144   // first source register is SP.
2145   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2146                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2147   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2148                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2149   def : AddSubRegAlias<mnemonic,
2150                        !cast<Instruction>(NAME#"Xrx64"),
2151                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2152   def : AddSubRegAlias<mnemonic,
2153                        !cast<Instruction>(NAME#"Xrx64"),
2154                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2155 }
2156
2157 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2158                    string alias, string cmpAlias> {
2159   let isCompare = 1, Defs = [NZCV] in {
2160   // Add/Subtract immediate
2161   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2162                            mnemonic, OpNode> {
2163     let Inst{31} = 0;
2164   }
2165   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2166                            mnemonic, OpNode> {
2167     let Inst{31} = 1;
2168   }
2169
2170   // Add/Subtract register
2171   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2172   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2173
2174   // Add/Subtract shifted register
2175   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2176                            OpNode> {
2177     let Inst{31} = 0;
2178   }
2179   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2180                            OpNode> {
2181     let Inst{31} = 1;
2182   }
2183
2184   // Add/Subtract extended register
2185   let AddedComplexity = 1 in {
2186   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2187                            arith_extended_reg32<i32>, mnemonic, OpNode> {
2188     let Inst{31} = 0;
2189   }
2190   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2191                            arith_extended_reg32<i64>, mnemonic, OpNode> {
2192     let Inst{31} = 1;
2193   }
2194   }
2195
2196   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2197                                arith_extendlsl64, mnemonic> {
2198     // UXTX and SXTX only.
2199     let Inst{14-13} = 0b11;
2200     let Inst{31} = 1;
2201   }
2202   } // Defs = [NZCV]
2203
2204   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2205   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2206                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2207                       addsub_shifted_imm32_neg:$imm), 0>;
2208   def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2209                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2210                        addsub_shifted_imm64_neg:$imm), 0>;
2211
2212   // Compare aliases
2213   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2214                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2215   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2216                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2217   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2218                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2219   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2220                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2221   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2222                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2223   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2224                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2225   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2226                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2227
2228   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2229   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2230                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2231   def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2232                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2233
2234   // Compare shorthands
2235   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2236                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2237   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2238                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2239   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2240                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2241   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2242                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2243
2244   // Register/register aliases with no shift when SP is not used.
2245   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2246                        GPR32, GPR32, GPR32, 0>;
2247   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2248                        GPR64, GPR64, GPR64, 0>;
2249
2250   // Register/register aliases with no shift when the first source register
2251   // is SP.
2252   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2253                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2254   def : AddSubRegAlias<mnemonic,
2255                        !cast<Instruction>(NAME#"Xrx64"),
2256                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2257 }
2258
2259 //---
2260 // Extract
2261 //---
2262 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2263                                       SDTCisPtrTy<3>]>;
2264 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2265
2266 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2267                      list<dag> patterns>
2268     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2269          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2270       Sched<[WriteExtr, ReadExtrHi]> {
2271   bits<5> Rd;
2272   bits<5> Rn;
2273   bits<5> Rm;
2274   bits<6> imm;
2275
2276   let Inst{30-23} = 0b00100111;
2277   let Inst{21}    = 0;
2278   let Inst{20-16} = Rm;
2279   let Inst{15-10} = imm;
2280   let Inst{9-5}   = Rn;
2281   let Inst{4-0}   = Rd;
2282 }
2283
2284 multiclass ExtractImm<string asm> {
2285   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2286                       [(set GPR32:$Rd,
2287                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2288     let Inst{31} = 0;
2289     let Inst{22} = 0;
2290     // imm<5> must be zero.
2291     let imm{5}   = 0;
2292   }
2293   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2294                       [(set GPR64:$Rd,
2295                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2296
2297     let Inst{31} = 1;
2298     let Inst{22} = 1;
2299   }
2300 }
2301
2302 //---
2303 // Bitfield
2304 //---
2305
2306 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2307 class BaseBitfieldImm<bits<2> opc,
2308                       RegisterClass regtype, Operand imm_type, string asm>
2309     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2310          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2311       Sched<[WriteIS, ReadI]> {
2312   bits<5> Rd;
2313   bits<5> Rn;
2314   bits<6> immr;
2315   bits<6> imms;
2316
2317   let Inst{30-29} = opc;
2318   let Inst{28-23} = 0b100110;
2319   let Inst{21-16} = immr;
2320   let Inst{15-10} = imms;
2321   let Inst{9-5}   = Rn;
2322   let Inst{4-0}   = Rd;
2323 }
2324
2325 multiclass BitfieldImm<bits<2> opc, string asm> {
2326   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2327     let Inst{31} = 0;
2328     let Inst{22} = 0;
2329     // imms<5> and immr<5> must be zero, else ReservedValue().
2330     let Inst{21} = 0;
2331     let Inst{15} = 0;
2332   }
2333   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2334     let Inst{31} = 1;
2335     let Inst{22} = 1;
2336   }
2337 }
2338
2339 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2340 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2341                       RegisterClass regtype, Operand imm_type, string asm>
2342     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2343                              imm_type:$imms),
2344          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2345       Sched<[WriteIS, ReadI]> {
2346   bits<5> Rd;
2347   bits<5> Rn;
2348   bits<6> immr;
2349   bits<6> imms;
2350
2351   let Inst{30-29} = opc;
2352   let Inst{28-23} = 0b100110;
2353   let Inst{21-16} = immr;
2354   let Inst{15-10} = imms;
2355   let Inst{9-5}   = Rn;
2356   let Inst{4-0}   = Rd;
2357 }
2358
2359 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2360   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2361     let Inst{31} = 0;
2362     let Inst{22} = 0;
2363     // imms<5> and immr<5> must be zero, else ReservedValue().
2364     let Inst{21} = 0;
2365     let Inst{15} = 0;
2366   }
2367   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2368     let Inst{31} = 1;
2369     let Inst{22} = 1;
2370   }
2371 }
2372
2373 //---
2374 // Logical
2375 //---
2376
2377 // Logical (immediate)
2378 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2379                      RegisterClass sregtype, Operand imm_type, string asm,
2380                      list<dag> pattern>
2381     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2382          asm, "\t$Rd, $Rn, $imm", "", pattern>,
2383       Sched<[WriteI, ReadI]> {
2384   bits<5>  Rd;
2385   bits<5>  Rn;
2386   bits<13> imm;
2387   let Inst{30-29} = opc;
2388   let Inst{28-23} = 0b100100;
2389   let Inst{22}    = imm{12};
2390   let Inst{21-16} = imm{11-6};
2391   let Inst{15-10} = imm{5-0};
2392   let Inst{9-5}   = Rn;
2393   let Inst{4-0}   = Rd;
2394
2395   let DecoderMethod = "DecodeLogicalImmInstruction";
2396 }
2397
2398 // Logical (shifted register)
2399 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2400                       logical_shifted_reg shifted_regtype, string asm,
2401                       list<dag> pattern>
2402     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2403         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2404       Sched<[WriteISReg, ReadI, ReadISReg]> {
2405   // The operands are in order to match the 'addr' MI operands, so we
2406   // don't need an encoder method and by-name matching. Just use the default
2407   // in-order handling. Since we're using by-order, make sure the names
2408   // do not match.
2409   bits<5> dst;
2410   bits<5> src1;
2411   bits<5> src2;
2412   bits<8> shift;
2413   let Inst{30-29} = opc;
2414   let Inst{28-24} = 0b01010;
2415   let Inst{23-22} = shift{7-6};
2416   let Inst{21}    = N;
2417   let Inst{20-16} = src2;
2418   let Inst{15-10} = shift{5-0};
2419   let Inst{9-5}   = src1;
2420   let Inst{4-0}   = dst;
2421
2422   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2423 }
2424
2425 // Aliases for register+register logical instructions.
2426 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2427     : InstAlias<asm#"\t$dst, $src1, $src2",
2428                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2429
2430 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2431                       string Alias> {
2432   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2433   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2434                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2435                                                logical_imm32:$imm))]> {
2436     let Inst{31} = 0;
2437     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2438   }
2439   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2440   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2441                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2442                                                logical_imm64:$imm))]> {
2443     let Inst{31} = 1;
2444   }
2445
2446   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2447                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2448                       logical_imm32_not:$imm), 0>;
2449   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2450                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2451                        logical_imm64_not:$imm), 0>;
2452 }
2453
2454 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2455                        string Alias> {
2456   let isCompare = 1, Defs = [NZCV] in {
2457   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2458       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2459     let Inst{31} = 0;
2460     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2461   }
2462   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2463       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2464     let Inst{31} = 1;
2465   }
2466   } // end Defs = [NZCV]
2467
2468   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2469                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2470                       logical_imm32_not:$imm), 0>;
2471   def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2472                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2473                        logical_imm64_not:$imm), 0>;
2474 }
2475
2476 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2477     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2478              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2479       Sched<[WriteI, ReadI, ReadI]>;
2480
2481 // Split from LogicalImm as not all instructions have both.
2482 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2483                       SDPatternOperator OpNode> {
2484   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2485   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2486   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2487   }
2488
2489   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2490                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2491                                                  logical_shifted_reg32:$Rm))]> {
2492     let Inst{31} = 0;
2493   }
2494   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2495                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2496                                                  logical_shifted_reg64:$Rm))]> {
2497     let Inst{31} = 1;
2498   }
2499
2500   def : LogicalRegAlias<mnemonic,
2501                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2502   def : LogicalRegAlias<mnemonic,
2503                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2504 }
2505
2506 // Split from LogicalReg to allow setting NZCV Defs
2507 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2508                        SDPatternOperator OpNode = null_frag> {
2509   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2510   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2511   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2512
2513   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2514             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2515     let Inst{31} = 0;
2516   }
2517   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2518             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2519     let Inst{31} = 1;
2520   }
2521   } // Defs = [NZCV]
2522
2523   def : LogicalRegAlias<mnemonic,
2524                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2525   def : LogicalRegAlias<mnemonic,
2526                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2527 }
2528
2529 //---
2530 // Conditionally set flags
2531 //---
2532
2533 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2534 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2535                             string mnemonic, SDNode OpNode>
2536     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2537          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2538          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2539                              (i32 imm:$cond), NZCV))]>,
2540       Sched<[WriteI, ReadI]> {
2541   let Uses = [NZCV];
2542   let Defs = [NZCV];
2543
2544   bits<5> Rn;
2545   bits<5> imm;
2546   bits<4> nzcv;
2547   bits<4> cond;
2548
2549   let Inst{30}    = op;
2550   let Inst{29-21} = 0b111010010;
2551   let Inst{20-16} = imm;
2552   let Inst{15-12} = cond;
2553   let Inst{11-10} = 0b10;
2554   let Inst{9-5}   = Rn;
2555   let Inst{4}     = 0b0;
2556   let Inst{3-0}   = nzcv;
2557 }
2558
2559 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2560 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2561                             SDNode OpNode>
2562     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2563          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2564          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2565                              (i32 imm:$cond), NZCV))]>,
2566       Sched<[WriteI, ReadI, ReadI]> {
2567   let Uses = [NZCV];
2568   let Defs = [NZCV];
2569
2570   bits<5> Rn;
2571   bits<5> Rm;
2572   bits<4> nzcv;
2573   bits<4> cond;
2574
2575   let Inst{30}    = op;
2576   let Inst{29-21} = 0b111010010;
2577   let Inst{20-16} = Rm;
2578   let Inst{15-12} = cond;
2579   let Inst{11-10} = 0b00;
2580   let Inst{9-5}   = Rn;
2581   let Inst{4}     = 0b0;
2582   let Inst{3-0}   = nzcv;
2583 }
2584
2585 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2586   // immediate operand variants
2587   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2588     let Inst{31} = 0;
2589   }
2590   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2591     let Inst{31} = 1;
2592   }
2593   // register operand variants
2594   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2595     let Inst{31} = 0;
2596   }
2597   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2598     let Inst{31} = 1;
2599   }
2600 }
2601
2602 //---
2603 // Conditional select
2604 //---
2605
2606 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2607     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2608          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2609          [(set regtype:$Rd,
2610                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2611       Sched<[WriteI, ReadI, ReadI]> {
2612   let Uses = [NZCV];
2613
2614   bits<5> Rd;
2615   bits<5> Rn;
2616   bits<5> Rm;
2617   bits<4> cond;
2618
2619   let Inst{30}    = op;
2620   let Inst{29-21} = 0b011010100;
2621   let Inst{20-16} = Rm;
2622   let Inst{15-12} = cond;
2623   let Inst{11-10} = op2;
2624   let Inst{9-5}   = Rn;
2625   let Inst{4-0}   = Rd;
2626 }
2627
2628 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2629   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2630     let Inst{31} = 0;
2631   }
2632   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2633     let Inst{31} = 1;
2634   }
2635 }
2636
2637 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2638                        PatFrag frag>
2639     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2640          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2641          [(set regtype:$Rd,
2642                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2643                (i32 imm:$cond), NZCV))]>,
2644       Sched<[WriteI, ReadI, ReadI]> {
2645   let Uses = [NZCV];
2646
2647   bits<5> Rd;
2648   bits<5> Rn;
2649   bits<5> Rm;
2650   bits<4> cond;
2651
2652   let Inst{30}    = op;
2653   let Inst{29-21} = 0b011010100;
2654   let Inst{20-16} = Rm;
2655   let Inst{15-12} = cond;
2656   let Inst{11-10} = op2;
2657   let Inst{9-5}   = Rn;
2658   let Inst{4-0}   = Rd;
2659 }
2660
2661 def inv_cond_XFORM : SDNodeXForm<imm, [{
2662   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2663   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2664                                    MVT::i32);
2665 }]>;
2666
2667 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2668   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2669     let Inst{31} = 0;
2670   }
2671   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2672     let Inst{31} = 1;
2673   }
2674
2675   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2676             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2677                                            (inv_cond_XFORM imm:$cond))>;
2678
2679   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2680             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2681                                            (inv_cond_XFORM imm:$cond))>;
2682 }
2683
2684 //---
2685 // Special Mask Value
2686 //---
2687 def maski8_or_more : Operand<i32>,
2688   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2689 }
2690 def maski16_or_more : Operand<i32>,
2691   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2692 }
2693
2694
2695 //---
2696 // Load/store
2697 //---
2698
2699 // (unsigned immediate)
2700 // Indexed for 8-bit registers. offset is in range [0,4095].
2701 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2702 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2703 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2704 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2705 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2706
2707 def gi_am_indexed8 :
2708     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
2709     GIComplexPatternEquiv<am_indexed8>;
2710 def gi_am_indexed16 :
2711     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
2712     GIComplexPatternEquiv<am_indexed16>;
2713 def gi_am_indexed32 :
2714     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
2715     GIComplexPatternEquiv<am_indexed32>;
2716 def gi_am_indexed64 :
2717     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
2718     GIComplexPatternEquiv<am_indexed64>;
2719 def gi_am_indexed128 :
2720     GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
2721     GIComplexPatternEquiv<am_indexed128>;
2722
2723 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2724   let Name = "UImm12Offset" # Scale;
2725   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2726   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2727   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2728 }
2729
2730 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2731 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2732 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2733 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2734 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2735
2736 class uimm12_scaled<int Scale> : Operand<i64> {
2737   let ParserMatchClass
2738    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2739   let EncoderMethod
2740    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2741   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2742 }
2743
2744 def uimm12s1 : uimm12_scaled<1>;
2745 def uimm12s2 : uimm12_scaled<2>;
2746 def uimm12s4 : uimm12_scaled<4>;
2747 def uimm12s8 : uimm12_scaled<8>;
2748 def uimm12s16 : uimm12_scaled<16>;
2749
2750 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2751                       string asm, list<dag> pattern>
2752     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2753   bits<5> Rt;
2754
2755   bits<5> Rn;
2756   bits<12> offset;
2757
2758   let Inst{31-30} = sz;
2759   let Inst{29-27} = 0b111;
2760   let Inst{26}    = V;
2761   let Inst{25-24} = 0b01;
2762   let Inst{23-22} = opc;
2763   let Inst{21-10} = offset;
2764   let Inst{9-5}   = Rn;
2765   let Inst{4-0}   = Rt;
2766
2767   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2768 }
2769
2770 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2771                   Operand indextype, string asm, list<dag> pattern> {
2772   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2773   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2774                            (ins GPR64sp:$Rn, indextype:$offset),
2775                            asm, pattern>,
2776            Sched<[WriteLD]>;
2777
2778   def : InstAlias<asm # "\t$Rt, [$Rn]",
2779                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2780 }
2781
2782 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2783              Operand indextype, string asm, list<dag> pattern> {
2784   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2785   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2786                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2787                            asm, pattern>,
2788            Sched<[WriteST]>;
2789
2790   def : InstAlias<asm # "\t$Rt, [$Rn]",
2791                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2792 }
2793
2794 // Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
2795 // substitute zero-registers automatically.
2796 //
2797 // TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
2798 //       into StoreUI.
2799 multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2800              Operand indextype, string asm, list<dag> pattern> {
2801   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2802   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2803                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2804                            asm, pattern>,
2805            Sched<[WriteST]>;
2806
2807   def : InstAlias<asm # "\t$Rt, [$Rn]",
2808                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2809 }
2810
2811 def PrefetchOperand : AsmOperandClass {
2812   let Name = "Prefetch";
2813   let ParserMethod = "tryParsePrefetch";
2814 }
2815 def prfop : Operand<i32> {
2816   let PrintMethod = "printPrefetchOp";
2817   let ParserMatchClass = PrefetchOperand;
2818 }
2819
2820 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2821 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2822     : BaseLoadStoreUI<sz, V, opc,
2823                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2824                       asm, pat>,
2825       Sched<[WriteLD]>;
2826
2827 //---
2828 // Load literal
2829 //---
2830
2831 // Load literal address: 19-bit immediate. The low two bits of the target
2832 // offset are implied zero and so are not part of the immediate.
2833 def am_ldrlit : Operand<iPTR> {
2834   let EncoderMethod = "getLoadLiteralOpValue";
2835   let DecoderMethod = "DecodePCRelLabel19";
2836   let PrintMethod = "printAlignedLabel";
2837   let ParserMatchClass = PCRelLabel19Operand;
2838   let OperandType = "OPERAND_PCREL";
2839 }
2840
2841 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2842 class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm>
2843     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2844         asm, "\t$Rt, $label", "", []>,
2845       Sched<[WriteLD]> {
2846   bits<5> Rt;
2847   bits<19> label;
2848   let Inst{31-30} = opc;
2849   let Inst{29-27} = 0b011;
2850   let Inst{26}    = V;
2851   let Inst{25-24} = 0b00;
2852   let Inst{23-5}  = label;
2853   let Inst{4-0}   = Rt;
2854 }
2855
2856 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2857 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2858     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2859         asm, "\t$Rt, $label", "", pat>,
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 //---
2872 // Load/store register offset
2873 //---
2874
2875 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2876 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2877 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2878 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2879 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2880
2881 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2882 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2883 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2884 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2885 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2886
2887 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2888   let Name = "Mem" # Reg # "Extend" # Width;
2889   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2890   let RenderMethod = "addMemExtendOperands";
2891   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2892 }
2893
2894 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2895   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2896   // the trivial shift.
2897   let RenderMethod = "addMemExtend8Operands";
2898 }
2899 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2900 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2901 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2902 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2903
2904 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2905   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2906   // the trivial shift.
2907   let RenderMethod = "addMemExtend8Operands";
2908 }
2909 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2910 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2911 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2912 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2913
2914 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2915         : Operand<i32> {
2916   let ParserMatchClass = ParserClass;
2917   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2918   let DecoderMethod = "DecodeMemExtend";
2919   let EncoderMethod = "getMemExtendOpValue";
2920   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2921 }
2922
2923 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2924 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2925 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2926 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2927 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2928
2929 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2930 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2931 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2932 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2933 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2934
2935 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2936                   Operand wextend, Operand xextend>  {
2937   // CodeGen-level pattern covering the entire addressing mode.
2938   ComplexPattern Wpat = windex;
2939   ComplexPattern Xpat = xindex;
2940
2941   // Asm-level Operand covering the valid "uxtw #3" style syntax.
2942   Operand Wext = wextend;
2943   Operand Xext = xextend;
2944 }
2945
2946 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2947 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2948 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2949 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2950 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2951                        ro_Xextend128>;
2952
2953 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2954                       string asm, dag ins, dag outs, list<dag> pat>
2955     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2956   bits<5> Rt;
2957   bits<5> Rn;
2958   bits<5> Rm;
2959   bits<2> extend;
2960   let Inst{31-30} = sz;
2961   let Inst{29-27} = 0b111;
2962   let Inst{26}    = V;
2963   let Inst{25-24} = 0b00;
2964   let Inst{23-22} = opc;
2965   let Inst{21}    = 1;
2966   let Inst{20-16} = Rm;
2967   let Inst{15}    = extend{1}; // sign extend Rm?
2968   let Inst{14}    = 1;
2969   let Inst{12}    = extend{0}; // do shift?
2970   let Inst{11-10} = 0b10;
2971   let Inst{9-5}   = Rn;
2972   let Inst{4-0}   = Rt;
2973 }
2974
2975 class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
2976   : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
2977               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2978
2979 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
2980                    string asm, ValueType Ty, SDPatternOperator loadop> {
2981   let AddedComplexity = 10 in
2982   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2983                  (outs regtype:$Rt),
2984                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2985                  [(set (Ty regtype:$Rt),
2986                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2987                                              ro_Wextend8:$extend)))]>,
2988            Sched<[WriteLDIdx, ReadAdrBase]> {
2989     let Inst{13} = 0b0;
2990   }
2991
2992   let AddedComplexity = 10 in
2993   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2994                  (outs regtype:$Rt),
2995                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2996                  [(set (Ty regtype:$Rt),
2997                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2998                                              ro_Xextend8:$extend)))]>,
2999            Sched<[WriteLDIdx, ReadAdrBase]> {
3000     let Inst{13} = 0b1;
3001   }
3002
3003   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3004 }
3005
3006 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3007                     string asm, ValueType Ty, SDPatternOperator storeop> {
3008   let AddedComplexity = 10 in
3009   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3010                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3011                  [(storeop (Ty regtype:$Rt),
3012                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3013                                          ro_Wextend8:$extend))]>,
3014             Sched<[WriteSTIdx, ReadAdrBase]> {
3015     let Inst{13} = 0b0;
3016   }
3017
3018   let AddedComplexity = 10 in
3019   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3020                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3021                  [(storeop (Ty regtype:$Rt),
3022                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3023                                          ro_Xextend8:$extend))]>,
3024             Sched<[WriteSTIdx, ReadAdrBase]> {
3025     let Inst{13} = 0b1;
3026   }
3027
3028   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3029 }
3030
3031 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3032                       string asm, dag ins, dag outs, list<dag> pat>
3033     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3034   bits<5> Rt;
3035   bits<5> Rn;
3036   bits<5> Rm;
3037   bits<2> extend;
3038   let Inst{31-30} = sz;
3039   let Inst{29-27} = 0b111;
3040   let Inst{26}    = V;
3041   let Inst{25-24} = 0b00;
3042   let Inst{23-22} = opc;
3043   let Inst{21}    = 1;
3044   let Inst{20-16} = Rm;
3045   let Inst{15}    = extend{1}; // sign extend Rm?
3046   let Inst{14}    = 1;
3047   let Inst{12}    = extend{0}; // do shift?
3048   let Inst{11-10} = 0b10;
3049   let Inst{9-5}   = Rn;
3050   let Inst{4-0}   = Rt;
3051 }
3052
3053 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3054                     string asm, ValueType Ty, SDPatternOperator loadop> {
3055   let AddedComplexity = 10 in
3056   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3057                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3058                  [(set (Ty regtype:$Rt),
3059                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3060                                               ro_Wextend16:$extend)))]>,
3061             Sched<[WriteLDIdx, ReadAdrBase]> {
3062     let Inst{13} = 0b0;
3063   }
3064
3065   let AddedComplexity = 10 in
3066   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3067                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3068                  [(set (Ty regtype:$Rt),
3069                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3070                                              ro_Xextend16:$extend)))]>,
3071             Sched<[WriteLDIdx, ReadAdrBase]> {
3072     let Inst{13} = 0b1;
3073   }
3074
3075   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3076 }
3077
3078 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3079                      string asm, ValueType Ty, SDPatternOperator storeop> {
3080   let AddedComplexity = 10 in
3081   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3082                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3083                 [(storeop (Ty regtype:$Rt),
3084                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3085                                          ro_Wextend16:$extend))]>,
3086            Sched<[WriteSTIdx, ReadAdrBase]> {
3087     let Inst{13} = 0b0;
3088   }
3089
3090   let AddedComplexity = 10 in
3091   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3092                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3093                 [(storeop (Ty regtype:$Rt),
3094                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3095                                          ro_Xextend16:$extend))]>,
3096            Sched<[WriteSTIdx, ReadAdrBase]> {
3097     let Inst{13} = 0b1;
3098   }
3099
3100   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3101 }
3102
3103 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3104                       string asm, dag ins, dag outs, list<dag> pat>
3105     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3106   bits<5> Rt;
3107   bits<5> Rn;
3108   bits<5> Rm;
3109   bits<2> extend;
3110   let Inst{31-30} = sz;
3111   let Inst{29-27} = 0b111;
3112   let Inst{26}    = V;
3113   let Inst{25-24} = 0b00;
3114   let Inst{23-22} = opc;
3115   let Inst{21}    = 1;
3116   let Inst{20-16} = Rm;
3117   let Inst{15}    = extend{1}; // sign extend Rm?
3118   let Inst{14}    = 1;
3119   let Inst{12}    = extend{0}; // do shift?
3120   let Inst{11-10} = 0b10;
3121   let Inst{9-5}   = Rn;
3122   let Inst{4-0}   = Rt;
3123 }
3124
3125 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3126                     string asm, ValueType Ty, SDPatternOperator loadop> {
3127   let AddedComplexity = 10 in
3128   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3129                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3130                  [(set (Ty regtype:$Rt),
3131                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3132                                               ro_Wextend32:$extend)))]>,
3133            Sched<[WriteLDIdx, ReadAdrBase]> {
3134     let Inst{13} = 0b0;
3135   }
3136
3137   let AddedComplexity = 10 in
3138   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3139                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3140                  [(set (Ty regtype:$Rt),
3141                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3142                                               ro_Xextend32:$extend)))]>,
3143            Sched<[WriteLDIdx, ReadAdrBase]> {
3144     let Inst{13} = 0b1;
3145   }
3146
3147   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3148 }
3149
3150 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3151                      string asm, ValueType Ty, SDPatternOperator storeop> {
3152   let AddedComplexity = 10 in
3153   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3154                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3155                 [(storeop (Ty regtype:$Rt),
3156                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3157                                          ro_Wextend32:$extend))]>,
3158             Sched<[WriteSTIdx, ReadAdrBase]> {
3159     let Inst{13} = 0b0;
3160   }
3161
3162   let AddedComplexity = 10 in
3163   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3164                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3165                 [(storeop (Ty regtype:$Rt),
3166                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3167                                         ro_Xextend32:$extend))]>,
3168             Sched<[WriteSTIdx, ReadAdrBase]> {
3169     let Inst{13} = 0b1;
3170   }
3171
3172   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3173 }
3174
3175 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3176                       string asm, dag ins, dag outs, list<dag> pat>
3177     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3178   bits<5> Rt;
3179   bits<5> Rn;
3180   bits<5> Rm;
3181   bits<2> extend;
3182   let Inst{31-30} = sz;
3183   let Inst{29-27} = 0b111;
3184   let Inst{26}    = V;
3185   let Inst{25-24} = 0b00;
3186   let Inst{23-22} = opc;
3187   let Inst{21}    = 1;
3188   let Inst{20-16} = Rm;
3189   let Inst{15}    = extend{1}; // sign extend Rm?
3190   let Inst{14}    = 1;
3191   let Inst{12}    = extend{0}; // do shift?
3192   let Inst{11-10} = 0b10;
3193   let Inst{9-5}   = Rn;
3194   let Inst{4-0}   = Rt;
3195 }
3196
3197 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3198                     string asm, ValueType Ty, SDPatternOperator loadop> {
3199   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3200   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3201                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3202                 [(set (Ty regtype:$Rt),
3203                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3204                                              ro_Wextend64:$extend)))]>,
3205            Sched<[WriteLDIdx, ReadAdrBase]> {
3206     let Inst{13} = 0b0;
3207   }
3208
3209   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3210   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3211                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3212                  [(set (Ty regtype:$Rt),
3213                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3214                                               ro_Xextend64:$extend)))]>,
3215            Sched<[WriteLDIdx, ReadAdrBase]> {
3216     let Inst{13} = 0b1;
3217   }
3218
3219   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3220 }
3221
3222 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3223                      string asm, ValueType Ty, SDPatternOperator storeop> {
3224   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3225   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3226                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3227                 [(storeop (Ty regtype:$Rt),
3228                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3229                                          ro_Wextend64:$extend))]>,
3230             Sched<[WriteSTIdx, ReadAdrBase]> {
3231     let Inst{13} = 0b0;
3232   }
3233
3234   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3235   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3236                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3237                 [(storeop (Ty regtype:$Rt),
3238                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3239                                          ro_Xextend64:$extend))]>,
3240             Sched<[WriteSTIdx, ReadAdrBase]> {
3241     let Inst{13} = 0b1;
3242   }
3243
3244   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3245 }
3246
3247 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3248                       string asm, dag ins, dag outs, list<dag> pat>
3249     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3250   bits<5> Rt;
3251   bits<5> Rn;
3252   bits<5> Rm;
3253   bits<2> extend;
3254   let Inst{31-30} = sz;
3255   let Inst{29-27} = 0b111;
3256   let Inst{26}    = V;
3257   let Inst{25-24} = 0b00;
3258   let Inst{23-22} = opc;
3259   let Inst{21}    = 1;
3260   let Inst{20-16} = Rm;
3261   let Inst{15}    = extend{1}; // sign extend Rm?
3262   let Inst{14}    = 1;
3263   let Inst{12}    = extend{0}; // do shift?
3264   let Inst{11-10} = 0b10;
3265   let Inst{9-5}   = Rn;
3266   let Inst{4-0}   = Rt;
3267 }
3268
3269 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3270                      string asm, ValueType Ty, SDPatternOperator loadop> {
3271   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3272   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3273                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3274                  [(set (Ty regtype:$Rt),
3275                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3276                                                ro_Wextend128:$extend)))]>,
3277             Sched<[WriteLDIdx, ReadAdrBase]> {
3278     let Inst{13} = 0b0;
3279   }
3280
3281   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3282   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3283                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3284                  [(set (Ty regtype:$Rt),
3285                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3286                                                ro_Xextend128:$extend)))]>,
3287             Sched<[WriteLDIdx, ReadAdrBase]> {
3288     let Inst{13} = 0b1;
3289   }
3290
3291   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3292 }
3293
3294 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3295                       string asm, ValueType Ty, SDPatternOperator storeop> {
3296   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3297   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3298                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3299                 []>,
3300             Sched<[WriteSTIdx, ReadAdrBase]> {
3301     let Inst{13} = 0b0;
3302   }
3303
3304   let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3305   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3306                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3307                 []>,
3308             Sched<[WriteSTIdx, ReadAdrBase]> {
3309     let Inst{13} = 0b1;
3310   }
3311
3312   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3313 }
3314
3315 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3316 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3317                      string asm, list<dag> pat>
3318     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3319       Sched<[WriteLD]> {
3320   bits<5> Rt;
3321   bits<5> Rn;
3322   bits<5> Rm;
3323   bits<2> extend;
3324   let Inst{31-30} = sz;
3325   let Inst{29-27} = 0b111;
3326   let Inst{26}    = V;
3327   let Inst{25-24} = 0b00;
3328   let Inst{23-22} = opc;
3329   let Inst{21}    = 1;
3330   let Inst{20-16} = Rm;
3331   let Inst{15}    = extend{1}; // sign extend Rm?
3332   let Inst{14}    = 1;
3333   let Inst{12}    = extend{0}; // do shift?
3334   let Inst{11-10} = 0b10;
3335   let Inst{9-5}   = Rn;
3336   let Inst{4-0}   = Rt;
3337 }
3338
3339 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3340   def roW : BasePrefetchRO<sz, V, opc, (outs),
3341                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3342                 asm, [(AArch64Prefetch imm:$Rt,
3343                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3344                                                     ro_Wextend64:$extend))]> {
3345     let Inst{13} = 0b0;
3346   }
3347
3348   def roX : BasePrefetchRO<sz, V, opc, (outs),
3349                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3350                 asm,  [(AArch64Prefetch imm:$Rt,
3351                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3352                                                      ro_Xextend64:$extend))]> {
3353     let Inst{13} = 0b1;
3354   }
3355
3356   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3357                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3358                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3359 }
3360
3361 //---
3362 // Load/store unscaled immediate
3363 //---
3364
3365 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3366 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3367 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3368 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3369 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3370
3371 def gi_am_unscaled8 :
3372     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3373     GIComplexPatternEquiv<am_unscaled8>;
3374 def gi_am_unscaled16 :
3375     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3376     GIComplexPatternEquiv<am_unscaled16>;
3377 def gi_am_unscaled32 :
3378     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3379     GIComplexPatternEquiv<am_unscaled32>;
3380 def gi_am_unscaled64 :
3381     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3382     GIComplexPatternEquiv<am_unscaled64>;
3383 def gi_am_unscaled128 :
3384     GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3385     GIComplexPatternEquiv<am_unscaled128>;
3386
3387
3388 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3389                            string asm, list<dag> pattern>
3390     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3391   bits<5> Rt;
3392   bits<5> Rn;
3393   bits<9> offset;
3394   let Inst{31-30} = sz;
3395   let Inst{29-27} = 0b111;
3396   let Inst{26}    = V;
3397   let Inst{25-24} = 0b00;
3398   let Inst{23-22} = opc;
3399   let Inst{21}    = 0;
3400   let Inst{20-12} = offset;
3401   let Inst{11-10} = 0b00;
3402   let Inst{9-5}   = Rn;
3403   let Inst{4-0}   = Rt;
3404
3405   let DecoderMethod = "DecodeSignedLdStInstruction";
3406 }
3407
3408 // Armv8.4 LDAPR & STLR with Immediate Offset instruction
3409 multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3410                               RegisterOperand regtype > {
3411   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3412                                (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3413           Sched<[WriteST]> {
3414     let Inst{29} = 0;
3415     let Inst{24} = 1;
3416   }
3417   def : InstAlias<asm # "\t$Rt, [$Rn]",
3418                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3419 }
3420
3421 multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3422                                RegisterOperand regtype > {
3423   def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3424                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3425                                asm, []>,
3426           Sched<[WriteST]> {
3427     let Inst{29} = 0;
3428     let Inst{24} = 1;
3429   }
3430   def : InstAlias<asm # "\t$Rt, [$Rn]",
3431                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3432 }
3433
3434 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3435                    string asm, list<dag> pattern> {
3436   let AddedComplexity = 1 in // try this before LoadUI
3437   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3438                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3439           Sched<[WriteLD]>;
3440
3441   def : InstAlias<asm # "\t$Rt, [$Rn]",
3442                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3443 }
3444
3445 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3446                          string asm, list<dag> pattern> {
3447   let AddedComplexity = 1 in // try this before StoreUI
3448   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3449                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3450                                asm, pattern>,
3451           Sched<[WriteST]>;
3452
3453   def : InstAlias<asm # "\t$Rt, [$Rn]",
3454                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3455 }
3456
3457 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3458                             list<dag> pat> {
3459   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3460   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3461                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3462                                asm, pat>,
3463           Sched<[WriteLD]>;
3464
3465   def : InstAlias<asm # "\t$Rt, [$Rn]",
3466                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3467 }
3468
3469 //---
3470 // Load/store unscaled immediate, unprivileged
3471 //---
3472
3473 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3474                                 dag oops, dag iops, string asm>
3475     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3476   bits<5> Rt;
3477   bits<5> Rn;
3478   bits<9> offset;
3479   let Inst{31-30} = sz;
3480   let Inst{29-27} = 0b111;
3481   let Inst{26}    = V;
3482   let Inst{25-24} = 0b00;
3483   let Inst{23-22} = opc;
3484   let Inst{21}    = 0;
3485   let Inst{20-12} = offset;
3486   let Inst{11-10} = 0b10;
3487   let Inst{9-5}   = Rn;
3488   let Inst{4-0}   = Rt;
3489
3490   let DecoderMethod = "DecodeSignedLdStInstruction";
3491 }
3492
3493 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3494                             RegisterClass regtype, string asm> {
3495   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3496   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3497                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
3498           Sched<[WriteLD]>;
3499
3500   def : InstAlias<asm # "\t$Rt, [$Rn]",
3501                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3502 }
3503
3504 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3505                              RegisterClass regtype, string asm> {
3506   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3507   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3508                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3509                                  asm>,
3510           Sched<[WriteST]>;
3511
3512   def : InstAlias<asm # "\t$Rt, [$Rn]",
3513                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3514 }
3515
3516 //---
3517 // Load/store pre-indexed
3518 //---
3519
3520 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3521                           string asm, string cstr, list<dag> pat>
3522     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3523   bits<5> Rt;
3524   bits<5> Rn;
3525   bits<9> offset;
3526   let Inst{31-30} = sz;
3527   let Inst{29-27} = 0b111;
3528   let Inst{26}    = V;
3529   let Inst{25-24} = 0;
3530   let Inst{23-22} = opc;
3531   let Inst{21}    = 0;
3532   let Inst{20-12} = offset;
3533   let Inst{11-10} = 0b11;
3534   let Inst{9-5}   = Rn;
3535   let Inst{4-0}   = Rt;
3536
3537   let DecoderMethod = "DecodeSignedLdStInstruction";
3538 }
3539
3540 let hasSideEffects = 0 in {
3541 let mayStore = 0, mayLoad = 1 in
3542 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3543              string asm>
3544     : BaseLoadStorePreIdx<sz, V, opc,
3545                      (outs GPR64sp:$wback, regtype:$Rt),
3546                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3547                      "$Rn = $wback,@earlyclobber $wback", []>,
3548       Sched<[WriteLD, WriteAdr]>;
3549
3550 let mayStore = 1, mayLoad = 0 in
3551 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3552                   string asm, SDPatternOperator storeop, ValueType Ty>
3553     : BaseLoadStorePreIdx<sz, V, opc,
3554                       (outs GPR64sp:$wback),
3555                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3556                       asm, "$Rn = $wback,@earlyclobber $wback",
3557       [(set GPR64sp:$wback,
3558             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3559       Sched<[WriteAdr, WriteST]>;
3560 } // hasSideEffects = 0
3561
3562 //---
3563 // Load/store post-indexed
3564 //---
3565
3566 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3567                           string asm, string cstr, list<dag> pat>
3568     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3569   bits<5> Rt;
3570   bits<5> Rn;
3571   bits<9> offset;
3572   let Inst{31-30} = sz;
3573   let Inst{29-27} = 0b111;
3574   let Inst{26}    = V;
3575   let Inst{25-24} = 0b00;
3576   let Inst{23-22} = opc;
3577   let Inst{21}    = 0b0;
3578   let Inst{20-12} = offset;
3579   let Inst{11-10} = 0b01;
3580   let Inst{9-5}   = Rn;
3581   let Inst{4-0}   = Rt;
3582
3583   let DecoderMethod = "DecodeSignedLdStInstruction";
3584 }
3585
3586 let hasSideEffects = 0 in {
3587 let mayStore = 0, mayLoad = 1 in
3588 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3589              string asm>
3590     : BaseLoadStorePostIdx<sz, V, opc,
3591                       (outs GPR64sp:$wback, regtype:$Rt),
3592                       (ins GPR64sp:$Rn, simm9:$offset),
3593                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3594       Sched<[WriteLD, WriteAdr]>;
3595
3596 let mayStore = 1, mayLoad = 0 in
3597 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3598                    string asm, SDPatternOperator storeop, ValueType Ty>
3599     : BaseLoadStorePostIdx<sz, V, opc,
3600                       (outs GPR64sp:$wback),
3601                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3602                        asm, "$Rn = $wback,@earlyclobber $wback",
3603       [(set GPR64sp:$wback,
3604             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3605     Sched<[WriteAdr, WriteST]>;
3606 } // hasSideEffects = 0
3607
3608
3609 //---
3610 // Load/store pair
3611 //---
3612
3613 // (indexed, offset)
3614
3615 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3616                               string asm>
3617     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3618   bits<5> Rt;
3619   bits<5> Rt2;
3620   bits<5> Rn;
3621   bits<7> offset;
3622   let Inst{31-30} = opc;
3623   let Inst{29-27} = 0b101;
3624   let Inst{26}    = V;
3625   let Inst{25-23} = 0b010;
3626   let Inst{22}    = L;
3627   let Inst{21-15} = offset;
3628   let Inst{14-10} = Rt2;
3629   let Inst{9-5}   = Rn;
3630   let Inst{4-0}   = Rt;
3631
3632   let DecoderMethod = "DecodePairLdStInstruction";
3633 }
3634
3635 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3636                           Operand indextype, string asm> {
3637   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3638   def i : BaseLoadStorePairOffset<opc, V, 1,
3639                                   (outs regtype:$Rt, regtype:$Rt2),
3640                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3641           Sched<[WriteLD, WriteLDHi]>;
3642
3643   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3644                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3645                                                   GPR64sp:$Rn, 0)>;
3646 }
3647
3648
3649 multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3650                            Operand indextype, string asm> {
3651   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3652   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3653                                   (ins regtype:$Rt, regtype:$Rt2,
3654                                        GPR64sp:$Rn, indextype:$offset),
3655                                   asm>,
3656           Sched<[WriteSTP]>;
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 // (pre-indexed)
3664 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3665                               string asm>
3666     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3667   bits<5> Rt;
3668   bits<5> Rt2;
3669   bits<5> Rn;
3670   bits<7> offset;
3671   let Inst{31-30} = opc;
3672   let Inst{29-27} = 0b101;
3673   let Inst{26}    = V;
3674   let Inst{25-23} = 0b011;
3675   let Inst{22}    = L;
3676   let Inst{21-15} = offset;
3677   let Inst{14-10} = Rt2;
3678   let Inst{9-5}   = Rn;
3679   let Inst{4-0}   = Rt;
3680
3681   let DecoderMethod = "DecodePairLdStInstruction";
3682 }
3683
3684 let hasSideEffects = 0 in {
3685 let mayStore = 0, mayLoad = 1 in
3686 class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3687                      Operand indextype, string asm>
3688     : BaseLoadStorePairPreIdx<opc, V, 1,
3689                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3690                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3691       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3692
3693 let mayStore = 1, mayLoad = 0 in
3694 class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3695                       Operand indextype, string asm>
3696     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3697                              (ins regtype:$Rt, regtype:$Rt2,
3698                                   GPR64sp:$Rn, indextype:$offset),
3699                              asm>,
3700       Sched<[WriteAdr, WriteSTP]>;
3701 } // hasSideEffects = 0
3702
3703 // (post-indexed)
3704
3705 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3706                               string asm>
3707     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3708   bits<5> Rt;
3709   bits<5> Rt2;
3710   bits<5> Rn;
3711   bits<7> offset;
3712   let Inst{31-30} = opc;
3713   let Inst{29-27} = 0b101;
3714   let Inst{26}    = V;
3715   let Inst{25-23} = 0b001;
3716   let Inst{22}    = L;
3717   let Inst{21-15} = offset;
3718   let Inst{14-10} = Rt2;
3719   let Inst{9-5}   = Rn;
3720   let Inst{4-0}   = Rt;
3721
3722   let DecoderMethod = "DecodePairLdStInstruction";
3723 }
3724
3725 let hasSideEffects = 0 in {
3726 let mayStore = 0, mayLoad = 1 in
3727 class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3728                       Operand idxtype, string asm>
3729     : BaseLoadStorePairPostIdx<opc, V, 1,
3730                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3731                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3732       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3733
3734 let mayStore = 1, mayLoad = 0 in
3735 class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3736                        Operand idxtype, string asm>
3737     : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3738                              (ins regtype:$Rt, regtype:$Rt2,
3739                                   GPR64sp:$Rn, idxtype:$offset),
3740                              asm>,
3741       Sched<[WriteAdr, WriteSTP]>;
3742 } // hasSideEffects = 0
3743
3744 //  (no-allocate)
3745
3746 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3747                               string asm>
3748     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3749   bits<5> Rt;
3750   bits<5> Rt2;
3751   bits<5> Rn;
3752   bits<7> offset;
3753   let Inst{31-30} = opc;
3754   let Inst{29-27} = 0b101;
3755   let Inst{26}    = V;
3756   let Inst{25-23} = 0b000;
3757   let Inst{22}    = L;
3758   let Inst{21-15} = offset;
3759   let Inst{14-10} = Rt2;
3760   let Inst{9-5}   = Rn;
3761   let Inst{4-0}   = Rt;
3762
3763   let DecoderMethod = "DecodePairLdStInstruction";
3764 }
3765
3766 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3767                            Operand indextype, string asm> {
3768   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3769   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3770                                    (outs regtype:$Rt, regtype:$Rt2),
3771                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3772           Sched<[WriteLD, WriteLDHi]>;
3773
3774
3775   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3776                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3777                                                   GPR64sp:$Rn, 0)>;
3778 }
3779
3780 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3781                       Operand indextype, string asm> {
3782   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3783   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3784                                    (ins regtype:$Rt, regtype:$Rt2,
3785                                         GPR64sp:$Rn, indextype:$offset),
3786                                    asm>,
3787           Sched<[WriteSTP]>;
3788
3789   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3790                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3791                                                   GPR64sp:$Rn, 0)>;
3792 }
3793
3794 //---
3795 // Load/store exclusive
3796 //---
3797
3798 // True exclusive operations write to and/or read from the system's exclusive
3799 // monitors, which as far as a compiler is concerned can be modelled as a
3800 // random shared memory address. Hence LoadExclusive mayStore.
3801 //
3802 // Since these instructions have the undefined register bits set to 1 in
3803 // their canonical form, we need a post encoder method to set those bits
3804 // to 1 when encoding these instructions. We do this using the
3805 // fixLoadStoreExclusive function. This function has template parameters:
3806 //
3807 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3808 //
3809 // hasRs indicates that the instruction uses the Rs field, so we won't set
3810 // it to 1 (and the same for Rt2). We don't need template parameters for
3811 // the other register fields since Rt and Rn are always used.
3812 //
3813 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3814 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3815                              dag oops, dag iops, string asm, string operands>
3816     : I<oops, iops, asm, operands, "", []> {
3817   let Inst{31-30} = sz;
3818   let Inst{29-24} = 0b001000;
3819   let Inst{23}    = o2;
3820   let Inst{22}    = L;
3821   let Inst{21}    = o1;
3822   let Inst{15}    = o0;
3823
3824   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3825 }
3826
3827 // Neither Rs nor Rt2 operands.
3828 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3829                                dag oops, dag iops, string asm, string operands>
3830     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3831   bits<5> Rt;
3832   bits<5> Rn;
3833   let Inst{20-16} = 0b11111;
3834   let Unpredictable{20-16} = 0b11111;
3835   let Inst{14-10} = 0b11111;
3836   let Unpredictable{14-10} = 0b11111;
3837   let Inst{9-5} = Rn;
3838   let Inst{4-0} = Rt;
3839
3840   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3841 }
3842
3843 // Simple load acquires don't set the exclusive monitor
3844 let mayLoad = 1, mayStore = 0 in
3845 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3846                   RegisterClass regtype, string asm>
3847     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3848                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3849       Sched<[WriteLD]>;
3850
3851 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3852                     RegisterClass regtype, string asm>
3853     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3854                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3855       Sched<[WriteLD]>;
3856
3857 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3858                        RegisterClass regtype, string asm>
3859     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3860                              (outs regtype:$Rt, regtype:$Rt2),
3861                              (ins GPR64sp0:$Rn), asm,
3862                              "\t$Rt, $Rt2, [$Rn]">,
3863       Sched<[WriteLD, WriteLDHi]> {
3864   bits<5> Rt;
3865   bits<5> Rt2;
3866   bits<5> Rn;
3867   let Inst{14-10} = Rt2;
3868   let Inst{9-5} = Rn;
3869   let Inst{4-0} = Rt;
3870
3871   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3872 }
3873
3874 // Simple store release operations do not check the exclusive monitor.
3875 let mayLoad = 0, mayStore = 1 in
3876 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3877                    RegisterClass regtype, string asm>
3878     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3879                                (ins regtype:$Rt, GPR64sp0:$Rn),
3880                                asm, "\t$Rt, [$Rn]">,
3881       Sched<[WriteST]>;
3882
3883 let mayLoad = 1, mayStore = 1 in
3884 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3885                      RegisterClass regtype, string asm>
3886     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3887                              (ins regtype:$Rt, GPR64sp0:$Rn),
3888                              asm, "\t$Ws, $Rt, [$Rn]">,
3889       Sched<[WriteSTX]> {
3890   bits<5> Ws;
3891   bits<5> Rt;
3892   bits<5> Rn;
3893   let Inst{20-16} = Ws;
3894   let Inst{9-5} = Rn;
3895   let Inst{4-0} = Rt;
3896
3897   let Constraints = "@earlyclobber $Ws";
3898   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3899 }
3900
3901 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3902                          RegisterClass regtype, string asm>
3903     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3904                              (outs GPR32:$Ws),
3905                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3906                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3907       Sched<[WriteSTX]> {
3908   bits<5> Ws;
3909   bits<5> Rt;
3910   bits<5> Rt2;
3911   bits<5> Rn;
3912   let Inst{20-16} = Ws;
3913   let Inst{14-10} = Rt2;
3914   let Inst{9-5} = Rn;
3915   let Inst{4-0} = Rt;
3916
3917   let Constraints = "@earlyclobber $Ws";
3918 }
3919
3920 //---
3921 // Exception generation
3922 //---
3923
3924 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3925 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3926     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3927       Sched<[WriteSys]> {
3928   bits<16> imm;
3929   let Inst{31-24} = 0b11010100;
3930   let Inst{23-21} = op1;
3931   let Inst{20-5}  = imm;
3932   let Inst{4-2}   = 0b000;
3933   let Inst{1-0}   = ll;
3934 }
3935
3936 let Predicates = [HasFPARMv8] in {
3937
3938 //---
3939 // Floating point to integer conversion
3940 //---
3941
3942 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3943                       RegisterClass srcType, RegisterClass dstType,
3944                       string asm, list<dag> pattern>
3945     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3946          asm, "\t$Rd, $Rn", "", pattern>,
3947       Sched<[WriteFCvt]> {
3948   bits<5> Rd;
3949   bits<5> Rn;
3950   let Inst{30-29} = 0b00;
3951   let Inst{28-24} = 0b11110;
3952   let Inst{23-22} = type;
3953   let Inst{21}    = 1;
3954   let Inst{20-19} = rmode;
3955   let Inst{18-16} = opcode;
3956   let Inst{15-10} = 0;
3957   let Inst{9-5}   = Rn;
3958   let Inst{4-0}   = Rd;
3959 }
3960
3961 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3962 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3963                       RegisterClass srcType, RegisterClass dstType,
3964                       Operand immType, string asm, list<dag> pattern>
3965     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3966          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3967       Sched<[WriteFCvt]> {
3968   bits<5> Rd;
3969   bits<5> Rn;
3970   bits<6> scale;
3971   let Inst{30-29} = 0b00;
3972   let Inst{28-24} = 0b11110;
3973   let Inst{23-22} = type;
3974   let Inst{21}    = 0;
3975   let Inst{20-19} = rmode;
3976   let Inst{18-16} = opcode;
3977   let Inst{15-10} = scale;
3978   let Inst{9-5}   = Rn;
3979   let Inst{4-0}   = Rd;
3980 }
3981
3982 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3983            SDPatternOperator OpN> {
3984   // Unscaled half-precision to 32-bit
3985   def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
3986                                      [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
3987     let Inst{31} = 0; // 32-bit GPR flag
3988     let Predicates = [HasFullFP16];
3989   }
3990
3991   // Unscaled half-precision to 64-bit
3992   def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
3993                                      [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
3994     let Inst{31} = 1; // 64-bit GPR flag
3995     let Predicates = [HasFullFP16];
3996   }
3997
3998   // Unscaled single-precision to 32-bit
3999   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4000                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4001     let Inst{31} = 0; // 32-bit GPR flag
4002   }
4003
4004   // Unscaled single-precision to 64-bit
4005   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4006                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4007     let Inst{31} = 1; // 64-bit GPR flag
4008   }
4009
4010   // Unscaled double-precision to 32-bit
4011   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4012                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4013     let Inst{31} = 0; // 32-bit GPR flag
4014   }
4015
4016   // Unscaled double-precision to 64-bit
4017   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4018                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4019     let Inst{31} = 1; // 64-bit GPR flag
4020   }
4021 }
4022
4023 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4024                              SDPatternOperator OpN> {
4025   // Scaled half-precision to 32-bit
4026   def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4027                               fixedpoint_f16_i32, asm,
4028               [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
4029                                           fixedpoint_f16_i32:$scale)))]> {
4030     let Inst{31} = 0; // 32-bit GPR flag
4031     let scale{5} = 1;
4032     let Predicates = [HasFullFP16];
4033   }
4034
4035   // Scaled half-precision to 64-bit
4036   def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4037                               fixedpoint_f16_i64, asm,
4038               [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
4039                                           fixedpoint_f16_i64:$scale)))]> {
4040     let Inst{31} = 1; // 64-bit GPR flag
4041     let Predicates = [HasFullFP16];
4042   }
4043
4044   // Scaled single-precision to 32-bit
4045   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4046                               fixedpoint_f32_i32, asm,
4047               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4048                                           fixedpoint_f32_i32:$scale)))]> {
4049     let Inst{31} = 0; // 32-bit GPR flag
4050     let scale{5} = 1;
4051   }
4052
4053   // Scaled single-precision to 64-bit
4054   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4055                               fixedpoint_f32_i64, asm,
4056               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4057                                           fixedpoint_f32_i64:$scale)))]> {
4058     let Inst{31} = 1; // 64-bit GPR flag
4059   }
4060
4061   // Scaled double-precision to 32-bit
4062   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4063                               fixedpoint_f64_i32, asm,
4064               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4065                                           fixedpoint_f64_i32:$scale)))]> {
4066     let Inst{31} = 0; // 32-bit GPR flag
4067     let scale{5} = 1;
4068   }
4069
4070   // Scaled double-precision to 64-bit
4071   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4072                               fixedpoint_f64_i64, asm,
4073               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4074                                           fixedpoint_f64_i64:$scale)))]> {
4075     let Inst{31} = 1; // 64-bit GPR flag
4076   }
4077 }
4078
4079 //---
4080 // Integer to floating point conversion
4081 //---
4082
4083 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4084 class BaseIntegerToFP<bit isUnsigned,
4085                       RegisterClass srcType, RegisterClass dstType,
4086                       Operand immType, string asm, list<dag> pattern>
4087     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4088          asm, "\t$Rd, $Rn, $scale", "", pattern>,
4089       Sched<[WriteFCvt]> {
4090   bits<5> Rd;
4091   bits<5> Rn;
4092   bits<6> scale;
4093   let Inst{30-24} = 0b0011110;
4094   let Inst{21-17} = 0b00001;
4095   let Inst{16}    = isUnsigned;
4096   let Inst{15-10} = scale;
4097   let Inst{9-5}   = Rn;
4098   let Inst{4-0}   = Rd;
4099 }
4100
4101 class BaseIntegerToFPUnscaled<bit isUnsigned,
4102                       RegisterClass srcType, RegisterClass dstType,
4103                       ValueType dvt, string asm, SDNode node>
4104     : I<(outs dstType:$Rd), (ins srcType:$Rn),
4105          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4106       Sched<[WriteFCvt]> {
4107   bits<5> Rd;
4108   bits<5> Rn;
4109   bits<6> scale;
4110   let Inst{30-24} = 0b0011110;
4111   let Inst{21-17} = 0b10001;
4112   let Inst{16}    = isUnsigned;
4113   let Inst{15-10} = 0b000000;
4114   let Inst{9-5}   = Rn;
4115   let Inst{4-0}   = Rd;
4116 }
4117
4118 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4119   // Unscaled
4120   def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4121     let Inst{31} = 0; // 32-bit GPR flag
4122     let Inst{23-22} = 0b11; // 16-bit FPR flag
4123     let Predicates = [HasFullFP16];
4124   }
4125
4126   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4127     let Inst{31} = 0; // 32-bit GPR flag
4128     let Inst{23-22} = 0b00; // 32-bit FPR flag
4129   }
4130
4131   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4132     let Inst{31} = 0; // 32-bit GPR flag
4133     let Inst{23-22} = 0b01; // 64-bit FPR flag
4134   }
4135
4136   def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4137     let Inst{31} = 1; // 64-bit GPR flag
4138     let Inst{23-22} = 0b11; // 16-bit FPR flag
4139     let Predicates = [HasFullFP16];
4140   }
4141
4142   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4143     let Inst{31} = 1; // 64-bit GPR flag
4144     let Inst{23-22} = 0b00; // 32-bit FPR flag
4145   }
4146
4147   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4148     let Inst{31} = 1; // 64-bit GPR flag
4149     let Inst{23-22} = 0b01; // 64-bit FPR flag
4150   }
4151
4152   // Scaled
4153   def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4154                              [(set FPR16:$Rd,
4155                                    (fdiv (node GPR32:$Rn),
4156                                          fixedpoint_f16_i32:$scale))]> {
4157     let Inst{31} = 0; // 32-bit GPR flag
4158     let Inst{23-22} = 0b11; // 16-bit FPR flag
4159     let scale{5} = 1;
4160     let Predicates = [HasFullFP16];
4161   }
4162
4163   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4164                              [(set FPR32:$Rd,
4165                                    (fdiv (node GPR32:$Rn),
4166                                          fixedpoint_f32_i32:$scale))]> {
4167     let Inst{31} = 0; // 32-bit GPR flag
4168     let Inst{23-22} = 0b00; // 32-bit FPR flag
4169     let scale{5} = 1;
4170   }
4171
4172   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4173                              [(set FPR64:$Rd,
4174                                    (fdiv (node GPR32:$Rn),
4175                                          fixedpoint_f64_i32:$scale))]> {
4176     let Inst{31} = 0; // 32-bit GPR flag
4177     let Inst{23-22} = 0b01; // 64-bit FPR flag
4178     let scale{5} = 1;
4179   }
4180
4181   def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4182                              [(set FPR16:$Rd,
4183                                    (fdiv (node GPR64:$Rn),
4184                                          fixedpoint_f16_i64:$scale))]> {
4185     let Inst{31} = 1; // 64-bit GPR flag
4186     let Inst{23-22} = 0b11; // 16-bit FPR flag
4187     let Predicates = [HasFullFP16];
4188   }
4189
4190   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4191                              [(set FPR32:$Rd,
4192                                    (fdiv (node GPR64:$Rn),
4193                                          fixedpoint_f32_i64:$scale))]> {
4194     let Inst{31} = 1; // 64-bit GPR flag
4195     let Inst{23-22} = 0b00; // 32-bit FPR flag
4196   }
4197
4198   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4199                              [(set FPR64:$Rd,
4200                                    (fdiv (node GPR64:$Rn),
4201                                          fixedpoint_f64_i64:$scale))]> {
4202     let Inst{31} = 1; // 64-bit GPR flag
4203     let Inst{23-22} = 0b01; // 64-bit FPR flag
4204   }
4205 }
4206
4207 //---
4208 // Unscaled integer <-> floating point conversion (i.e. FMOV)
4209 //---
4210
4211 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4212 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4213                       RegisterClass srcType, RegisterClass dstType,
4214                       string asm>
4215     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4216         // We use COPY_TO_REGCLASS for these bitconvert operations.
4217         // copyPhysReg() expands the resultant COPY instructions after
4218         // regalloc is done. This gives greater freedom for the allocator
4219         // and related passes (coalescing, copy propagation, et. al.) to
4220         // be more effective.
4221         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4222       Sched<[WriteFCopy]> {
4223   bits<5> Rd;
4224   bits<5> Rn;
4225   let Inst{30-24} = 0b0011110;
4226   let Inst{21}    = 1;
4227   let Inst{20-19} = rmode;
4228   let Inst{18-16} = opcode;
4229   let Inst{15-10} = 0b000000;
4230   let Inst{9-5}   = Rn;
4231   let Inst{4-0}   = Rd;
4232 }
4233
4234 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4235 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4236                      RegisterClass srcType, RegisterOperand dstType, string asm,
4237                      string kind>
4238     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4239         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4240       Sched<[WriteFCopy]> {
4241   bits<5> Rd;
4242   bits<5> Rn;
4243   let Inst{30-23} = 0b00111101;
4244   let Inst{21}    = 1;
4245   let Inst{20-19} = rmode;
4246   let Inst{18-16} = opcode;
4247   let Inst{15-10} = 0b000000;
4248   let Inst{9-5}   = Rn;
4249   let Inst{4-0}   = Rd;
4250
4251   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4252 }
4253
4254 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4255 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4256                      RegisterOperand srcType, RegisterClass dstType, string asm,
4257                      string kind>
4258     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4259         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4260       Sched<[WriteFCopy]> {
4261   bits<5> Rd;
4262   bits<5> Rn;
4263   let Inst{30-23} = 0b00111101;
4264   let Inst{21}    = 1;
4265   let Inst{20-19} = rmode;
4266   let Inst{18-16} = opcode;
4267   let Inst{15-10} = 0b000000;
4268   let Inst{9-5}   = Rn;
4269   let Inst{4-0}   = Rd;
4270
4271   let DecoderMethod =  "DecodeFMOVLaneInstruction";
4272 }
4273
4274
4275 multiclass UnscaledConversion<string asm> {
4276   def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4277     let Inst{31} = 0; // 32-bit GPR flag
4278     let Inst{23-22} = 0b11; // 16-bit FPR flag
4279     let Predicates = [HasFullFP16];
4280   }
4281
4282   def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4283     let Inst{31} = 1; // 64-bit GPR flag
4284     let Inst{23-22} = 0b11; // 16-bit FPR flag
4285     let Predicates = [HasFullFP16];
4286   }
4287
4288   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4289     let Inst{31} = 0; // 32-bit GPR flag
4290     let Inst{23-22} = 0b00; // 32-bit FPR flag
4291   }
4292
4293   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4294     let Inst{31} = 1; // 64-bit GPR flag
4295     let Inst{23-22} = 0b01; // 64-bit FPR flag
4296   }
4297
4298   def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4299     let Inst{31} = 0; // 32-bit GPR flag
4300     let Inst{23-22} = 0b11; // 16-bit FPR flag
4301     let Predicates = [HasFullFP16];
4302   }
4303
4304   def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4305     let Inst{31} = 1; // 64-bit GPR flag
4306     let Inst{23-22} = 0b11; // 16-bit FPR flag
4307     let Predicates = [HasFullFP16];
4308   }
4309
4310   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4311     let Inst{31} = 0; // 32-bit GPR flag
4312     let Inst{23-22} = 0b00; // 32-bit FPR flag
4313   }
4314
4315   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4316     let Inst{31} = 1; // 64-bit GPR flag
4317     let Inst{23-22} = 0b01; // 64-bit FPR flag
4318   }
4319
4320   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4321                                              asm, ".d"> {
4322     let Inst{31} = 1;
4323     let Inst{22} = 0;
4324   }
4325
4326   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4327                                                asm, ".d"> {
4328     let Inst{31} = 1;
4329     let Inst{22} = 0;
4330   }
4331 }
4332
4333 //---
4334 // Floating point conversion
4335 //---
4336
4337 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4338                        RegisterClass srcType, string asm, list<dag> pattern>
4339     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4340       Sched<[WriteFCvt]> {
4341   bits<5> Rd;
4342   bits<5> Rn;
4343   let Inst{31-24} = 0b00011110;
4344   let Inst{23-22} = type;
4345   let Inst{21-17} = 0b10001;
4346   let Inst{16-15} = opcode;
4347   let Inst{14-10} = 0b10000;
4348   let Inst{9-5}   = Rn;
4349   let Inst{4-0}   = Rd;
4350 }
4351
4352 multiclass FPConversion<string asm> {
4353   // Double-precision to Half-precision
4354   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4355                              [(set FPR16:$Rd, (fpround FPR64:$Rn))]>;
4356
4357   // Double-precision to Single-precision
4358   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4359                              [(set FPR32:$Rd, (fpround FPR64:$Rn))]>;
4360
4361   // Half-precision to Double-precision
4362   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4363                              [(set FPR64:$Rd, (fpextend FPR16:$Rn))]>;
4364
4365   // Half-precision to Single-precision
4366   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4367                              [(set FPR32:$Rd, (fpextend FPR16:$Rn))]>;
4368
4369   // Single-precision to Double-precision
4370   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4371                              [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4372
4373   // Single-precision to Half-precision
4374   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4375                              [(set FPR16:$Rd, (fpround FPR32:$Rn))]>;
4376 }
4377
4378 //---
4379 // Single operand floating point data processing
4380 //---
4381
4382 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4383 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
4384                               ValueType vt, string asm, SDPatternOperator node>
4385     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4386          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4387       Sched<[WriteF]> {
4388   bits<5> Rd;
4389   bits<5> Rn;
4390   let Inst{31-24} = 0b00011110;
4391   let Inst{21-19} = 0b100;
4392   let Inst{18-15} = opcode;
4393   let Inst{14-10} = 0b10000;
4394   let Inst{9-5}   = Rn;
4395   let Inst{4-0}   = Rd;
4396 }
4397
4398 multiclass SingleOperandFPData<bits<4> opcode, string asm,
4399                                SDPatternOperator node = null_frag> {
4400   def Hr : BaseSingleOperandFPData<opcode, FPR16, f16, asm, node> {
4401     let Inst{23-22} = 0b11; // 16-bit size flag
4402     let Predicates = [HasFullFP16];
4403   }
4404
4405   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4406     let Inst{23-22} = 0b00; // 32-bit size flag
4407   }
4408
4409   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4410     let Inst{23-22} = 0b01; // 64-bit size flag
4411   }
4412 }
4413
4414 //---
4415 // Two operand floating point data processing
4416 //---
4417
4418 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4419 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4420                            string asm, list<dag> pat>
4421     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4422          asm, "\t$Rd, $Rn, $Rm", "", pat>,
4423       Sched<[WriteF]> {
4424   bits<5> Rd;
4425   bits<5> Rn;
4426   bits<5> Rm;
4427   let Inst{31-24} = 0b00011110;
4428   let Inst{21}    = 1;
4429   let Inst{20-16} = Rm;
4430   let Inst{15-12} = opcode;
4431   let Inst{11-10} = 0b10;
4432   let Inst{9-5}   = Rn;
4433   let Inst{4-0}   = Rd;
4434 }
4435
4436 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4437                             SDPatternOperator node = null_frag> {
4438   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4439                          [(set (f16 FPR16:$Rd),
4440                                (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4441     let Inst{23-22} = 0b11; // 16-bit size flag
4442     let Predicates = [HasFullFP16];
4443   }
4444
4445   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4446                          [(set (f32 FPR32:$Rd),
4447                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4448     let Inst{23-22} = 0b00; // 32-bit size flag
4449   }
4450
4451   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4452                          [(set (f64 FPR64:$Rd),
4453                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4454     let Inst{23-22} = 0b01; // 64-bit size flag
4455   }
4456 }
4457
4458 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4459   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4460                   [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4461     let Inst{23-22} = 0b11; // 16-bit size flag
4462     let Predicates = [HasFullFP16];
4463   }
4464
4465   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4466                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4467     let Inst{23-22} = 0b00; // 32-bit size flag
4468   }
4469
4470   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4471                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4472     let Inst{23-22} = 0b01; // 64-bit size flag
4473   }
4474 }
4475
4476
4477 //---
4478 // Three operand floating point data processing
4479 //---
4480
4481 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4482                              RegisterClass regtype, string asm, list<dag> pat>
4483     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4484          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4485       Sched<[WriteFMul]> {
4486   bits<5> Rd;
4487   bits<5> Rn;
4488   bits<5> Rm;
4489   bits<5> Ra;
4490   let Inst{31-24} = 0b00011111;
4491   let Inst{21}    = isNegated;
4492   let Inst{20-16} = Rm;
4493   let Inst{15}    = isSub;
4494   let Inst{14-10} = Ra;
4495   let Inst{9-5}   = Rn;
4496   let Inst{4-0}   = Rd;
4497 }
4498
4499 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4500                               SDPatternOperator node> {
4501   def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4502             [(set FPR16:$Rd,
4503                   (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4504     let Inst{23-22} = 0b11; // 16-bit size flag
4505     let Predicates = [HasFullFP16];
4506   }
4507
4508   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4509             [(set FPR32:$Rd,
4510                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4511     let Inst{23-22} = 0b00; // 32-bit size flag
4512   }
4513
4514   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4515             [(set FPR64:$Rd,
4516                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4517     let Inst{23-22} = 0b01; // 64-bit size flag
4518   }
4519 }
4520
4521 //---
4522 // Floating point data comparisons
4523 //---
4524
4525 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4526 class BaseOneOperandFPComparison<bit signalAllNans,
4527                                  RegisterClass regtype, string asm,
4528                                  list<dag> pat>
4529     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4530       Sched<[WriteFCmp]> {
4531   bits<5> Rn;
4532   let Inst{31-24} = 0b00011110;
4533   let Inst{21}    = 1;
4534
4535   let Inst{15-10} = 0b001000;
4536   let Inst{9-5}   = Rn;
4537   let Inst{4}     = signalAllNans;
4538   let Inst{3-0}   = 0b1000;
4539
4540   // Rm should be 0b00000 canonically, but we need to accept any value.
4541   let PostEncoderMethod = "fixOneOperandFPComparison";
4542 }
4543
4544 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4545 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4546                                 string asm, list<dag> pat>
4547     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4548       Sched<[WriteFCmp]> {
4549   bits<5> Rm;
4550   bits<5> Rn;
4551   let Inst{31-24} = 0b00011110;
4552   let Inst{21}    = 1;
4553   let Inst{20-16} = Rm;
4554   let Inst{15-10} = 0b001000;
4555   let Inst{9-5}   = Rn;
4556   let Inst{4}     = signalAllNans;
4557   let Inst{3-0}   = 0b0000;
4558 }
4559
4560 multiclass FPComparison<bit signalAllNans, string asm,
4561                         SDPatternOperator OpNode = null_frag> {
4562   let Defs = [NZCV] in {
4563   def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4564       [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4565     let Inst{23-22} = 0b11;
4566     let Predicates = [HasFullFP16];
4567   }
4568
4569   def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4570       [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4571     let Inst{23-22} = 0b11;
4572     let Predicates = [HasFullFP16];
4573   }
4574
4575   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4576       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4577     let Inst{23-22} = 0b00;
4578   }
4579
4580   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4581       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4582     let Inst{23-22} = 0b00;
4583   }
4584
4585   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4586       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4587     let Inst{23-22} = 0b01;
4588   }
4589
4590   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4591       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4592     let Inst{23-22} = 0b01;
4593   }
4594   } // Defs = [NZCV]
4595 }
4596
4597 //---
4598 // Floating point conditional comparisons
4599 //---
4600
4601 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4602 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4603                            string mnemonic, list<dag> pat>
4604     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4605          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4606       Sched<[WriteFCmp]> {
4607   let Uses = [NZCV];
4608   let Defs = [NZCV];
4609
4610   bits<5> Rn;
4611   bits<5> Rm;
4612   bits<4> nzcv;
4613   bits<4> cond;
4614
4615   let Inst{31-24} = 0b00011110;
4616   let Inst{21}    = 1;
4617   let Inst{20-16} = Rm;
4618   let Inst{15-12} = cond;
4619   let Inst{11-10} = 0b01;
4620   let Inst{9-5}   = Rn;
4621   let Inst{4}     = signalAllNans;
4622   let Inst{3-0}   = nzcv;
4623 }
4624
4625 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4626                             SDPatternOperator OpNode = null_frag> {
4627   def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic, []> {
4628     let Inst{23-22} = 0b11;
4629     let Predicates = [HasFullFP16];
4630   }
4631
4632   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4633       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4634                           (i32 imm:$cond), NZCV))]> {
4635     let Inst{23-22} = 0b00;
4636   }
4637
4638   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4639       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4640                           (i32 imm:$cond), NZCV))]> {
4641     let Inst{23-22} = 0b01;
4642   }
4643 }
4644
4645 //---
4646 // Floating point conditional select
4647 //---
4648
4649 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4650     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4651          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4652          [(set regtype:$Rd,
4653                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4654                           (i32 imm:$cond), NZCV))]>,
4655       Sched<[WriteF]> {
4656   bits<5> Rd;
4657   bits<5> Rn;
4658   bits<5> Rm;
4659   bits<4> cond;
4660
4661   let Inst{31-24} = 0b00011110;
4662   let Inst{21}    = 1;
4663   let Inst{20-16} = Rm;
4664   let Inst{15-12} = cond;
4665   let Inst{11-10} = 0b11;
4666   let Inst{9-5}   = Rn;
4667   let Inst{4-0}   = Rd;
4668 }
4669
4670 multiclass FPCondSelect<string asm> {
4671   let Uses = [NZCV] in {
4672   def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4673     let Inst{23-22} = 0b11;
4674     let Predicates = [HasFullFP16];
4675   }
4676
4677   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4678     let Inst{23-22} = 0b00;
4679   }
4680
4681   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4682     let Inst{23-22} = 0b01;
4683   }
4684   } // Uses = [NZCV]
4685 }
4686
4687 //---
4688 // Floating move immediate
4689 //---
4690
4691 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4692   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4693       [(set regtype:$Rd, fpimmtype:$imm)]>,
4694     Sched<[WriteFImm]> {
4695   bits<5> Rd;
4696   bits<8> imm;
4697   let Inst{31-24} = 0b00011110;
4698   let Inst{21}    = 1;
4699   let Inst{20-13} = imm;
4700   let Inst{12-5}  = 0b10000000;
4701   let Inst{4-0}   = Rd;
4702 }
4703
4704 multiclass FPMoveImmediate<string asm> {
4705   def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4706     let Inst{23-22} = 0b11;
4707     let Predicates = [HasFullFP16];
4708   }
4709
4710   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4711     let Inst{23-22} = 0b00;
4712   }
4713
4714   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4715     let Inst{23-22} = 0b01;
4716   }
4717 }
4718 } // end of 'let Predicates = [HasFPARMv8]'
4719
4720 //----------------------------------------------------------------------------
4721 // AdvSIMD
4722 //----------------------------------------------------------------------------
4723
4724 let Predicates = [HasNEON] in {
4725
4726 //----------------------------------------------------------------------------
4727 // AdvSIMD three register vector instructions
4728 //----------------------------------------------------------------------------
4729
4730 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4731 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4732                         RegisterOperand regtype, string asm, string kind,
4733                         list<dag> pattern>
4734   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4735       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4736       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4737     Sched<[WriteV]> {
4738   bits<5> Rd;
4739   bits<5> Rn;
4740   bits<5> Rm;
4741   let Inst{31}    = 0;
4742   let Inst{30}    = Q;
4743   let Inst{29}    = U;
4744   let Inst{28-24} = 0b01110;
4745   let Inst{23-21} = size;
4746   let Inst{20-16} = Rm;
4747   let Inst{15-11} = opcode;
4748   let Inst{10}    = 1;
4749   let Inst{9-5}   = Rn;
4750   let Inst{4-0}   = Rd;
4751 }
4752
4753 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4754 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
4755                         RegisterOperand regtype, string asm, string kind,
4756                         list<dag> pattern>
4757   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4758       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4759       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4760     Sched<[WriteV]> {
4761   bits<5> Rd;
4762   bits<5> Rn;
4763   bits<5> Rm;
4764   let Inst{31}    = 0;
4765   let Inst{30}    = Q;
4766   let Inst{29}    = U;
4767   let Inst{28-24} = 0b01110;
4768   let Inst{23-21} = size;
4769   let Inst{20-16} = Rm;
4770   let Inst{15-11} = opcode;
4771   let Inst{10}    = 1;
4772   let Inst{9-5}   = Rn;
4773   let Inst{4-0}   = Rd;
4774 }
4775
4776 class BaseSIMDThreeSameVectorDot<bit Q, bit U, string asm, string kind1,
4777                                  string kind2, RegisterOperand RegType,
4778                                  ValueType AccumType, ValueType InputType,
4779                                  SDPatternOperator OpNode> :
4780         BaseSIMDThreeSameVectorTied<Q, U, 0b100, 0b10010, RegType, asm, kind1,
4781         [(set (AccumType RegType:$dst),
4782               (OpNode (AccumType RegType:$Rd),
4783                       (InputType RegType:$Rn),
4784                       (InputType RegType:$Rm)))]> {
4785   let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
4786 }
4787
4788 multiclass SIMDThreeSameVectorDot<bit U, string asm, SDPatternOperator OpNode> {
4789   def v8i8  : BaseSIMDThreeSameVectorDot<0, U, asm, ".2s", ".8b", V64,
4790                                          v2i32, v8i8, OpNode>;
4791   def v16i8 : BaseSIMDThreeSameVectorDot<1, U, asm, ".4s", ".16b", V128,
4792                                          v4i32, v16i8, OpNode>;
4793 }
4794
4795 // All operand sizes distinguished in the encoding.
4796 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4797                                SDPatternOperator OpNode> {
4798   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4799                                       asm, ".8b",
4800          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4801   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4802                                       asm, ".16b",
4803          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4804   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4805                                       asm, ".4h",
4806          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4807   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4808                                       asm, ".8h",
4809          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4810   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4811                                       asm, ".2s",
4812          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4813   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4814                                       asm, ".4s",
4815          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4816   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
4817                                       asm, ".2d",
4818          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4819 }
4820
4821 // As above, but D sized elements unsupported.
4822 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4823                                   SDPatternOperator OpNode> {
4824   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4825                                       asm, ".8b",
4826         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4827   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4828                                       asm, ".16b",
4829         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4830   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4831                                       asm, ".4h",
4832         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4833   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4834                                       asm, ".8h",
4835         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4836   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4837                                       asm, ".2s",
4838         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4839   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4840                                       asm, ".4s",
4841         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4842 }
4843
4844 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4845                                   SDPatternOperator OpNode> {
4846   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
4847                                       asm, ".8b",
4848       [(set (v8i8 V64:$dst),
4849             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4850   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
4851                                       asm, ".16b",
4852       [(set (v16i8 V128:$dst),
4853             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4854   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
4855                                       asm, ".4h",
4856       [(set (v4i16 V64:$dst),
4857             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4858   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
4859                                       asm, ".8h",
4860       [(set (v8i16 V128:$dst),
4861             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4862   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
4863                                       asm, ".2s",
4864       [(set (v2i32 V64:$dst),
4865             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4866   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
4867                                       asm, ".4s",
4868       [(set (v4i32 V128:$dst),
4869             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4870 }
4871
4872 // As above, but only B sized elements supported.
4873 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4874                                 SDPatternOperator OpNode> {
4875   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4876                                       asm, ".8b",
4877     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4878   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4879                                       asm, ".16b",
4880     [(set (v16i8 V128:$Rd),
4881           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4882 }
4883
4884 // As above, but only floating point elements supported.
4885 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
4886                                  string asm, SDPatternOperator OpNode> {
4887   let Predicates = [HasNEON, HasFullFP16] in {
4888   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4889                                       asm, ".4h",
4890         [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4891   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4892                                       asm, ".8h",
4893         [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4894   } // Predicates = [HasNEON, HasFullFP16]
4895   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4896                                       asm, ".2s",
4897         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4898   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4899                                       asm, ".4s",
4900         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4901   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4902                                       asm, ".2d",
4903         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4904 }
4905
4906 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
4907                                     string asm,
4908                                     SDPatternOperator OpNode> {
4909   let Predicates = [HasNEON, HasFullFP16] in {
4910   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4911                                       asm, ".4h",
4912         [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4913   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4914                                       asm, ".8h",
4915         [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4916   } // Predicates = [HasNEON, HasFullFP16]
4917   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4918                                       asm, ".2s",
4919         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4920   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4921                                       asm, ".4s",
4922         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4923   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4924                                       asm, ".2d",
4925         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4926 }
4927
4928 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
4929                                  string asm, SDPatternOperator OpNode> {
4930   let Predicates = [HasNEON, HasFullFP16] in {
4931   def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
4932                                       asm, ".4h",
4933      [(set (v4f16 V64:$dst),
4934            (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4935   def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
4936                                       asm, ".8h",
4937      [(set (v8f16 V128:$dst),
4938            (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4939   } // Predicates = [HasNEON, HasFullFP16]
4940   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
4941                                       asm, ".2s",
4942      [(set (v2f32 V64:$dst),
4943            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4944   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
4945                                       asm, ".4s",
4946      [(set (v4f32 V128:$dst),
4947            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4948   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
4949                                       asm, ".2d",
4950      [(set (v2f64 V128:$dst),
4951            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4952 }
4953
4954 // As above, but D and B sized elements unsupported.
4955 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4956                                 SDPatternOperator OpNode> {
4957   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4958                                       asm, ".4h",
4959         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4960   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4961                                       asm, ".8h",
4962         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4963   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4964                                       asm, ".2s",
4965         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4966   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4967                                       asm, ".4s",
4968         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4969 }
4970
4971 // Logical three vector ops share opcode bits, and only use B sized elements.
4972 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4973                                   SDPatternOperator OpNode = null_frag> {
4974   def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
4975                                      asm, ".8b",
4976                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4977   def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
4978                                      asm, ".16b",
4979                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4980
4981   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4982           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4983   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4984           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4985   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4986           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4987
4988   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4989       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4990   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4991       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4992   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4993       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4994 }
4995
4996 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4997                                   string asm, SDPatternOperator OpNode> {
4998   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
4999                                      asm, ".8b",
5000              [(set (v8i8 V64:$dst),
5001                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5002   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5003                                      asm, ".16b",
5004              [(set (v16i8 V128:$dst),
5005                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5006                            (v16i8 V128:$Rm)))]>;
5007
5008   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5009                            (v4i16 V64:$RHS))),
5010           (!cast<Instruction>(NAME#"v8i8")
5011             V64:$LHS, V64:$MHS, V64:$RHS)>;
5012   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5013                            (v2i32 V64:$RHS))),
5014           (!cast<Instruction>(NAME#"v8i8")
5015             V64:$LHS, V64:$MHS, V64:$RHS)>;
5016   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5017                            (v1i64 V64:$RHS))),
5018           (!cast<Instruction>(NAME#"v8i8")
5019             V64:$LHS, V64:$MHS, V64:$RHS)>;
5020
5021   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5022                            (v8i16 V128:$RHS))),
5023       (!cast<Instruction>(NAME#"v16i8")
5024         V128:$LHS, V128:$MHS, V128:$RHS)>;
5025   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5026                            (v4i32 V128:$RHS))),
5027       (!cast<Instruction>(NAME#"v16i8")
5028         V128:$LHS, V128:$MHS, V128:$RHS)>;
5029   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5030                            (v2i64 V128:$RHS))),
5031       (!cast<Instruction>(NAME#"v16i8")
5032         V128:$LHS, V128:$MHS, V128:$RHS)>;
5033 }
5034
5035
5036 //----------------------------------------------------------------------------
5037 // AdvSIMD two register vector instructions.
5038 //----------------------------------------------------------------------------
5039
5040 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5041 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5042                             bits<2> size2, RegisterOperand regtype, string asm,
5043                             string dstkind, string srckind, list<dag> pattern>
5044   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5045       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5046       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5047     Sched<[WriteV]> {
5048   bits<5> Rd;
5049   bits<5> Rn;
5050   let Inst{31}    = 0;
5051   let Inst{30}    = Q;
5052   let Inst{29}    = U;
5053   let Inst{28-24} = 0b01110;
5054   let Inst{23-22} = size;
5055   let Inst{21} = 0b1;
5056   let Inst{20-19} = size2;
5057   let Inst{18-17} = 0b00;
5058   let Inst{16-12} = opcode;
5059   let Inst{11-10} = 0b10;
5060   let Inst{9-5}   = Rn;
5061   let Inst{4-0}   = Rd;
5062 }
5063
5064 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5065 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5066                                 bits<2> size2, RegisterOperand regtype,
5067                                 string asm, string dstkind, string srckind,
5068                                 list<dag> pattern>
5069   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5070       "{\t$Rd" # dstkind # ", $Rn" # srckind #
5071       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5072     Sched<[WriteV]> {
5073   bits<5> Rd;
5074   bits<5> Rn;
5075   let Inst{31}    = 0;
5076   let Inst{30}    = Q;
5077   let Inst{29}    = U;
5078   let Inst{28-24} = 0b01110;
5079   let Inst{23-22} = size;
5080   let Inst{21} = 0b1;
5081   let Inst{20-19} = size2;
5082   let Inst{18-17} = 0b00;
5083   let Inst{16-12} = opcode;
5084   let Inst{11-10} = 0b10;
5085   let Inst{9-5}   = Rn;
5086   let Inst{4-0}   = Rd;
5087 }
5088
5089 // Supports B, H, and S element sizes.
5090 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5091                             SDPatternOperator OpNode> {
5092   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5093                                       asm, ".8b", ".8b",
5094                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5095   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5096                                       asm, ".16b", ".16b",
5097                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5098   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5099                                       asm, ".4h", ".4h",
5100                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5101   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5102                                       asm, ".8h", ".8h",
5103                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5104   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5105                                       asm, ".2s", ".2s",
5106                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5107   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5108                                       asm, ".4s", ".4s",
5109                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5110 }
5111
5112 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5113                             RegisterOperand regtype, string asm, string dstkind,
5114                             string srckind, string amount>
5115   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5116       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5117       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5118     Sched<[WriteV]> {
5119   bits<5> Rd;
5120   bits<5> Rn;
5121   let Inst{31}    = 0;
5122   let Inst{30}    = Q;
5123   let Inst{29-24} = 0b101110;
5124   let Inst{23-22} = size;
5125   let Inst{21-10} = 0b100001001110;
5126   let Inst{9-5}   = Rn;
5127   let Inst{4-0}   = Rd;
5128 }
5129
5130 multiclass SIMDVectorLShiftLongBySizeBHS {
5131   let hasSideEffects = 0 in {
5132   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5133                                              "shll", ".8h",  ".8b", "8">;
5134   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5135                                              "shll2", ".8h", ".16b", "8">;
5136   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5137                                              "shll", ".4s",  ".4h", "16">;
5138   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5139                                              "shll2", ".4s", ".8h", "16">;
5140   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5141                                              "shll", ".2d",  ".2s", "32">;
5142   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5143                                              "shll2", ".2d", ".4s", "32">;
5144   }
5145 }
5146
5147 // Supports all element sizes.
5148 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5149                              SDPatternOperator OpNode> {
5150   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5151                                       asm, ".4h", ".8b",
5152                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5153   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5154                                       asm, ".8h", ".16b",
5155                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5156   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5157                                       asm, ".2s", ".4h",
5158                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5159   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5160                                       asm, ".4s", ".8h",
5161                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5162   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5163                                       asm, ".1d", ".2s",
5164                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5165   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5166                                       asm, ".2d", ".4s",
5167                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5168 }
5169
5170 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5171                                  SDPatternOperator OpNode> {
5172   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5173                                           asm, ".4h", ".8b",
5174       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5175                                       (v8i8 V64:$Rn)))]>;
5176   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5177                                           asm, ".8h", ".16b",
5178       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5179                                       (v16i8 V128:$Rn)))]>;
5180   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5181                                           asm, ".2s", ".4h",
5182       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5183                                       (v4i16 V64:$Rn)))]>;
5184   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5185                                           asm, ".4s", ".8h",
5186       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5187                                       (v8i16 V128:$Rn)))]>;
5188   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5189                                           asm, ".1d", ".2s",
5190       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5191                                       (v2i32 V64:$Rn)))]>;
5192   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5193                                           asm, ".2d", ".4s",
5194       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5195                                       (v4i32 V128:$Rn)))]>;
5196 }
5197
5198 // Supports all element sizes, except 1xD.
5199 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5200                                   SDPatternOperator OpNode> {
5201   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5202                                     asm, ".8b", ".8b",
5203     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5204   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5205                                     asm, ".16b", ".16b",
5206     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5207   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5208                                     asm, ".4h", ".4h",
5209     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5210   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5211                                     asm, ".8h", ".8h",
5212     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5213   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5214                                     asm, ".2s", ".2s",
5215     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5216   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5217                                     asm, ".4s", ".4s",
5218     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5219   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5220                                     asm, ".2d", ".2d",
5221     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5222 }
5223
5224 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5225                              SDPatternOperator OpNode = null_frag> {
5226   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5227                                 asm, ".8b", ".8b",
5228     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5229   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5230                                 asm, ".16b", ".16b",
5231     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5232   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5233                                 asm, ".4h", ".4h",
5234     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5235   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5236                                 asm, ".8h", ".8h",
5237     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5238   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5239                                 asm, ".2s", ".2s",
5240     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5241   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5242                                 asm, ".4s", ".4s",
5243     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5244   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5245                                 asm, ".2d", ".2d",
5246     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5247 }
5248
5249
5250 // Supports only B element sizes.
5251 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5252                           SDPatternOperator OpNode> {
5253   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5254                                 asm, ".8b", ".8b",
5255                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5256   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5257                                 asm, ".16b", ".16b",
5258                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5259
5260 }
5261
5262 // Supports only B and H element sizes.
5263 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5264                                 SDPatternOperator OpNode> {
5265   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5266                                 asm, ".8b", ".8b",
5267                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5268   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5269                                 asm, ".16b", ".16b",
5270                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5271   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5272                                 asm, ".4h", ".4h",
5273                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5274   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5275                                 asm, ".8h", ".8h",
5276                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5277 }
5278
5279 // Supports only S and D element sizes, uses high bit of the size field
5280 // as an extra opcode bit.
5281 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5282                            SDPatternOperator OpNode> {
5283   let Predicates = [HasNEON, HasFullFP16] in {
5284   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5285                                 asm, ".4h", ".4h",
5286                           [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5287   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5288                                 asm, ".8h", ".8h",
5289                           [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5290   } // Predicates = [HasNEON, HasFullFP16]
5291   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5292                                 asm, ".2s", ".2s",
5293                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5294   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5295                                 asm, ".4s", ".4s",
5296                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5297   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5298                                 asm, ".2d", ".2d",
5299                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5300 }
5301
5302 // Supports only S element size.
5303 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5304                            SDPatternOperator OpNode> {
5305   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5306                                 asm, ".2s", ".2s",
5307                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5308   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5309                                 asm, ".4s", ".4s",
5310                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5311 }
5312
5313
5314 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5315                            SDPatternOperator OpNode> {
5316   let Predicates = [HasNEON, HasFullFP16] in {
5317   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5318                                 asm, ".4h", ".4h",
5319                           [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5320   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5321                                 asm, ".8h", ".8h",
5322                           [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5323   } // Predicates = [HasNEON, HasFullFP16]
5324   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5325                                 asm, ".2s", ".2s",
5326                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5327   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5328                                 asm, ".4s", ".4s",
5329                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5330   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5331                                 asm, ".2d", ".2d",
5332                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5333 }
5334
5335 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5336                            SDPatternOperator OpNode> {
5337   let Predicates = [HasNEON, HasFullFP16] in {
5338   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5339                                 asm, ".4h", ".4h",
5340                           [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5341   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5342                                 asm, ".8h", ".8h",
5343                           [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5344   } // Predicates = [HasNEON, HasFullFP16]
5345   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5346                                 asm, ".2s", ".2s",
5347                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5348   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5349                                 asm, ".4s", ".4s",
5350                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5351   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5352                                 asm, ".2d", ".2d",
5353                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5354 }
5355
5356
5357 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5358                            RegisterOperand inreg, RegisterOperand outreg,
5359                            string asm, string outkind, string inkind,
5360                            list<dag> pattern>
5361   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5362       "{\t$Rd" # outkind # ", $Rn" # inkind #
5363       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5364     Sched<[WriteV]> {
5365   bits<5> Rd;
5366   bits<5> Rn;
5367   let Inst{31}    = 0;
5368   let Inst{30}    = Q;
5369   let Inst{29}    = U;
5370   let Inst{28-24} = 0b01110;
5371   let Inst{23-22} = size;
5372   let Inst{21-17} = 0b10000;
5373   let Inst{16-12} = opcode;
5374   let Inst{11-10} = 0b10;
5375   let Inst{9-5}   = Rn;
5376   let Inst{4-0}   = Rd;
5377 }
5378
5379 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5380                            RegisterOperand inreg, RegisterOperand outreg,
5381                            string asm, string outkind, string inkind,
5382                            list<dag> pattern>
5383   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5384       "{\t$Rd" # outkind # ", $Rn" # inkind #
5385       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5386     Sched<[WriteV]> {
5387   bits<5> Rd;
5388   bits<5> Rn;
5389   let Inst{31}    = 0;
5390   let Inst{30}    = Q;
5391   let Inst{29}    = U;
5392   let Inst{28-24} = 0b01110;
5393   let Inst{23-22} = size;
5394   let Inst{21-17} = 0b10000;
5395   let Inst{16-12} = opcode;
5396   let Inst{11-10} = 0b10;
5397   let Inst{9-5}   = Rn;
5398   let Inst{4-0}   = Rd;
5399 }
5400
5401 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
5402                               SDPatternOperator OpNode> {
5403   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
5404                                       asm, ".8b", ".8h",
5405         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5406   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
5407                                       asm#"2", ".16b", ".8h", []>;
5408   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
5409                                       asm, ".4h", ".4s",
5410         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5411   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
5412                                       asm#"2", ".8h", ".4s", []>;
5413   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
5414                                       asm, ".2s", ".2d",
5415         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5416   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
5417                                       asm#"2", ".4s", ".2d", []>;
5418
5419   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
5420             (!cast<Instruction>(NAME # "v16i8")
5421                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5422   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
5423             (!cast<Instruction>(NAME # "v8i16")
5424                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5425   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
5426             (!cast<Instruction>(NAME # "v4i32")
5427                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5428 }
5429
5430 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
5431                            bits<5> opcode, RegisterOperand regtype, string asm,
5432                            string kind, string zero, ValueType dty,
5433                            ValueType sty, SDNode OpNode>
5434   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5435       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5436       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5437       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5438     Sched<[WriteV]> {
5439   bits<5> Rd;
5440   bits<5> Rn;
5441   let Inst{31}    = 0;
5442   let Inst{30}    = Q;
5443   let Inst{29}    = U;
5444   let Inst{28-24} = 0b01110;
5445   let Inst{23-22} = size;
5446   let Inst{21} = 0b1;
5447   let Inst{20-19} = size2;
5448   let Inst{18-17} = 0b00;
5449   let Inst{16-12} = opcode;
5450   let Inst{11-10} = 0b10;
5451   let Inst{9-5}   = Rn;
5452   let Inst{4-0}   = Rd;
5453 }
5454
5455 // Comparisons support all element sizes, except 1xD.
5456 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5457                             SDNode OpNode> {
5458   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5459                                      asm, ".8b", "0",
5460                                      v8i8, v8i8, OpNode>;
5461   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5462                                      asm, ".16b", "0",
5463                                      v16i8, v16i8, OpNode>;
5464   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5465                                      asm, ".4h", "0",
5466                                      v4i16, v4i16, OpNode>;
5467   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5468                                      asm, ".8h", "0",
5469                                      v8i16, v8i16, OpNode>;
5470   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5471                                      asm, ".2s", "0",
5472                                      v2i32, v2i32, OpNode>;
5473   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5474                                      asm, ".4s", "0",
5475                                      v4i32, v4i32, OpNode>;
5476   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5477                                      asm, ".2d", "0",
5478                                      v2i64, v2i64, OpNode>;
5479 }
5480
5481 // FP Comparisons support only S and D element sizes (and H for v8.2a).
5482 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5483                               string asm, SDNode OpNode> {
5484
5485   let Predicates = [HasNEON, HasFullFP16] in {
5486   def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5487                                      asm, ".4h", "0.0",
5488                                      v4i16, v4f16, OpNode>;
5489   def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5490                                      asm, ".8h", "0.0",
5491                                      v8i16, v8f16, OpNode>;
5492   } // Predicates = [HasNEON, HasFullFP16]
5493   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5494                                      asm, ".2s", "0.0",
5495                                      v2i32, v2f32, OpNode>;
5496   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5497                                      asm, ".4s", "0.0",
5498                                      v4i32, v4f32, OpNode>;
5499   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5500                                      asm, ".2d", "0.0",
5501                                      v2i64, v2f64, OpNode>;
5502
5503   let Predicates = [HasNEON, HasFullFP16] in {
5504   def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5505                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5506   def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5507                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5508   }
5509   def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5510                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5511   def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5512                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5513   def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5514                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5515   let Predicates = [HasNEON, HasFullFP16] in {
5516   def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5517                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5518   def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5519                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5520   }
5521   def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5522                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5523   def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5524                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5525   def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5526                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5527 }
5528
5529 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5530 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5531                              RegisterOperand outtype, RegisterOperand intype,
5532                              string asm, string VdTy, string VnTy,
5533                              list<dag> pattern>
5534   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5535       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5536     Sched<[WriteV]> {
5537   bits<5> Rd;
5538   bits<5> Rn;
5539   let Inst{31}    = 0;
5540   let Inst{30}    = Q;
5541   let Inst{29}    = U;
5542   let Inst{28-24} = 0b01110;
5543   let Inst{23-22} = size;
5544   let Inst{21-17} = 0b10000;
5545   let Inst{16-12} = opcode;
5546   let Inst{11-10} = 0b10;
5547   let Inst{9-5}   = Rn;
5548   let Inst{4-0}   = Rd;
5549 }
5550
5551 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5552                              RegisterOperand outtype, RegisterOperand intype,
5553                              string asm, string VdTy, string VnTy,
5554                              list<dag> pattern>
5555   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5556       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5557     Sched<[WriteV]> {
5558   bits<5> Rd;
5559   bits<5> Rn;
5560   let Inst{31}    = 0;
5561   let Inst{30}    = Q;
5562   let Inst{29}    = U;
5563   let Inst{28-24} = 0b01110;
5564   let Inst{23-22} = size;
5565   let Inst{21-17} = 0b10000;
5566   let Inst{16-12} = opcode;
5567   let Inst{11-10} = 0b10;
5568   let Inst{9-5}   = Rn;
5569   let Inst{4-0}   = Rd;
5570 }
5571
5572 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5573   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5574                                     asm, ".4s", ".4h", []>;
5575   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5576                                     asm#"2", ".4s", ".8h", []>;
5577   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5578                                     asm, ".2d", ".2s", []>;
5579   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5580                                     asm#"2", ".2d", ".4s", []>;
5581 }
5582
5583 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5584   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5585                                     asm, ".4h", ".4s", []>;
5586   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5587                                     asm#"2", ".8h", ".4s", []>;
5588   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5589                                     asm, ".2s", ".2d", []>;
5590   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5591                                     asm#"2", ".4s", ".2d", []>;
5592 }
5593
5594 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5595                                      Intrinsic OpNode> {
5596   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5597                                      asm, ".2s", ".2d",
5598                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5599   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5600                                     asm#"2", ".4s", ".2d", []>;
5601
5602   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5603             (!cast<Instruction>(NAME # "v4f32")
5604                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5605 }
5606
5607 //----------------------------------------------------------------------------
5608 // AdvSIMD three register different-size vector instructions.
5609 //----------------------------------------------------------------------------
5610
5611 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5612 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5613                       RegisterOperand outtype, RegisterOperand intype1,
5614                       RegisterOperand intype2, string asm,
5615                       string outkind, string inkind1, string inkind2,
5616                       list<dag> pattern>
5617   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5618       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5619       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5620     Sched<[WriteV]> {
5621   bits<5> Rd;
5622   bits<5> Rn;
5623   bits<5> Rm;
5624   let Inst{31}    = 0;
5625   let Inst{30}    = size{0};
5626   let Inst{29}    = U;
5627   let Inst{28-24} = 0b01110;
5628   let Inst{23-22} = size{2-1};
5629   let Inst{21}    = 1;
5630   let Inst{20-16} = Rm;
5631   let Inst{15-12} = opcode;
5632   let Inst{11-10} = 0b00;
5633   let Inst{9-5}   = Rn;
5634   let Inst{4-0}   = Rd;
5635 }
5636
5637 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5638 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5639                       RegisterOperand outtype, RegisterOperand intype1,
5640                       RegisterOperand intype2, string asm,
5641                       string outkind, string inkind1, string inkind2,
5642                       list<dag> pattern>
5643   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5644       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5645       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5646     Sched<[WriteV]> {
5647   bits<5> Rd;
5648   bits<5> Rn;
5649   bits<5> Rm;
5650   let Inst{31}    = 0;
5651   let Inst{30}    = size{0};
5652   let Inst{29}    = U;
5653   let Inst{28-24} = 0b01110;
5654   let Inst{23-22} = size{2-1};
5655   let Inst{21}    = 1;
5656   let Inst{20-16} = Rm;
5657   let Inst{15-12} = opcode;
5658   let Inst{11-10} = 0b00;
5659   let Inst{9-5}   = Rn;
5660   let Inst{4-0}   = Rd;
5661 }
5662
5663 // FIXME: TableGen doesn't know how to deal with expanded types that also
5664 //        change the element count (in this case, placing the results in
5665 //        the high elements of the result register rather than the low
5666 //        elements). Until that's fixed, we can't code-gen those.
5667 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5668                                     Intrinsic IntOp> {
5669   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5670                                                   V64, V128, V128,
5671                                                   asm, ".8b", ".8h", ".8h",
5672      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5673   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5674                                                   V128, V128, V128,
5675                                                   asm#"2", ".16b", ".8h", ".8h",
5676      []>;
5677   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5678                                                   V64, V128, V128,
5679                                                   asm, ".4h", ".4s", ".4s",
5680      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5681   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5682                                                   V128, V128, V128,
5683                                                   asm#"2", ".8h", ".4s", ".4s",
5684      []>;
5685   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5686                                                   V64, V128, V128,
5687                                                   asm, ".2s", ".2d", ".2d",
5688      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5689   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5690                                                   V128, V128, V128,
5691                                                   asm#"2", ".4s", ".2d", ".2d",
5692      []>;
5693
5694
5695   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5696   // a version attached to an instruction.
5697   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5698                                                    (v8i16 V128:$Rm))),
5699             (!cast<Instruction>(NAME # "v8i16_v16i8")
5700                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5701                 V128:$Rn, V128:$Rm)>;
5702   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5703                                                     (v4i32 V128:$Rm))),
5704             (!cast<Instruction>(NAME # "v4i32_v8i16")
5705                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5706                 V128:$Rn, V128:$Rm)>;
5707   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5708                                                     (v2i64 V128:$Rm))),
5709             (!cast<Instruction>(NAME # "v2i64_v4i32")
5710                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5711                 V128:$Rn, V128:$Rm)>;
5712 }
5713
5714 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5715                                       Intrinsic IntOp> {
5716   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5717                                             V128, V64, V64,
5718                                             asm, ".8h", ".8b", ".8b",
5719       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5720   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5721                                             V128, V128, V128,
5722                                             asm#"2", ".8h", ".16b", ".16b", []>;
5723   let Predicates = [HasAES] in {
5724     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5725                                               V128, V64, V64,
5726                                               asm, ".1q", ".1d", ".1d", []>;
5727     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5728                                               V128, V128, V128,
5729                                               asm#"2", ".1q", ".2d", ".2d", []>;
5730   }
5731
5732   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5733                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
5734       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5735 }
5736
5737 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5738                                  SDPatternOperator OpNode> {
5739   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5740                                                   V128, V64, V64,
5741                                                   asm, ".4s", ".4h", ".4h",
5742       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5743   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5744                                                   V128, V128, V128,
5745                                                   asm#"2", ".4s", ".8h", ".8h",
5746       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5747                                       (extract_high_v8i16 V128:$Rm)))]>;
5748   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5749                                                   V128, V64, V64,
5750                                                   asm, ".2d", ".2s", ".2s",
5751       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5752   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5753                                                   V128, V128, V128,
5754                                                   asm#"2", ".2d", ".4s", ".4s",
5755       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5756                                       (extract_high_v4i32 V128:$Rm)))]>;
5757 }
5758
5759 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5760                                   SDPatternOperator OpNode = null_frag> {
5761   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5762                                                   V128, V64, V64,
5763                                                   asm, ".8h", ".8b", ".8b",
5764       [(set (v8i16 V128:$Rd),
5765             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5766   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5767                                                  V128, V128, V128,
5768                                                  asm#"2", ".8h", ".16b", ".16b",
5769       [(set (v8i16 V128:$Rd),
5770             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5771                                 (extract_high_v16i8 V128:$Rm)))))]>;
5772   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5773                                                   V128, V64, V64,
5774                                                   asm, ".4s", ".4h", ".4h",
5775       [(set (v4i32 V128:$Rd),
5776             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5777   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5778                                                   V128, V128, V128,
5779                                                   asm#"2", ".4s", ".8h", ".8h",
5780       [(set (v4i32 V128:$Rd),
5781             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5782                                   (extract_high_v8i16 V128:$Rm)))))]>;
5783   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5784                                                   V128, V64, V64,
5785                                                   asm, ".2d", ".2s", ".2s",
5786       [(set (v2i64 V128:$Rd),
5787             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5788   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5789                                                   V128, V128, V128,
5790                                                   asm#"2", ".2d", ".4s", ".4s",
5791       [(set (v2i64 V128:$Rd),
5792             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5793                                  (extract_high_v4i32 V128:$Rm)))))]>;
5794 }
5795
5796 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5797                                           string asm,
5798                                           SDPatternOperator OpNode> {
5799   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5800                                                   V128, V64, V64,
5801                                                   asm, ".8h", ".8b", ".8b",
5802     [(set (v8i16 V128:$dst),
5803           (add (v8i16 V128:$Rd),
5804                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5805   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5806                                                  V128, V128, V128,
5807                                                  asm#"2", ".8h", ".16b", ".16b",
5808     [(set (v8i16 V128:$dst),
5809           (add (v8i16 V128:$Rd),
5810                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5811                                    (extract_high_v16i8 V128:$Rm))))))]>;
5812   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5813                                                   V128, V64, V64,
5814                                                   asm, ".4s", ".4h", ".4h",
5815     [(set (v4i32 V128:$dst),
5816           (add (v4i32 V128:$Rd),
5817                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5818   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5819                                                   V128, V128, V128,
5820                                                   asm#"2", ".4s", ".8h", ".8h",
5821     [(set (v4i32 V128:$dst),
5822           (add (v4i32 V128:$Rd),
5823                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5824                                     (extract_high_v8i16 V128:$Rm))))))]>;
5825   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5826                                                   V128, V64, V64,
5827                                                   asm, ".2d", ".2s", ".2s",
5828     [(set (v2i64 V128:$dst),
5829           (add (v2i64 V128:$Rd),
5830                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5831   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5832                                                   V128, V128, V128,
5833                                                   asm#"2", ".2d", ".4s", ".4s",
5834     [(set (v2i64 V128:$dst),
5835           (add (v2i64 V128:$Rd),
5836                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5837                                     (extract_high_v4i32 V128:$Rm))))))]>;
5838 }
5839
5840 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5841                                   SDPatternOperator OpNode = null_frag> {
5842   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5843                                                   V128, V64, V64,
5844                                                   asm, ".8h", ".8b", ".8b",
5845       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5846   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5847                                                  V128, V128, V128,
5848                                                  asm#"2", ".8h", ".16b", ".16b",
5849       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5850                                       (extract_high_v16i8 V128:$Rm)))]>;
5851   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5852                                                   V128, V64, V64,
5853                                                   asm, ".4s", ".4h", ".4h",
5854       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5855   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5856                                                   V128, V128, V128,
5857                                                   asm#"2", ".4s", ".8h", ".8h",
5858       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5859                                       (extract_high_v8i16 V128:$Rm)))]>;
5860   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5861                                                   V128, V64, V64,
5862                                                   asm, ".2d", ".2s", ".2s",
5863       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5864   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5865                                                   V128, V128, V128,
5866                                                   asm#"2", ".2d", ".4s", ".4s",
5867       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5868                                       (extract_high_v4i32 V128:$Rm)))]>;
5869 }
5870
5871 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5872                                       string asm,
5873                                       SDPatternOperator OpNode> {
5874   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5875                                                   V128, V64, V64,
5876                                                   asm, ".8h", ".8b", ".8b",
5877     [(set (v8i16 V128:$dst),
5878           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5879   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5880                                                  V128, V128, V128,
5881                                                  asm#"2", ".8h", ".16b", ".16b",
5882     [(set (v8i16 V128:$dst),
5883           (OpNode (v8i16 V128:$Rd),
5884                   (extract_high_v16i8 V128:$Rn),
5885                   (extract_high_v16i8 V128:$Rm)))]>;
5886   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5887                                                   V128, V64, V64,
5888                                                   asm, ".4s", ".4h", ".4h",
5889     [(set (v4i32 V128:$dst),
5890           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5891   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5892                                                   V128, V128, V128,
5893                                                   asm#"2", ".4s", ".8h", ".8h",
5894     [(set (v4i32 V128:$dst),
5895           (OpNode (v4i32 V128:$Rd),
5896                   (extract_high_v8i16 V128:$Rn),
5897                   (extract_high_v8i16 V128:$Rm)))]>;
5898   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5899                                                   V128, V64, V64,
5900                                                   asm, ".2d", ".2s", ".2s",
5901     [(set (v2i64 V128:$dst),
5902           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5903   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5904                                                   V128, V128, V128,
5905                                                   asm#"2", ".2d", ".4s", ".4s",
5906     [(set (v2i64 V128:$dst),
5907           (OpNode (v2i64 V128:$Rd),
5908                   (extract_high_v4i32 V128:$Rn),
5909                   (extract_high_v4i32 V128:$Rm)))]>;
5910 }
5911
5912 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5913                                            SDPatternOperator Accum> {
5914   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5915                                                   V128, V64, V64,
5916                                                   asm, ".4s", ".4h", ".4h",
5917     [(set (v4i32 V128:$dst),
5918           (Accum (v4i32 V128:$Rd),
5919                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5920                                                 (v4i16 V64:$Rm)))))]>;
5921   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5922                                                   V128, V128, V128,
5923                                                   asm#"2", ".4s", ".8h", ".8h",
5924     [(set (v4i32 V128:$dst),
5925           (Accum (v4i32 V128:$Rd),
5926                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5927                                             (extract_high_v8i16 V128:$Rm)))))]>;
5928   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5929                                                   V128, V64, V64,
5930                                                   asm, ".2d", ".2s", ".2s",
5931     [(set (v2i64 V128:$dst),
5932           (Accum (v2i64 V128:$Rd),
5933                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5934                                                 (v2i32 V64:$Rm)))))]>;
5935   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5936                                                   V128, V128, V128,
5937                                                   asm#"2", ".2d", ".4s", ".4s",
5938     [(set (v2i64 V128:$dst),
5939           (Accum (v2i64 V128:$Rd),
5940                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5941                                             (extract_high_v4i32 V128:$Rm)))))]>;
5942 }
5943
5944 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5945                                   SDPatternOperator OpNode> {
5946   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5947                                                   V128, V128, V64,
5948                                                   asm, ".8h", ".8h", ".8b",
5949        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5950   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5951                                                   V128, V128, V128,
5952                                                   asm#"2", ".8h", ".8h", ".16b",
5953        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5954                                        (extract_high_v16i8 V128:$Rm)))]>;
5955   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5956                                                   V128, V128, V64,
5957                                                   asm, ".4s", ".4s", ".4h",
5958        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5959   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5960                                                   V128, V128, V128,
5961                                                   asm#"2", ".4s", ".4s", ".8h",
5962        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5963                                        (extract_high_v8i16 V128:$Rm)))]>;
5964   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5965                                                   V128, V128, V64,
5966                                                   asm, ".2d", ".2d", ".2s",
5967        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5968   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5969                                                   V128, V128, V128,
5970                                                   asm#"2", ".2d", ".2d", ".4s",
5971        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5972                                        (extract_high_v4i32 V128:$Rm)))]>;
5973 }
5974
5975 //----------------------------------------------------------------------------
5976 // AdvSIMD bitwise extract from vector
5977 //----------------------------------------------------------------------------
5978
5979 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5980                              string asm, string kind>
5981   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5982       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5983       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5984       [(set (vty regtype:$Rd),
5985             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5986     Sched<[WriteV]> {
5987   bits<5> Rd;
5988   bits<5> Rn;
5989   bits<5> Rm;
5990   bits<4> imm;
5991   let Inst{31}    = 0;
5992   let Inst{30}    = size;
5993   let Inst{29-21} = 0b101110000;
5994   let Inst{20-16} = Rm;
5995   let Inst{15}    = 0;
5996   let Inst{14-11} = imm;
5997   let Inst{10}    = 0;
5998   let Inst{9-5}   = Rn;
5999   let Inst{4-0}   = Rd;
6000 }
6001
6002
6003 multiclass SIMDBitwiseExtract<string asm> {
6004   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6005     let imm{3} = 0;
6006   }
6007   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6008 }
6009
6010 //----------------------------------------------------------------------------
6011 // AdvSIMD zip vector
6012 //----------------------------------------------------------------------------
6013
6014 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6015                         string asm, string kind, SDNode OpNode, ValueType valty>
6016   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6017       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6018       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6019       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6020     Sched<[WriteV]> {
6021   bits<5> Rd;
6022   bits<5> Rn;
6023   bits<5> Rm;
6024   let Inst{31}    = 0;
6025   let Inst{30}    = size{0};
6026   let Inst{29-24} = 0b001110;
6027   let Inst{23-22} = size{2-1};
6028   let Inst{21}    = 0;
6029   let Inst{20-16} = Rm;
6030   let Inst{15}    = 0;
6031   let Inst{14-12} = opc;
6032   let Inst{11-10} = 0b10;
6033   let Inst{9-5}   = Rn;
6034   let Inst{4-0}   = Rd;
6035 }
6036
6037 multiclass SIMDZipVector<bits<3>opc, string asm,
6038                          SDNode OpNode> {
6039   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6040       asm, ".8b", OpNode, v8i8>;
6041   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6042       asm, ".16b", OpNode, v16i8>;
6043   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6044       asm, ".4h", OpNode, v4i16>;
6045   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6046       asm, ".8h", OpNode, v8i16>;
6047   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6048       asm, ".2s", OpNode, v2i32>;
6049   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6050       asm, ".4s", OpNode, v4i32>;
6051   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6052       asm, ".2d", OpNode, v2i64>;
6053
6054   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6055         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6056   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6057         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6058   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6059         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6060   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6061         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6062   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6063         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6064 }
6065
6066 //----------------------------------------------------------------------------
6067 // AdvSIMD three register scalar instructions
6068 //----------------------------------------------------------------------------
6069
6070 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6071 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6072                         RegisterClass regtype, string asm,
6073                         list<dag> pattern>
6074   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6075       "\t$Rd, $Rn, $Rm", "", pattern>,
6076     Sched<[WriteV]> {
6077   bits<5> Rd;
6078   bits<5> Rn;
6079   bits<5> Rm;
6080   let Inst{31-30} = 0b01;
6081   let Inst{29}    = U;
6082   let Inst{28-24} = 0b11110;
6083   let Inst{23-21} = size;
6084   let Inst{20-16} = Rm;
6085   let Inst{15-11} = opcode;
6086   let Inst{10}    = 1;
6087   let Inst{9-5}   = Rn;
6088   let Inst{4-0}   = Rd;
6089 }
6090
6091 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6092 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6093                         dag oops, dag iops, string asm,
6094             list<dag> pattern>
6095   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6096     Sched<[WriteV]> {
6097   bits<5> Rd;
6098   bits<5> Rn;
6099   bits<5> Rm;
6100   let Inst{31-30} = 0b01;
6101   let Inst{29}    = U;
6102   let Inst{28-24} = 0b11110;
6103   let Inst{23-22} = size;
6104   let Inst{21}    = R;
6105   let Inst{20-16} = Rm;
6106   let Inst{15-11} = opcode;
6107   let Inst{10}    = 1;
6108   let Inst{9-5}   = Rn;
6109   let Inst{4-0}   = Rd;
6110 }
6111
6112 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6113                             SDPatternOperator OpNode> {
6114   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6115     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6116 }
6117
6118 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6119                                SDPatternOperator OpNode> {
6120   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6121     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6122   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6123   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6124   def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6125
6126   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6127             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6128   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6129             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6130 }
6131
6132 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6133                              SDPatternOperator OpNode> {
6134   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6135                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6136   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6137 }
6138
6139 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6140                                  SDPatternOperator OpNode = null_frag> {
6141   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6142                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6143                                      asm, []>;
6144   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6145                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6146                                      asm, []>;
6147 }
6148
6149 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6150                              SDPatternOperator OpNode = null_frag> {
6151   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6152     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6153       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6154     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6155       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6156     let Predicates = [HasNEON, HasFullFP16] in {
6157     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6158       [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
6159     } // Predicates = [HasNEON, HasFullFP16]
6160   }
6161
6162   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6163             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6164 }
6165
6166 multiclass SIMDThreeScalarFPCmp<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 (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6171     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6172       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6173     let Predicates = [HasNEON, HasFullFP16] in {
6174     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6175       []>;
6176     } // Predicates = [HasNEON, HasFullFP16]
6177   }
6178
6179   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6180             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6181 }
6182
6183 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6184               dag oops, dag iops, string asm, string cstr, list<dag> pat>
6185   : I<oops, iops, asm,
6186       "\t$Rd, $Rn, $Rm", cstr, pat>,
6187     Sched<[WriteV]> {
6188   bits<5> Rd;
6189   bits<5> Rn;
6190   bits<5> Rm;
6191   let Inst{31-30} = 0b01;
6192   let Inst{29}    = U;
6193   let Inst{28-24} = 0b11110;
6194   let Inst{23-22} = size;
6195   let Inst{21}    = 1;
6196   let Inst{20-16} = Rm;
6197   let Inst{15-11} = opcode;
6198   let Inst{10}    = 0;
6199   let Inst{9-5}   = Rn;
6200   let Inst{4-0}   = Rd;
6201 }
6202
6203 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6204 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6205                                   SDPatternOperator OpNode = null_frag> {
6206   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6207                                       (outs FPR32:$Rd),
6208                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6209   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6210                                       (outs FPR64:$Rd),
6211                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6212             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6213 }
6214
6215 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6216 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6217                                   SDPatternOperator OpNode = null_frag> {
6218   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6219                                       (outs FPR32:$dst),
6220                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6221                                       asm, "$Rd = $dst", []>;
6222   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6223                                       (outs FPR64:$dst),
6224                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6225                                       asm, "$Rd = $dst",
6226             [(set (i64 FPR64:$dst),
6227                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6228 }
6229
6230 //----------------------------------------------------------------------------
6231 // AdvSIMD two register scalar instructions
6232 //----------------------------------------------------------------------------
6233
6234 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6235 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6236                         RegisterClass regtype, RegisterClass regtype2,
6237                         string asm, list<dag> pat>
6238   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6239       "\t$Rd, $Rn", "", pat>,
6240     Sched<[WriteV]> {
6241   bits<5> Rd;
6242   bits<5> Rn;
6243   let Inst{31-30} = 0b01;
6244   let Inst{29}    = U;
6245   let Inst{28-24} = 0b11110;
6246   let Inst{23-22} = size;
6247   let Inst{21} = 0b1;
6248   let Inst{20-19} = size2;
6249   let Inst{18-17} = 0b00;
6250   let Inst{16-12} = opcode;
6251   let Inst{11-10} = 0b10;
6252   let Inst{9-5}   = Rn;
6253   let Inst{4-0}   = Rd;
6254 }
6255
6256 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6257 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6258                         RegisterClass regtype, RegisterClass regtype2,
6259                         string asm, list<dag> pat>
6260   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6261       "\t$Rd, $Rn", "$Rd = $dst", pat>,
6262     Sched<[WriteV]> {
6263   bits<5> Rd;
6264   bits<5> Rn;
6265   let Inst{31-30} = 0b01;
6266   let Inst{29}    = U;
6267   let Inst{28-24} = 0b11110;
6268   let Inst{23-22} = size;
6269   let Inst{21-17} = 0b10000;
6270   let Inst{16-12} = opcode;
6271   let Inst{11-10} = 0b10;
6272   let Inst{9-5}   = Rn;
6273   let Inst{4-0}   = Rd;
6274 }
6275
6276
6277 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6278 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6279                         RegisterClass regtype, string asm, string zero>
6280   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6281       "\t$Rd, $Rn, #" # zero, "", []>,
6282     Sched<[WriteV]> {
6283   bits<5> Rd;
6284   bits<5> Rn;
6285   let Inst{31-30} = 0b01;
6286   let Inst{29}    = U;
6287   let Inst{28-24} = 0b11110;
6288   let Inst{23-22} = size;
6289   let Inst{21} = 0b1;
6290   let Inst{20-19} = size2;
6291   let Inst{18-17} = 0b00;
6292   let Inst{16-12} = opcode;
6293   let Inst{11-10} = 0b10;
6294   let Inst{9-5}   = Rn;
6295   let Inst{4-0}   = Rd;
6296 }
6297
6298 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6299   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6300      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6301     Sched<[WriteV]> {
6302   bits<5> Rd;
6303   bits<5> Rn;
6304   let Inst{31-17} = 0b011111100110000;
6305   let Inst{16-12} = opcode;
6306   let Inst{11-10} = 0b10;
6307   let Inst{9-5}   = Rn;
6308   let Inst{4-0}   = Rd;
6309 }
6310
6311 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6312                              SDPatternOperator OpNode> {
6313   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6314
6315   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6316             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6317 }
6318
6319 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6320                               SDPatternOperator OpNode> {
6321   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6322   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6323   let Predicates = [HasNEON, HasFullFP16] in {
6324   def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6325   }
6326
6327   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6328                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6329   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6330                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6331   let Predicates = [HasNEON, HasFullFP16] in {
6332   def : InstAlias<asm # "\t$Rd, $Rn, #0",
6333                   (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6334   }
6335
6336   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6337             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6338 }
6339
6340 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6341                           SDPatternOperator OpNode = null_frag> {
6342   def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6343     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6344
6345   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6346             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6347 }
6348
6349 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6350   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6351   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6352   let Predicates = [HasNEON, HasFullFP16] in {
6353   def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6354   }
6355 }
6356
6357 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6358                               SDPatternOperator OpNode> {
6359   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6360                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6361   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6362                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6363   let Predicates = [HasNEON, HasFullFP16] in {
6364   def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6365                                 [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
6366   }
6367 }
6368
6369 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6370                              SDPatternOperator OpNode = null_frag> {
6371   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6372     def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6373            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6374     def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6375            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6376     def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6377     def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6378   }
6379
6380   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6381             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6382 }
6383
6384 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6385                                  Intrinsic OpNode> {
6386   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6387     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6388         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6389     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6390         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
6391     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
6392     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
6393   }
6394
6395   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
6396             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
6397 }
6398
6399
6400
6401 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6402 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
6403                                  SDPatternOperator OpNode = null_frag> {
6404   def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
6405         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6406   def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
6407   def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
6408 }
6409
6410 //----------------------------------------------------------------------------
6411 // AdvSIMD scalar pairwise instructions
6412 //----------------------------------------------------------------------------
6413
6414 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6415 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
6416                         RegisterOperand regtype, RegisterOperand vectype,
6417                         string asm, string kind>
6418   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6419       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
6420     Sched<[WriteV]> {
6421   bits<5> Rd;
6422   bits<5> Rn;
6423   let Inst{31-30} = 0b01;
6424   let Inst{29}    = U;
6425   let Inst{28-24} = 0b11110;
6426   let Inst{23-22} = size;
6427   let Inst{21-17} = 0b11000;
6428   let Inst{16-12} = opcode;
6429   let Inst{11-10} = 0b10;
6430   let Inst{9-5}   = Rn;
6431   let Inst{4-0}   = Rd;
6432 }
6433
6434 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6435   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6436                                       asm, ".2d">;
6437 }
6438
6439 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6440   let Predicates = [HasNEON, HasFullFP16] in {
6441   def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6442                                       asm, ".2h">;
6443   }
6444   def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6445                                       asm, ".2s">;
6446   def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6447                                       asm, ".2d">;
6448 }
6449
6450 //----------------------------------------------------------------------------
6451 // AdvSIMD across lanes instructions
6452 //----------------------------------------------------------------------------
6453
6454 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6455 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6456                           RegisterClass regtype, RegisterOperand vectype,
6457                           string asm, string kind, list<dag> pattern>
6458   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6459       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6460     Sched<[WriteV]> {
6461   bits<5> Rd;
6462   bits<5> Rn;
6463   let Inst{31}    = 0;
6464   let Inst{30}    = Q;
6465   let Inst{29}    = U;
6466   let Inst{28-24} = 0b01110;
6467   let Inst{23-22} = size;
6468   let Inst{21-17} = 0b11000;
6469   let Inst{16-12} = opcode;
6470   let Inst{11-10} = 0b10;
6471   let Inst{9-5}   = Rn;
6472   let Inst{4-0}   = Rd;
6473 }
6474
6475 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6476                               string asm> {
6477   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
6478                                    asm, ".8b", []>;
6479   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
6480                                    asm, ".16b", []>;
6481   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6482                                    asm, ".4h", []>;
6483   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6484                                    asm, ".8h", []>;
6485   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6486                                    asm, ".4s", []>;
6487 }
6488
6489 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6490   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6491                                    asm, ".8b", []>;
6492   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6493                                    asm, ".16b", []>;
6494   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6495                                    asm, ".4h", []>;
6496   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6497                                    asm, ".8h", []>;
6498   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6499                                    asm, ".4s", []>;
6500 }
6501
6502 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6503                             Intrinsic intOp> {
6504   let Predicates = [HasNEON, HasFullFP16] in {
6505   def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6506                                    asm, ".4h",
6507         [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6508   def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6509                                    asm, ".8h",
6510         [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6511   } // Predicates = [HasNEON, HasFullFP16]
6512   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6513                                    asm, ".4s",
6514         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6515 }
6516
6517 //----------------------------------------------------------------------------
6518 // AdvSIMD INS/DUP instructions
6519 //----------------------------------------------------------------------------
6520
6521 // FIXME: There has got to be a better way to factor these. ugh.
6522
6523 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6524                      string operands, string constraints, list<dag> pattern>
6525   : I<outs, ins, asm, operands, constraints, pattern>,
6526     Sched<[WriteV]> {
6527   bits<5> Rd;
6528   bits<5> Rn;
6529   let Inst{31} = 0;
6530   let Inst{30} = Q;
6531   let Inst{29} = op;
6532   let Inst{28-21} = 0b01110000;
6533   let Inst{15} = 0;
6534   let Inst{10} = 1;
6535   let Inst{9-5} = Rn;
6536   let Inst{4-0} = Rd;
6537 }
6538
6539 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6540                       RegisterOperand vecreg, RegisterClass regtype>
6541   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6542                    "{\t$Rd" # size # ", $Rn" #
6543                    "|" # size # "\t$Rd, $Rn}", "",
6544                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6545   let Inst{20-16} = imm5;
6546   let Inst{14-11} = 0b0001;
6547 }
6548
6549 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6550                          ValueType vectype, ValueType insreg,
6551                          RegisterOperand vecreg, Operand idxtype,
6552                          ValueType elttype, SDNode OpNode>
6553   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6554                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6555                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6556                  [(set (vectype vecreg:$Rd),
6557                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6558   let Inst{14-11} = 0b0000;
6559 }
6560
6561 class SIMDDup64FromElement
6562   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6563                        VectorIndexD, i64, AArch64duplane64> {
6564   bits<1> idx;
6565   let Inst{20} = idx;
6566   let Inst{19-16} = 0b1000;
6567 }
6568
6569 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6570                            RegisterOperand vecreg>
6571   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6572                        VectorIndexS, i64, AArch64duplane32> {
6573   bits<2> idx;
6574   let Inst{20-19} = idx;
6575   let Inst{18-16} = 0b100;
6576 }
6577
6578 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6579                            RegisterOperand vecreg>
6580   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6581                        VectorIndexH, i64, AArch64duplane16> {
6582   bits<3> idx;
6583   let Inst{20-18} = idx;
6584   let Inst{17-16} = 0b10;
6585 }
6586
6587 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6588                           RegisterOperand vecreg>
6589   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6590                        VectorIndexB, i64, AArch64duplane8> {
6591   bits<4> idx;
6592   let Inst{20-17} = idx;
6593   let Inst{16} = 1;
6594 }
6595
6596 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6597                   Operand idxtype, string asm, list<dag> pattern>
6598   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6599                    "{\t$Rd, $Rn" # size # "$idx" #
6600                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6601   let Inst{14-11} = imm4;
6602 }
6603
6604 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6605                Operand idxtype>
6606   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6607 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6608                Operand idxtype>
6609   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6610       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6611
6612 class SIMDMovAlias<string asm, string size, Instruction inst,
6613                    RegisterClass regtype, Operand idxtype>
6614     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6615                     "|" # size # "\t$dst, $src$idx}",
6616                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6617
6618 multiclass SMov {
6619   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6620     bits<4> idx;
6621     let Inst{20-17} = idx;
6622     let Inst{16} = 1;
6623   }
6624   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6625     bits<4> idx;
6626     let Inst{20-17} = idx;
6627     let Inst{16} = 1;
6628   }
6629   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6630     bits<3> idx;
6631     let Inst{20-18} = idx;
6632     let Inst{17-16} = 0b10;
6633   }
6634   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6635     bits<3> idx;
6636     let Inst{20-18} = idx;
6637     let Inst{17-16} = 0b10;
6638   }
6639   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6640     bits<2> idx;
6641     let Inst{20-19} = idx;
6642     let Inst{18-16} = 0b100;
6643   }
6644 }
6645
6646 multiclass UMov {
6647   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6648     bits<4> idx;
6649     let Inst{20-17} = idx;
6650     let Inst{16} = 1;
6651   }
6652   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6653     bits<3> idx;
6654     let Inst{20-18} = idx;
6655     let Inst{17-16} = 0b10;
6656   }
6657   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6658     bits<2> idx;
6659     let Inst{20-19} = idx;
6660     let Inst{18-16} = 0b100;
6661   }
6662   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6663     bits<1> idx;
6664     let Inst{20} = idx;
6665     let Inst{19-16} = 0b1000;
6666   }
6667   def : SIMDMovAlias<"mov", ".s",
6668                      !cast<Instruction>(NAME#"vi32"),
6669                      GPR32, VectorIndexS>;
6670   def : SIMDMovAlias<"mov", ".d",
6671                      !cast<Instruction>(NAME#"vi64"),
6672                      GPR64, VectorIndexD>;
6673 }
6674
6675 class SIMDInsFromMain<string size, ValueType vectype,
6676                       RegisterClass regtype, Operand idxtype>
6677   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6678                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6679                    "{\t$Rd" # size # "$idx, $Rn" #
6680                    "|" # size # "\t$Rd$idx, $Rn}",
6681                    "$Rd = $dst",
6682             [(set V128:$dst,
6683               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6684   let Inst{14-11} = 0b0011;
6685 }
6686
6687 class SIMDInsFromElement<string size, ValueType vectype,
6688                          ValueType elttype, Operand idxtype>
6689   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6690                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6691                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6692                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
6693                    "$Rd = $dst",
6694          [(set V128:$dst,
6695                (vector_insert
6696                  (vectype V128:$Rd),
6697                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6698                  idxtype:$idx))]>;
6699
6700 class SIMDInsMainMovAlias<string size, Instruction inst,
6701                           RegisterClass regtype, Operand idxtype>
6702     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6703                         "|" # size #"\t$dst$idx, $src}",
6704                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6705 class SIMDInsElementMovAlias<string size, Instruction inst,
6706                              Operand idxtype>
6707     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6708                       # "|" # size #"\t$dst$idx, $src$idx2}",
6709                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6710
6711
6712 multiclass SIMDIns {
6713   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6714     bits<4> idx;
6715     let Inst{20-17} = idx;
6716     let Inst{16} = 1;
6717   }
6718   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6719     bits<3> idx;
6720     let Inst{20-18} = idx;
6721     let Inst{17-16} = 0b10;
6722   }
6723   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6724     bits<2> idx;
6725     let Inst{20-19} = idx;
6726     let Inst{18-16} = 0b100;
6727   }
6728   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6729     bits<1> idx;
6730     let Inst{20} = idx;
6731     let Inst{19-16} = 0b1000;
6732   }
6733
6734   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6735     bits<4> idx;
6736     bits<4> idx2;
6737     let Inst{20-17} = idx;
6738     let Inst{16} = 1;
6739     let Inst{14-11} = idx2;
6740   }
6741   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6742     bits<3> idx;
6743     bits<3> idx2;
6744     let Inst{20-18} = idx;
6745     let Inst{17-16} = 0b10;
6746     let Inst{14-12} = idx2;
6747     let Inst{11} = {?};
6748   }
6749   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6750     bits<2> idx;
6751     bits<2> idx2;
6752     let Inst{20-19} = idx;
6753     let Inst{18-16} = 0b100;
6754     let Inst{14-13} = idx2;
6755     let Inst{12-11} = {?,?};
6756   }
6757   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6758     bits<1> idx;
6759     bits<1> idx2;
6760     let Inst{20} = idx;
6761     let Inst{19-16} = 0b1000;
6762     let Inst{14} = idx2;
6763     let Inst{13-11} = {?,?,?};
6764   }
6765
6766   // For all forms of the INS instruction, the "mov" mnemonic is the
6767   // preferred alias. Why they didn't just call the instruction "mov" in
6768   // the first place is a very good question indeed...
6769   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6770                          GPR32, VectorIndexB>;
6771   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6772                          GPR32, VectorIndexH>;
6773   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6774                          GPR32, VectorIndexS>;
6775   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6776                          GPR64, VectorIndexD>;
6777
6778   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6779                          VectorIndexB>;
6780   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6781                          VectorIndexH>;
6782   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6783                          VectorIndexS>;
6784   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6785                          VectorIndexD>;
6786 }
6787
6788 //----------------------------------------------------------------------------
6789 // AdvSIMD TBL/TBX
6790 //----------------------------------------------------------------------------
6791
6792 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6793 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6794                           RegisterOperand listtype, string asm, string kind>
6795   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6796        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6797     Sched<[WriteV]> {
6798   bits<5> Vd;
6799   bits<5> Vn;
6800   bits<5> Vm;
6801   let Inst{31}    = 0;
6802   let Inst{30}    = Q;
6803   let Inst{29-21} = 0b001110000;
6804   let Inst{20-16} = Vm;
6805   let Inst{15}    = 0;
6806   let Inst{14-13} = len;
6807   let Inst{12}    = op;
6808   let Inst{11-10} = 0b00;
6809   let Inst{9-5}   = Vn;
6810   let Inst{4-0}   = Vd;
6811 }
6812
6813 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6814 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6815                           RegisterOperand listtype, string asm, string kind>
6816   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6817        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6818     Sched<[WriteV]> {
6819   bits<5> Vd;
6820   bits<5> Vn;
6821   bits<5> Vm;
6822   let Inst{31}    = 0;
6823   let Inst{30}    = Q;
6824   let Inst{29-21} = 0b001110000;
6825   let Inst{20-16} = Vm;
6826   let Inst{15}    = 0;
6827   let Inst{14-13} = len;
6828   let Inst{12}    = op;
6829   let Inst{11-10} = 0b00;
6830   let Inst{9-5}   = Vn;
6831   let Inst{4-0}   = Vd;
6832 }
6833
6834 class SIMDTableLookupAlias<string asm, Instruction inst,
6835                           RegisterOperand vectype, RegisterOperand listtype>
6836     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6837                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6838
6839 multiclass SIMDTableLookup<bit op, string asm> {
6840   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6841                                       asm, ".8b">;
6842   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6843                                       asm, ".8b">;
6844   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6845                                       asm, ".8b">;
6846   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6847                                       asm, ".8b">;
6848   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6849                                       asm, ".16b">;
6850   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6851                                       asm, ".16b">;
6852   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6853                                       asm, ".16b">;
6854   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6855                                       asm, ".16b">;
6856
6857   def : SIMDTableLookupAlias<asm # ".8b",
6858                          !cast<Instruction>(NAME#"v8i8One"),
6859                          V64, VecListOne128>;
6860   def : SIMDTableLookupAlias<asm # ".8b",
6861                          !cast<Instruction>(NAME#"v8i8Two"),
6862                          V64, VecListTwo128>;
6863   def : SIMDTableLookupAlias<asm # ".8b",
6864                          !cast<Instruction>(NAME#"v8i8Three"),
6865                          V64, VecListThree128>;
6866   def : SIMDTableLookupAlias<asm # ".8b",
6867                          !cast<Instruction>(NAME#"v8i8Four"),
6868                          V64, VecListFour128>;
6869   def : SIMDTableLookupAlias<asm # ".16b",
6870                          !cast<Instruction>(NAME#"v16i8One"),
6871                          V128, VecListOne128>;
6872   def : SIMDTableLookupAlias<asm # ".16b",
6873                          !cast<Instruction>(NAME#"v16i8Two"),
6874                          V128, VecListTwo128>;
6875   def : SIMDTableLookupAlias<asm # ".16b",
6876                          !cast<Instruction>(NAME#"v16i8Three"),
6877                          V128, VecListThree128>;
6878   def : SIMDTableLookupAlias<asm # ".16b",
6879                          !cast<Instruction>(NAME#"v16i8Four"),
6880                          V128, VecListFour128>;
6881 }
6882
6883 multiclass SIMDTableLookupTied<bit op, string asm> {
6884   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6885                                       asm, ".8b">;
6886   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6887                                       asm, ".8b">;
6888   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6889                                       asm, ".8b">;
6890   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6891                                       asm, ".8b">;
6892   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6893                                       asm, ".16b">;
6894   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6895                                       asm, ".16b">;
6896   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6897                                       asm, ".16b">;
6898   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6899                                       asm, ".16b">;
6900
6901   def : SIMDTableLookupAlias<asm # ".8b",
6902                          !cast<Instruction>(NAME#"v8i8One"),
6903                          V64, VecListOne128>;
6904   def : SIMDTableLookupAlias<asm # ".8b",
6905                          !cast<Instruction>(NAME#"v8i8Two"),
6906                          V64, VecListTwo128>;
6907   def : SIMDTableLookupAlias<asm # ".8b",
6908                          !cast<Instruction>(NAME#"v8i8Three"),
6909                          V64, VecListThree128>;
6910   def : SIMDTableLookupAlias<asm # ".8b",
6911                          !cast<Instruction>(NAME#"v8i8Four"),
6912                          V64, VecListFour128>;
6913   def : SIMDTableLookupAlias<asm # ".16b",
6914                          !cast<Instruction>(NAME#"v16i8One"),
6915                          V128, VecListOne128>;
6916   def : SIMDTableLookupAlias<asm # ".16b",
6917                          !cast<Instruction>(NAME#"v16i8Two"),
6918                          V128, VecListTwo128>;
6919   def : SIMDTableLookupAlias<asm # ".16b",
6920                          !cast<Instruction>(NAME#"v16i8Three"),
6921                          V128, VecListThree128>;
6922   def : SIMDTableLookupAlias<asm # ".16b",
6923                          !cast<Instruction>(NAME#"v16i8Four"),
6924                          V128, VecListFour128>;
6925 }
6926
6927
6928 //----------------------------------------------------------------------------
6929 // AdvSIMD scalar CPY
6930 //----------------------------------------------------------------------------
6931 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6932 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6933                         string kind, Operand idxtype>
6934   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6935        "{\t$dst, $src" # kind # "$idx" #
6936        "|\t$dst, $src$idx}", "", []>,
6937     Sched<[WriteV]> {
6938   bits<5> dst;
6939   bits<5> src;
6940   let Inst{31-21} = 0b01011110000;
6941   let Inst{15-10} = 0b000001;
6942   let Inst{9-5}   = src;
6943   let Inst{4-0}   = dst;
6944 }
6945
6946 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6947       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6948     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6949                     # "|\t$dst, $src$index}",
6950                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6951
6952
6953 multiclass SIMDScalarCPY<string asm> {
6954   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6955     bits<4> idx;
6956     let Inst{20-17} = idx;
6957     let Inst{16} = 1;
6958   }
6959   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6960     bits<3> idx;
6961     let Inst{20-18} = idx;
6962     let Inst{17-16} = 0b10;
6963   }
6964   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6965     bits<2> idx;
6966     let Inst{20-19} = idx;
6967     let Inst{18-16} = 0b100;
6968   }
6969   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6970     bits<1> idx;
6971     let Inst{20} = idx;
6972     let Inst{19-16} = 0b1000;
6973   }
6974
6975   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6976                                                           VectorIndexD:$idx)))),
6977             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6978
6979   // 'DUP' mnemonic aliases.
6980   def : SIMDScalarCPYAlias<"dup", ".b",
6981                            !cast<Instruction>(NAME#"i8"),
6982                            FPR8, V128, VectorIndexB>;
6983   def : SIMDScalarCPYAlias<"dup", ".h",
6984                            !cast<Instruction>(NAME#"i16"),
6985                            FPR16, V128, VectorIndexH>;
6986   def : SIMDScalarCPYAlias<"dup", ".s",
6987                            !cast<Instruction>(NAME#"i32"),
6988                            FPR32, V128, VectorIndexS>;
6989   def : SIMDScalarCPYAlias<"dup", ".d",
6990                            !cast<Instruction>(NAME#"i64"),
6991                            FPR64, V128, VectorIndexD>;
6992 }
6993
6994 //----------------------------------------------------------------------------
6995 // AdvSIMD modified immediate instructions
6996 //----------------------------------------------------------------------------
6997
6998 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
6999                           string asm, string op_string,
7000                           string cstr, list<dag> pattern>
7001   : I<oops, iops, asm, op_string, cstr, pattern>,
7002     Sched<[WriteV]> {
7003   bits<5> Rd;
7004   bits<8> imm8;
7005   let Inst{31}    = 0;
7006   let Inst{30}    = Q;
7007   let Inst{29}    = op;
7008   let Inst{28-19} = 0b0111100000;
7009   let Inst{18-16} = imm8{7-5};
7010   let Inst{11} = op2;
7011   let Inst{10} = 1;
7012   let Inst{9-5}   = imm8{4-0};
7013   let Inst{4-0}   = Rd;
7014 }
7015
7016 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7017                                 Operand immtype, dag opt_shift_iop,
7018                                 string opt_shift, string asm, string kind,
7019                                 list<dag> pattern>
7020   : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7021                         !con((ins immtype:$imm8), opt_shift_iop), asm,
7022                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
7023                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7024                         "", pattern> {
7025   let DecoderMethod = "DecodeModImmInstruction";
7026 }
7027
7028 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7029                                 Operand immtype, dag opt_shift_iop,
7030                                 string opt_shift, string asm, string kind,
7031                                 list<dag> pattern>
7032   : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7033                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7034                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7035                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7036                         "$Rd = $dst", pattern> {
7037   let DecoderMethod = "DecodeModImmTiedInstruction";
7038 }
7039
7040 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7041                                      RegisterOperand vectype, string asm,
7042                                      string kind, list<dag> pattern>
7043   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7044                               (ins logical_vec_shift:$shift),
7045                               "$shift", asm, kind, pattern> {
7046   bits<2> shift;
7047   let Inst{15}    = b15_b12{1};
7048   let Inst{14-13} = shift;
7049   let Inst{12}    = b15_b12{0};
7050 }
7051
7052 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7053                                      RegisterOperand vectype, string asm,
7054                                      string kind, list<dag> pattern>
7055   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7056                               (ins logical_vec_shift:$shift),
7057                               "$shift", asm, kind, pattern> {
7058   bits<2> shift;
7059   let Inst{15}    = b15_b12{1};
7060   let Inst{14-13} = shift;
7061   let Inst{12}    = b15_b12{0};
7062 }
7063
7064
7065 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7066                                          RegisterOperand vectype, string asm,
7067                                          string kind, list<dag> pattern>
7068   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7069                               (ins logical_vec_hw_shift:$shift),
7070                               "$shift", asm, kind, pattern> {
7071   bits<2> shift;
7072   let Inst{15} = b15_b12{1};
7073   let Inst{14} = 0;
7074   let Inst{13} = shift{0};
7075   let Inst{12} = b15_b12{0};
7076 }
7077
7078 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7079                                          RegisterOperand vectype, string asm,
7080                                          string kind, list<dag> pattern>
7081   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7082                               (ins logical_vec_hw_shift:$shift),
7083                               "$shift", asm, kind, pattern> {
7084   bits<2> shift;
7085   let Inst{15} = b15_b12{1};
7086   let Inst{14} = 0;
7087   let Inst{13} = shift{0};
7088   let Inst{12} = b15_b12{0};
7089 }
7090
7091 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7092                                       string asm> {
7093   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7094                                                  asm, ".4h", []>;
7095   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7096                                                  asm, ".8h", []>;
7097
7098   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7099                                              asm, ".2s", []>;
7100   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7101                                              asm, ".4s", []>;
7102 }
7103
7104 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7105                                       bits<2> w_cmode, string asm,
7106                                       SDNode OpNode> {
7107   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7108                                                  asm, ".4h",
7109              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7110                                              imm0_255:$imm8,
7111                                              (i32 imm:$shift)))]>;
7112   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7113                                                  asm, ".8h",
7114              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7115                                               imm0_255:$imm8,
7116                                               (i32 imm:$shift)))]>;
7117
7118   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7119                                              asm, ".2s",
7120              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7121                                              imm0_255:$imm8,
7122                                              (i32 imm:$shift)))]>;
7123   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7124                                              asm, ".4s",
7125              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7126                                               imm0_255:$imm8,
7127                                               (i32 imm:$shift)))]>;
7128 }
7129
7130 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7131                              RegisterOperand vectype, string asm,
7132                              string kind, list<dag> pattern>
7133   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7134                               (ins move_vec_shift:$shift),
7135                               "$shift", asm, kind, pattern> {
7136   bits<1> shift;
7137   let Inst{15-13} = cmode{3-1};
7138   let Inst{12}    = shift;
7139 }
7140
7141 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7142                                    RegisterOperand vectype,
7143                                    Operand imm_type, string asm,
7144                                    string kind, list<dag> pattern>
7145   : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7146                               asm, kind, pattern> {
7147   let Inst{15-12} = cmode;
7148 }
7149
7150 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7151                                    list<dag> pattern>
7152   : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7153                         "\t$Rd, $imm8", "", pattern> {
7154   let Inst{15-12} = cmode;
7155   let DecoderMethod = "DecodeModImmInstruction";
7156 }
7157
7158 //----------------------------------------------------------------------------
7159 // AdvSIMD indexed element
7160 //----------------------------------------------------------------------------
7161
7162 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7163 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7164                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7165                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7166                       string apple_kind, string dst_kind, string lhs_kind,
7167                       string rhs_kind, list<dag> pattern>
7168   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7169       asm,
7170       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7171       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7172     Sched<[WriteV]> {
7173   bits<5> Rd;
7174   bits<5> Rn;
7175   bits<5> Rm;
7176
7177   let Inst{31}    = 0;
7178   let Inst{30}    = Q;
7179   let Inst{29}    = U;
7180   let Inst{28}    = Scalar;
7181   let Inst{27-24} = 0b1111;
7182   let Inst{23-22} = size;
7183   // Bit 21 must be set by the derived class.
7184   let Inst{20-16} = Rm;
7185   let Inst{15-12} = opc;
7186   // Bit 11 must be set by the derived class.
7187   let Inst{10}    = 0;
7188   let Inst{9-5}   = Rn;
7189   let Inst{4-0}   = Rd;
7190 }
7191
7192 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7193 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7194                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
7195                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
7196                       string apple_kind, string dst_kind, string lhs_kind,
7197                       string rhs_kind, list<dag> pattern>
7198   : I<(outs dst_reg:$dst),
7199       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7200       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7201       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7202     Sched<[WriteV]> {
7203   bits<5> Rd;
7204   bits<5> Rn;
7205   bits<5> Rm;
7206
7207   let Inst{31}    = 0;
7208   let Inst{30}    = Q;
7209   let Inst{29}    = U;
7210   let Inst{28}    = Scalar;
7211   let Inst{27-24} = 0b1111;
7212   let Inst{23-22} = size;
7213   // Bit 21 must be set by the derived class.
7214   let Inst{20-16} = Rm;
7215   let Inst{15-12} = opc;
7216   // Bit 11 must be set by the derived class.
7217   let Inst{10}    = 0;
7218   let Inst{9-5}   = Rn;
7219   let Inst{4-0}   = Rd;
7220 }
7221
7222 // ARMv8.2 Index Dot product instructions
7223 class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, string asm, string dst_kind,
7224                                       string lhs_kind, string rhs_kind,
7225                                       RegisterOperand RegType,
7226                                       ValueType AccumType, ValueType InputType,
7227                                       SDPatternOperator OpNode> :
7228         BaseSIMDIndexedTied<Q, U, 0b0, 0b10, 0b1110, RegType, RegType, V128,
7229                             VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7230         [(set (AccumType RegType:$dst),
7231               (AccumType (OpNode (AccumType RegType:$Rd),
7232                                  (InputType RegType:$Rn),
7233                                  (InputType (bitconvert (AccumType
7234                                     (AArch64duplane32 (v4i32 V128:$Rm),
7235                                         VectorIndexS:$idx)))))))]> {
7236   bits<2> idx;
7237   let Inst{21}    = idx{0};  // L
7238   let Inst{11}    = idx{1};  // H
7239 }
7240
7241 multiclass SIMDThreeSameVectorDotIndex<bit U, string asm,
7242                                        SDPatternOperator OpNode> {
7243   def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, asm, ".2s", ".8b", ".4b", V64,
7244                                               v2i32, v8i8, OpNode>;
7245   def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, asm, ".4s", ".16b", ".4b", V128,
7246                                               v4i32, v16i8, OpNode>;
7247 }
7248
7249 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
7250                          SDPatternOperator OpNode> {
7251   let Predicates = [HasNEON, HasFullFP16] in {
7252   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
7253                                       V64, V64,
7254                                       V128_lo, VectorIndexH,
7255                                       asm, ".4h", ".4h", ".4h", ".h",
7256     [(set (v4f16 V64:$Rd),
7257         (OpNode (v4f16 V64:$Rn),
7258          (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7259     bits<3> idx;
7260     let Inst{11} = idx{2};
7261     let Inst{21} = idx{1};
7262     let Inst{20} = idx{0};
7263   }
7264
7265   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
7266                                       V128, V128,
7267                                       V128_lo, VectorIndexH,
7268                                       asm, ".8h", ".8h", ".8h", ".h",
7269     [(set (v8f16 V128:$Rd),
7270         (OpNode (v8f16 V128:$Rn),
7271          (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7272     bits<3> idx;
7273     let Inst{11} = idx{2};
7274     let Inst{21} = idx{1};
7275     let Inst{20} = idx{0};
7276   }
7277   } // Predicates = [HasNEON, HasFullFP16]
7278
7279   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7280                                       V64, V64,
7281                                       V128, VectorIndexS,
7282                                       asm, ".2s", ".2s", ".2s", ".s",
7283     [(set (v2f32 V64:$Rd),
7284         (OpNode (v2f32 V64:$Rn),
7285          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7286     bits<2> idx;
7287     let Inst{11} = idx{1};
7288     let Inst{21} = idx{0};
7289   }
7290
7291   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7292                                       V128, V128,
7293                                       V128, VectorIndexS,
7294                                       asm, ".4s", ".4s", ".4s", ".s",
7295     [(set (v4f32 V128:$Rd),
7296         (OpNode (v4f32 V128:$Rn),
7297          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7298     bits<2> idx;
7299     let Inst{11} = idx{1};
7300     let Inst{21} = idx{0};
7301   }
7302
7303   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
7304                                       V128, V128,
7305                                       V128, VectorIndexD,
7306                                       asm, ".2d", ".2d", ".2d", ".d",
7307     [(set (v2f64 V128:$Rd),
7308         (OpNode (v2f64 V128:$Rn),
7309          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
7310     bits<1> idx;
7311     let Inst{11} = idx{0};
7312     let Inst{21} = 0;
7313   }
7314
7315   let Predicates = [HasNEON, HasFullFP16] in {
7316   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
7317                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7318                                       asm, ".h", "", "", ".h",
7319     [(set (f16 FPR16Op:$Rd),
7320           (OpNode (f16 FPR16Op:$Rn),
7321                   (f16 (vector_extract (v8f16 V128_lo:$Rm),
7322                                        VectorIndexH:$idx))))]> {
7323     bits<3> idx;
7324     let Inst{11} = idx{2};
7325     let Inst{21} = idx{1};
7326     let Inst{20} = idx{0};
7327   }
7328   } // Predicates = [HasNEON, HasFullFP16]
7329
7330   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7331                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7332                                       asm, ".s", "", "", ".s",
7333     [(set (f32 FPR32Op:$Rd),
7334           (OpNode (f32 FPR32Op:$Rn),
7335                   (f32 (vector_extract (v4f32 V128:$Rm),
7336                                        VectorIndexS:$idx))))]> {
7337     bits<2> idx;
7338     let Inst{11} = idx{1};
7339     let Inst{21} = idx{0};
7340   }
7341
7342   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
7343                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7344                                       asm, ".d", "", "", ".d",
7345     [(set (f64 FPR64Op:$Rd),
7346           (OpNode (f64 FPR64Op:$Rn),
7347                   (f64 (vector_extract (v2f64 V128:$Rm),
7348                                        VectorIndexD:$idx))))]> {
7349     bits<1> idx;
7350     let Inst{11} = idx{0};
7351     let Inst{21} = 0;
7352   }
7353 }
7354
7355 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
7356   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
7357   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7358                            (AArch64duplane32 (v4f32 V128:$Rm),
7359                                            VectorIndexS:$idx))),
7360             (!cast<Instruction>(INST # v2i32_indexed)
7361                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7362   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7363                            (AArch64dup (f32 FPR32Op:$Rm)))),
7364             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
7365                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7366
7367
7368   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
7369   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7370                            (AArch64duplane32 (v4f32 V128:$Rm),
7371                                            VectorIndexS:$idx))),
7372             (!cast<Instruction>(INST # "v4i32_indexed")
7373                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7374   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7375                            (AArch64dup (f32 FPR32Op:$Rm)))),
7376             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
7377                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7378
7379   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
7380   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7381                            (AArch64duplane64 (v2f64 V128:$Rm),
7382                                            VectorIndexD:$idx))),
7383             (!cast<Instruction>(INST # "v2i64_indexed")
7384                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7385   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7386                            (AArch64dup (f64 FPR64Op:$Rm)))),
7387             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
7388                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
7389
7390   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
7391   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7392                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
7393             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7394                 V128:$Rm, VectorIndexS:$idx)>;
7395   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7396                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
7397             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7398                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
7399
7400   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
7401   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
7402                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
7403             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
7404                 V128:$Rm, VectorIndexD:$idx)>;
7405 }
7406
7407 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
7408   let Predicates = [HasNEON, HasFullFP16] in {
7409   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
7410                                           V128_lo, VectorIndexH,
7411                                           asm, ".4h", ".4h", ".4h", ".h", []> {
7412     bits<3> idx;
7413     let Inst{11} = idx{2};
7414     let Inst{21} = idx{1};
7415     let Inst{20} = idx{0};
7416   }
7417
7418   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
7419                                           V128, V128,
7420                                           V128_lo, VectorIndexH,
7421                                           asm, ".8h", ".8h", ".8h", ".h", []> {
7422     bits<3> idx;
7423     let Inst{11} = idx{2};
7424     let Inst{21} = idx{1};
7425     let Inst{20} = idx{0};
7426   }
7427   } // Predicates = [HasNEON, HasFullFP16]
7428
7429   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
7430                                           V128, VectorIndexS,
7431                                           asm, ".2s", ".2s", ".2s", ".s", []> {
7432     bits<2> idx;
7433     let Inst{11} = idx{1};
7434     let Inst{21} = idx{0};
7435   }
7436
7437   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7438                                       V128, V128,
7439                                       V128, VectorIndexS,
7440                                       asm, ".4s", ".4s", ".4s", ".s", []> {
7441     bits<2> idx;
7442     let Inst{11} = idx{1};
7443     let Inst{21} = idx{0};
7444   }
7445
7446   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
7447                                       V128, V128,
7448                                       V128, VectorIndexD,
7449                                       asm, ".2d", ".2d", ".2d", ".d", []> {
7450     bits<1> idx;
7451     let Inst{11} = idx{0};
7452     let Inst{21} = 0;
7453   }
7454
7455   let Predicates = [HasNEON, HasFullFP16] in {
7456   def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
7457                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7458                                       asm, ".h", "", "", ".h", []> {
7459     bits<3> idx;
7460     let Inst{11} = idx{2};
7461     let Inst{21} = idx{1};
7462     let Inst{20} = idx{0};
7463   }
7464   } // Predicates = [HasNEON, HasFullFP16]
7465
7466   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7467                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7468                                       asm, ".s", "", "", ".s", []> {
7469     bits<2> idx;
7470     let Inst{11} = idx{1};
7471     let Inst{21} = idx{0};
7472   }
7473
7474   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7475                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7476                                       asm, ".d", "", "", ".d", []> {
7477     bits<1> idx;
7478     let Inst{11} = idx{0};
7479     let Inst{21} = 0;
7480   }
7481 }
7482
7483 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7484                          SDPatternOperator OpNode> {
7485   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7486                                       V128_lo, VectorIndexH,
7487                                       asm, ".4h", ".4h", ".4h", ".h",
7488     [(set (v4i16 V64:$Rd),
7489         (OpNode (v4i16 V64:$Rn),
7490          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7491     bits<3> idx;
7492     let Inst{11} = idx{2};
7493     let Inst{21} = idx{1};
7494     let Inst{20} = idx{0};
7495   }
7496
7497   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7498                                       V128, V128,
7499                                       V128_lo, VectorIndexH,
7500                                       asm, ".8h", ".8h", ".8h", ".h",
7501     [(set (v8i16 V128:$Rd),
7502        (OpNode (v8i16 V128:$Rn),
7503          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7504     bits<3> idx;
7505     let Inst{11} = idx{2};
7506     let Inst{21} = idx{1};
7507     let Inst{20} = idx{0};
7508   }
7509
7510   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7511                                       V64, V64,
7512                                       V128, VectorIndexS,
7513                                       asm, ".2s", ".2s", ".2s",  ".s",
7514     [(set (v2i32 V64:$Rd),
7515        (OpNode (v2i32 V64:$Rn),
7516           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7517     bits<2> idx;
7518     let Inst{11} = idx{1};
7519     let Inst{21} = idx{0};
7520   }
7521
7522   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7523                                       V128, V128,
7524                                       V128, VectorIndexS,
7525                                       asm, ".4s", ".4s", ".4s", ".s",
7526     [(set (v4i32 V128:$Rd),
7527        (OpNode (v4i32 V128:$Rn),
7528           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7529     bits<2> idx;
7530     let Inst{11} = idx{1};
7531     let Inst{21} = idx{0};
7532   }
7533
7534   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7535                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7536                                       asm, ".h", "", "", ".h", []> {
7537     bits<3> idx;
7538     let Inst{11} = idx{2};
7539     let Inst{21} = idx{1};
7540     let Inst{20} = idx{0};
7541   }
7542
7543   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7544                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7545                                       asm, ".s", "", "", ".s",
7546       [(set (i32 FPR32Op:$Rd),
7547             (OpNode FPR32Op:$Rn,
7548                     (i32 (vector_extract (v4i32 V128:$Rm),
7549                                          VectorIndexS:$idx))))]> {
7550     bits<2> idx;
7551     let Inst{11} = idx{1};
7552     let Inst{21} = idx{0};
7553   }
7554 }
7555
7556 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7557                                SDPatternOperator OpNode> {
7558   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7559                                       V64, V64,
7560                                       V128_lo, VectorIndexH,
7561                                       asm, ".4h", ".4h", ".4h", ".h",
7562     [(set (v4i16 V64:$Rd),
7563         (OpNode (v4i16 V64:$Rn),
7564          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7565     bits<3> idx;
7566     let Inst{11} = idx{2};
7567     let Inst{21} = idx{1};
7568     let Inst{20} = idx{0};
7569   }
7570
7571   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7572                                       V128, V128,
7573                                       V128_lo, VectorIndexH,
7574                                       asm, ".8h", ".8h", ".8h", ".h",
7575     [(set (v8i16 V128:$Rd),
7576        (OpNode (v8i16 V128:$Rn),
7577          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7578     bits<3> idx;
7579     let Inst{11} = idx{2};
7580     let Inst{21} = idx{1};
7581     let Inst{20} = idx{0};
7582   }
7583
7584   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7585                                       V64, V64,
7586                                       V128, VectorIndexS,
7587                                       asm, ".2s", ".2s", ".2s", ".s",
7588     [(set (v2i32 V64:$Rd),
7589        (OpNode (v2i32 V64:$Rn),
7590           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7591     bits<2> idx;
7592     let Inst{11} = idx{1};
7593     let Inst{21} = idx{0};
7594   }
7595
7596   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7597                                       V128, V128,
7598                                       V128, VectorIndexS,
7599                                       asm, ".4s", ".4s", ".4s", ".s",
7600     [(set (v4i32 V128:$Rd),
7601        (OpNode (v4i32 V128:$Rn),
7602           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7603     bits<2> idx;
7604     let Inst{11} = idx{1};
7605     let Inst{21} = idx{0};
7606   }
7607 }
7608
7609 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7610                                    SDPatternOperator OpNode> {
7611   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7612                                           V128_lo, VectorIndexH,
7613                                           asm, ".4h", ".4h", ".4h", ".h",
7614     [(set (v4i16 V64:$dst),
7615         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7616          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7617     bits<3> idx;
7618     let Inst{11} = idx{2};
7619     let Inst{21} = idx{1};
7620     let Inst{20} = idx{0};
7621   }
7622
7623   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7624                                       V128, V128,
7625                                       V128_lo, VectorIndexH,
7626                                       asm, ".8h", ".8h", ".8h", ".h",
7627     [(set (v8i16 V128:$dst),
7628        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7629          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7630     bits<3> idx;
7631     let Inst{11} = idx{2};
7632     let Inst{21} = idx{1};
7633     let Inst{20} = idx{0};
7634   }
7635
7636   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7637                                       V64, V64,
7638                                       V128, VectorIndexS,
7639                                       asm, ".2s", ".2s", ".2s", ".s",
7640     [(set (v2i32 V64:$dst),
7641        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7642           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7643     bits<2> idx;
7644     let Inst{11} = idx{1};
7645     let Inst{21} = idx{0};
7646   }
7647
7648   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7649                                       V128, V128,
7650                                       V128, VectorIndexS,
7651                                       asm, ".4s", ".4s", ".4s", ".s",
7652     [(set (v4i32 V128:$dst),
7653        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7654           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7655     bits<2> idx;
7656     let Inst{11} = idx{1};
7657     let Inst{21} = idx{0};
7658   }
7659 }
7660
7661 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
7662                              SDPatternOperator OpNode> {
7663   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7664                                       V128, V64,
7665                                       V128_lo, VectorIndexH,
7666                                       asm, ".4s", ".4s", ".4h", ".h",
7667     [(set (v4i32 V128:$Rd),
7668         (OpNode (v4i16 V64:$Rn),
7669          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7670     bits<3> idx;
7671     let Inst{11} = idx{2};
7672     let Inst{21} = idx{1};
7673     let Inst{20} = idx{0};
7674   }
7675
7676   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7677                                       V128, V128,
7678                                       V128_lo, VectorIndexH,
7679                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7680     [(set (v4i32 V128:$Rd),
7681           (OpNode (extract_high_v8i16 V128:$Rn),
7682                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7683                                                       VectorIndexH:$idx))))]> {
7684
7685     bits<3> idx;
7686     let Inst{11} = idx{2};
7687     let Inst{21} = idx{1};
7688     let Inst{20} = idx{0};
7689   }
7690
7691   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7692                                       V128, V64,
7693                                       V128, VectorIndexS,
7694                                       asm, ".2d", ".2d", ".2s", ".s",
7695     [(set (v2i64 V128:$Rd),
7696         (OpNode (v2i32 V64:$Rn),
7697          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7698     bits<2> idx;
7699     let Inst{11} = idx{1};
7700     let Inst{21} = idx{0};
7701   }
7702
7703   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7704                                       V128, V128,
7705                                       V128, VectorIndexS,
7706                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7707     [(set (v2i64 V128:$Rd),
7708           (OpNode (extract_high_v4i32 V128:$Rn),
7709                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7710                                                       VectorIndexS:$idx))))]> {
7711     bits<2> idx;
7712     let Inst{11} = idx{1};
7713     let Inst{21} = idx{0};
7714   }
7715
7716   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7717                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7718                                       asm, ".h", "", "", ".h", []> {
7719     bits<3> idx;
7720     let Inst{11} = idx{2};
7721     let Inst{21} = idx{1};
7722     let Inst{20} = idx{0};
7723   }
7724
7725   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7726                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7727                                       asm, ".s", "", "", ".s", []> {
7728     bits<2> idx;
7729     let Inst{11} = idx{1};
7730     let Inst{21} = idx{0};
7731   }
7732 }
7733
7734 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
7735                                        SDPatternOperator Accum> {
7736   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7737                                       V128, V64,
7738                                       V128_lo, VectorIndexH,
7739                                       asm, ".4s", ".4s", ".4h", ".h",
7740     [(set (v4i32 V128:$dst),
7741           (Accum (v4i32 V128:$Rd),
7742                  (v4i32 (int_aarch64_neon_sqdmull
7743                              (v4i16 V64:$Rn),
7744                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7745                                                     VectorIndexH:$idx))))))]> {
7746     bits<3> idx;
7747     let Inst{11} = idx{2};
7748     let Inst{21} = idx{1};
7749     let Inst{20} = idx{0};
7750   }
7751
7752   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
7753   // intermediate EXTRACT_SUBREG would be untyped.
7754   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
7755                 (i32 (vector_extract (v4i32
7756                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7757                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7758                                                     VectorIndexH:$idx)))),
7759                          (i64 0))))),
7760             (EXTRACT_SUBREG
7761                 (!cast<Instruction>(NAME # v4i16_indexed)
7762                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
7763                     V128_lo:$Rm, VectorIndexH:$idx),
7764                 ssub)>;
7765
7766   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7767                                       V128, V128,
7768                                       V128_lo, VectorIndexH,
7769                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7770     [(set (v4i32 V128:$dst),
7771           (Accum (v4i32 V128:$Rd),
7772                  (v4i32 (int_aarch64_neon_sqdmull
7773                             (extract_high_v8i16 V128:$Rn),
7774                             (extract_high_v8i16
7775                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7776                                                 VectorIndexH:$idx))))))]> {
7777     bits<3> idx;
7778     let Inst{11} = idx{2};
7779     let Inst{21} = idx{1};
7780     let Inst{20} = idx{0};
7781   }
7782
7783   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7784                                       V128, V64,
7785                                       V128, VectorIndexS,
7786                                       asm, ".2d", ".2d", ".2s", ".s",
7787     [(set (v2i64 V128:$dst),
7788         (Accum (v2i64 V128:$Rd),
7789                (v2i64 (int_aarch64_neon_sqdmull
7790                           (v2i32 V64:$Rn),
7791                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
7792                                                  VectorIndexS:$idx))))))]> {
7793     bits<2> idx;
7794     let Inst{11} = idx{1};
7795     let Inst{21} = idx{0};
7796   }
7797
7798   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7799                                       V128, V128,
7800                                       V128, VectorIndexS,
7801                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7802     [(set (v2i64 V128:$dst),
7803           (Accum (v2i64 V128:$Rd),
7804                  (v2i64 (int_aarch64_neon_sqdmull
7805                             (extract_high_v4i32 V128:$Rn),
7806                             (extract_high_v4i32
7807                                 (AArch64duplane32 (v4i32 V128:$Rm),
7808                                                 VectorIndexS:$idx))))))]> {
7809     bits<2> idx;
7810     let Inst{11} = idx{1};
7811     let Inst{21} = idx{0};
7812   }
7813
7814   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
7815                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7816                                       asm, ".h", "", "", ".h", []> {
7817     bits<3> idx;
7818     let Inst{11} = idx{2};
7819     let Inst{21} = idx{1};
7820     let Inst{20} = idx{0};
7821   }
7822
7823
7824   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7825                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7826                                       asm, ".s", "", "", ".s",
7827     [(set (i64 FPR64Op:$dst),
7828           (Accum (i64 FPR64Op:$Rd),
7829                  (i64 (int_aarch64_neon_sqdmulls_scalar
7830                             (i32 FPR32Op:$Rn),
7831                             (i32 (vector_extract (v4i32 V128:$Rm),
7832                                                  VectorIndexS:$idx))))))]> {
7833
7834     bits<2> idx;
7835     let Inst{11} = idx{1};
7836     let Inst{21} = idx{0};
7837   }
7838 }
7839
7840 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
7841                                    SDPatternOperator OpNode> {
7842   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7843   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7844                                       V128, V64,
7845                                       V128_lo, VectorIndexH,
7846                                       asm, ".4s", ".4s", ".4h", ".h",
7847     [(set (v4i32 V128:$Rd),
7848         (OpNode (v4i16 V64:$Rn),
7849          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7850     bits<3> idx;
7851     let Inst{11} = idx{2};
7852     let Inst{21} = idx{1};
7853     let Inst{20} = idx{0};
7854   }
7855
7856   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7857                                       V128, V128,
7858                                       V128_lo, VectorIndexH,
7859                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7860     [(set (v4i32 V128:$Rd),
7861           (OpNode (extract_high_v8i16 V128:$Rn),
7862                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7863                                                       VectorIndexH:$idx))))]> {
7864
7865     bits<3> idx;
7866     let Inst{11} = idx{2};
7867     let Inst{21} = idx{1};
7868     let Inst{20} = idx{0};
7869   }
7870
7871   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7872                                       V128, V64,
7873                                       V128, VectorIndexS,
7874                                       asm, ".2d", ".2d", ".2s", ".s",
7875     [(set (v2i64 V128:$Rd),
7876         (OpNode (v2i32 V64:$Rn),
7877          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7878     bits<2> idx;
7879     let Inst{11} = idx{1};
7880     let Inst{21} = idx{0};
7881   }
7882
7883   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7884                                       V128, V128,
7885                                       V128, VectorIndexS,
7886                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7887     [(set (v2i64 V128:$Rd),
7888           (OpNode (extract_high_v4i32 V128:$Rn),
7889                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7890                                                       VectorIndexS:$idx))))]> {
7891     bits<2> idx;
7892     let Inst{11} = idx{1};
7893     let Inst{21} = idx{0};
7894   }
7895   }
7896 }
7897
7898 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7899                                        SDPatternOperator OpNode> {
7900   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7901   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7902                                       V128, V64,
7903                                       V128_lo, VectorIndexH,
7904                                       asm, ".4s", ".4s", ".4h", ".h",
7905     [(set (v4i32 V128:$dst),
7906         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7907          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7908     bits<3> idx;
7909     let Inst{11} = idx{2};
7910     let Inst{21} = idx{1};
7911     let Inst{20} = idx{0};
7912   }
7913
7914   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7915                                       V128, V128,
7916                                       V128_lo, VectorIndexH,
7917                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7918     [(set (v4i32 V128:$dst),
7919           (OpNode (v4i32 V128:$Rd),
7920                   (extract_high_v8i16 V128:$Rn),
7921                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7922                                                       VectorIndexH:$idx))))]> {
7923     bits<3> idx;
7924     let Inst{11} = idx{2};
7925     let Inst{21} = idx{1};
7926     let Inst{20} = idx{0};
7927   }
7928
7929   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7930                                       V128, V64,
7931                                       V128, VectorIndexS,
7932                                       asm, ".2d", ".2d", ".2s", ".s",
7933     [(set (v2i64 V128:$dst),
7934         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7935          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7936     bits<2> idx;
7937     let Inst{11} = idx{1};
7938     let Inst{21} = idx{0};
7939   }
7940
7941   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7942                                       V128, V128,
7943                                       V128, VectorIndexS,
7944                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7945     [(set (v2i64 V128:$dst),
7946           (OpNode (v2i64 V128:$Rd),
7947                   (extract_high_v4i32 V128:$Rn),
7948                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7949                                                       VectorIndexS:$idx))))]> {
7950     bits<2> idx;
7951     let Inst{11} = idx{1};
7952     let Inst{21} = idx{0};
7953   }
7954   }
7955 }
7956
7957 //----------------------------------------------------------------------------
7958 // AdvSIMD scalar shift by immediate
7959 //----------------------------------------------------------------------------
7960
7961 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7962 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7963                      RegisterClass regtype1, RegisterClass regtype2,
7964                      Operand immtype, string asm, list<dag> pattern>
7965   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7966       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7967     Sched<[WriteV]> {
7968   bits<5> Rd;
7969   bits<5> Rn;
7970   bits<7> imm;
7971   let Inst{31-30} = 0b01;
7972   let Inst{29}    = U;
7973   let Inst{28-23} = 0b111110;
7974   let Inst{22-16} = fixed_imm;
7975   let Inst{15-11} = opc;
7976   let Inst{10}    = 1;
7977   let Inst{9-5} = Rn;
7978   let Inst{4-0} = Rd;
7979 }
7980
7981 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7982 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7983                      RegisterClass regtype1, RegisterClass regtype2,
7984                      Operand immtype, string asm, list<dag> pattern>
7985   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7986       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7987     Sched<[WriteV]> {
7988   bits<5> Rd;
7989   bits<5> Rn;
7990   bits<7> imm;
7991   let Inst{31-30} = 0b01;
7992   let Inst{29}    = U;
7993   let Inst{28-23} = 0b111110;
7994   let Inst{22-16} = fixed_imm;
7995   let Inst{15-11} = opc;
7996   let Inst{10}    = 1;
7997   let Inst{9-5} = Rn;
7998   let Inst{4-0} = Rd;
7999 }
8000
8001
8002 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8003   let Predicates = [HasNEON, HasFullFP16] in {
8004   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8005                               FPR16, FPR16, vecshiftR16, asm, []> {
8006     let Inst{19-16} = imm{3-0};
8007   }
8008   } // Predicates = [HasNEON, HasFullFP16]
8009   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8010                               FPR32, FPR32, vecshiftR32, asm, []> {
8011     let Inst{20-16} = imm{4-0};
8012   }
8013   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8014                               FPR64, FPR64, vecshiftR64, asm, []> {
8015     let Inst{21-16} = imm{5-0};
8016   }
8017 }
8018
8019 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8020                              SDPatternOperator OpNode> {
8021   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8022                               FPR64, FPR64, vecshiftR64, asm,
8023   [(set (i64 FPR64:$Rd),
8024      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8025     let Inst{21-16} = imm{5-0};
8026   }
8027
8028   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8029             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8030 }
8031
8032 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8033                                  SDPatternOperator OpNode = null_frag> {
8034   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8035                               FPR64, FPR64, vecshiftR64, asm,
8036   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8037                                                    (i32 vecshiftR64:$imm)))]> {
8038     let Inst{21-16} = imm{5-0};
8039   }
8040
8041   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8042                            (i32 vecshiftR64:$imm))),
8043             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8044                                             vecshiftR64:$imm)>;
8045 }
8046
8047 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8048                              SDPatternOperator OpNode> {
8049   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8050                               FPR64, FPR64, vecshiftL64, asm,
8051     [(set (v1i64 FPR64:$Rd),
8052        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8053     let Inst{21-16} = imm{5-0};
8054   }
8055 }
8056
8057 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8058 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8059   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8060                               FPR64, FPR64, vecshiftL64, asm, []> {
8061     let Inst{21-16} = imm{5-0};
8062   }
8063 }
8064
8065 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8066 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8067                                SDPatternOperator OpNode = null_frag> {
8068   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8069                               FPR8, FPR16, vecshiftR8, asm, []> {
8070     let Inst{18-16} = imm{2-0};
8071   }
8072
8073   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8074                               FPR16, FPR32, vecshiftR16, asm, []> {
8075     let Inst{19-16} = imm{3-0};
8076   }
8077
8078   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8079                               FPR32, FPR64, vecshiftR32, asm,
8080     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8081     let Inst{20-16} = imm{4-0};
8082   }
8083 }
8084
8085 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8086                                 SDPatternOperator OpNode> {
8087   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8088                               FPR8, FPR8, vecshiftL8, asm, []> {
8089     let Inst{18-16} = imm{2-0};
8090   }
8091
8092   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8093                               FPR16, FPR16, vecshiftL16, asm, []> {
8094     let Inst{19-16} = imm{3-0};
8095   }
8096
8097   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8098                               FPR32, FPR32, vecshiftL32, asm,
8099     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8100     let Inst{20-16} = imm{4-0};
8101   }
8102
8103   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8104                               FPR64, FPR64, vecshiftL64, asm,
8105     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8106     let Inst{21-16} = imm{5-0};
8107   }
8108
8109   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8110             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8111 }
8112
8113 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8114   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8115                               FPR8, FPR8, vecshiftR8, asm, []> {
8116     let Inst{18-16} = imm{2-0};
8117   }
8118
8119   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8120                               FPR16, FPR16, vecshiftR16, asm, []> {
8121     let Inst{19-16} = imm{3-0};
8122   }
8123
8124   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8125                               FPR32, FPR32, vecshiftR32, asm, []> {
8126     let Inst{20-16} = imm{4-0};
8127   }
8128
8129   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8130                               FPR64, FPR64, vecshiftR64, asm, []> {
8131     let Inst{21-16} = imm{5-0};
8132   }
8133 }
8134
8135 //----------------------------------------------------------------------------
8136 // AdvSIMD vector x indexed element
8137 //----------------------------------------------------------------------------
8138
8139 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8140 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8141                      RegisterOperand dst_reg, RegisterOperand src_reg,
8142                      Operand immtype,
8143                      string asm, string dst_kind, string src_kind,
8144                      list<dag> pattern>
8145   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
8146       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8147            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
8148     Sched<[WriteV]> {
8149   bits<5> Rd;
8150   bits<5> Rn;
8151   let Inst{31}    = 0;
8152   let Inst{30}    = Q;
8153   let Inst{29}    = U;
8154   let Inst{28-23} = 0b011110;
8155   let Inst{22-16} = fixed_imm;
8156   let Inst{15-11} = opc;
8157   let Inst{10}    = 1;
8158   let Inst{9-5}   = Rn;
8159   let Inst{4-0}   = Rd;
8160 }
8161
8162 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8163 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8164                      RegisterOperand vectype1, RegisterOperand vectype2,
8165                      Operand immtype,
8166                      string asm, string dst_kind, string src_kind,
8167                      list<dag> pattern>
8168   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
8169       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8170            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
8171     Sched<[WriteV]> {
8172   bits<5> Rd;
8173   bits<5> Rn;
8174   let Inst{31}    = 0;
8175   let Inst{30}    = Q;
8176   let Inst{29}    = U;
8177   let Inst{28-23} = 0b011110;
8178   let Inst{22-16} = fixed_imm;
8179   let Inst{15-11} = opc;
8180   let Inst{10}    = 1;
8181   let Inst{9-5}   = Rn;
8182   let Inst{4-0}   = Rd;
8183 }
8184
8185 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
8186                               Intrinsic OpNode> {
8187   let Predicates = [HasNEON, HasFullFP16] in {
8188   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8189                                   V64, V64, vecshiftR16,
8190                                   asm, ".4h", ".4h",
8191       [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
8192     bits<4> imm;
8193     let Inst{19-16} = imm;
8194   }
8195
8196   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8197                                   V128, V128, vecshiftR16,
8198                                   asm, ".8h", ".8h",
8199       [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
8200     bits<4> imm;
8201     let Inst{19-16} = imm;
8202   }
8203   } // Predicates = [HasNEON, HasFullFP16]
8204   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8205                                   V64, V64, vecshiftR32,
8206                                   asm, ".2s", ".2s",
8207       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
8208     bits<5> imm;
8209     let Inst{20-16} = imm;
8210   }
8211
8212   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8213                                   V128, V128, vecshiftR32,
8214                                   asm, ".4s", ".4s",
8215       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
8216     bits<5> imm;
8217     let Inst{20-16} = imm;
8218   }
8219
8220   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8221                                   V128, V128, vecshiftR64,
8222                                   asm, ".2d", ".2d",
8223       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
8224     bits<6> imm;
8225     let Inst{21-16} = imm;
8226   }
8227 }
8228
8229 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
8230                                   Intrinsic OpNode> {
8231   let Predicates = [HasNEON, HasFullFP16] in {
8232   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8233                                   V64, V64, vecshiftR16,
8234                                   asm, ".4h", ".4h",
8235       [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
8236     bits<4> imm;
8237     let Inst{19-16} = imm;
8238   }
8239
8240   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8241                                   V128, V128, vecshiftR16,
8242                                   asm, ".8h", ".8h",
8243       [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
8244     bits<4> imm;
8245     let Inst{19-16} = imm;
8246   }
8247   } // Predicates = [HasNEON, HasFullFP16]
8248
8249   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8250                                   V64, V64, vecshiftR32,
8251                                   asm, ".2s", ".2s",
8252       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
8253     bits<5> imm;
8254     let Inst{20-16} = imm;
8255   }
8256
8257   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8258                                   V128, V128, vecshiftR32,
8259                                   asm, ".4s", ".4s",
8260       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
8261     bits<5> imm;
8262     let Inst{20-16} = imm;
8263   }
8264
8265   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8266                                   V128, V128, vecshiftR64,
8267                                   asm, ".2d", ".2d",
8268       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
8269     bits<6> imm;
8270     let Inst{21-16} = imm;
8271   }
8272 }
8273
8274 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
8275                                      SDPatternOperator OpNode> {
8276   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8277                                   V64, V128, vecshiftR16Narrow,
8278                                   asm, ".8b", ".8h",
8279       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
8280     bits<3> imm;
8281     let Inst{18-16} = imm;
8282   }
8283
8284   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8285                                   V128, V128, vecshiftR16Narrow,
8286                                   asm#"2", ".16b", ".8h", []> {
8287     bits<3> imm;
8288     let Inst{18-16} = imm;
8289     let hasSideEffects = 0;
8290   }
8291
8292   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8293                                   V64, V128, vecshiftR32Narrow,
8294                                   asm, ".4h", ".4s",
8295       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
8296     bits<4> imm;
8297     let Inst{19-16} = imm;
8298   }
8299
8300   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8301                                   V128, V128, vecshiftR32Narrow,
8302                                   asm#"2", ".8h", ".4s", []> {
8303     bits<4> imm;
8304     let Inst{19-16} = imm;
8305     let hasSideEffects = 0;
8306   }
8307
8308   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8309                                   V64, V128, vecshiftR64Narrow,
8310                                   asm, ".2s", ".2d",
8311       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
8312     bits<5> imm;
8313     let Inst{20-16} = imm;
8314   }
8315
8316   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8317                                   V128, V128, vecshiftR64Narrow,
8318                                   asm#"2", ".4s", ".2d", []> {
8319     bits<5> imm;
8320     let Inst{20-16} = imm;
8321     let hasSideEffects = 0;
8322   }
8323
8324   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
8325   // themselves, so put them here instead.
8326
8327   // Patterns involving what's effectively an insert high and a normal
8328   // intrinsic, represented by CONCAT_VECTORS.
8329   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
8330                                                    vecshiftR16Narrow:$imm)),
8331             (!cast<Instruction>(NAME # "v16i8_shift")
8332                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8333                 V128:$Rn, vecshiftR16Narrow:$imm)>;
8334   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
8335                                                      vecshiftR32Narrow:$imm)),
8336             (!cast<Instruction>(NAME # "v8i16_shift")
8337                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8338                 V128:$Rn, vecshiftR32Narrow:$imm)>;
8339   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
8340                                                      vecshiftR64Narrow:$imm)),
8341             (!cast<Instruction>(NAME # "v4i32_shift")
8342                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8343                 V128:$Rn, vecshiftR64Narrow:$imm)>;
8344 }
8345
8346 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
8347                                 SDPatternOperator OpNode> {
8348   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8349                                   V64, V64, vecshiftL8,
8350                                   asm, ".8b", ".8b",
8351                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8352                        (i32 vecshiftL8:$imm)))]> {
8353     bits<3> imm;
8354     let Inst{18-16} = imm;
8355   }
8356
8357   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8358                                   V128, V128, vecshiftL8,
8359                                   asm, ".16b", ".16b",
8360              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8361                    (i32 vecshiftL8:$imm)))]> {
8362     bits<3> imm;
8363     let Inst{18-16} = imm;
8364   }
8365
8366   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8367                                   V64, V64, vecshiftL16,
8368                                   asm, ".4h", ".4h",
8369               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8370                     (i32 vecshiftL16:$imm)))]> {
8371     bits<4> imm;
8372     let Inst{19-16} = imm;
8373   }
8374
8375   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8376                                   V128, V128, vecshiftL16,
8377                                   asm, ".8h", ".8h",
8378             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8379                   (i32 vecshiftL16:$imm)))]> {
8380     bits<4> imm;
8381     let Inst{19-16} = imm;
8382   }
8383
8384   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8385                                   V64, V64, vecshiftL32,
8386                                   asm, ".2s", ".2s",
8387               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8388                     (i32 vecshiftL32:$imm)))]> {
8389     bits<5> imm;
8390     let Inst{20-16} = imm;
8391   }
8392
8393   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8394                                   V128, V128, vecshiftL32,
8395                                   asm, ".4s", ".4s",
8396             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8397                   (i32 vecshiftL32:$imm)))]> {
8398     bits<5> imm;
8399     let Inst{20-16} = imm;
8400   }
8401
8402   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8403                                   V128, V128, vecshiftL64,
8404                                   asm, ".2d", ".2d",
8405             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8406                   (i32 vecshiftL64:$imm)))]> {
8407     bits<6> imm;
8408     let Inst{21-16} = imm;
8409   }
8410 }
8411
8412 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
8413                                 SDPatternOperator OpNode> {
8414   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8415                                   V64, V64, vecshiftR8,
8416                                   asm, ".8b", ".8b",
8417                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8418                        (i32 vecshiftR8:$imm)))]> {
8419     bits<3> imm;
8420     let Inst{18-16} = imm;
8421   }
8422
8423   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8424                                   V128, V128, vecshiftR8,
8425                                   asm, ".16b", ".16b",
8426              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8427                    (i32 vecshiftR8:$imm)))]> {
8428     bits<3> imm;
8429     let Inst{18-16} = imm;
8430   }
8431
8432   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8433                                   V64, V64, vecshiftR16,
8434                                   asm, ".4h", ".4h",
8435               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8436                     (i32 vecshiftR16:$imm)))]> {
8437     bits<4> imm;
8438     let Inst{19-16} = imm;
8439   }
8440
8441   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8442                                   V128, V128, vecshiftR16,
8443                                   asm, ".8h", ".8h",
8444             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8445                   (i32 vecshiftR16:$imm)))]> {
8446     bits<4> imm;
8447     let Inst{19-16} = imm;
8448   }
8449
8450   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8451                                   V64, V64, vecshiftR32,
8452                                   asm, ".2s", ".2s",
8453               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8454                     (i32 vecshiftR32:$imm)))]> {
8455     bits<5> imm;
8456     let Inst{20-16} = imm;
8457   }
8458
8459   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8460                                   V128, V128, vecshiftR32,
8461                                   asm, ".4s", ".4s",
8462             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8463                   (i32 vecshiftR32:$imm)))]> {
8464     bits<5> imm;
8465     let Inst{20-16} = imm;
8466   }
8467
8468   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8469                                   V128, V128, vecshiftR64,
8470                                   asm, ".2d", ".2d",
8471             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8472                   (i32 vecshiftR64:$imm)))]> {
8473     bits<6> imm;
8474     let Inst{21-16} = imm;
8475   }
8476 }
8477
8478 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8479 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8480                                     SDPatternOperator OpNode = null_frag> {
8481   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8482                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
8483                  [(set (v8i8 V64:$dst),
8484                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8485                            (i32 vecshiftR8:$imm)))]> {
8486     bits<3> imm;
8487     let Inst{18-16} = imm;
8488   }
8489
8490   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8491                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
8492              [(set (v16i8 V128:$dst),
8493                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8494                        (i32 vecshiftR8:$imm)))]> {
8495     bits<3> imm;
8496     let Inst{18-16} = imm;
8497   }
8498
8499   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8500                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
8501               [(set (v4i16 V64:$dst),
8502                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8503                         (i32 vecshiftR16:$imm)))]> {
8504     bits<4> imm;
8505     let Inst{19-16} = imm;
8506   }
8507
8508   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8509                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
8510             [(set (v8i16 V128:$dst),
8511               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8512                       (i32 vecshiftR16:$imm)))]> {
8513     bits<4> imm;
8514     let Inst{19-16} = imm;
8515   }
8516
8517   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8518                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
8519               [(set (v2i32 V64:$dst),
8520                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8521                         (i32 vecshiftR32:$imm)))]> {
8522     bits<5> imm;
8523     let Inst{20-16} = imm;
8524   }
8525
8526   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8527                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
8528             [(set (v4i32 V128:$dst),
8529               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8530                       (i32 vecshiftR32:$imm)))]> {
8531     bits<5> imm;
8532     let Inst{20-16} = imm;
8533   }
8534
8535   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8536                                   V128, V128, vecshiftR64,
8537                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8538               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8539                       (i32 vecshiftR64:$imm)))]> {
8540     bits<6> imm;
8541     let Inst{21-16} = imm;
8542   }
8543 }
8544
8545 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8546                                     SDPatternOperator OpNode = null_frag> {
8547   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8548                                   V64, V64, vecshiftL8,
8549                                   asm, ".8b", ".8b",
8550                     [(set (v8i8 V64:$dst),
8551                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8552                                   (i32 vecshiftL8:$imm)))]> {
8553     bits<3> imm;
8554     let Inst{18-16} = imm;
8555   }
8556
8557   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8558                                   V128, V128, vecshiftL8,
8559                                   asm, ".16b", ".16b",
8560                     [(set (v16i8 V128:$dst),
8561                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8562                                   (i32 vecshiftL8:$imm)))]> {
8563     bits<3> imm;
8564     let Inst{18-16} = imm;
8565   }
8566
8567   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8568                                   V64, V64, vecshiftL16,
8569                                   asm, ".4h", ".4h",
8570                     [(set (v4i16 V64:$dst),
8571                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8572                                    (i32 vecshiftL16:$imm)))]> {
8573     bits<4> imm;
8574     let Inst{19-16} = imm;
8575   }
8576
8577   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8578                                   V128, V128, vecshiftL16,
8579                                   asm, ".8h", ".8h",
8580                     [(set (v8i16 V128:$dst),
8581                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8582                                   (i32 vecshiftL16:$imm)))]> {
8583     bits<4> imm;
8584     let Inst{19-16} = imm;
8585   }
8586
8587   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8588                                   V64, V64, vecshiftL32,
8589                                   asm, ".2s", ".2s",
8590                     [(set (v2i32 V64:$dst),
8591                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8592                                   (i32 vecshiftL32:$imm)))]> {
8593     bits<5> imm;
8594     let Inst{20-16} = imm;
8595   }
8596
8597   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8598                                   V128, V128, vecshiftL32,
8599                                   asm, ".4s", ".4s",
8600                     [(set (v4i32 V128:$dst),
8601                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8602                                   (i32 vecshiftL32:$imm)))]> {
8603     bits<5> imm;
8604     let Inst{20-16} = imm;
8605   }
8606
8607   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8608                                   V128, V128, vecshiftL64,
8609                                   asm, ".2d", ".2d",
8610                     [(set (v2i64 V128:$dst),
8611                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8612                                   (i32 vecshiftL64:$imm)))]> {
8613     bits<6> imm;
8614     let Inst{21-16} = imm;
8615   }
8616 }
8617
8618 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8619                                    SDPatternOperator OpNode> {
8620   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8621                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
8622       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8623     bits<3> imm;
8624     let Inst{18-16} = imm;
8625   }
8626
8627   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8628                                   V128, V128, vecshiftL8,
8629                                   asm#"2", ".8h", ".16b",
8630       [(set (v8i16 V128:$Rd),
8631             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8632     bits<3> imm;
8633     let Inst{18-16} = imm;
8634   }
8635
8636   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8637                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
8638       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8639     bits<4> imm;
8640     let Inst{19-16} = imm;
8641   }
8642
8643   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8644                                   V128, V128, vecshiftL16,
8645                                   asm#"2", ".4s", ".8h",
8646       [(set (v4i32 V128:$Rd),
8647             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8648
8649     bits<4> imm;
8650     let Inst{19-16} = imm;
8651   }
8652
8653   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8654                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
8655       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8656     bits<5> imm;
8657     let Inst{20-16} = imm;
8658   }
8659
8660   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8661                                   V128, V128, vecshiftL32,
8662                                   asm#"2", ".2d", ".4s",
8663       [(set (v2i64 V128:$Rd),
8664             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
8665     bits<5> imm;
8666     let Inst{20-16} = imm;
8667   }
8668 }
8669
8670
8671 //---
8672 // Vector load/store
8673 //---
8674 // SIMD ldX/stX no-index memory references don't allow the optional
8675 // ", #0" constant and handle post-indexing explicitly, so we use
8676 // a more specialized parse method for them. Otherwise, it's the same as
8677 // the general GPR64sp handling.
8678
8679 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
8680                    string asm, dag oops, dag iops, list<dag> pattern>
8681   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
8682   bits<5> Vt;
8683   bits<5> Rn;
8684   let Inst{31} = 0;
8685   let Inst{30} = Q;
8686   let Inst{29-23} = 0b0011000;
8687   let Inst{22} = L;
8688   let Inst{21-16} = 0b000000;
8689   let Inst{15-12} = opcode;
8690   let Inst{11-10} = size;
8691   let Inst{9-5} = Rn;
8692   let Inst{4-0} = Vt;
8693 }
8694
8695 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
8696                        string asm, dag oops, dag iops>
8697   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
8698   bits<5> Vt;
8699   bits<5> Rn;
8700   bits<5> Xm;
8701   let Inst{31} = 0;
8702   let Inst{30} = Q;
8703   let Inst{29-23} = 0b0011001;
8704   let Inst{22} = L;
8705   let Inst{21} = 0;
8706   let Inst{20-16} = Xm;
8707   let Inst{15-12} = opcode;
8708   let Inst{11-10} = size;
8709   let Inst{9-5} = Rn;
8710   let Inst{4-0} = Vt;
8711 }
8712
8713 // The immediate form of AdvSIMD post-indexed addressing is encoded with
8714 // register post-index addressing from the zero register.
8715 multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
8716                            int Offset, int Size> {
8717   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8718   //      "ld1\t$Vt, [$Rn], #16"
8719   // may get mapped to
8720   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8721   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8722                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8723                       GPR64sp:$Rn,
8724                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8725                       XZR), 1>;
8726
8727   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8728   //      "ld1.8b\t$Vt, [$Rn], #16"
8729   // may get mapped to
8730   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8731   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8732                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8733                       GPR64sp:$Rn,
8734                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8735                       XZR), 0>;
8736
8737   // E.g. "ld1.8b { v0, v1 }, [x1]"
8738   //      "ld1\t$Vt, [$Rn]"
8739   // may get mapped to
8740   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
8741   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8742                   (!cast<Instruction>(BaseName # Count # "v" # layout)
8743                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8744                       GPR64sp:$Rn), 0>;
8745
8746   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
8747   //      "ld1\t$Vt, [$Rn], $Xm"
8748   // may get mapped to
8749   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
8750   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8751                   (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
8752                       GPR64sp:$Rn,
8753                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8754                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8755 }
8756
8757 multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
8758                        int Offset128, int Offset64, bits<4> opcode> {
8759   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8760     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
8761                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
8762                            (ins GPR64sp:$Rn), []>;
8763     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
8764                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
8765                            (ins GPR64sp:$Rn), []>;
8766     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
8767                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
8768                            (ins GPR64sp:$Rn), []>;
8769     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
8770                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
8771                            (ins GPR64sp:$Rn), []>;
8772     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
8773                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
8774                            (ins GPR64sp:$Rn), []>;
8775     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
8776                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
8777                            (ins GPR64sp:$Rn), []>;
8778     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
8779                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
8780                            (ins GPR64sp:$Rn), []>;
8781
8782
8783     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
8784                        (outs GPR64sp:$wback,
8785                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
8786                        (ins GPR64sp:$Rn,
8787                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8788     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
8789                        (outs GPR64sp:$wback,
8790                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
8791                        (ins GPR64sp:$Rn,
8792                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8793     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
8794                        (outs GPR64sp:$wback,
8795                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
8796                        (ins GPR64sp:$Rn,
8797                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8798     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
8799                        (outs GPR64sp:$wback,
8800                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
8801                        (ins GPR64sp:$Rn,
8802                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8803     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
8804                        (outs GPR64sp:$wback,
8805                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
8806                        (ins GPR64sp:$Rn,
8807                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8808     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
8809                        (outs GPR64sp:$wback,
8810                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
8811                        (ins GPR64sp:$Rn,
8812                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8813     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
8814                        (outs GPR64sp:$wback,
8815                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
8816                        (ins GPR64sp:$Rn,
8817                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8818   }
8819
8820   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
8821   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
8822   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
8823   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
8824   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
8825   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
8826   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
8827 }
8828
8829 // Only ld1/st1 has a v1d version.
8830 multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
8831                        int Offset128, int Offset64, bits<4> opcode> {
8832   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
8833     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
8834                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8835                                  GPR64sp:$Rn), []>;
8836     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
8837                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8838                                 GPR64sp:$Rn), []>;
8839     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
8840                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8841                                 GPR64sp:$Rn), []>;
8842     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
8843                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8844                                 GPR64sp:$Rn), []>;
8845     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
8846                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8847                                 GPR64sp:$Rn), []>;
8848     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
8849                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8850                                 GPR64sp:$Rn), []>;
8851     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
8852                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8853                                 GPR64sp:$Rn), []>;
8854
8855     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
8856                        (outs GPR64sp:$wback),
8857                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8858                             GPR64sp:$Rn,
8859                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8860     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
8861                        (outs GPR64sp:$wback),
8862                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8863                             GPR64sp:$Rn,
8864                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8865     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
8866                        (outs GPR64sp:$wback),
8867                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8868                             GPR64sp:$Rn,
8869                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8870     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
8871                        (outs GPR64sp:$wback),
8872                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8873                             GPR64sp:$Rn,
8874                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8875     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
8876                        (outs GPR64sp:$wback),
8877                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8878                             GPR64sp:$Rn,
8879                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8880     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
8881                        (outs GPR64sp:$wback),
8882                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8883                             GPR64sp:$Rn,
8884                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8885     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
8886                        (outs GPR64sp:$wback),
8887                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8888                             GPR64sp:$Rn,
8889                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8890   }
8891
8892   defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
8893   defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
8894   defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
8895   defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
8896   defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
8897   defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
8898   defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
8899 }
8900
8901 multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
8902                        int Offset128, int Offset64, bits<4> opcode>
8903   : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
8904
8905   // LD1 instructions have extra "1d" variants.
8906   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8907     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8908                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8909                            (ins GPR64sp:$Rn), []>;
8910
8911     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8912                        (outs GPR64sp:$wback,
8913                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
8914                        (ins GPR64sp:$Rn,
8915                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8916   }
8917
8918   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
8919 }
8920
8921 multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
8922                        int Offset128, int Offset64, bits<4> opcode>
8923   : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
8924
8925   // ST1 instructions have extra "1d" variants.
8926   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8927     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8928                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8929                                 GPR64sp:$Rn), []>;
8930
8931     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8932                        (outs GPR64sp:$wback),
8933                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8934                             GPR64sp:$Rn,
8935                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8936   }
8937
8938   defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
8939 }
8940
8941 multiclass SIMDLd1Multiple<string asm> {
8942   defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
8943   defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
8944   defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
8945   defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
8946 }
8947
8948 multiclass SIMDSt1Multiple<string asm> {
8949   defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
8950   defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
8951   defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
8952   defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
8953 }
8954
8955 multiclass SIMDLd2Multiple<string asm> {
8956   defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
8957 }
8958
8959 multiclass SIMDSt2Multiple<string asm> {
8960   defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
8961 }
8962
8963 multiclass SIMDLd3Multiple<string asm> {
8964   defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
8965 }
8966
8967 multiclass SIMDSt3Multiple<string asm> {
8968   defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
8969 }
8970
8971 multiclass SIMDLd4Multiple<string asm> {
8972   defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
8973 }
8974
8975 multiclass SIMDSt4Multiple<string asm> {
8976   defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
8977 }
8978
8979 //---
8980 // AdvSIMD Load/store single-element
8981 //---
8982
8983 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8984                          string asm, string operands, string cst,
8985                          dag oops, dag iops, list<dag> pattern>
8986   : I<oops, iops, asm, operands, cst, pattern> {
8987   bits<5> Vt;
8988   bits<5> Rn;
8989   let Inst{31} = 0;
8990   let Inst{29-24} = 0b001101;
8991   let Inst{22} = L;
8992   let Inst{21} = R;
8993   let Inst{15-13} = opcode;
8994   let Inst{9-5} = Rn;
8995   let Inst{4-0} = Vt;
8996 }
8997
8998 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8999                          string asm, string operands, string cst,
9000                          dag oops, dag iops, list<dag> pattern>
9001   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9002   bits<5> Vt;
9003   bits<5> Rn;
9004   let Inst{31} = 0;
9005   let Inst{29-24} = 0b001101;
9006   let Inst{22} = L;
9007   let Inst{21} = R;
9008   let Inst{15-13} = opcode;
9009   let Inst{9-5} = Rn;
9010   let Inst{4-0} = Vt;
9011 }
9012
9013
9014 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9015 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9016                   DAGOperand listtype>
9017   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9018                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
9019                        []> {
9020   let Inst{30} = Q;
9021   let Inst{23} = 0;
9022   let Inst{20-16} = 0b00000;
9023   let Inst{12} = S;
9024   let Inst{11-10} = size;
9025 }
9026 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9027 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9028                       string asm, DAGOperand listtype, DAGOperand GPR64pi>
9029   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9030                        "$Rn = $wback",
9031                        (outs GPR64sp:$wback, listtype:$Vt),
9032                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9033   bits<5> Xm;
9034   let Inst{30} = Q;
9035   let Inst{23} = 1;
9036   let Inst{20-16} = Xm;
9037   let Inst{12} = S;
9038   let Inst{11-10} = size;
9039 }
9040
9041 multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9042                           int Offset, int Size> {
9043   // E.g. "ld1r { v0.8b }, [x1], #1"
9044   //      "ld1r.8b\t$Vt, [$Rn], #1"
9045   // may get mapped to
9046   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9047   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9048                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9049                       GPR64sp:$Rn,
9050                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9051                       XZR), 1>;
9052
9053   // E.g. "ld1r.8b { v0 }, [x1], #1"
9054   //      "ld1r.8b\t$Vt, [$Rn], #1"
9055   // may get mapped to
9056   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9057   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9058                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9059                       GPR64sp:$Rn,
9060                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9061                       XZR), 0>;
9062
9063   // E.g. "ld1r.8b { v0 }, [x1]"
9064   //      "ld1r.8b\t$Vt, [$Rn]"
9065   // may get mapped to
9066   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9067   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9068                   (!cast<Instruction>(BaseName # "v" # layout)
9069                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9070                       GPR64sp:$Rn), 0>;
9071
9072   // E.g. "ld1r.8b { v0 }, [x1], x2"
9073   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9074   // may get mapped to
9075   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9076   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9077                   (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9078                       GPR64sp:$Rn,
9079                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9080                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9081 }
9082
9083 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9084   int Offset1, int Offset2, int Offset4, int Offset8> {
9085   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9086                         !cast<DAGOperand>("VecList" # Count # "8b")>;
9087   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9088                         !cast<DAGOperand>("VecList" # Count #"16b")>;
9089   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9090                         !cast<DAGOperand>("VecList" # Count #"4h")>;
9091   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9092                         !cast<DAGOperand>("VecList" # Count #"8h")>;
9093   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9094                         !cast<DAGOperand>("VecList" # Count #"2s")>;
9095   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9096                         !cast<DAGOperand>("VecList" # Count #"4s")>;
9097   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9098                         !cast<DAGOperand>("VecList" # Count #"1d")>;
9099   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9100                         !cast<DAGOperand>("VecList" # Count #"2d")>;
9101
9102   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9103                                  !cast<DAGOperand>("VecList" # Count # "8b"),
9104                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9105   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9106                                  !cast<DAGOperand>("VecList" # Count # "16b"),
9107                                  !cast<DAGOperand>("GPR64pi" # Offset1)>;
9108   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9109                                  !cast<DAGOperand>("VecList" # Count # "4h"),
9110                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9111   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9112                                  !cast<DAGOperand>("VecList" # Count # "8h"),
9113                                  !cast<DAGOperand>("GPR64pi" # Offset2)>;
9114   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9115                                  !cast<DAGOperand>("VecList" # Count # "2s"),
9116                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9117   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9118                                  !cast<DAGOperand>("VecList" # Count # "4s"),
9119                                  !cast<DAGOperand>("GPR64pi" # Offset4)>;
9120   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9121                                  !cast<DAGOperand>("VecList" # Count # "1d"),
9122                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9123   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9124                                  !cast<DAGOperand>("VecList" # Count # "2d"),
9125                                  !cast<DAGOperand>("GPR64pi" # Offset8)>;
9126
9127   defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
9128   defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9129   defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
9130   defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
9131   defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
9132   defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
9133   defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
9134   defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
9135 }
9136
9137 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9138                       dag oops, dag iops, list<dag> pattern>
9139   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9140                        pattern> {
9141   // idx encoded in Q:S:size fields.
9142   bits<4> idx;
9143   let Inst{30} = idx{3};
9144   let Inst{23} = 0;
9145   let Inst{20-16} = 0b00000;
9146   let Inst{12} = idx{2};
9147   let Inst{11-10} = idx{1-0};
9148 }
9149 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
9150                       dag oops, dag iops, list<dag> pattern>
9151   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9152                            oops, iops, pattern> {
9153   // idx encoded in Q:S:size fields.
9154   bits<4> idx;
9155   let Inst{30} = idx{3};
9156   let Inst{23} = 0;
9157   let Inst{20-16} = 0b00000;
9158   let Inst{12} = idx{2};
9159   let Inst{11-10} = idx{1-0};
9160 }
9161 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
9162                           dag oops, dag iops>
9163   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9164                        "$Rn = $wback", oops, iops, []> {
9165   // idx encoded in Q:S:size fields.
9166   bits<4> idx;
9167   bits<5> Xm;
9168   let Inst{30} = idx{3};
9169   let Inst{23} = 1;
9170   let Inst{20-16} = Xm;
9171   let Inst{12} = idx{2};
9172   let Inst{11-10} = idx{1-0};
9173 }
9174 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
9175                           dag oops, dag iops>
9176   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9177                            "$Rn = $wback", oops, iops, []> {
9178   // idx encoded in Q:S:size fields.
9179   bits<4> idx;
9180   bits<5> Xm;
9181   let Inst{30} = idx{3};
9182   let Inst{23} = 1;
9183   let Inst{20-16} = Xm;
9184   let Inst{12} = idx{2};
9185   let Inst{11-10} = idx{1-0};
9186 }
9187
9188 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
9189                       dag oops, dag iops, list<dag> pattern>
9190   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9191                        pattern> {
9192   // idx encoded in Q:S:size<1> fields.
9193   bits<3> idx;
9194   let Inst{30} = idx{2};
9195   let Inst{23} = 0;
9196   let Inst{20-16} = 0b00000;
9197   let Inst{12} = idx{1};
9198   let Inst{11} = idx{0};
9199   let Inst{10} = size;
9200 }
9201 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
9202                       dag oops, dag iops, list<dag> pattern>
9203   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9204                            oops, iops, pattern> {
9205   // idx encoded in Q:S:size<1> fields.
9206   bits<3> idx;
9207   let Inst{30} = idx{2};
9208   let Inst{23} = 0;
9209   let Inst{20-16} = 0b00000;
9210   let Inst{12} = idx{1};
9211   let Inst{11} = idx{0};
9212   let Inst{10} = size;
9213 }
9214
9215 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9216                           dag oops, dag iops>
9217   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9218                        "$Rn = $wback", oops, iops, []> {
9219   // idx encoded in Q:S:size<1> fields.
9220   bits<3> idx;
9221   bits<5> Xm;
9222   let Inst{30} = idx{2};
9223   let Inst{23} = 1;
9224   let Inst{20-16} = Xm;
9225   let Inst{12} = idx{1};
9226   let Inst{11} = idx{0};
9227   let Inst{10} = size;
9228 }
9229 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9230                           dag oops, dag iops>
9231   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9232                            "$Rn = $wback", oops, iops, []> {
9233   // idx encoded in Q:S:size<1> fields.
9234   bits<3> idx;
9235   bits<5> Xm;
9236   let Inst{30} = idx{2};
9237   let Inst{23} = 1;
9238   let Inst{20-16} = Xm;
9239   let Inst{12} = idx{1};
9240   let Inst{11} = idx{0};
9241   let Inst{10} = size;
9242 }
9243 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9244                       dag oops, dag iops, list<dag> pattern>
9245   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9246                        pattern> {
9247   // idx encoded in Q:S fields.
9248   bits<2> idx;
9249   let Inst{30} = idx{1};
9250   let Inst{23} = 0;
9251   let Inst{20-16} = 0b00000;
9252   let Inst{12} = idx{0};
9253   let Inst{11-10} = size;
9254 }
9255 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9256                       dag oops, dag iops, list<dag> pattern>
9257   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9258                            oops, iops, pattern> {
9259   // idx encoded in Q:S fields.
9260   bits<2> idx;
9261   let Inst{30} = idx{1};
9262   let Inst{23} = 0;
9263   let Inst{20-16} = 0b00000;
9264   let Inst{12} = idx{0};
9265   let Inst{11-10} = size;
9266 }
9267 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
9268                           string asm, dag oops, dag iops>
9269   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9270                        "$Rn = $wback", oops, iops, []> {
9271   // idx encoded in Q:S fields.
9272   bits<2> idx;
9273   bits<5> Xm;
9274   let Inst{30} = idx{1};
9275   let Inst{23} = 1;
9276   let Inst{20-16} = Xm;
9277   let Inst{12} = idx{0};
9278   let Inst{11-10} = size;
9279 }
9280 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9281                           string asm, dag oops, dag iops>
9282   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9283                            "$Rn = $wback", oops, iops, []> {
9284   // idx encoded in Q:S fields.
9285   bits<2> idx;
9286   bits<5> Xm;
9287   let Inst{30} = idx{1};
9288   let Inst{23} = 1;
9289   let Inst{20-16} = Xm;
9290   let Inst{12} = idx{0};
9291   let Inst{11-10} = size;
9292 }
9293 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9294                       dag oops, dag iops, list<dag> pattern>
9295   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9296                        pattern> {
9297   // idx encoded in Q field.
9298   bits<1> idx;
9299   let Inst{30} = idx;
9300   let Inst{23} = 0;
9301   let Inst{20-16} = 0b00000;
9302   let Inst{12} = 0;
9303   let Inst{11-10} = size;
9304 }
9305 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9306                       dag oops, dag iops, list<dag> pattern>
9307   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9308                            oops, iops, pattern> {
9309   // idx encoded in Q field.
9310   bits<1> idx;
9311   let Inst{30} = idx;
9312   let Inst{23} = 0;
9313   let Inst{20-16} = 0b00000;
9314   let Inst{12} = 0;
9315   let Inst{11-10} = size;
9316 }
9317 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
9318                           string asm, dag oops, dag iops>
9319   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9320                        "$Rn = $wback", oops, iops, []> {
9321   // idx encoded in Q field.
9322   bits<1> idx;
9323   bits<5> Xm;
9324   let Inst{30} = idx;
9325   let Inst{23} = 1;
9326   let Inst{20-16} = Xm;
9327   let Inst{12} = 0;
9328   let Inst{11-10} = size;
9329 }
9330 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9331                           string asm, dag oops, dag iops>
9332   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9333                            "$Rn = $wback", oops, iops, []> {
9334   // idx encoded in Q field.
9335   bits<1> idx;
9336   bits<5> Xm;
9337   let Inst{30} = idx;
9338   let Inst{23} = 1;
9339   let Inst{20-16} = Xm;
9340   let Inst{12} = 0;
9341   let Inst{11-10} = size;
9342 }
9343
9344 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9345 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
9346                          RegisterOperand listtype,
9347                          RegisterOperand GPR64pi> {
9348   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
9349                            (outs listtype:$dst),
9350                            (ins listtype:$Vt, VectorIndexB:$idx,
9351                                 GPR64sp:$Rn), []>;
9352
9353   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
9354                             (outs GPR64sp:$wback, listtype:$dst),
9355                             (ins listtype:$Vt, VectorIndexB:$idx,
9356                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9357 }
9358 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9359 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
9360                          RegisterOperand listtype,
9361                          RegisterOperand GPR64pi> {
9362   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
9363                             (outs listtype:$dst),
9364                             (ins listtype:$Vt, VectorIndexH:$idx,
9365                                  GPR64sp:$Rn), []>;
9366
9367   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
9368                             (outs GPR64sp:$wback, listtype:$dst),
9369                             (ins listtype:$Vt, VectorIndexH:$idx,
9370                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9371 }
9372 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9373 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
9374                          RegisterOperand listtype,
9375                          RegisterOperand GPR64pi> {
9376   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
9377                             (outs listtype:$dst),
9378                             (ins listtype:$Vt, VectorIndexS:$idx,
9379                                  GPR64sp:$Rn), []>;
9380
9381   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
9382                             (outs GPR64sp:$wback, listtype:$dst),
9383                             (ins listtype:$Vt, VectorIndexS:$idx,
9384                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9385 }
9386 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9387 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
9388                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9389   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
9390                             (outs listtype:$dst),
9391                             (ins listtype:$Vt, VectorIndexD:$idx,
9392                                  GPR64sp:$Rn), []>;
9393
9394   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
9395                             (outs GPR64sp:$wback, listtype:$dst),
9396                             (ins listtype:$Vt, VectorIndexD:$idx,
9397                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9398 }
9399 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9400 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
9401                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9402   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
9403                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
9404                                         GPR64sp:$Rn), []>;
9405
9406   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
9407                                     (outs GPR64sp:$wback),
9408                                     (ins listtype:$Vt, VectorIndexB:$idx,
9409                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
9410 }
9411 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9412 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
9413                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9414   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
9415                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
9416                                          GPR64sp:$Rn), []>;
9417
9418   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
9419                             (outs GPR64sp:$wback),
9420                             (ins listtype:$Vt, VectorIndexH:$idx,
9421                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9422 }
9423 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9424 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
9425                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9426   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
9427                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
9428                                          GPR64sp:$Rn), []>;
9429
9430   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
9431                             (outs GPR64sp:$wback),
9432                             (ins listtype:$Vt, VectorIndexS:$idx,
9433                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9434 }
9435 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9436 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
9437                          RegisterOperand listtype, RegisterOperand GPR64pi> {
9438   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
9439                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
9440                                          GPR64sp:$Rn), []>;
9441
9442   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
9443                             (outs GPR64sp:$wback),
9444                             (ins listtype:$Vt, VectorIndexD:$idx,
9445                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
9446 }
9447
9448 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
9449                                  string Count, int Offset, Operand idxtype> {
9450   // E.g. "ld1 { v0.8b }[0], [x1], #1"
9451   //      "ld1\t$Vt, [$Rn], #1"
9452   // may get mapped to
9453   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9454   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
9455                   (!cast<Instruction>(NAME # Type  # "_POST")
9456                       GPR64sp:$Rn,
9457                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9458                       idxtype:$idx, XZR), 1>;
9459
9460   // E.g. "ld1.8b { v0 }[0], [x1], #1"
9461   //      "ld1.8b\t$Vt, [$Rn], #1"
9462   // may get mapped to
9463   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9464   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9465                   (!cast<Instruction>(NAME # Type # "_POST")
9466                       GPR64sp:$Rn,
9467                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9468                       idxtype:$idx, XZR), 0>;
9469
9470   // E.g. "ld1.8b { v0 }[0], [x1]"
9471   //      "ld1.8b\t$Vt, [$Rn]"
9472   // may get mapped to
9473   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9474   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9475                       (!cast<Instruction>(NAME # Type)
9476                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9477                          idxtype:$idx, GPR64sp:$Rn), 0>;
9478
9479   // E.g. "ld1.8b { v0 }[0], [x1], x2"
9480   //      "ld1.8b\t$Vt, [$Rn], $Xm"
9481   // may get mapped to
9482   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9483   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9484                       (!cast<Instruction>(NAME # Type # "_POST")
9485                          GPR64sp:$Rn,
9486                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9487                          idxtype:$idx,
9488                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9489 }
9490
9491 multiclass SIMDLdSt1SingleAliases<string asm> {
9492   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
9493   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9494   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9495   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9496 }
9497
9498 multiclass SIMDLdSt2SingleAliases<string asm> {
9499   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
9500   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
9501   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
9502   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9503 }
9504
9505 multiclass SIMDLdSt3SingleAliases<string asm> {
9506   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
9507   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
9508   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9509   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9510 }
9511
9512 multiclass SIMDLdSt4SingleAliases<string asm> {
9513   defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
9514   defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
9515   defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9516   defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9517 }
9518 } // end of 'let Predicates = [HasNEON]'
9519
9520 //----------------------------------------------------------------------------
9521 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9522 //----------------------------------------------------------------------------
9523
9524 let Predicates = [HasNEON, HasRDM] in {
9525
9526 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9527                                     RegisterOperand regtype, string asm,
9528                                     string kind, list<dag> pattern>
9529   : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9530                                 pattern> {
9531 }
9532 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9533                                              SDPatternOperator Accum> {
9534   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9535     [(set (v4i16 V64:$dst),
9536           (Accum (v4i16 V64:$Rd),
9537                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9538                                                    (v4i16 V64:$Rm)))))]>;
9539   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9540     [(set (v8i16 V128:$dst),
9541           (Accum (v8i16 V128:$Rd),
9542                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9543                                                    (v8i16 V128:$Rm)))))]>;
9544   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9545     [(set (v2i32 V64:$dst),
9546           (Accum (v2i32 V64:$Rd),
9547                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9548                                                    (v2i32 V64:$Rm)))))]>;
9549   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9550     [(set (v4i32 V128:$dst),
9551           (Accum (v4i32 V128:$Rd),
9552                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9553                                                    (v4i32 V128:$Rm)))))]>;
9554 }
9555
9556 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9557                                      SDPatternOperator Accum> {
9558   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9559                                           V64, V64, V128_lo, VectorIndexH,
9560                                           asm, ".4h", ".4h", ".4h", ".h",
9561     [(set (v4i16 V64:$dst),
9562           (Accum (v4i16 V64:$Rd),
9563                  (v4i16 (int_aarch64_neon_sqrdmulh
9564                           (v4i16 V64:$Rn),
9565                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9566                                                     VectorIndexH:$idx))))))]> {
9567     bits<3> idx;
9568     let Inst{11} = idx{2};
9569     let Inst{21} = idx{1};
9570     let Inst{20} = idx{0};
9571   }
9572
9573   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9574                                           V128, V128, V128_lo, VectorIndexH,
9575                                           asm, ".8h", ".8h", ".8h", ".h",
9576     [(set (v8i16 V128:$dst),
9577           (Accum (v8i16 V128:$Rd),
9578                  (v8i16 (int_aarch64_neon_sqrdmulh
9579                           (v8i16 V128:$Rn),
9580                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9581                                                    VectorIndexH:$idx))))))]> {
9582     bits<3> idx;
9583     let Inst{11} = idx{2};
9584     let Inst{21} = idx{1};
9585     let Inst{20} = idx{0};
9586   }
9587
9588   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9589                                           V64, V64, V128, VectorIndexS,
9590                                           asm, ".2s", ".2s", ".2s", ".s",
9591     [(set (v2i32 V64:$dst),
9592         (Accum (v2i32 V64:$Rd),
9593                (v2i32 (int_aarch64_neon_sqrdmulh
9594                         (v2i32 V64:$Rn),
9595                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9596                                                  VectorIndexS:$idx))))))]> {
9597     bits<2> idx;
9598     let Inst{11} = idx{1};
9599     let Inst{21} = idx{0};
9600   }
9601
9602   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9603   // an intermediate EXTRACT_SUBREG would be untyped.
9604   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
9605   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9606   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9607                        (i32 (vector_extract
9608                                (v4i32 (insert_subvector
9609                                        (undef),
9610                                         (v2i32 (int_aarch64_neon_sqrdmulh
9611                                                  (v2i32 V64:$Rn),
9612                                                  (v2i32 (AArch64duplane32
9613                                                           (v4i32 V128:$Rm),
9614                                                           VectorIndexS:$idx)))),
9615                                       (i32 0))),
9616                                (i64 0))))),
9617             (EXTRACT_SUBREG
9618                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9619                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
9620                                                 FPR32Op:$Rd,
9621                                                 ssub)),
9622                           V64:$Rn,
9623                           V128:$Rm,
9624                           VectorIndexS:$idx)),
9625                 ssub)>;
9626
9627   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9628                                           V128, V128, V128, VectorIndexS,
9629                                           asm, ".4s", ".4s", ".4s", ".s",
9630     [(set (v4i32 V128:$dst),
9631           (Accum (v4i32 V128:$Rd),
9632                  (v4i32 (int_aarch64_neon_sqrdmulh
9633                           (v4i32 V128:$Rn),
9634                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9635                                                    VectorIndexS:$idx))))))]> {
9636     bits<2> idx;
9637     let Inst{11} = idx{1};
9638     let Inst{21} = idx{0};
9639   }
9640
9641   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9642   // an intermediate EXTRACT_SUBREG would be untyped.
9643   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9644                         (i32 (vector_extract
9645                                (v4i32 (int_aarch64_neon_sqrdmulh
9646                                         (v4i32 V128:$Rn),
9647                                         (v4i32 (AArch64duplane32
9648                                                  (v4i32 V128:$Rm),
9649                                                  VectorIndexS:$idx)))),
9650                                (i64 0))))),
9651             (EXTRACT_SUBREG
9652                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9653                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
9654                                                FPR32Op:$Rd,
9655                                                ssub)),
9656                          V128:$Rn,
9657                          V128:$Rm,
9658                          VectorIndexS:$idx)),
9659                 ssub)>;
9660
9661   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9662                                         FPR16Op, FPR16Op, V128_lo,
9663                                         VectorIndexH, asm, ".h", "", "", ".h",
9664                                         []> {
9665     bits<3> idx;
9666     let Inst{11} = idx{2};
9667     let Inst{21} = idx{1};
9668     let Inst{20} = idx{0};
9669   }
9670
9671   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9672                                         FPR32Op, FPR32Op, V128, VectorIndexS,
9673                                         asm, ".s", "", "", ".s",
9674     [(set (i32 FPR32Op:$dst),
9675           (Accum (i32 FPR32Op:$Rd),
9676                  (i32 (int_aarch64_neon_sqrdmulh
9677                         (i32 FPR32Op:$Rn),
9678                         (i32 (vector_extract (v4i32 V128:$Rm),
9679                                              VectorIndexS:$idx))))))]> {
9680     bits<2> idx;
9681     let Inst{11} = idx{1};
9682     let Inst{21} = idx{0};
9683   }
9684 }
9685 } // let Predicates = [HasNeon, HasRDM]
9686
9687 //----------------------------------------------------------------------------
9688 // ARMv8.3 Complex ADD/MLA instructions
9689 //----------------------------------------------------------------------------
9690
9691 class ComplexRotationOperand<int Angle, int Remainder, string Type>
9692   : AsmOperandClass {
9693   let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
9694   let DiagnosticType = "InvalidComplexRotation" # Type;
9695   let Name = "ComplexRotation" # Type;
9696 }
9697 def complexrotateop : Operand<i32> {
9698   let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
9699   let PrintMethod = "printComplexRotationOp<90, 0>";
9700 }
9701 def complexrotateopodd : Operand<i32> {
9702   let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
9703   let PrintMethod = "printComplexRotationOp<180, 90>";
9704 }
9705
9706 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9707 class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
9708                                      RegisterOperand regtype, Operand rottype,
9709                                      string asm, string kind, list<dag> pattern>
9710   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
9711       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
9712       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
9713     Sched<[WriteV]> {
9714   bits<5> Rd;
9715   bits<5> Rn;
9716   bits<5> Rm;
9717   bits<1> rot;
9718   let Inst{31}    = 0;
9719   let Inst{30}    = Q;
9720   let Inst{29}    = U;
9721   let Inst{28-24} = 0b01110;
9722   let Inst{23-22} = size;
9723   let Inst{21}    = 0;
9724   let Inst{20-16} = Rm;
9725   let Inst{15-13} = opcode;
9726   // Non-tied version (FCADD) only has one rotation bit
9727   let Inst{12}    = rot;
9728   let Inst{11}    = 0;
9729   let Inst{10}    = 1;
9730   let Inst{9-5}   = Rn;
9731   let Inst{4-0}   = Rd;
9732 }
9733
9734 multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
9735                                           string asm, SDPatternOperator OpNode>{
9736   let Predicates = [HasV8_3a, HasNEON, HasFullFP16] in {
9737   def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
9738               asm, ".4h",
9739               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
9740                                               (v4f16 V64:$Rn),
9741                                               (v4f16 V64:$Rm),
9742                                               (rottype i32:$rot)))]>;
9743
9744   def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
9745               asm, ".8h",
9746               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
9747                                                (v8f16 V128:$Rn),
9748                                                (v8f16 V128:$Rm),
9749                                                (rottype i32:$rot)))]>;
9750   }
9751
9752   let Predicates = [HasV8_3a, HasNEON] in {
9753   def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
9754               asm, ".2s",
9755               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
9756                                               (v2f32 V64:$Rn),
9757                                               (v2f32 V64:$Rm),
9758                                               (rottype i32:$rot)))]>;
9759
9760   def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
9761               asm, ".4s",
9762               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
9763                                                (v4f32 V128:$Rn),
9764                                                (v4f32 V128:$Rm),
9765                                                (rottype i32:$rot)))]>;
9766
9767   def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
9768               asm, ".2d",
9769               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
9770                                                (v2f64 V128:$Rn),
9771                                                (v2f64 V128:$Rm),
9772                                                (rottype i32:$rot)))]>;
9773   }
9774 }
9775
9776 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9777 class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
9778                                          bits<3> opcode,
9779                                          RegisterOperand regtype,
9780                                          Operand rottype, string asm,
9781                                          string kind, list<dag> pattern>
9782   : I<(outs regtype:$dst),
9783       (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
9784       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
9785       "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
9786     Sched<[WriteV]> {
9787   bits<5> Rd;
9788   bits<5> Rn;
9789   bits<5> Rm;
9790   bits<2> rot;
9791   let Inst{31}    = 0;
9792   let Inst{30}    = Q;
9793   let Inst{29}    = U;
9794   let Inst{28-24} = 0b01110;
9795   let Inst{23-22} = size;
9796   let Inst{21}    = 0;
9797   let Inst{20-16} = Rm;
9798   let Inst{15-13} = opcode;
9799   let Inst{12-11} = rot;
9800   let Inst{10}    = 1;
9801   let Inst{9-5}   = Rn;
9802   let Inst{4-0}   = Rd;
9803 }
9804
9805 multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
9806                                              Operand rottype, string asm,
9807                                              SDPatternOperator OpNode> {
9808   let Predicates = [HasV8_3a, HasNEON, HasFullFP16] in {
9809   def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
9810               rottype, asm, ".4h",
9811               [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
9812                                               (v4f16 V64:$Rn),
9813                                               (v4f16 V64:$Rm),
9814                                               (rottype i32:$rot)))]>;
9815
9816   def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
9817               rottype, asm, ".8h",
9818               [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
9819                                                (v8f16 V128:$Rn),
9820                                                (v8f16 V128:$Rm),
9821                                                (rottype i32:$rot)))]>;
9822   }
9823
9824   let Predicates = [HasV8_3a, HasNEON] in {
9825   def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
9826               rottype, asm, ".2s",
9827               [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
9828                                               (v2f32 V64:$Rn),
9829                                               (v2f32 V64:$Rm),
9830                                               (rottype i32:$rot)))]>;
9831
9832   def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
9833               rottype, asm, ".4s",
9834               [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
9835                                                (v4f32 V128:$Rn),
9836                                                (v4f32 V128:$Rm),
9837                                                (rottype i32:$rot)))]>;
9838
9839   def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
9840               rottype, asm, ".2d",
9841               [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
9842                                                (v2f64 V128:$Rn),
9843                                                (v2f64 V128:$Rm),
9844                                                (rottype i32:$rot)))]>;
9845   }
9846 }
9847
9848 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9849 class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
9850                                  bit opc1, bit opc2, RegisterOperand dst_reg,
9851                                  RegisterOperand lhs_reg,
9852                                  RegisterOperand rhs_reg, Operand vec_idx,
9853                                  Operand rottype, string asm, string apple_kind,
9854                                  string dst_kind, string lhs_kind,
9855                                  string rhs_kind, list<dag> pattern>
9856   : I<(outs dst_reg:$dst),
9857       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
9858       asm,
9859       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
9860       "$idx, $rot" # "|" # apple_kind #
9861       "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
9862     Sched<[WriteV]> {
9863   bits<5> Rd;
9864   bits<5> Rn;
9865   bits<5> Rm;
9866   bits<2> rot;
9867
9868   let Inst{31}    = 0;
9869   let Inst{30}    = Q;
9870   let Inst{29}    = U;
9871   let Inst{28}    = Scalar;
9872   let Inst{27-24} = 0b1111;
9873   let Inst{23-22} = size;
9874   // Bit 21 must be set by the derived class.
9875   let Inst{20-16} = Rm;
9876   let Inst{15}    = opc1;
9877   let Inst{14-13} = rot;
9878   let Inst{12}    = opc2;
9879   // Bit 11 must be set by the derived class.
9880   let Inst{10}    = 0;
9881   let Inst{9-5}   = Rn;
9882   let Inst{4-0}   = Rd;
9883 }
9884
9885 // The complex instructions index by pairs of elements, so the VectorIndexes
9886 // don't match the lane types, and the index bits are different to the other
9887 // classes.
9888 multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
9889                                      string asm, SDPatternOperator OpNode> {
9890   let Predicates = [HasV8_3a,HasNEON,HasFullFP16] in {
9891   def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
9892                       V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
9893                       ".4h", ".h", []> {
9894     bits<1> idx;
9895     let Inst{11} = 0;
9896     let Inst{21} = idx{0};
9897   }
9898
9899   def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
9900                       V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
9901                       ".8h", ".8h", ".h", []> {
9902     bits<2> idx;
9903     let Inst{11} = idx{1};
9904     let Inst{21} = idx{0};
9905   }
9906   } // Predicates = [HasV8_3a,HasNEON,HasFullFP16]
9907
9908   let Predicates = [HasV8_3a,HasNEON] in {
9909   def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
9910                       V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
9911                       ".4s", ".4s", ".s", []> {
9912     bits<1> idx;
9913     let Inst{11} = idx{0};
9914     let Inst{21} = 0;
9915   }
9916   } // Predicates = [HasV8_3a,HasNEON]
9917 }
9918
9919 //----------------------------------------------------------------------------
9920 // Crypto extensions
9921 //----------------------------------------------------------------------------
9922
9923 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9924 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
9925               list<dag> pat>
9926   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
9927     Sched<[WriteV]>{
9928   bits<5> Rd;
9929   bits<5> Rn;
9930   let Inst{31-16} = 0b0100111000101000;
9931   let Inst{15-12} = opc;
9932   let Inst{11-10} = 0b10;
9933   let Inst{9-5}   = Rn;
9934   let Inst{4-0}   = Rd;
9935 }
9936
9937 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
9938   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
9939             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
9940
9941 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
9942   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
9943             "$Rd = $dst",
9944             [(set (v16i8 V128:$dst),
9945                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
9946
9947 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9948 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
9949                      dag oops, dag iops, list<dag> pat>
9950   : I<oops, iops, asm,
9951       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
9952       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
9953     Sched<[WriteV]>{
9954   bits<5> Rd;
9955   bits<5> Rn;
9956   bits<5> Rm;
9957   let Inst{31-21} = 0b01011110000;
9958   let Inst{20-16} = Rm;
9959   let Inst{15}    = 0;
9960   let Inst{14-12} = opc;
9961   let Inst{11-10} = 0b00;
9962   let Inst{9-5}   = Rn;
9963   let Inst{4-0}   = Rd;
9964 }
9965
9966 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
9967   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9968                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
9969                    [(set (v4i32 FPR128:$dst),
9970                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
9971                                  (v4i32 V128:$Rm)))]>;
9972
9973 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
9974   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
9975                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
9976                    [(set (v4i32 V128:$dst),
9977                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9978                                  (v4i32 V128:$Rm)))]>;
9979
9980 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
9981   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9982                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
9983                    [(set (v4i32 FPR128:$dst),
9984                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
9985                                  (v4i32 V128:$Rm)))]>;
9986
9987 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9988 class SHA2OpInst<bits<4> opc, string asm, string kind,
9989                  string cstr, dag oops, dag iops,
9990                  list<dag> pat>
9991   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
9992                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
9993     Sched<[WriteV]>{
9994   bits<5> Rd;
9995   bits<5> Rn;
9996   let Inst{31-16} = 0b0101111000101000;
9997   let Inst{15-12} = opc;
9998   let Inst{11-10} = 0b10;
9999   let Inst{9-5}   = Rn;
10000   let Inst{4-0}   = Rd;
10001 }
10002
10003 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10004   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10005                (ins V128:$Rd, V128:$Rn),
10006                [(set (v4i32 V128:$dst),
10007                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10008
10009 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10010   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10011                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10012
10013 // Armv8.2-A Crypto extensions
10014 class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10015                     list<dag> pattern>
10016   : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10017   bits<5> Vd;
10018   bits<5> Vn;
10019   let Inst{31-25} = 0b1100111;
10020   let Inst{9-5}   = Vn;
10021   let Inst{4-0}   = Vd;
10022 }
10023
10024 class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10025   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10026                   "$Vm = $Vd", []> {
10027   let Inst{31-25} = 0b1100111;
10028   let Inst{24-21} = 0b0110;
10029   let Inst{20-15} = 0b000001;
10030   let Inst{14}    = op0;
10031   let Inst{13-12} = 0b00;
10032   let Inst{11-10} = op1;
10033 }
10034 class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10035   : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d}">;
10036 class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10037   : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s}">;
10038
10039 class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10040                 string asmops, string cst>
10041   : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10042   bits<5> Vm;
10043   let Inst{24-21} = 0b0011;
10044   let Inst{20-16} = Vm;
10045   let Inst{15}    = 0b1;
10046   let Inst{14}    = op0;
10047   let Inst{13-12} = 0b00;
10048   let Inst{11-10} = op1;
10049 }
10050 class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10051   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10052               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "">;
10053 class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10054   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10055               "{\t$Vd.2d, $Vn.2d, $Vm.2d}", "$Vd = $Vdst">;
10056 class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10057   : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10058               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "">;
10059 class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10060   : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10061               "{\t$Vd.4s, $Vn.4s, $Vm.4s}", "$Vd = $Vdst">;
10062 class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10063   : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10064               asm, "{\t$Vd, $Vn, $Vm.2d}", "$Vd = $Vdst">;
10065
10066 class CryptoRRRR<bits<2>op0, string asm, string asmops>
10067   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10068                   asmops, "", []> {
10069   bits<5> Vm;
10070   bits<5> Va;
10071   let Inst{24-23} = 0b00;
10072   let Inst{22-21} = op0;
10073   let Inst{20-16} = Vm;
10074   let Inst{15}    = 0b0;
10075   let Inst{14-10} = Va;
10076 }
10077 class CryptoRRRR_16B<bits<2>op0, string asm>
10078  : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b}"> {
10079 }
10080 class CryptoRRRR_4S<bits<2>op0, string asm>
10081  : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s}"> {
10082 }
10083
10084 class CryptoRRRi6<string asm>
10085   : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10086                   "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm}", "", []> {
10087   bits<6> imm;
10088   bits<5> Vm;
10089   let Inst{24-21} = 0b0100;
10090   let Inst{20-16} = Vm;
10091   let Inst{15-10} = imm;
10092   let Inst{9-5}   = Vn;
10093   let Inst{4-0}   = Vd;
10094 }
10095
10096 class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10097   : BaseCryptoV82<(outs V128:$Vdst),
10098                   (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10099                   asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm}", "$Vd = $Vdst", []> {
10100   bits<2> imm;
10101   bits<5> Vm;
10102   let Inst{24-21} = 0b0010;
10103   let Inst{20-16} = Vm;
10104   let Inst{15}    = 0b1;
10105   let Inst{14}    = op0;
10106   let Inst{13-12} = imm;
10107   let Inst{11-10} = op1;
10108 }
10109
10110 //----------------------------------------------------------------------------
10111 // v8.1 atomic instructions extension:
10112 // * CAS
10113 // * CASP
10114 // * SWP
10115 // * LDOPregister<OP>, and aliases STOPregister<OP>
10116
10117 // Instruction encodings:
10118 //
10119 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
10120 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
10121 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
10122 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
10123 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
10124 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
10125
10126 // Instruction syntax:
10127 //
10128 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10129 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10130 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10131 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
10132 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10133 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
10134 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10135 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
10136 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
10137 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
10138
10139 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10140 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
10141                       string cstr, list<dag> pattern>
10142       : I<oops, iops, asm, operands, cstr, pattern> {
10143   bits<2> Sz;
10144   bit NP;
10145   bit Acq;
10146   bit Rel;
10147   bits<5> Rs;
10148   bits<5> Rn;
10149   bits<5> Rt;
10150   let Inst{31-30} = Sz;
10151   let Inst{29-24} = 0b001000;
10152   let Inst{23} = NP;
10153   let Inst{22} = Acq;
10154   let Inst{21} = 0b1;
10155   let Inst{20-16} = Rs;
10156   let Inst{15} = Rel;
10157   let Inst{14-10} = 0b11111;
10158   let Inst{9-5} = Rn;
10159   let Inst{4-0} = Rt;
10160   let Predicates = [HasLSE];
10161 }
10162
10163 class BaseCAS<string order, string size, RegisterClass RC>
10164       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10165                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
10166                         "$out = $Rs",[]>,
10167         Sched<[WriteAtomic]> {
10168   let NP = 1;
10169 }
10170
10171 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
10172   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
10173   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
10174   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
10175   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
10176 }
10177
10178 class BaseCASP<string order, string size, RegisterOperand RC>
10179       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10180                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
10181                         "$out = $Rs",[]>,
10182         Sched<[WriteAtomic]> {
10183   let NP = 0;
10184 }
10185
10186 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
10187   let Sz = 0b00, Acq = Acq, Rel = Rel in
10188     def W : BaseCASP<order, "", WSeqPairClassOperand>;
10189   let Sz = 0b01, Acq = Acq, Rel = Rel in
10190     def X : BaseCASP<order, "", XSeqPairClassOperand>;
10191 }
10192
10193 let Predicates = [HasLSE] in
10194 class BaseSWP<string order, string size, RegisterClass RC>
10195       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
10196           "\t$Rs, $Rt, [$Rn]","",[]>,
10197         Sched<[WriteAtomic]> {
10198   bits<2> Sz;
10199   bit Acq;
10200   bit Rel;
10201   bits<5> Rs;
10202   bits<3> opc = 0b000;
10203   bits<5> Rn;
10204   bits<5> Rt;
10205   let Inst{31-30} = Sz;
10206   let Inst{29-24} = 0b111000;
10207   let Inst{23} = Acq;
10208   let Inst{22} = Rel;
10209   let Inst{21} = 0b1;
10210   let Inst{20-16} = Rs;
10211   let Inst{15} = 0b1;
10212   let Inst{14-12} = opc;
10213   let Inst{11-10} = 0b00;
10214   let Inst{9-5} = Rn;
10215   let Inst{4-0} = Rt;
10216   let Predicates = [HasLSE];
10217 }
10218
10219 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
10220   let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
10221   let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
10222   let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
10223   let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
10224 }
10225
10226 let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10227 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
10228       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
10229           "\t$Rs, $Rt, [$Rn]","",[]>,
10230         Sched<[WriteAtomic]> {
10231   bits<2> Sz;
10232   bit Acq;
10233   bit Rel;
10234   bits<5> Rs;
10235   bits<3> opc;
10236   bits<5> Rn;
10237   bits<5> Rt;
10238   let Inst{31-30} = Sz;
10239   let Inst{29-24} = 0b111000;
10240   let Inst{23} = Acq;
10241   let Inst{22} = Rel;
10242   let Inst{21} = 0b1;
10243   let Inst{20-16} = Rs;
10244   let Inst{15} = 0b0;
10245   let Inst{14-12} = opc;
10246   let Inst{11-10} = 0b00;
10247   let Inst{9-5} = Rn;
10248   let Inst{4-0} = Rt;
10249   let Predicates = [HasLSE];
10250 }
10251
10252 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
10253                         string order> {
10254   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
10255     def B : BaseLDOPregister<op, order, "b", GPR32>;
10256   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
10257     def H : BaseLDOPregister<op, order, "h", GPR32>;
10258   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
10259     def W : BaseLDOPregister<op, order, "", GPR32>;
10260   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
10261     def X : BaseLDOPregister<op, order, "", GPR64>;
10262 }
10263
10264 // Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
10265 // complex DAG for DstRHS.
10266 let Predicates = [HasLSE] in
10267 multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
10268                                          string size, dag SrcRHS, dag DstRHS> {
10269   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
10270             (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
10271   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
10272             (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
10273   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
10274             (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
10275   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
10276             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10277   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
10278             (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10279 }
10280
10281 multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
10282                                      string size, dag RHS> {
10283   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
10284 }
10285
10286 multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
10287                                          string size, dag LHS, dag RHS> {
10288   defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
10289 }
10290
10291 multiclass LDOPregister_patterns<string inst, string op> {
10292   defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
10293   defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
10294   defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
10295   defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
10296 }
10297
10298 multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
10299   defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
10300                         (i64 GPR64:$Rm),
10301                         (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
10302   defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
10303                         (i32 GPR32:$Rm),
10304                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10305   defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
10306                         (i32 GPR32:$Rm),
10307                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10308   defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
10309                         (i32 GPR32:$Rm),
10310                         (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10311 }
10312
10313 let Predicates = [HasLSE] in
10314 multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
10315                                         string size, dag OLD, dag NEW> {
10316   def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
10317             (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
10318   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
10319             (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10320   def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
10321             (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10322   def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
10323             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10324   def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
10325             (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10326 }
10327
10328 multiclass CASregister_patterns_ord<string inst, string suffix, string op,
10329                                     string size, dag OLD, dag NEW> {
10330   defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
10331 }
10332
10333 multiclass CASregister_patterns<string inst, string op> {
10334   defm : CASregister_patterns_ord<inst, "X", op, "64",
10335                         (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
10336   defm : CASregister_patterns_ord<inst, "W", op, "32",
10337                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10338   defm : CASregister_patterns_ord<inst, "H", op, "16",
10339                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10340   defm : CASregister_patterns_ord<inst, "B", op, "8",
10341                         (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10342 }
10343
10344 let Predicates = [HasLSE] in
10345 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
10346                         Instruction inst> :
10347       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
10348
10349 multiclass STOPregister<string asm, string instr> {
10350   def : BaseSTOPregister<asm # "lb", GPR32, WZR,
10351                     !cast<Instruction>(instr # "LB")>;
10352   def : BaseSTOPregister<asm # "lh", GPR32, WZR,
10353                     !cast<Instruction>(instr # "LH")>;
10354   def : BaseSTOPregister<asm # "l",  GPR32, WZR,
10355                     !cast<Instruction>(instr # "LW")>;
10356   def : BaseSTOPregister<asm # "l",  GPR64, XZR,
10357                     !cast<Instruction>(instr # "LX")>;
10358   def : BaseSTOPregister<asm # "b",  GPR32, WZR,
10359                     !cast<Instruction>(instr # "B")>;
10360   def : BaseSTOPregister<asm # "h",  GPR32, WZR,
10361                     !cast<Instruction>(instr # "H")>;
10362   def : BaseSTOPregister<asm,        GPR32, WZR,
10363                     !cast<Instruction>(instr # "W")>;
10364   def : BaseSTOPregister<asm,        GPR64, XZR,
10365                     !cast<Instruction>(instr # "X")>;
10366 }
10367
10368 //----------------------------------------------------------------------------
10369 // Allow the size specifier tokens to be upper case, not just lower.
10370 def : TokenAlias<".4B", ".4b">;  // Add dot product
10371 def : TokenAlias<".8B", ".8b">;
10372 def : TokenAlias<".4H", ".4h">;
10373 def : TokenAlias<".2S", ".2s">;
10374 def : TokenAlias<".1D", ".1d">;
10375 def : TokenAlias<".16B", ".16b">;
10376 def : TokenAlias<".8H", ".8h">;
10377 def : TokenAlias<".4S", ".4s">;
10378 def : TokenAlias<".2D", ".2d">;
10379 def : TokenAlias<".1Q", ".1q">;
10380 def : TokenAlias<".2H", ".2h">;
10381 def : TokenAlias<".B", ".b">;
10382 def : TokenAlias<".H", ".h">;
10383 def : TokenAlias<".S", ".s">;
10384 def : TokenAlias<".D", ".d">;
10385 def : TokenAlias<".Q", ".q">;