[ARM64] Ensure immediates in extend operands are in a valid range
[oota-llvm.git] / lib / Target / ARM64 / ARM64InstrFormats.td
1 //===- ARM64InstrFormats.td - ARM64 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 ARM64 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 // ARM64 Instruction Format
25 class ARM64Inst<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   = "ARM64";
36   Format F        = f;
37   bits<2> Form    = F.Value;
38   let Pattern     = [];
39   let Constraints = cstr;
40 }
41
42 // Pseudo instructions (don't have encoding information)
43 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
44     : ARM64Inst<PseudoFrm, cstr> {
45   dag OutOperandList = oops;
46   dag InOperandList  = iops;
47   let Pattern        = pattern;
48   let isCodeGenOnly  = 1;
49 }
50
51 // Real instructions (have encoding information)
52 class EncodedI<string cstr, list<dag> pattern> : ARM64Inst<NormalFrm, cstr> {
53   let Pattern = pattern;
54   let Size = 4;
55 }
56
57 // Normal instructions
58 class I<dag oops, dag iops, string asm, string operands, string cstr,
59         list<dag> pattern>
60     : EncodedI<cstr, pattern> {
61   dag OutOperandList = oops;
62   dag InOperandList  = iops;
63   let AsmString      = !strconcat(asm, operands);
64 }
65
66 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
67 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
68 class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
69
70 // Helper fragment for an extract of the high portion of a 128-bit vector.
71 def extract_high_v16i8 :
72    UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
73 def extract_high_v8i16 :
74    UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
75 def extract_high_v4i32 :
76    UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
77 def extract_high_v2i64 :
78    UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
79
80 //===----------------------------------------------------------------------===//
81 // Asm Operand Classes.
82 //
83
84 // Shifter operand for arithmetic shifted encodings.
85 def ShifterOperand : AsmOperandClass {
86   let Name = "Shifter";
87 }
88
89 // Shifter operand for mov immediate encodings.
90 def MovImm32ShifterOperand : AsmOperandClass {
91   let SuperClasses = [ShifterOperand];
92   let Name = "MovImm32Shifter";
93 }
94 def MovImm64ShifterOperand : AsmOperandClass {
95   let SuperClasses = [ShifterOperand];
96   let Name = "MovImm64Shifter";
97 }
98
99 // Shifter operand for arithmetic register shifted encodings.
100 def ArithmeticShifterOperand : AsmOperandClass {
101   let SuperClasses = [ShifterOperand];
102   let Name = "ArithmeticShifter";
103 }
104
105 // Shifter operand for arithmetic shifted encodings for ADD/SUB instructions.
106 def AddSubShifterOperand : AsmOperandClass {
107   let SuperClasses = [ArithmeticShifterOperand];
108   let Name = "AddSubShifter";
109 }
110
111 // Shifter operand for logical vector 128/64-bit shifted encodings.
112 def LogicalVecShifterOperand : AsmOperandClass {
113   let SuperClasses = [ShifterOperand];
114   let Name = "LogicalVecShifter";
115 }
116 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
117   let SuperClasses = [LogicalVecShifterOperand];
118   let Name = "LogicalVecHalfWordShifter";
119 }
120
121 // The "MSL" shifter on the vector MOVI instruction.
122 def MoveVecShifterOperand : AsmOperandClass {
123   let SuperClasses = [ShifterOperand];
124   let Name = "MoveVecShifter";
125 }
126
127 // Extend operand for arithmetic encodings.
128 def ExtendOperand : AsmOperandClass {
129   let Name = "Extend";
130   let DiagnosticType = "AddSubRegExtendLarge";
131 }
132 def ExtendOperand64 : AsmOperandClass {
133   let SuperClasses = [ExtendOperand];
134   let Name = "Extend64";
135   let DiagnosticType = "AddSubRegExtendSmall";
136 }
137 // 'extend' that's a lsl of a 64-bit register.
138 def ExtendOperandLSL64 : AsmOperandClass {
139   let SuperClasses = [ExtendOperand];
140   let Name = "ExtendLSL64";
141   let DiagnosticType = "AddSubRegExtendLarge";
142 }
143
144 // 8-bit floating-point immediate encodings.
145 def FPImmOperand : AsmOperandClass {
146   let Name = "FPImm";
147   let ParserMethod = "tryParseFPImm";
148 }
149
150 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
151 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
152 // are encoded as the eight bit value 'abcdefgh'.
153 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
154
155
156 //===----------------------------------------------------------------------===//
157 // Operand Definitions.
158 //
159
160 // ADR[P] instruction labels.
161 def AdrpOperand : AsmOperandClass {
162   let Name = "AdrpLabel";
163   let ParserMethod = "tryParseAdrpLabel";
164   let DiagnosticType = "InvalidLabel";
165 }
166 def adrplabel : Operand<i64> {
167   let EncoderMethod = "getAdrLabelOpValue";
168   let PrintMethod = "printAdrpLabel";
169   let ParserMatchClass = AdrpOperand;
170 }
171
172 def AdrOperand : AsmOperandClass {
173   let Name = "AdrLabel";
174   let ParserMethod = "tryParseAdrLabel";
175   let DiagnosticType = "InvalidLabel";
176 }
177 def adrlabel : Operand<i64> {
178   let EncoderMethod = "getAdrLabelOpValue";
179   let ParserMatchClass = AdrOperand;
180 }
181
182 // simm9 predicate - True if the immediate is in the range [-256, 255].
183 def SImm9Operand : AsmOperandClass {
184   let Name = "SImm9";
185   let DiagnosticType = "InvalidMemoryIndexedSImm9";
186 }
187 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
188   let ParserMatchClass = SImm9Operand;
189 }
190
191 // simm7s4 predicate - True if the immediate is a multiple of 4 in the range
192 // [-256, 252].
193 def SImm7s4Operand : AsmOperandClass {
194   let Name = "SImm7s4";
195   let DiagnosticType = "InvalidMemoryIndexed32SImm7";
196 }
197 def simm7s4 : Operand<i32> {
198   let ParserMatchClass = SImm7s4Operand;
199   let PrintMethod = "printImmScale<4>";
200 }
201
202 // simm7s8 predicate - True if the immediate is a multiple of 8 in the range
203 // [-512, 504].
204 def SImm7s8Operand : AsmOperandClass {
205   let Name = "SImm7s8";
206   let DiagnosticType = "InvalidMemoryIndexed64SImm7";
207 }
208 def simm7s8 : Operand<i32> {
209   let ParserMatchClass = SImm7s8Operand;
210   let PrintMethod = "printImmScale<8>";
211 }
212
213 // simm7s16 predicate - True if the immediate is a multiple of 16 in the range
214 // [-1024, 1008].
215 def SImm7s16Operand : AsmOperandClass {
216   let Name = "SImm7s16";
217   let DiagnosticType = "InvalidMemoryIndexed64SImm7";
218 }
219 def simm7s16 : Operand<i32> {
220   let ParserMatchClass = SImm7s16Operand;
221   let PrintMethod = "printImmScale<16>";
222 }
223
224 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
225 def Imm0_65535Operand : AsmOperandClass { let Name = "Imm0_65535"; }
226 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
227   return ((uint32_t)Imm) < 65536;
228 }]> {
229   let ParserMatchClass = Imm0_65535Operand;
230   let PrintMethod = "printHexImm";
231 }
232
233 class AsmImmRange<int Low, int High> : AsmOperandClass {
234   let Name = "Imm" # Low # "_" # High;
235   let DiagnosticType = "InvalidImm" # Low # "_" # High;
236 }
237
238 def Imm1_8Operand : AsmImmRange<1, 8>;
239 def Imm1_16Operand : AsmImmRange<1, 16>;
240 def Imm1_32Operand : AsmImmRange<1, 32>;
241 def Imm1_64Operand : AsmImmRange<1, 64>;
242
243 def MovZSymbolG3AsmOperand : AsmOperandClass {
244   let Name = "MovZSymbolG3";
245   let RenderMethod = "addImmOperands";
246 }
247
248 def movz_symbol_g3 : Operand<i32> {
249   let ParserMatchClass = MovZSymbolG3AsmOperand;
250 }
251
252 def MovZSymbolG2AsmOperand : AsmOperandClass {
253   let Name = "MovZSymbolG2";
254   let RenderMethod = "addImmOperands";
255 }
256
257 def movz_symbol_g2 : Operand<i32> {
258   let ParserMatchClass = MovZSymbolG2AsmOperand;
259 }
260
261 def MovZSymbolG1AsmOperand : AsmOperandClass {
262   let Name = "MovZSymbolG1";
263   let RenderMethod = "addImmOperands";
264 }
265
266 def movz_symbol_g1 : Operand<i32> {
267   let ParserMatchClass = MovZSymbolG1AsmOperand;
268 }
269
270 def MovZSymbolG0AsmOperand : AsmOperandClass {
271   let Name = "MovZSymbolG0";
272   let RenderMethod = "addImmOperands";
273 }
274
275 def movz_symbol_g0 : Operand<i32> {
276   let ParserMatchClass = MovZSymbolG0AsmOperand;
277 }
278
279 def MovKSymbolG3AsmOperand : AsmOperandClass {
280   let Name = "MovKSymbolG3";
281   let RenderMethod = "addImmOperands";
282 }
283
284 def movk_symbol_g3 : Operand<i32> {
285   let ParserMatchClass = MovKSymbolG3AsmOperand;
286 }
287
288 def MovKSymbolG2AsmOperand : AsmOperandClass {
289   let Name = "MovKSymbolG2";
290   let RenderMethod = "addImmOperands";
291 }
292
293 def movk_symbol_g2 : Operand<i32> {
294   let ParserMatchClass = MovKSymbolG2AsmOperand;
295 }
296
297 def MovKSymbolG1AsmOperand : AsmOperandClass {
298   let Name = "MovKSymbolG1";
299   let RenderMethod = "addImmOperands";
300 }
301
302 def movk_symbol_g1 : Operand<i32> {
303   let ParserMatchClass = MovKSymbolG1AsmOperand;
304 }
305
306 def MovKSymbolG0AsmOperand : AsmOperandClass {
307   let Name = "MovKSymbolG0";
308   let RenderMethod = "addImmOperands";
309 }
310
311 def movk_symbol_g0 : Operand<i32> {
312   let ParserMatchClass = MovKSymbolG0AsmOperand;
313 }
314
315 class fixedpoint_i32<ValueType FloatVT>
316   : Operand<FloatVT>,
317     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
318   let EncoderMethod = "getFixedPointScaleOpValue";
319   let DecoderMethod = "DecodeFixedPointScaleImm32";
320   let ParserMatchClass = Imm1_32Operand;
321 }
322
323 class fixedpoint_i64<ValueType FloatVT>
324   : Operand<FloatVT>,
325     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
326   let EncoderMethod = "getFixedPointScaleOpValue";
327   let DecoderMethod = "DecodeFixedPointScaleImm64";
328   let ParserMatchClass = Imm1_64Operand;
329 }
330
331 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
332 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
333
334 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
335 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
336
337 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
338   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
339 }]> {
340   let EncoderMethod = "getVecShiftR8OpValue";
341   let DecoderMethod = "DecodeVecShiftR8Imm";
342   let ParserMatchClass = Imm1_8Operand;
343 }
344 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
345   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
346 }]> {
347   let EncoderMethod = "getVecShiftR16OpValue";
348   let DecoderMethod = "DecodeVecShiftR16Imm";
349   let ParserMatchClass = Imm1_16Operand;
350 }
351 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
352   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
353 }]> {
354   let EncoderMethod = "getVecShiftR16OpValue";
355   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
356   let ParserMatchClass = Imm1_8Operand;
357 }
358 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
359   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
360 }]> {
361   let EncoderMethod = "getVecShiftR32OpValue";
362   let DecoderMethod = "DecodeVecShiftR32Imm";
363   let ParserMatchClass = Imm1_32Operand;
364 }
365 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
366   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
367 }]> {
368   let EncoderMethod = "getVecShiftR32OpValue";
369   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
370   let ParserMatchClass = Imm1_16Operand;
371 }
372 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
373   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
374 }]> {
375   let EncoderMethod = "getVecShiftR64OpValue";
376   let DecoderMethod = "DecodeVecShiftR64Imm";
377   let ParserMatchClass = Imm1_64Operand;
378 }
379 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
380   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
381 }]> {
382   let EncoderMethod = "getVecShiftR64OpValue";
383   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
384   let ParserMatchClass = Imm1_32Operand;
385 }
386
387 def Imm0_7Operand : AsmImmRange<0, 7>;
388 def Imm0_15Operand : AsmImmRange<0, 15>;
389 def Imm0_31Operand : AsmImmRange<0, 31>;
390 def Imm0_63Operand : AsmImmRange<0, 63>;
391
392 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
393   return (((uint32_t)Imm) < 8);
394 }]> {
395   let EncoderMethod = "getVecShiftL8OpValue";
396   let DecoderMethod = "DecodeVecShiftL8Imm";
397   let ParserMatchClass = Imm0_7Operand;
398 }
399 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
400   return (((uint32_t)Imm) < 16);
401 }]> {
402   let EncoderMethod = "getVecShiftL16OpValue";
403   let DecoderMethod = "DecodeVecShiftL16Imm";
404   let ParserMatchClass = Imm0_15Operand;
405 }
406 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
407   return (((uint32_t)Imm) < 32);
408 }]> {
409   let EncoderMethod = "getVecShiftL32OpValue";
410   let DecoderMethod = "DecodeVecShiftL32Imm";
411   let ParserMatchClass = Imm0_31Operand;
412 }
413 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
414   return (((uint32_t)Imm) < 64);
415 }]> {
416   let EncoderMethod = "getVecShiftL64OpValue";
417   let DecoderMethod = "DecodeVecShiftL64Imm";
418   let ParserMatchClass = Imm0_63Operand;
419 }
420
421
422 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
423 // instructions for splatting repeating bit patterns across the immediate.
424 def logical_imm32_XFORM : SDNodeXForm<imm, [{
425   uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
426   return CurDAG->getTargetConstant(enc, MVT::i32);
427 }]>;
428 def logical_imm64_XFORM : SDNodeXForm<imm, [{
429   uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
430   return CurDAG->getTargetConstant(enc, MVT::i32);
431 }]>;
432
433 def LogicalImm32Operand : AsmOperandClass { let Name = "LogicalImm32"; }
434 def LogicalImm64Operand : AsmOperandClass { let Name = "LogicalImm64"; }
435 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
436   return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 32);
437 }], logical_imm32_XFORM> {
438   let PrintMethod = "printLogicalImm32";
439   let ParserMatchClass = LogicalImm32Operand;
440 }
441 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
442   return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 64);
443 }], logical_imm64_XFORM> {
444   let PrintMethod = "printLogicalImm64";
445   let ParserMatchClass = LogicalImm64Operand;
446 }
447
448 // imm0_255 predicate - True if the immediate is in the range [0,255].
449 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
450 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
451   return ((uint32_t)Imm) < 256;
452 }]> {
453   let ParserMatchClass = Imm0_255Operand;
454   let PrintMethod = "printHexImm";
455 }
456
457 // imm0_127 predicate - True if the immediate is in the range [0,127]
458 def Imm0_127Operand : AsmOperandClass { let Name = "Imm0_127"; }
459 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
460   return ((uint32_t)Imm) < 128;
461 }]> {
462   let ParserMatchClass = Imm0_127Operand;
463   let PrintMethod = "printHexImm";
464 }
465
466 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
467 // for all shift-amounts.
468
469 // imm0_63 predicate - True if the immediate is in the range [0,63]
470 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
471   return ((uint64_t)Imm) < 64;
472 }]> {
473   let ParserMatchClass = Imm0_63Operand;
474 }
475
476 // imm0_31 predicate - True if the immediate is in the range [0,31]
477 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
478   return ((uint64_t)Imm) < 32;
479 }]> {
480   let ParserMatchClass = Imm0_31Operand;
481 }
482
483 // imm0_15 predicate - True if the immediate is in the range [0,15]
484 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
485   return ((uint64_t)Imm) < 16;
486 }]> {
487   let ParserMatchClass = Imm0_15Operand;
488 }
489
490 // imm0_7 predicate - True if the immediate is in the range [0,7]
491 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
492   return ((uint64_t)Imm) < 8;
493 }]> {
494   let ParserMatchClass = Imm0_7Operand;
495 }
496
497 // An arithmetic shifter operand:
498 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
499 //  {5-0} - imm6
500 def arith_shift : Operand<i32> {
501   let PrintMethod = "printShifter";
502   let ParserMatchClass = ArithmeticShifterOperand;
503 }
504
505 class arith_shifted_reg<ValueType Ty, RegisterClass regclass>
506     : Operand<Ty>,
507       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
508   let PrintMethod = "printShiftedRegister";
509   let MIOperandInfo = (ops regclass, arith_shift);
510 }
511
512 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32>;
513 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64>;
514
515 // An arithmetic shifter operand:
516 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
517 //  {5-0} - imm6
518 def logical_shift : Operand<i32> {
519   let PrintMethod = "printShifter";
520   let ParserMatchClass = ShifterOperand;
521 }
522
523 class logical_shifted_reg<ValueType Ty, RegisterClass regclass>
524     : Operand<Ty>,
525       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
526   let PrintMethod = "printShiftedRegister";
527   let MIOperandInfo = (ops regclass, logical_shift);
528 }
529
530 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32>;
531 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64>;
532
533 // A logical vector shifter operand:
534 //  {7-6} - shift type: 00 = lsl
535 //  {5-0} - imm6: #0, #8, #16, or #24
536 def logical_vec_shift : Operand<i32> {
537   let PrintMethod = "printShifter";
538   let EncoderMethod = "getVecShifterOpValue";
539   let ParserMatchClass = LogicalVecShifterOperand;
540 }
541
542 // A logical vector half-word shifter operand:
543 //  {7-6} - shift type: 00 = lsl
544 //  {5-0} - imm6: #0 or #8
545 def logical_vec_hw_shift : Operand<i32> {
546   let PrintMethod = "printShifter";
547   let EncoderMethod = "getVecShifterOpValue";
548   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
549 }
550
551 // A vector move shifter operand:
552 //  {0} - imm1: #8 or #16
553 def move_vec_shift : Operand<i32> {
554   let PrintMethod = "printShifter";
555   let EncoderMethod = "getMoveVecShifterOpValue";
556   let ParserMatchClass = MoveVecShifterOperand;
557 }
558
559 // An ADD/SUB immediate shifter operand:
560 //  {7-6} - shift type: 00 = lsl
561 //  {5-0} - imm6: #0 or #12
562 def addsub_shift : Operand<i32> {
563   let ParserMatchClass = AddSubShifterOperand;
564 }
565
566 class addsub_shifted_imm<ValueType Ty>
567     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
568   let PrintMethod = "printAddSubImm";
569   let EncoderMethod = "getAddSubImmOpValue";
570   let MIOperandInfo = (ops i32imm, addsub_shift);
571 }
572
573 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
574 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
575
576 class neg_addsub_shifted_imm<ValueType Ty>
577     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
578   let PrintMethod = "printAddSubImm";
579   let EncoderMethod = "getAddSubImmOpValue";
580   let MIOperandInfo = (ops i32imm, addsub_shift);
581 }
582
583 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
584 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
585
586 // An extend operand:
587 //  {5-3} - extend type
588 //  {2-0} - imm3
589 def arith_extend : Operand<i32> {
590   let PrintMethod = "printExtend";
591   let ParserMatchClass = ExtendOperand;
592 }
593 def arith_extend64 : Operand<i32> {
594   let PrintMethod = "printExtend";
595   let ParserMatchClass = ExtendOperand64;
596 }
597
598 // 'extend' that's a lsl of a 64-bit register.
599 def arith_extendlsl64 : Operand<i32> {
600   let PrintMethod = "printExtend";
601   let ParserMatchClass = ExtendOperandLSL64;
602 }
603
604 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
605                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
606   let PrintMethod = "printExtendedRegister";
607   let MIOperandInfo = (ops GPR32, arith_extend);
608 }
609
610 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
611                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
612   let PrintMethod = "printExtendedRegister";
613   let MIOperandInfo = (ops GPR32, arith_extend64);
614 }
615
616 // Floating-point immediate.
617 def fpimm32 : Operand<f32>,
618               PatLeaf<(f32 fpimm), [{
619       return ARM64_AM::getFP32Imm(N->getValueAPF()) != -1;
620     }], SDNodeXForm<fpimm, [{
621       APFloat InVal = N->getValueAPF();
622       uint32_t enc = ARM64_AM::getFP32Imm(InVal);
623       return CurDAG->getTargetConstant(enc, MVT::i32);
624     }]>> {
625   let ParserMatchClass = FPImmOperand;
626   let PrintMethod = "printFPImmOperand";
627 }
628 def fpimm64 : Operand<f64>,
629               PatLeaf<(f64 fpimm), [{
630       return ARM64_AM::getFP64Imm(N->getValueAPF()) != -1;
631     }], SDNodeXForm<fpimm, [{
632       APFloat InVal = N->getValueAPF();
633       uint32_t enc = ARM64_AM::getFP64Imm(InVal);
634       return CurDAG->getTargetConstant(enc, MVT::i32);
635     }]>> {
636   let ParserMatchClass = FPImmOperand;
637   let PrintMethod = "printFPImmOperand";
638 }
639
640 def fpimm8 : Operand<i32> {
641   let ParserMatchClass = FPImmOperand;
642   let PrintMethod = "printFPImmOperand";
643 }
644
645 def fpimm0 : PatLeaf<(fpimm), [{
646   return N->isExactlyValue(+0.0);
647 }]>;
648
649 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
650 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
651 // are encoded as the eight bit value 'abcdefgh'.
652 def simdimmtype10 : Operand<i32>,
653                     PatLeaf<(f64 fpimm), [{
654       return ARM64_AM::isAdvSIMDModImmType10(N->getValueAPF()
655                                                .bitcastToAPInt()
656                                                .getZExtValue());
657     }], SDNodeXForm<fpimm, [{
658       APFloat InVal = N->getValueAPF();
659       uint32_t enc = ARM64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
660                                                            .bitcastToAPInt()
661                                                            .getZExtValue());
662       return CurDAG->getTargetConstant(enc, MVT::i32);
663     }]>> {
664   let ParserMatchClass = SIMDImmType10Operand;
665   let PrintMethod = "printSIMDType10Operand";
666 }
667
668
669 //---
670 // System management
671 //---
672
673 // Base encoding for system instruction operands.
674 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
675 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands>
676     : I<oops, iops, asm, operands, "", []> {
677   let Inst{31-22} = 0b1101010100;
678   let Inst{21}    = L;
679 }
680
681 // System instructions which do not have an Rt register.
682 class SimpleSystemI<bit L, dag iops, string asm, string operands>
683     : BaseSystemI<L, (outs), iops, asm, operands> {
684   let Inst{4-0} = 0b11111;
685 }
686
687 // System instructions which have an Rt register.
688 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
689     : BaseSystemI<L, oops, iops, asm, operands>,
690       Sched<[WriteSys]> {
691   bits<5> Rt;
692   let Inst{4-0} = Rt;
693 }
694
695 // Hint instructions that take both a CRm and a 3-bit immediate.
696 class HintI<string mnemonic>
697     : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "">,
698       Sched<[WriteHint]> {
699   bits <7> imm;
700   let Inst{20-12} = 0b000110010;
701   let Inst{11-5} = imm;
702 }
703
704 // System instructions taking a single literal operand which encodes into
705 // CRm. op2 differentiates the opcodes.
706 def BarrierAsmOperand : AsmOperandClass {
707   let Name = "Barrier";
708   let ParserMethod = "tryParseBarrierOperand";
709 }
710 def barrier_op : Operand<i32> {
711   let PrintMethod = "printBarrierOption";
712   let ParserMatchClass = BarrierAsmOperand;
713 }
714 class CRmSystemI<Operand crmtype, bits<3> opc, string asm>
715     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">,
716       Sched<[WriteBarrier]> {
717   bits<4> CRm;
718   let Inst{20-12} = 0b000110011;
719   let Inst{11-8} = CRm;
720   let Inst{7-5} = opc;
721 }
722
723 // MRS/MSR system instructions. These have different operand classes because
724 // a different subset of registers can be accessed through each instruction.
725 def MRSSystemRegisterOperand : AsmOperandClass {
726   let Name = "MRSSystemRegister";
727   let ParserMethod = "tryParseSysReg";
728   let DiagnosticType = "MRS";
729 }
730 // concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate.
731 def mrs_sysreg_op : Operand<i32> {
732   let ParserMatchClass = MRSSystemRegisterOperand;
733   let DecoderMethod = "DecodeMRSSystemRegister";
734   let PrintMethod = "printMRSSystemRegister";
735 }
736
737 def MSRSystemRegisterOperand : AsmOperandClass {
738   let Name = "MSRSystemRegister";
739   let ParserMethod = "tryParseSysReg";
740   let DiagnosticType = "MSR";
741 }
742 def msr_sysreg_op : Operand<i32> {
743   let ParserMatchClass = MSRSystemRegisterOperand;
744   let DecoderMethod = "DecodeMSRSystemRegister";
745   let PrintMethod = "printMSRSystemRegister";
746 }
747
748 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
749                        "mrs", "\t$Rt, $systemreg"> {
750   bits<15> systemreg;
751   let Inst{20} = 1;
752   let Inst{19-5} = systemreg;
753 }
754
755 // FIXME: Some of these def NZCV, others don't. Best way to model that?
756 // Explicitly modeling each of the system register as a register class
757 // would do it, but feels like overkill at this point.
758 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
759                        "msr", "\t$systemreg, $Rt"> {
760   bits<15> systemreg;
761   let Inst{20} = 1;
762   let Inst{19-5} = systemreg;
763 }
764
765 def SystemPStateFieldOperand : AsmOperandClass {
766   let Name = "SystemPStateField";
767   let ParserMethod = "tryParseSysReg";
768 }
769 def pstatefield_op : Operand<i32> {
770   let ParserMatchClass = SystemPStateFieldOperand;
771   let PrintMethod = "printSystemPStateField";
772 }
773
774 let Defs = [NZCV] in
775 class MSRpstateI
776   : SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm),
777                   "msr", "\t$pstate_field, $imm">,
778     Sched<[WriteSys]> {
779   bits<6> pstatefield;
780   bits<4> imm;
781   let Inst{20-19} = 0b00;
782   let Inst{18-16} = pstatefield{5-3};
783   let Inst{15-12} = 0b0100;
784   let Inst{11-8} = imm;
785   let Inst{7-5} = pstatefield{2-0};
786
787   let DecoderMethod = "DecodeSystemPStateInstruction";
788 }
789
790 // SYS and SYSL generic system instructions.
791 def SysCRAsmOperand : AsmOperandClass {
792   let Name = "SysCR";
793   let ParserMethod = "tryParseSysCROperand";
794 }
795
796 def sys_cr_op : Operand<i32> {
797   let PrintMethod = "printSysCROperand";
798   let ParserMatchClass = SysCRAsmOperand;
799 }
800
801 class SystemXtI<bit L, string asm>
802   : RtSystemI<L, (outs),
803        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
804        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
805   bits<3> op1;
806   bits<4> Cn;
807   bits<4> Cm;
808   bits<3> op2;
809   let Inst{20-19} = 0b01;
810   let Inst{18-16} = op1;
811   let Inst{15-12} = Cn;
812   let Inst{11-8}  = Cm;
813   let Inst{7-5}   = op2;
814 }
815
816 class SystemLXtI<bit L, string asm>
817   : RtSystemI<L, (outs),
818        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
819        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
820   bits<3> op1;
821   bits<4> Cn;
822   bits<4> Cm;
823   bits<3> op2;
824   let Inst{20-19} = 0b01;
825   let Inst{18-16} = op1;
826   let Inst{15-12} = Cn;
827   let Inst{11-8}  = Cm;
828   let Inst{7-5}   = op2;
829 }
830
831
832 // Branch (register) instructions:
833 //
834 //  case opc of
835 //    0001 blr
836 //    0000 br
837 //    0101 dret
838 //    0100 eret
839 //    0010 ret
840 //    otherwise UNDEFINED
841 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
842                     string operands, list<dag> pattern>
843     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
844   let Inst{31-25} = 0b1101011;
845   let Inst{24-21} = opc;
846   let Inst{20-16} = 0b11111;
847   let Inst{15-10} = 0b000000;
848   let Inst{4-0}   = 0b00000;
849 }
850
851 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
852     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
853   bits<5> Rn;
854   let Inst{9-5} = Rn;
855 }
856
857 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
858 class SpecialReturn<bits<4> opc, string asm>
859     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
860   let Inst{9-5} = 0b11111;
861 }
862
863 //---
864 // Conditional branch instruction.
865 //---
866 // Branch condition code.
867 // 4-bit immediate. Pretty-printed as .<cc>
868 def dotCcode : Operand<i32> {
869   let PrintMethod = "printDotCondCode";
870 }
871
872 // Conditional branch target. 19-bit immediate. The low two bits of the target
873 // offset are implied zero and so are not part of the immediate.
874 def PCRelLabel19Operand : AsmOperandClass {
875   let Name = "PCRelLabel19";
876 }
877 def am_brcond : Operand<OtherVT> {
878   let EncoderMethod = "getCondBranchTargetOpValue";
879   let DecoderMethod = "DecodePCRelLabel19";
880   let PrintMethod = "printAlignedLabel";
881   let ParserMatchClass = PCRelLabel19Operand;
882 }
883
884 class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
885                      "b", "$cond\t$target", "",
886                      [(ARM64brcond bb:$target, imm:$cond, NZCV)]>,
887                    Sched<[WriteBr]> {
888   let isBranch = 1;
889   let isTerminator = 1;
890   let Uses = [NZCV];
891
892   bits<4> cond;
893   bits<19> target;
894   let Inst{31-24} = 0b01010100;
895   let Inst{23-5} = target;
896   let Inst{4} = 0;
897   let Inst{3-0} = cond;
898 }
899
900 //---
901 // Compare-and-branch instructions.
902 //---
903 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
904     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
905          asm, "\t$Rt, $target", "",
906          [(node regtype:$Rt, bb:$target)]>,
907       Sched<[WriteBr]> {
908   let isBranch = 1;
909   let isTerminator = 1;
910
911   bits<5> Rt;
912   bits<19> target;
913   let Inst{30-25} = 0b011010;
914   let Inst{24}    = op;
915   let Inst{23-5}  = target;
916   let Inst{4-0}   = Rt;
917 }
918
919 multiclass CmpBranch<bit op, string asm, SDNode node> {
920   def W : BaseCmpBranch<GPR32, op, asm, node> {
921     let Inst{31} = 0;
922   }
923   def X : BaseCmpBranch<GPR64, op, asm, node> {
924     let Inst{31} = 1;
925   }
926 }
927
928 //---
929 // Test-bit-and-branch instructions.
930 //---
931 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
932 // the target offset are implied zero and so are not part of the immediate.
933 def BranchTarget14Operand : AsmOperandClass {
934   let Name = "BranchTarget14";
935 }
936 def am_tbrcond : Operand<OtherVT> {
937   let EncoderMethod = "getTestBranchTargetOpValue";
938   let PrintMethod = "printAlignedLabel";
939   let ParserMatchClass = BranchTarget14Operand;
940 }
941
942 class TestBranch<bit op, string asm, SDNode node>
943     : I<(outs), (ins GPR64:$Rt, imm0_63:$bit_off, am_tbrcond:$target),
944        asm, "\t$Rt, $bit_off, $target", "",
945        [(node GPR64:$Rt, imm0_63:$bit_off, bb:$target)]>,
946       Sched<[WriteBr]> {
947   let isBranch = 1;
948   let isTerminator = 1;
949
950   bits<5> Rt;
951   bits<6> bit_off;
952   bits<14> target;
953
954   let Inst{31}    = bit_off{5};
955   let Inst{30-25} = 0b011011;
956   let Inst{24}    = op;
957   let Inst{23-19} = bit_off{4-0};
958   let Inst{18-5}  = target;
959   let Inst{4-0}   = Rt;
960
961   let DecoderMethod = "DecodeTestAndBranch";
962 }
963
964 //---
965 // Unconditional branch (immediate) instructions.
966 //---
967 def BranchTarget26Operand : AsmOperandClass {
968   let Name = "BranchTarget26";
969 }
970 def am_b_target : Operand<OtherVT> {
971   let EncoderMethod = "getBranchTargetOpValue";
972   let PrintMethod = "printAlignedLabel";
973   let ParserMatchClass = BranchTarget26Operand;
974 }
975 def am_bl_target : Operand<i64> {
976   let EncoderMethod = "getBranchTargetOpValue";
977   let PrintMethod = "printAlignedLabel";
978   let ParserMatchClass = BranchTarget26Operand;
979 }
980
981 class BImm<bit op, dag iops, string asm, list<dag> pattern>
982     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
983   bits<26> addr;
984   let Inst{31}    = op;
985   let Inst{30-26} = 0b00101;
986   let Inst{25-0}  = addr;
987
988   let DecoderMethod = "DecodeUnconditionalBranch";
989 }
990
991 class BranchImm<bit op, string asm, list<dag> pattern>
992     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
993 class CallImm<bit op, string asm, list<dag> pattern>
994     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
995
996 //---
997 // Basic one-operand data processing instructions.
998 //---
999
1000 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1001 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1002                          SDPatternOperator node>
1003   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1004       [(set regtype:$Rd, (node regtype:$Rn))]>,
1005     Sched<[WriteI]> {
1006   bits<5> Rd;
1007   bits<5> Rn;
1008
1009   let Inst{30-13} = 0b101101011000000000;
1010   let Inst{12-10} = opc;
1011   let Inst{9-5}   = Rn;
1012   let Inst{4-0}   = Rd;
1013 }
1014
1015 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1016 multiclass OneOperandData<bits<3> opc, string asm,
1017                           SDPatternOperator node = null_frag> {
1018   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1019     let Inst{31} = 0;
1020   }
1021
1022   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1023     let Inst{31} = 1;
1024   }
1025 }
1026
1027 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1028     : BaseOneOperandData<opc, GPR32, asm, node> {
1029   let Inst{31} = 0;
1030 }
1031
1032 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1033     : BaseOneOperandData<opc, GPR64, asm, node> {
1034   let Inst{31} = 1;
1035 }
1036
1037 //---
1038 // Basic two-operand data processing instructions.
1039 //---
1040 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1041                           list<dag> pattern>
1042     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1043         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1044       Sched<[WriteI]> {
1045   let Uses = [NZCV];
1046   bits<5> Rd;
1047   bits<5> Rn;
1048   bits<5> Rm;
1049   let Inst{30}    = isSub;
1050   let Inst{28-21} = 0b11010000;
1051   let Inst{20-16} = Rm;
1052   let Inst{15-10} = 0;
1053   let Inst{9-5}   = Rn;
1054   let Inst{4-0}   = Rd;
1055 }
1056
1057 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1058                       SDNode OpNode>
1059     : BaseBaseAddSubCarry<isSub, regtype, asm,
1060         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1061
1062 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1063                               SDNode OpNode>
1064     : BaseBaseAddSubCarry<isSub, regtype, asm,
1065         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1066          (implicit NZCV)]> {
1067   let Defs = [NZCV];
1068 }
1069
1070 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1071                        SDNode OpNode, SDNode OpNode_setflags> {
1072   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1073     let Inst{31} = 0;
1074     let Inst{29} = 0;
1075   }
1076   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1077     let Inst{31} = 1;
1078     let Inst{29} = 0;
1079   }
1080
1081   // Sets flags.
1082   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1083                                     OpNode_setflags> {
1084     let Inst{31} = 0;
1085     let Inst{29} = 1;
1086   }
1087   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1088                                     OpNode_setflags> {
1089     let Inst{31} = 1;
1090     let Inst{29} = 1;
1091   }
1092 }
1093
1094 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1095                      SDPatternOperator OpNode>
1096   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1097       asm, "\t$Rd, $Rn, $Rm", "",
1098       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1099   bits<5> Rd;
1100   bits<5> Rn;
1101   bits<5> Rm;
1102   let Inst{30-21} = 0b0011010110;
1103   let Inst{20-16} = Rm;
1104   let Inst{15-14} = 0b00;
1105   let Inst{13-10} = opc;
1106   let Inst{9-5}   = Rn;
1107   let Inst{4-0}   = Rd;
1108 }
1109
1110 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1111               SDPatternOperator OpNode>
1112     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1113   let Inst{10}    = isSigned;
1114 }
1115
1116 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1117   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1118            Sched<[WriteID32]> {
1119     let Inst{31} = 0;
1120   }
1121   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1122            Sched<[WriteID64]> {
1123     let Inst{31} = 1;
1124   }
1125 }
1126
1127 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1128                 SDPatternOperator OpNode = null_frag>
1129   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1130     Sched<[WriteIS]> {
1131   let Inst{11-10} = shift_type;
1132 }
1133
1134 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1135   def Wr : BaseShift<shift_type, GPR32, asm> {
1136     let Inst{31} = 0;
1137   }
1138
1139   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1140     let Inst{31} = 1;
1141   }
1142
1143   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1144             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1145                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1146
1147   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1148             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1149
1150   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1151             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1152
1153   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1154             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1155 }
1156
1157 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1158     : InstAlias<asm#" $dst, $src1, $src2",
1159                 (inst regtype:$dst, regtype:$src1, regtype:$src2)>;
1160
1161 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1162                        RegisterClass addtype, string asm,
1163                        list<dag> pattern>
1164   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1165       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1166   bits<5> Rd;
1167   bits<5> Rn;
1168   bits<5> Rm;
1169   bits<5> Ra;
1170   let Inst{30-24} = 0b0011011;
1171   let Inst{23-21} = opc;
1172   let Inst{20-16} = Rm;
1173   let Inst{15}    = isSub;
1174   let Inst{14-10} = Ra;
1175   let Inst{9-5}   = Rn;
1176   let Inst{4-0}   = Rd;
1177 }
1178
1179 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1180   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1181       [(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))]>,
1182       Sched<[WriteIM32]> {
1183     let Inst{31} = 0;
1184   }
1185
1186   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1187       [(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))]>,
1188       Sched<[WriteIM64]> {
1189     let Inst{31} = 1;
1190   }
1191 }
1192
1193 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1194                    SDNode AccNode, SDNode ExtNode>
1195   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1196     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1197                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1198     Sched<[WriteIM32]> {
1199   let Inst{31} = 1;
1200 }
1201
1202 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1203   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1204       asm, "\t$Rd, $Rn, $Rm", "",
1205       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1206     Sched<[WriteIM64]> {
1207   bits<5> Rd;
1208   bits<5> Rn;
1209   bits<5> Rm;
1210   let Inst{31-24} = 0b10011011;
1211   let Inst{23-21} = opc;
1212   let Inst{20-16} = Rm;
1213   let Inst{15}    = 0;
1214   let Inst{9-5}   = Rn;
1215   let Inst{4-0}   = Rd;
1216
1217   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1218   // (i.e. all bits 1) but is ignored by the processor.
1219   let PostEncoderMethod = "fixMulHigh";
1220 }
1221
1222 class MulAccumWAlias<string asm, Instruction inst>
1223     : InstAlias<asm#" $dst, $src1, $src2",
1224                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1225 class MulAccumXAlias<string asm, Instruction inst>
1226     : InstAlias<asm#" $dst, $src1, $src2",
1227                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1228 class WideMulAccumAlias<string asm, Instruction inst>
1229     : InstAlias<asm#" $dst, $src1, $src2",
1230                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1231
1232 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1233               SDPatternOperator OpNode, string asm>
1234   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1235       asm, "\t$Rd, $Rn, $Rm", "",
1236       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1237     Sched<[WriteISReg]> {
1238   bits<5> Rd;
1239   bits<5> Rn;
1240   bits<5> Rm;
1241
1242   let Inst{31} = sf;
1243   let Inst{30-21} = 0b0011010110;
1244   let Inst{20-16} = Rm;
1245   let Inst{15-13} = 0b010;
1246   let Inst{12} = C;
1247   let Inst{11-10} = sz;
1248   let Inst{9-5} = Rn;
1249   let Inst{4-0} = Rd;
1250   let Predicates = [HasCRC];
1251 }
1252
1253 //---
1254 // Address generation.
1255 //---
1256
1257 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1258     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1259         pattern>,
1260       Sched<[WriteI]> {
1261   bits<5>  Xd;
1262   bits<21> label;
1263   let Inst{31}    = page;
1264   let Inst{30-29} = label{1-0};
1265   let Inst{28-24} = 0b10000;
1266   let Inst{23-5}  = label{20-2};
1267   let Inst{4-0}   = Xd;
1268
1269   let DecoderMethod = "DecodeAdrInstruction";
1270 }
1271
1272 //---
1273 // Move immediate.
1274 //---
1275
1276 def movimm32_imm : Operand<i32> {
1277   let ParserMatchClass = Imm0_65535Operand;
1278   let EncoderMethod = "getMoveWideImmOpValue";
1279   let PrintMethod = "printHexImm";
1280 }
1281 def movimm32_shift : Operand<i32> {
1282   let PrintMethod = "printShifter";
1283   let ParserMatchClass = MovImm32ShifterOperand;
1284 }
1285 def movimm64_shift : Operand<i32> {
1286   let PrintMethod = "printShifter";
1287   let ParserMatchClass = MovImm64ShifterOperand;
1288 }
1289 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1290 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1291                         string asm>
1292   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1293        asm, "\t$Rd, $imm$shift", "", []>,
1294     Sched<[WriteImm]> {
1295   bits<5> Rd;
1296   bits<16> imm;
1297   bits<6> shift;
1298   let Inst{30-29} = opc;
1299   let Inst{28-23} = 0b100101;
1300   let Inst{22-21} = shift{5-4};
1301   let Inst{20-5}  = imm;
1302   let Inst{4-0}   = Rd;
1303
1304   let DecoderMethod = "DecodeMoveImmInstruction";
1305 }
1306
1307 multiclass MoveImmediate<bits<2> opc, string asm> {
1308   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1309     let Inst{31} = 0;
1310   }
1311
1312   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1313     let Inst{31} = 1;
1314   }
1315 }
1316
1317 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1318 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1319                           string asm>
1320   : I<(outs regtype:$Rd),
1321       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1322        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1323     Sched<[WriteI]> {
1324   bits<5> Rd;
1325   bits<16> imm;
1326   bits<6> shift;
1327   let Inst{30-29} = opc;
1328   let Inst{28-23} = 0b100101;
1329   let Inst{22-21} = shift{5-4};
1330   let Inst{20-5}  = imm;
1331   let Inst{4-0}   = Rd;
1332
1333   let DecoderMethod = "DecodeMoveImmInstruction";
1334 }
1335
1336 multiclass InsertImmediate<bits<2> opc, string asm> {
1337   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1338     let Inst{31} = 0;
1339   }
1340
1341   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1342     let Inst{31} = 1;
1343   }
1344 }
1345
1346 //---
1347 // Add/Subtract
1348 //---
1349
1350 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1351                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1352                     string asm, SDPatternOperator OpNode>
1353     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1354         asm, "\t$Rd, $Rn, $imm", "",
1355         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1356       Sched<[WriteI]>  {
1357   bits<5>  Rd;
1358   bits<5>  Rn;
1359   bits<14> imm;
1360   let Inst{30}    = isSub;
1361   let Inst{29}    = setFlags;
1362   let Inst{28-24} = 0b10001;
1363   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1364   let Inst{21-10} = imm{11-0};
1365   let Inst{9-5}   = Rn;
1366   let Inst{4-0}   = Rd;
1367   let DecoderMethod = "DecodeBaseAddSubImm";
1368 }
1369
1370 class BaseAddSubRegPseudo<RegisterClass regtype,
1371                           SDPatternOperator OpNode>
1372     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1373              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1374       Sched<[WriteI]>;
1375
1376 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1377                      arith_shifted_reg shifted_regtype, string asm,
1378                      SDPatternOperator OpNode>
1379     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1380         asm, "\t$Rd, $Rn, $Rm", "",
1381         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1382       Sched<[WriteISReg]> {
1383   // The operands are in order to match the 'addr' MI operands, so we
1384   // don't need an encoder method and by-name matching. Just use the default
1385   // in-order handling. Since we're using by-order, make sure the names
1386   // do not match.
1387   bits<5> dst;
1388   bits<5> src1;
1389   bits<5> src2;
1390   bits<8> shift;
1391   let Inst{30}    = isSub;
1392   let Inst{29}    = setFlags;
1393   let Inst{28-24} = 0b01011;
1394   let Inst{23-22} = shift{7-6};
1395   let Inst{21}    = 0;
1396   let Inst{20-16} = src2;
1397   let Inst{15-10} = shift{5-0};
1398   let Inst{9-5}   = src1;
1399   let Inst{4-0}   = dst;
1400
1401   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1402 }
1403
1404 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1405                      RegisterClass src1Regtype, Operand src2Regtype,
1406                      string asm, SDPatternOperator OpNode>
1407     : I<(outs dstRegtype:$R1),
1408         (ins src1Regtype:$R2, src2Regtype:$R3),
1409         asm, "\t$R1, $R2, $R3", "",
1410         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1411       Sched<[WriteIEReg]> {
1412   bits<5> Rd;
1413   bits<5> Rn;
1414   bits<5> Rm;
1415   bits<6> ext;
1416   let Inst{30}    = isSub;
1417   let Inst{29}    = setFlags;
1418   let Inst{28-24} = 0b01011;
1419   let Inst{23-21} = 0b001;
1420   let Inst{20-16} = Rm;
1421   let Inst{15-13} = ext{5-3};
1422   let Inst{12-10} = ext{2-0};
1423   let Inst{9-5}   = Rn;
1424   let Inst{4-0}   = Rd;
1425
1426   let DecoderMethod = "DecodeAddSubERegInstruction";
1427 }
1428
1429 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1430 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1431                        RegisterClass src1Regtype, RegisterClass src2Regtype,
1432                        Operand ext_op, string asm>
1433     : I<(outs dstRegtype:$Rd),
1434         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1435         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1436       Sched<[WriteIEReg]> {
1437   bits<5> Rd;
1438   bits<5> Rn;
1439   bits<5> Rm;
1440   bits<6> ext;
1441   let Inst{30}    = isSub;
1442   let Inst{29}    = setFlags;
1443   let Inst{28-24} = 0b01011;
1444   let Inst{23-21} = 0b001;
1445   let Inst{20-16} = Rm;
1446   let Inst{15}    = ext{5};
1447   let Inst{12-10} = ext{2-0};
1448   let Inst{9-5}   = Rn;
1449   let Inst{4-0}   = Rd;
1450
1451   let DecoderMethod = "DecodeAddSubERegInstruction";
1452 }
1453
1454 // Aliases for register+register add/subtract.
1455 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1456                      RegisterClass src1Regtype, RegisterClass src2Regtype,
1457                      int shiftExt>
1458     : InstAlias<asm#" $dst, $src1, $src2",
1459                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1460                       shiftExt)>;
1461
1462 multiclass AddSub<bit isSub, string mnemonic,
1463                   SDPatternOperator OpNode = null_frag> {
1464   let hasSideEffects = 0 in {
1465   // Add/Subtract immediate
1466   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1467                            mnemonic, OpNode> {
1468     let Inst{31} = 0;
1469   }
1470   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1471                            mnemonic, OpNode> {
1472     let Inst{31} = 1;
1473   }
1474
1475   // Add/Subtract register - Only used for CodeGen
1476   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1477   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1478
1479   // Add/Subtract shifted register
1480   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1481                            OpNode> {
1482     let Inst{31} = 0;
1483   }
1484   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1485                            OpNode> {
1486     let Inst{31} = 1;
1487   }
1488   }
1489
1490   // Add/Subtract extended register
1491   let AddedComplexity = 1, hasSideEffects = 0 in {
1492   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1493                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1494     let Inst{31} = 0;
1495   }
1496   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1497                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1498     let Inst{31} = 1;
1499   }
1500   }
1501
1502   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1503                                arith_extendlsl64, mnemonic> {
1504     // UXTX and SXTX only.
1505     let Inst{14-13} = 0b11;
1506     let Inst{31} = 1;
1507   }
1508
1509   // Register/register aliases with no shift when SP is not used.
1510   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1511                        GPR32, GPR32, GPR32, 0>;
1512   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1513                        GPR64, GPR64, GPR64, 0>;
1514
1515   // Register/register aliases with no shift when either the destination or
1516   // first source register is SP.  This relies on the shifted register aliases
1517   // above matching first in the case when SP is not used.
1518   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1519                        GPR32sp, GPR32sp, GPR32, 16>; // UXTW #0
1520   def : AddSubRegAlias<mnemonic,
1521                        !cast<Instruction>(NAME#"Xrx64"),
1522                        GPR64sp, GPR64sp, GPR64, 24>; // UXTX #0
1523 }
1524
1525 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode> {
1526   let isCompare = 1, Defs = [NZCV] in {
1527   // Add/Subtract immediate
1528   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1529                            mnemonic, OpNode> {
1530     let Inst{31} = 0;
1531   }
1532   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1533                            mnemonic, OpNode> {
1534     let Inst{31} = 1;
1535   }
1536
1537   // Add/Subtract register
1538   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1539   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1540
1541   // Add/Subtract shifted register
1542   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1543                            OpNode> {
1544     let Inst{31} = 0;
1545   }
1546   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1547                            OpNode> {
1548     let Inst{31} = 1;
1549   }
1550
1551   // Add/Subtract extended register
1552   let AddedComplexity = 1 in {
1553   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1554                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1555     let Inst{31} = 0;
1556   }
1557   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1558                            arith_extended_reg32<i64>, mnemonic, OpNode> {
1559     let Inst{31} = 1;
1560   }
1561   }
1562
1563   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1564                                arith_extendlsl64, mnemonic> {
1565     // UXTX and SXTX only.
1566     let Inst{14-13} = 0b11;
1567     let Inst{31} = 1;
1568   }
1569   } // Defs = [NZCV]
1570
1571   // Register/register aliases with no shift when SP is not used.
1572   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1573                        GPR32, GPR32, GPR32, 0>;
1574   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1575                        GPR64, GPR64, GPR64, 0>;
1576
1577   // Register/register aliases with no shift when the first source register
1578   // is SP.  This relies on the shifted register aliases above matching first
1579   // in the case when SP is not used.
1580   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1581                        GPR32, GPR32sp, GPR32, 16>; // UXTW #0
1582   def : AddSubRegAlias<mnemonic,
1583                        !cast<Instruction>(NAME#"Xrx64"),
1584                        GPR64, GPR64sp, GPR64, 24>; // UXTX #0
1585 }
1586
1587 //---
1588 // Extract
1589 //---
1590 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1591                                       SDTCisPtrTy<3>]>;
1592 def ARM64Extr : SDNode<"ARM64ISD::EXTR", SDTA64EXTR>;
1593
1594 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1595                      list<dag> patterns>
1596     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1597          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1598       Sched<[WriteExtr, ReadExtrHi]> {
1599   bits<5> Rd;
1600   bits<5> Rn;
1601   bits<5> Rm;
1602   bits<6> imm;
1603
1604   let Inst{30-23} = 0b00100111;
1605   let Inst{21}    = 0;
1606   let Inst{20-16} = Rm;
1607   let Inst{15-10} = imm;
1608   let Inst{9-5}   = Rn;
1609   let Inst{4-0}   = Rd;
1610 }
1611
1612 multiclass ExtractImm<string asm> {
1613   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1614                       [(set GPR32:$Rd,
1615                         (ARM64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1616     let Inst{31} = 0;
1617     let Inst{22} = 0;
1618     // imm<5> must be zero.
1619     let imm{5}   = 0;
1620   }
1621   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1622                       [(set GPR64:$Rd,
1623                         (ARM64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1624
1625     let Inst{31} = 1;
1626     let Inst{22} = 1;
1627   }
1628 }
1629
1630 //---
1631 // Bitfield
1632 //---
1633
1634 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1635 class BaseBitfieldImm<bits<2> opc,
1636                       RegisterClass regtype, Operand imm_type, string asm>
1637     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1638          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1639       Sched<[WriteIS]> {
1640   bits<5> Rd;
1641   bits<5> Rn;
1642   bits<6> immr;
1643   bits<6> imms;
1644
1645   let Inst{30-29} = opc;
1646   let Inst{28-23} = 0b100110;
1647   let Inst{21-16} = immr;
1648   let Inst{15-10} = imms;
1649   let Inst{9-5}   = Rn;
1650   let Inst{4-0}   = Rd;
1651 }
1652
1653 multiclass BitfieldImm<bits<2> opc, string asm> {
1654   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1655     let Inst{31} = 0;
1656     let Inst{22} = 0;
1657     // imms<5> and immr<5> must be zero, else ReservedValue().
1658     let Inst{21} = 0;
1659     let Inst{15} = 0;
1660   }
1661   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1662     let Inst{31} = 1;
1663     let Inst{22} = 1;
1664   }
1665 }
1666
1667 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1668 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1669                       RegisterClass regtype, Operand imm_type, string asm>
1670     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1671                              imm_type:$imms),
1672          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1673       Sched<[WriteIS]> {
1674   bits<5> Rd;
1675   bits<5> Rn;
1676   bits<6> immr;
1677   bits<6> imms;
1678
1679   let Inst{30-29} = opc;
1680   let Inst{28-23} = 0b100110;
1681   let Inst{21-16} = immr;
1682   let Inst{15-10} = imms;
1683   let Inst{9-5}   = Rn;
1684   let Inst{4-0}   = Rd;
1685 }
1686
1687 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1688   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1689     let Inst{31} = 0;
1690     let Inst{22} = 0;
1691     // imms<5> and immr<5> must be zero, else ReservedValue().
1692     let Inst{21} = 0;
1693     let Inst{15} = 0;
1694   }
1695   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1696     let Inst{31} = 1;
1697     let Inst{22} = 1;
1698   }
1699 }
1700
1701 //---
1702 // Logical
1703 //---
1704
1705 // Logical (immediate)
1706 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1707                      RegisterClass sregtype, Operand imm_type, string asm,
1708                      list<dag> pattern>
1709     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1710          asm, "\t$Rd, $Rn, $imm", "", pattern>,
1711       Sched<[WriteI]> {
1712   bits<5>  Rd;
1713   bits<5>  Rn;
1714   bits<13> imm;
1715   let Inst{30-29} = opc;
1716   let Inst{28-23} = 0b100100;
1717   let Inst{22}    = imm{12};
1718   let Inst{21-16} = imm{11-6};
1719   let Inst{15-10} = imm{5-0};
1720   let Inst{9-5}   = Rn;
1721   let Inst{4-0}   = Rd;
1722
1723   let DecoderMethod = "DecodeLogicalImmInstruction";
1724 }
1725
1726 // Logical (shifted register)
1727 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1728                       logical_shifted_reg shifted_regtype, string asm,
1729                       list<dag> pattern>
1730     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1731         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1732       Sched<[WriteISReg]> {
1733   // The operands are in order to match the 'addr' MI operands, so we
1734   // don't need an encoder method and by-name matching. Just use the default
1735   // in-order handling. Since we're using by-order, make sure the names
1736   // do not match.
1737   bits<5> dst;
1738   bits<5> src1;
1739   bits<5> src2;
1740   bits<8> shift;
1741   let Inst{30-29} = opc;
1742   let Inst{28-24} = 0b01010;
1743   let Inst{23-22} = shift{7-6};
1744   let Inst{21}    = N;
1745   let Inst{20-16} = src2;
1746   let Inst{15-10} = shift{5-0};
1747   let Inst{9-5}   = src1;
1748   let Inst{4-0}   = dst;
1749
1750   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1751 }
1752
1753 // Aliases for register+register logical instructions.
1754 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1755     : InstAlias<asm#" $dst, $src1, $src2",
1756                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1757
1758 let AddedComplexity = 6 in
1759 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
1760   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1761                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1762                                                logical_imm32:$imm))]> {
1763     let Inst{31} = 0;
1764     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1765   }
1766   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1767                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1768                                                logical_imm64:$imm))]> {
1769     let Inst{31} = 1;
1770   }
1771 }
1772
1773 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
1774   let isCompare = 1, Defs = [NZCV] in {
1775   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
1776       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
1777     let Inst{31} = 0;
1778     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1779   }
1780   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
1781       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
1782     let Inst{31} = 1;
1783   }
1784   } // end Defs = [NZCV]
1785 }
1786
1787 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
1788     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1789              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1790       Sched<[WriteI]>;
1791
1792 // Split from LogicalImm as not all instructions have both.
1793 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
1794                       SDPatternOperator OpNode> {
1795   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1796   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1797
1798   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1799                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
1800                                                  logical_shifted_reg32:$Rm))]> {
1801     let Inst{31} = 0;
1802   }
1803   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1804                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
1805                                                  logical_shifted_reg64:$Rm))]> {
1806     let Inst{31} = 1;
1807   }
1808
1809   def : LogicalRegAlias<mnemonic,
1810                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
1811   def : LogicalRegAlias<mnemonic,
1812                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
1813 }
1814
1815 // Split from LogicalReg to allow setting NZCV Defs
1816 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
1817                        SDPatternOperator OpNode = null_frag> {
1818   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
1819   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1820   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1821
1822   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1823             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
1824     let Inst{31} = 0;
1825   }
1826   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1827             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
1828     let Inst{31} = 1;
1829   }
1830   } // Defs = [NZCV]
1831
1832   def : LogicalRegAlias<mnemonic,
1833                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
1834   def : LogicalRegAlias<mnemonic,
1835                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
1836 }
1837
1838 //---
1839 // Conditionally set flags
1840 //---
1841
1842 // Condition code.
1843 // 4-bit immediate. Pretty-printed as <cc>
1844 def ccode : Operand<i32> {
1845   let PrintMethod = "printCondCode";
1846 }
1847
1848 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1849 class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
1850     : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
1851          asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
1852       Sched<[WriteI]> {
1853   let Uses = [NZCV];
1854   let Defs = [NZCV];
1855
1856   bits<5> Rn;
1857   bits<5> imm;
1858   bits<4> nzcv;
1859   bits<4> cond;
1860
1861   let Inst{30}    = op;
1862   let Inst{29-21} = 0b111010010;
1863   let Inst{20-16} = imm;
1864   let Inst{15-12} = cond;
1865   let Inst{11-10} = 0b10;
1866   let Inst{9-5}   = Rn;
1867   let Inst{4}     = 0b0;
1868   let Inst{3-0}   = nzcv;
1869 }
1870
1871 multiclass CondSetFlagsImm<bit op, string asm> {
1872   def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
1873     let Inst{31} = 0;
1874   }
1875   def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
1876     let Inst{31} = 1;
1877   }
1878 }
1879
1880 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1881 class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
1882     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
1883          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
1884       Sched<[WriteI]> {
1885   let Uses = [NZCV];
1886   let Defs = [NZCV];
1887
1888   bits<5> Rn;
1889   bits<5> Rm;
1890   bits<4> nzcv;
1891   bits<4> cond;
1892
1893   let Inst{30}    = op;
1894   let Inst{29-21} = 0b111010010;
1895   let Inst{20-16} = Rm;
1896   let Inst{15-12} = cond;
1897   let Inst{11-10} = 0b00;
1898   let Inst{9-5}   = Rn;
1899   let Inst{4}     = 0b0;
1900   let Inst{3-0}   = nzcv;
1901 }
1902
1903 multiclass CondSetFlagsReg<bit op, string asm> {
1904   def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
1905     let Inst{31} = 0;
1906   }
1907   def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
1908     let Inst{31} = 1;
1909   }
1910 }
1911
1912 //---
1913 // Conditional select
1914 //---
1915
1916 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
1917     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1918          asm, "\t$Rd, $Rn, $Rm, $cond", "",
1919          [(set regtype:$Rd,
1920                (ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
1921       Sched<[WriteI]> {
1922   let Uses = [NZCV];
1923
1924   bits<5> Rd;
1925   bits<5> Rn;
1926   bits<5> Rm;
1927   bits<4> cond;
1928
1929   let Inst{30}    = op;
1930   let Inst{29-21} = 0b011010100;
1931   let Inst{20-16} = Rm;
1932   let Inst{15-12} = cond;
1933   let Inst{11-10} = op2;
1934   let Inst{9-5}   = Rn;
1935   let Inst{4-0}   = Rd;
1936 }
1937
1938 multiclass CondSelect<bit op, bits<2> op2, string asm> {
1939   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
1940     let Inst{31} = 0;
1941   }
1942   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
1943     let Inst{31} = 1;
1944   }
1945 }
1946
1947 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
1948                        PatFrag frag>
1949     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1950          asm, "\t$Rd, $Rn, $Rm, $cond", "",
1951          [(set regtype:$Rd,
1952                (ARM64csel regtype:$Rn, (frag regtype:$Rm),
1953                (i32 imm:$cond), NZCV))]>,
1954       Sched<[WriteI]> {
1955   let Uses = [NZCV];
1956
1957   bits<5> Rd;
1958   bits<5> Rn;
1959   bits<5> Rm;
1960   bits<4> cond;
1961
1962   let Inst{30}    = op;
1963   let Inst{29-21} = 0b011010100;
1964   let Inst{20-16} = Rm;
1965   let Inst{15-12} = cond;
1966   let Inst{11-10} = op2;
1967   let Inst{9-5}   = Rn;
1968   let Inst{4-0}   = Rd;
1969 }
1970
1971 def inv_cond_XFORM : SDNodeXForm<imm, [{
1972   ARM64CC::CondCode CC = static_cast<ARM64CC::CondCode>(N->getZExtValue());
1973   return CurDAG->getTargetConstant(ARM64CC::getInvertedCondCode(CC), MVT::i32);
1974 }]>;
1975
1976 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
1977   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
1978     let Inst{31} = 0;
1979   }
1980   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
1981     let Inst{31} = 1;
1982   }
1983
1984   def : Pat<(ARM64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
1985             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
1986                                            (inv_cond_XFORM imm:$cond))>;
1987
1988   def : Pat<(ARM64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
1989             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
1990                                            (inv_cond_XFORM imm:$cond))>;
1991 }
1992
1993 //---
1994 // Special Mask Value
1995 //---
1996 def maski8_or_more : Operand<i32>,
1997   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
1998 }
1999 def maski16_or_more : Operand<i32>,
2000   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2001 }
2002
2003
2004 //---
2005 // Load/store
2006 //---
2007
2008 // (unsigned immediate)
2009 // Indexed for 8-bit registers. offset is in range [0,4095].
2010 def MemoryIndexed8Operand : AsmOperandClass {
2011   let Name = "MemoryIndexed8";
2012   let DiagnosticType = "InvalidMemoryIndexed8";
2013 }
2014 def am_indexed8 : Operand<i64>,
2015                   ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []> {
2016   let PrintMethod = "printAMIndexed<8>";
2017   let EncoderMethod
2018       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale1>";
2019   let ParserMatchClass = MemoryIndexed8Operand;
2020   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2021 }
2022
2023 // Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190],
2024 // stored as immval/2 (the 12-bit literal that encodes directly into the insn).
2025 def MemoryIndexed16Operand : AsmOperandClass {
2026   let Name = "MemoryIndexed16";
2027   let DiagnosticType = "InvalidMemoryIndexed16";
2028 }
2029 def am_indexed16 : Operand<i64>,
2030                    ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []> {
2031   let PrintMethod = "printAMIndexed<16>";
2032   let EncoderMethod
2033       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale2>";
2034   let ParserMatchClass = MemoryIndexed16Operand;
2035   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2036 }
2037
2038 // Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380],
2039 // stored as immval/4 (the 12-bit literal that encodes directly into the insn).
2040 def MemoryIndexed32Operand : AsmOperandClass {
2041   let Name = "MemoryIndexed32";
2042   let DiagnosticType = "InvalidMemoryIndexed32";
2043 }
2044 def am_indexed32 : Operand<i64>,
2045                    ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []> {
2046   let PrintMethod = "printAMIndexed<32>";
2047   let EncoderMethod
2048       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale4>";
2049   let ParserMatchClass = MemoryIndexed32Operand;
2050   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2051 }
2052
2053 // Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760],
2054 // stored as immval/8 (the 12-bit literal that encodes directly into the insn).
2055 def MemoryIndexed64Operand : AsmOperandClass {
2056   let Name = "MemoryIndexed64";
2057   let DiagnosticType = "InvalidMemoryIndexed64";
2058 }
2059 def am_indexed64 : Operand<i64>,
2060                    ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []> {
2061   let PrintMethod = "printAMIndexed<64>";
2062   let EncoderMethod
2063       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale8>";
2064   let ParserMatchClass = MemoryIndexed64Operand;
2065   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2066 }
2067
2068 // Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520],
2069 // stored as immval/16 (the 12-bit literal that encodes directly into the insn).
2070 def MemoryIndexed128Operand : AsmOperandClass {
2071   let Name = "MemoryIndexed128";
2072   let DiagnosticType = "InvalidMemoryIndexed128";
2073 }
2074 def am_indexed128 : Operand<i64>,
2075                    ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []> {
2076   let PrintMethod = "printAMIndexed<128>";
2077   let EncoderMethod
2078       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale16>";
2079   let ParserMatchClass = MemoryIndexed128Operand;
2080   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2081 }
2082
2083 // No offset.
2084 def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; }
2085 def am_noindex : Operand<i64>,
2086                  ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
2087   let PrintMethod = "printAMNoIndex";
2088   let ParserMatchClass = MemoryNoIndexOperand;
2089   let MIOperandInfo = (ops GPR64sp:$base);
2090 }
2091
2092 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2093                       string asm, list<dag> pattern>
2094     : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2095   bits<5> dst;
2096
2097   bits<17> addr;
2098   bits<5> base = addr{4-0};
2099   bits<12> offset = addr{16-5};
2100
2101   let Inst{31-30} = sz;
2102   let Inst{29-27} = 0b111;
2103   let Inst{26}    = V;
2104   let Inst{25-24} = 0b01;
2105   let Inst{23-22} = opc;
2106   let Inst{21-10} = offset;
2107   let Inst{9-5}   = base;
2108   let Inst{4-0}   = dst;
2109
2110   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2111 }
2112
2113 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2114 class LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2115              Operand indextype, string asm, list<dag> pattern>
2116     : BaseLoadStoreUI<sz, V, opc,
2117                       (outs regtype:$Rt), (ins indextype:$addr), asm, pattern>,
2118       Sched<[WriteLD]>;
2119
2120 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2121 class StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2122              Operand indextype, string asm, list<dag> pattern>
2123     : BaseLoadStoreUI<sz, V, opc,
2124                       (outs), (ins regtype:$Rt, indextype:$addr), asm, pattern>,
2125       Sched<[WriteST]>;
2126
2127 def PrefetchOperand : AsmOperandClass {
2128   let Name = "Prefetch";
2129   let ParserMethod = "tryParsePrefetch";
2130 }
2131 def prfop : Operand<i32> {
2132   let PrintMethod = "printPrefetchOp";
2133   let ParserMatchClass = PrefetchOperand;
2134 }
2135
2136 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2137 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2138     : BaseLoadStoreUI<sz, V, opc,
2139                       (outs), (ins prfop:$Rt, am_indexed64:$addr), asm, pat>,
2140       Sched<[WriteLD]>;
2141
2142 //---
2143 // Load literal
2144 //---
2145
2146 // Load literal address: 19-bit immediate. The low two bits of the target
2147 // offset are implied zero and so are not part of the immediate.
2148 def am_ldrlit : Operand<OtherVT> {
2149   let EncoderMethod = "getLoadLiteralOpValue";
2150   let DecoderMethod = "DecodePCRelLabel19";
2151   let PrintMethod = "printAlignedLabel";
2152   let ParserMatchClass = PCRelLabel19Operand;
2153 }
2154
2155 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2156 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2157     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2158         asm, "\t$Rt, $label", "", []>,
2159       Sched<[WriteLD]> {
2160   bits<5> Rt;
2161   bits<19> label;
2162   let Inst{31-30} = opc;
2163   let Inst{29-27} = 0b011;
2164   let Inst{26}    = V;
2165   let Inst{25-24} = 0b00;
2166   let Inst{23-5}  = label;
2167   let Inst{4-0}   = Rt;
2168 }
2169
2170 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2171 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2172     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2173         asm, "\t$Rt, $label", "", pat>,
2174       Sched<[WriteLD]> {
2175   bits<5> Rt;
2176   bits<19> label;
2177   let Inst{31-30} = opc;
2178   let Inst{29-27} = 0b011;
2179   let Inst{26}    = V;
2180   let Inst{25-24} = 0b00;
2181   let Inst{23-5}  = label;
2182   let Inst{4-0}   = Rt;
2183 }
2184
2185 //---
2186 // Load/store register offset
2187 //---
2188
2189 class MemROAsmOperand<int sz> : AsmOperandClass {
2190   let Name = "MemoryRegisterOffset"#sz;
2191 }
2192
2193 def MemROAsmOperand8 : MemROAsmOperand<8>;
2194 def MemROAsmOperand16 : MemROAsmOperand<16>;
2195 def MemROAsmOperand32 : MemROAsmOperand<32>;
2196 def MemROAsmOperand64 : MemROAsmOperand<64>;
2197 def MemROAsmOperand128 : MemROAsmOperand<128>;
2198
2199 class ro_indexed<int sz> : Operand<i64> { // ComplexPattern<...>
2200   let PrintMethod = "printMemoryRegOffset<" # sz # ">";
2201   let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend);
2202 }
2203
2204 def ro_indexed8 : ro_indexed<8>, ComplexPattern<i64, 3, "SelectAddrModeRO8", []> {
2205   let ParserMatchClass = MemROAsmOperand8;
2206 }
2207
2208 def ro_indexed16 : ro_indexed<16>, ComplexPattern<i64, 3, "SelectAddrModeRO16", []> {
2209   let ParserMatchClass = MemROAsmOperand16;
2210 }
2211
2212 def ro_indexed32 : ro_indexed<32>, ComplexPattern<i64, 3, "SelectAddrModeRO32", []> {
2213   let ParserMatchClass = MemROAsmOperand32;
2214 }
2215
2216 def ro_indexed64 : ro_indexed<64>, ComplexPattern<i64, 3, "SelectAddrModeRO64", []> {
2217   let ParserMatchClass = MemROAsmOperand64;
2218 }
2219
2220 def ro_indexed128 : ro_indexed<128>, ComplexPattern<i64, 3, "SelectAddrModeRO128", []> {
2221   let ParserMatchClass = MemROAsmOperand128;
2222 }
2223
2224 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2225                       string asm, dag ins, dag outs, list<dag> pat>
2226     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2227   // The operands are in order to match the 'addr' MI operands, so we
2228   // don't need an encoder method and by-name matching. Just use the default
2229   // in-order handling. Since we're using by-order, make sure the names
2230   // do not match.
2231   bits<5> dst;
2232   bits<5> base;
2233   bits<5> offset;
2234   bits<4> extend;
2235   let Inst{31-30} = sz;
2236   let Inst{29-27} = 0b111;
2237   let Inst{26}    = V;
2238   let Inst{25-24} = 0b00;
2239   let Inst{23-22} = opc;
2240   let Inst{21}    = 1;
2241   let Inst{20-16} = offset;
2242   let Inst{15-13} = extend{3-1};
2243
2244   let Inst{12}    = extend{0};
2245   let Inst{11-10} = 0b10;
2246   let Inst{9-5}   = base;
2247   let Inst{4-0}   = dst;
2248
2249   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2250 }
2251
2252 class Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2253              string asm, list<dag> pat>
2254   : LoadStore8RO<sz, V, opc, regtype, asm,
2255                  (outs regtype:$Rt), (ins ro_indexed8:$addr), pat>,
2256     Sched<[WriteLDIdx, ReadAdrBase]>;
2257
2258 class Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2259              string asm, list<dag> pat>
2260   : LoadStore8RO<sz, V, opc, regtype, asm,
2261                  (outs), (ins regtype:$Rt, ro_indexed8:$addr), pat>,
2262     Sched<[WriteSTIdx, ReadAdrBase]>;
2263
2264 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2265                       string asm, dag ins, dag outs, list<dag> pat>
2266     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2267   // The operands are in order to match the 'addr' MI operands, so we
2268   // don't need an encoder method and by-name matching. Just use the default
2269   // in-order handling. Since we're using by-order, make sure the names
2270   // do not match.
2271   bits<5> dst;
2272   bits<5> base;
2273   bits<5> offset;
2274   bits<4> extend;
2275   let Inst{31-30} = sz;
2276   let Inst{29-27} = 0b111;
2277   let Inst{26}    = V;
2278   let Inst{25-24} = 0b00;
2279   let Inst{23-22} = opc;
2280   let Inst{21}    = 1;
2281   let Inst{20-16} = offset;
2282   let Inst{15-13} = extend{3-1};
2283
2284   let Inst{12}    = extend{0};
2285   let Inst{11-10} = 0b10;
2286   let Inst{9-5}   = base;
2287   let Inst{4-0}   = dst;
2288
2289   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2290 }
2291
2292 class Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2293              string asm, list<dag> pat>
2294   : LoadStore16RO<sz, V, opc, regtype, asm,
2295                  (outs regtype:$Rt), (ins ro_indexed16:$addr), pat>,
2296     Sched<[WriteLDIdx, ReadAdrBase]>;
2297
2298 class Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2299              string asm, list<dag> pat>
2300   : LoadStore16RO<sz, V, opc, regtype, asm,
2301                  (outs), (ins regtype:$Rt, ro_indexed16:$addr), pat>,
2302     Sched<[WriteSTIdx, ReadAdrBase]>;
2303
2304 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2305                       string asm, dag ins, dag outs, list<dag> pat>
2306     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2307   // The operands are in order to match the 'addr' MI operands, so we
2308   // don't need an encoder method and by-name matching. Just use the default
2309   // in-order handling. Since we're using by-order, make sure the names
2310   // do not match.
2311   bits<5> dst;
2312   bits<5> base;
2313   bits<5> offset;
2314   bits<4> extend;
2315   let Inst{31-30} = sz;
2316   let Inst{29-27} = 0b111;
2317   let Inst{26}    = V;
2318   let Inst{25-24} = 0b00;
2319   let Inst{23-22} = opc;
2320   let Inst{21}    = 1;
2321   let Inst{20-16} = offset;
2322   let Inst{15-13} = extend{3-1};
2323
2324   let Inst{12}    = extend{0};
2325   let Inst{11-10} = 0b10;
2326   let Inst{9-5}   = base;
2327   let Inst{4-0}   = dst;
2328
2329   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2330 }
2331
2332 class Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2333              string asm, list<dag> pat>
2334   : LoadStore32RO<sz, V, opc, regtype, asm,
2335                  (outs regtype:$Rt), (ins ro_indexed32:$addr), pat>,
2336     Sched<[WriteLDIdx, ReadAdrBase]>;
2337
2338 class Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2339              string asm, list<dag> pat>
2340   : LoadStore32RO<sz, V, opc, regtype, asm,
2341                  (outs), (ins regtype:$Rt, ro_indexed32:$addr), pat>,
2342     Sched<[WriteSTIdx, ReadAdrBase]>;
2343
2344 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2345                       string asm, dag ins, dag outs, list<dag> pat>
2346     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2347   // The operands are in order to match the 'addr' MI operands, so we
2348   // don't need an encoder method and by-name matching. Just use the default
2349   // in-order handling. Since we're using by-order, make sure the names
2350   // do not match.
2351   bits<5> dst;
2352   bits<5> base;
2353   bits<5> offset;
2354   bits<4> extend;
2355   let Inst{31-30} = sz;
2356   let Inst{29-27} = 0b111;
2357   let Inst{26}    = V;
2358   let Inst{25-24} = 0b00;
2359   let Inst{23-22} = opc;
2360   let Inst{21}    = 1;
2361   let Inst{20-16} = offset;
2362   let Inst{15-13} = extend{3-1};
2363
2364   let Inst{12}    = extend{0};
2365   let Inst{11-10} = 0b10;
2366   let Inst{9-5}   = base;
2367   let Inst{4-0}   = dst;
2368
2369   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2370 }
2371
2372 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2373 class Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2374              string asm, list<dag> pat>
2375   : LoadStore64RO<sz, V, opc, regtype, asm,
2376                  (outs regtype:$Rt), (ins ro_indexed64:$addr), pat>,
2377     Sched<[WriteLDIdx, ReadAdrBase]>;
2378
2379 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2380 class Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2381              string asm, list<dag> pat>
2382   : LoadStore64RO<sz, V, opc, regtype, asm,
2383                  (outs), (ins regtype:$Rt, ro_indexed64:$addr), pat>,
2384     Sched<[WriteSTIdx, ReadAdrBase]>;
2385
2386
2387 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2388                       string asm, dag ins, dag outs, list<dag> pat>
2389     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2390   // The operands are in order to match the 'addr' MI operands, so we
2391   // don't need an encoder method and by-name matching. Just use the default
2392   // in-order handling. Since we're using by-order, make sure the names
2393   // do not match.
2394   bits<5> dst;
2395   bits<5> base;
2396   bits<5> offset;
2397   bits<4> extend;
2398   let Inst{31-30} = sz;
2399   let Inst{29-27} = 0b111;
2400   let Inst{26}    = V;
2401   let Inst{25-24} = 0b00;
2402   let Inst{23-22} = opc;
2403   let Inst{21}    = 1;
2404   let Inst{20-16} = offset;
2405   let Inst{15-13} = extend{3-1};
2406
2407   let Inst{12}    = extend{0};
2408   let Inst{11-10} = 0b10;
2409   let Inst{9-5}   = base;
2410   let Inst{4-0}   = dst;
2411
2412   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2413 }
2414
2415 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2416 class Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2417              string asm, list<dag> pat>
2418   : LoadStore128RO<sz, V, opc, regtype, asm,
2419                  (outs regtype:$Rt), (ins ro_indexed128:$addr), pat>,
2420     Sched<[WriteLDIdx, ReadAdrBase]>;
2421
2422 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2423 class Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2424              string asm, list<dag> pat>
2425   : LoadStore128RO<sz, V, opc, regtype, asm,
2426                  (outs), (ins regtype:$Rt, ro_indexed128:$addr), pat>,
2427     Sched<[WriteSTIdx, ReadAdrBase]>;
2428
2429 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2430 class PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2431     : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm,
2432          "\t$Rt, $addr", "", pat>,
2433       Sched<[WriteLD]> {
2434   // The operands are in order to match the 'addr' MI operands, so we
2435   // don't need an encoder method and by-name matching. Just use the default
2436   // in-order handling. Since we're using by-order, make sure the names
2437   // do not match.
2438   bits<5> dst;
2439   bits<5> base;
2440   bits<5> offset;
2441   bits<4> extend;
2442   let Inst{31-30} = sz;
2443   let Inst{29-27} = 0b111;
2444   let Inst{26}    = V;
2445   let Inst{25-24} = 0b00;
2446   let Inst{23-22} = opc;
2447   let Inst{21}    = 1;
2448   let Inst{20-16} = offset;
2449   let Inst{15-13} = extend{3-1};
2450
2451   let Inst{12}    = extend{0};
2452   let Inst{11-10} = 0b10;
2453   let Inst{9-5}   = base;
2454   let Inst{4-0}   = dst;
2455
2456   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2457 }
2458
2459 //---
2460 // Load/store unscaled immediate
2461 //---
2462
2463 def MemoryUnscaledOperand : AsmOperandClass {
2464   let Name = "MemoryUnscaled";
2465   let DiagnosticType = "InvalidMemoryIndexedSImm9";
2466 }
2467 class am_unscaled_operand : Operand<i64> {
2468   let PrintMethod = "printAMIndexed<8>";
2469   let ParserMatchClass = MemoryUnscaledOperand;
2470   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2471 }
2472 class am_unscaled_wb_operand : Operand<i64> {
2473   let PrintMethod = "printAMIndexedWB<8>";
2474   let ParserMatchClass = MemoryUnscaledOperand;
2475   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2476 }
2477 def am_unscaled   : am_unscaled_operand;
2478 def am_unscaled_wb: am_unscaled_wb_operand;
2479 def am_unscaled8  : am_unscaled_operand,
2480                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2481 def am_unscaled16 : am_unscaled_operand,
2482                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2483 def am_unscaled32 : am_unscaled_operand,
2484                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2485 def am_unscaled64 : am_unscaled_operand,
2486                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2487 def am_unscaled128 : am_unscaled_operand,
2488                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2489
2490 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2491                            string asm, list<dag> pattern>
2492     : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2493   // The operands are in order to match the 'addr' MI operands, so we
2494   // don't need an encoder method and by-name matching. Just use the default
2495   // in-order handling. Since we're using by-order, make sure the names
2496   // do not match.
2497   bits<5> dst;
2498   bits<5> base;
2499   bits<9> offset;
2500   let Inst{31-30} = sz;
2501   let Inst{29-27} = 0b111;
2502   let Inst{26}    = V;
2503   let Inst{25-24} = 0b00;
2504   let Inst{23-22} = opc;
2505   let Inst{21}    = 0;
2506   let Inst{20-12} = offset;
2507   let Inst{11-10} = 0b00;
2508   let Inst{9-5}   = base;
2509   let Inst{4-0}   = dst;
2510
2511   let DecoderMethod = "DecodeSignedLdStInstruction";
2512 }
2513
2514 let AddedComplexity = 1 in // try this before LoadUI
2515 class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2516                    Operand amtype, string asm, list<dag> pattern>
2517     : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2518                            (ins amtype:$addr), asm, pattern>,
2519       Sched<[WriteLD]>;
2520
2521 let AddedComplexity = 1 in // try this before StoreUI
2522 class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2523                     Operand amtype, string asm, list<dag> pattern>
2524     : BaseLoadStoreUnscale<sz, V, opc, (outs),
2525                            (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2526       Sched<[WriteST]>;
2527
2528 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2529 class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2530     : BaseLoadStoreUnscale<sz, V, opc, (outs),
2531                            (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2532       Sched<[WriteLD]>;
2533
2534 //---
2535 // Load/store unscaled immediate, unprivileged
2536 //---
2537
2538 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2539                                 dag oops, dag iops, string asm>
2540     : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2541   // The operands are in order to match the 'addr' MI operands, so we
2542   // don't need an encoder method and by-name matching. Just use the default
2543   // in-order handling. Since we're using by-order, make sure the names
2544   // do not match.
2545   bits<5> dst;
2546   bits<5> base;
2547   bits<9> offset;
2548   let Inst{31-30} = sz;
2549   let Inst{29-27} = 0b111;
2550   let Inst{26}    = V;
2551   let Inst{25-24} = 0b00;
2552   let Inst{23-22} = opc;
2553   let Inst{21}    = 0;
2554   let Inst{20-12} = offset;
2555   let Inst{11-10} = 0b10;
2556   let Inst{9-5}   = base;
2557   let Inst{4-0}   = dst;
2558
2559   let DecoderMethod = "DecodeSignedLdStInstruction";
2560 }
2561
2562 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2563 class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2564                    string asm>
2565     : BaseLoadStoreUnprivileged<sz, V, opc,
2566                       (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2567       Sched<[WriteLD]>;
2568 }
2569
2570 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2571 class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2572                     string asm>
2573     : BaseLoadStoreUnprivileged<sz, V, opc,
2574                       (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2575       Sched<[WriteST]>;
2576 }
2577
2578 //---
2579 // Load/store pre-indexed
2580 //---
2581
2582 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2583                           string asm, string cstr>
2584     : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2585   // The operands are in order to match the 'addr' MI operands, so we
2586   // don't need an encoder method and by-name matching. Just use the default
2587   // in-order handling.
2588   bits<5> dst;
2589   bits<5> base;
2590   bits<9> offset;
2591   let Inst{31-30} = sz;
2592   let Inst{29-27} = 0b111;
2593   let Inst{26}    = V;
2594   let Inst{25-24} = 0;
2595   let Inst{23-22} = opc;
2596   let Inst{21}    = 0;
2597   let Inst{20-12} = offset;
2598   let Inst{11-10} = 0b11;
2599   let Inst{9-5}   = base;
2600   let Inst{4-0}   = dst;
2601
2602   let DecoderMethod = "DecodeSignedLdStInstruction";
2603 }
2604
2605 let hasSideEffects = 0 in {
2606 let mayStore = 0, mayLoad = 1 in
2607 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2608 //        we need the complex addressing mode for the memory reference, but
2609 //        we also need the write-back specified as a tied operand to the
2610 //        base register. That combination does not play nicely with
2611 //        the asm matcher and friends.
2612 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2613              string asm>
2614     : BaseLoadStorePreIdx<sz, V, opc,
2615                      (outs regtype:$Rt/*, GPR64sp:$wback*/),
2616                      (ins am_unscaled_wb:$addr), asm, ""/*"$addr.base = $wback"*/>,
2617       Sched<[WriteLD, WriteAdr]>;
2618
2619 let mayStore = 1, mayLoad = 0 in
2620 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2621              string asm>
2622     : BaseLoadStorePreIdx<sz, V, opc,
2623                       (outs/* GPR64sp:$wback*/),
2624                       (ins regtype:$Rt, am_unscaled_wb:$addr),
2625                        asm, ""/*"$addr.base = $wback"*/>,
2626       Sched<[WriteAdr, WriteST]>;
2627 } // hasSideEffects = 0
2628
2629 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2630 // logic finally gets smart enough to strip off tied operands that are just
2631 // for isel convenience, we can get rid of these pseudos and just reference
2632 // the real instructions directly.
2633 //
2634 // Ironically, also because of the writeback operands, we can't put the
2635 // matcher pattern directly on the instruction, but need to define it
2636 // separately.
2637 //
2638 // Loads aren't matched with patterns here at all, but rather in C++
2639 // custom lowering.
2640 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2641 class LoadPreIdxPseudo<RegisterClass regtype>
2642     : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2643              (ins am_noindex:$addr, simm9:$offset), [],
2644               "$addr.base = $wback,@earlyclobber $wback">,
2645       Sched<[WriteLD, WriteAdr]>;
2646 class LoadPostIdxPseudo<RegisterClass regtype>
2647     : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2648              (ins am_noindex:$addr, simm9:$offset), [],
2649               "$addr.base = $wback,@earlyclobber $wback">,
2650       Sched<[WriteLD, WriteI]>;
2651 }
2652 multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2653                              SDPatternOperator OpNode> {
2654   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2655   def _isel: Pseudo<(outs GPR64sp:$wback),
2656                     (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2657                     "$addr.base = $wback,@earlyclobber $wback">,
2658       Sched<[WriteAdr, WriteST]>;
2659
2660   def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2661             (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2662                                             simm9:$offset)>;
2663 }
2664
2665 //---
2666 // Load/store post-indexed
2667 //---
2668
2669 // (pre-index) load/stores.
2670 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2671                           string asm, string cstr>
2672     : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2673   // The operands are in order to match the 'addr' MI operands, so we
2674   // don't need an encoder method and by-name matching. Just use the default
2675   // in-order handling.
2676   bits<5> dst;
2677   bits<5> base;
2678   bits<9> offset;
2679   let Inst{31-30} = sz;
2680   let Inst{29-27} = 0b111;
2681   let Inst{26}    = V;
2682   let Inst{25-24} = 0b00;
2683   let Inst{23-22} = opc;
2684   let Inst{21}    = 0b0;
2685   let Inst{20-12} = offset;
2686   let Inst{11-10} = 0b01;
2687   let Inst{9-5}   = base;
2688   let Inst{4-0}   = dst;
2689
2690   let DecoderMethod = "DecodeSignedLdStInstruction";
2691 }
2692
2693 let hasSideEffects = 0 in {
2694 let mayStore = 0, mayLoad = 1 in
2695 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2696 //        we need the complex addressing mode for the memory reference, but
2697 //        we also need the write-back specified as a tied operand to the
2698 //        base register. That combination does not play nicely with
2699 //        the asm matcher and friends.
2700 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2701              string asm>
2702     : BaseLoadStorePostIdx<sz, V, opc,
2703                       (outs regtype:$Rt/*, GPR64sp:$wback*/),
2704                       (ins am_noindex:$addr, simm9:$idx),
2705                       asm, ""/*"$addr.base = $wback"*/>,
2706       Sched<[WriteLD, WriteI]>;
2707
2708 let mayStore = 1, mayLoad = 0 in
2709 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2710              string asm>
2711     : BaseLoadStorePostIdx<sz, V, opc,
2712                       (outs/* GPR64sp:$wback*/),
2713                       (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2714                        asm, ""/*"$addr.base = $wback"*/>,
2715     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2716 } // hasSideEffects = 0
2717
2718 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2719 // logic finally gets smart enough to strip off tied operands that are just
2720 // for isel convenience, we can get rid of these pseudos and just reference
2721 // the real instructions directly.
2722 //
2723 // Ironically, also because of the writeback operands, we can't put the
2724 // matcher pattern directly on the instruction, but need to define it
2725 // separately.
2726 multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2727                               SDPatternOperator OpNode, Instruction Insn> {
2728   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2729   def _isel: Pseudo<(outs GPR64sp:$wback),
2730                     (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2731                     "$addr.base = $wback,@earlyclobber $wback">,
2732       PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2733       Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2734
2735   def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2736             (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2737                                             simm9:$idx)>;
2738 }
2739
2740 //---
2741 // Load/store pair
2742 //---
2743
2744 // (indexed, offset)
2745
2746 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2747                               string asm>
2748     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2749   // The operands are in order to match the 'addr' MI operands, so we
2750   // don't need an encoder method and by-name matching. Just use the default
2751   // in-order handling. Since we're using by-order, make sure the names
2752   // do not match.
2753   bits<5> dst;
2754   bits<5> dst2;
2755   bits<5> base;
2756   bits<7> offset;
2757   let Inst{31-30} = opc;
2758   let Inst{29-27} = 0b101;
2759   let Inst{26}    = V;
2760   let Inst{25-23} = 0b010;
2761   let Inst{22}    = L;
2762   let Inst{21-15} = offset;
2763   let Inst{14-10} = dst2;
2764   let Inst{9-5}   = base;
2765   let Inst{4-0}   = dst;
2766
2767   let DecoderMethod = "DecodePairLdStInstruction";
2768 }
2769
2770 let hasSideEffects = 0 in {
2771 let mayStore = 0, mayLoad = 1 in
2772 class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2773                      Operand indextype, string asm>
2774     : BaseLoadStorePairOffset<opc, V, 1,
2775                               (outs regtype:$Rt, regtype:$Rt2),
2776                               (ins indextype:$addr), asm>,
2777       Sched<[WriteLD, WriteLDHi]>;
2778
2779 let mayLoad = 0, mayStore = 1 in
2780 class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2781                       Operand indextype, string asm>
2782     : BaseLoadStorePairOffset<opc, V, 0, (outs),
2783                              (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2784                              asm>,
2785       Sched<[WriteSTP]>;
2786 } // hasSideEffects = 0
2787
2788 // (pre-indexed)
2789
2790 def MemoryIndexed32SImm7 : AsmOperandClass {
2791   let Name = "MemoryIndexed32SImm7";
2792   let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2793 }
2794 def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2795   let PrintMethod = "printAMIndexed<32>";
2796   let ParserMatchClass = MemoryIndexed32SImm7;
2797   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2798 }
2799 def am_indexed32simm7_wb : Operand<i32> { // ComplexPattern<...>
2800   let PrintMethod = "printAMIndexedWB<32>";
2801   let ParserMatchClass = MemoryIndexed32SImm7;
2802   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2803 }
2804
2805 def MemoryIndexed64SImm7 : AsmOperandClass {
2806   let Name = "MemoryIndexed64SImm7";
2807   let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2808 }
2809 def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2810   let PrintMethod = "printAMIndexed<64>";
2811   let ParserMatchClass = MemoryIndexed64SImm7;
2812   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2813 }
2814 def am_indexed64simm7_wb : Operand<i32> { // ComplexPattern<...>
2815   let PrintMethod = "printAMIndexedWB<64>";
2816   let ParserMatchClass = MemoryIndexed64SImm7;
2817   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2818 }
2819
2820 def MemoryIndexed128SImm7 : AsmOperandClass {
2821   let Name = "MemoryIndexed128SImm7";
2822   let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2823 }
2824 def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2825   let PrintMethod = "printAMIndexed<128>";
2826   let ParserMatchClass = MemoryIndexed128SImm7;
2827   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2828 }
2829 def am_indexed128simm7_wb : Operand<i32> { // ComplexPattern<...>
2830   let PrintMethod = "printAMIndexedWB<128>";
2831   let ParserMatchClass = MemoryIndexed128SImm7;
2832   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2833 }
2834
2835 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2836                               string asm>
2837     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2838   // The operands are in order to match the 'addr' MI operands, so we
2839   // don't need an encoder method and by-name matching. Just use the default
2840   // in-order handling. Since we're using by-order, make sure the names
2841   // do not match.
2842   bits<5> dst;
2843   bits<5> dst2;
2844   bits<5> base;
2845   bits<7> offset;
2846   let Inst{31-30} = opc;
2847   let Inst{29-27} = 0b101;
2848   let Inst{26}    = V;
2849   let Inst{25-23} = 0b011;
2850   let Inst{22}    = L;
2851   let Inst{21-15} = offset;
2852   let Inst{14-10} = dst2;
2853   let Inst{9-5}   = base;
2854   let Inst{4-0}   = dst;
2855
2856   let DecoderMethod = "DecodePairLdStInstruction";
2857 }
2858
2859 let hasSideEffects = 0 in {
2860 let mayStore = 0, mayLoad = 1 in
2861 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2862                      Operand addrmode, string asm>
2863     : BaseLoadStorePairPreIdx<opc, V, 1,
2864                               (outs regtype:$Rt, regtype:$Rt2),
2865                               (ins addrmode:$addr), asm>,
2866       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2867
2868 let mayStore = 1, mayLoad = 0 in
2869 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2870                       Operand addrmode, string asm>
2871     : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2872                              (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2873                              asm>,
2874       Sched<[WriteAdr, WriteSTP]>;
2875 } // hasSideEffects = 0
2876
2877 // (post-indexed)
2878
2879 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2880                               string asm>
2881     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2882   // The operands are in order to match the 'addr' MI operands, so we
2883   // don't need an encoder method and by-name matching. Just use the default
2884   // in-order handling. Since we're using by-order, make sure the names
2885   // do not match.
2886   bits<5> dst;
2887   bits<5> dst2;
2888   bits<5> base;
2889   bits<7> offset;
2890   let Inst{31-30} = opc;
2891   let Inst{29-27} = 0b101;
2892   let Inst{26}    = V;
2893   let Inst{25-23} = 0b001;
2894   let Inst{22}    = L;
2895   let Inst{21-15} = offset;
2896   let Inst{14-10} = dst2;
2897   let Inst{9-5}   = base;
2898   let Inst{4-0}   = dst;
2899
2900   let DecoderMethod = "DecodePairLdStInstruction";
2901 }
2902
2903 let hasSideEffects = 0 in {
2904 let mayStore = 0, mayLoad = 1 in
2905 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2906                       Operand idxtype, string asm>
2907     : BaseLoadStorePairPostIdx<opc, V, 1,
2908                               (outs regtype:$Rt, regtype:$Rt2),
2909                               (ins am_noindex:$addr, idxtype:$idx), asm>,
2910       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2911
2912 let mayStore = 1, mayLoad = 0 in
2913 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2914                        Operand idxtype, string asm>
2915     : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2916                              (ins regtype:$Rt, regtype:$Rt2,
2917                                   am_noindex:$addr, idxtype:$idx),
2918                              asm>,
2919       Sched<[WriteAdr, WriteSTP]>;
2920 } // hasSideEffects = 0
2921
2922 //  (no-allocate)
2923
2924 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2925                               string asm>
2926     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2927   // The operands are in order to match the 'addr' MI operands, so we
2928   // don't need an encoder method and by-name matching. Just use the default
2929   // in-order handling. Since we're using by-order, make sure the names
2930   // do not match.
2931   bits<5> dst;
2932   bits<5> dst2;
2933   bits<5> base;
2934   bits<7> offset;
2935   let Inst{31-30} = opc;
2936   let Inst{29-27} = 0b101;
2937   let Inst{26}    = V;
2938   let Inst{25-23} = 0b000;
2939   let Inst{22}    = L;
2940   let Inst{21-15} = offset;
2941   let Inst{14-10} = dst2;
2942   let Inst{9-5}   = base;
2943   let Inst{4-0}   = dst;
2944
2945   let DecoderMethod = "DecodePairLdStInstruction";
2946 }
2947
2948 let hasSideEffects = 0 in {
2949 let mayStore = 0, mayLoad = 1 in
2950 class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2951                      Operand indextype, string asm>
2952     : BaseLoadStorePairNoAlloc<opc, V, 1,
2953                               (outs regtype:$Rt, regtype:$Rt2),
2954                               (ins indextype:$addr), asm>,
2955       Sched<[WriteLD, WriteLDHi]>;
2956
2957 let mayStore = 1, mayLoad = 0 in
2958 class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2959                       Operand indextype, string asm>
2960     : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
2961                              (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2962                              asm>,
2963       Sched<[WriteSTP]>;
2964 } // hasSideEffects = 0
2965
2966 //---
2967 // Load/store exclusive
2968 //---
2969
2970 // True exclusive operations write to and/or read from the system's exclusive
2971 // monitors, which as far as a compiler is concerned can be modelled as a
2972 // random shared memory address. Hence LoadExclusive mayStore.
2973 //
2974 // Since these instructions have the undefined register bits set to 1 in
2975 // their canonical form, we need a post encoder method to set those bits
2976 // to 1 when encoding these instructions. We do this using the
2977 // fixLoadStoreExclusive function. This function has template parameters:
2978 //
2979 // fixLoadStoreExclusive<int hasRs, int hasRt2>
2980 //
2981 // hasRs indicates that the instruction uses the Rs field, so we won't set
2982 // it to 1 (and the same for Rt2). We don't need template parameters for
2983 // the other register fields since Rt and Rn are always used.
2984 //
2985 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
2986 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2987                              dag oops, dag iops, string asm, string operands>
2988     : I<oops, iops, asm, operands, "", []> {
2989   let Inst{31-30} = sz;
2990   let Inst{29-24} = 0b001000;
2991   let Inst{23}    = o2;
2992   let Inst{22}    = L;
2993   let Inst{21}    = o1;
2994   let Inst{15}    = o0;
2995
2996   let DecoderMethod = "DecodeExclusiveLdStInstruction";
2997 }
2998
2999 // Neither Rs nor Rt2 operands.
3000 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3001                                dag oops, dag iops, string asm, string operands>
3002     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3003   bits<5> reg;
3004   bits<5> base;
3005   let Inst{9-5} = base;
3006   let Inst{4-0} = reg;
3007
3008   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3009 }
3010
3011 // Simple load acquires don't set the exclusive monitor
3012 let mayLoad = 1, mayStore = 0 in
3013 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3014                   RegisterClass regtype, string asm>
3015     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3016                                (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
3017       Sched<[WriteLD]>;
3018
3019 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3020                     RegisterClass regtype, string asm>
3021     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3022                                (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
3023       Sched<[WriteLD]>;
3024
3025 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3026                        RegisterClass regtype, string asm>
3027     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3028                              (outs regtype:$Rt, regtype:$Rt2),
3029                              (ins am_noindex:$addr), asm,
3030                              "\t$Rt, $Rt2, $addr">,
3031       Sched<[WriteLD, WriteLDHi]> {
3032   bits<5> dst1;
3033   bits<5> dst2;
3034   bits<5> base;
3035   let Inst{14-10} = dst2;
3036   let Inst{9-5} = base;
3037   let Inst{4-0} = dst1;
3038
3039   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3040 }
3041
3042 // Simple store release operations do not check the exclusive monitor.
3043 let mayLoad = 0, mayStore = 1 in
3044 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3045                    RegisterClass regtype, string asm>
3046     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3047                                (ins regtype:$Rt, am_noindex:$addr),
3048                                asm, "\t$Rt, $addr">,
3049       Sched<[WriteST]>;
3050
3051 let mayLoad = 1, mayStore = 1 in
3052 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3053                      RegisterClass regtype, string asm>
3054     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3055                              (ins regtype:$Rt, am_noindex:$addr),
3056                              asm, "\t$Ws, $Rt, $addr">,
3057       Sched<[WriteSTX]> {
3058   bits<5> status;
3059   bits<5> reg;
3060   bits<5> base;
3061   let Inst{20-16} = status;
3062   let Inst{9-5} = base;
3063   let Inst{4-0} = reg;
3064
3065   let Constraints = "@earlyclobber $Ws";
3066   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3067 }
3068
3069 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3070                          RegisterClass regtype, string asm>
3071     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3072                              (outs GPR32:$Ws),
3073                              (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
3074                               asm, "\t$Ws, $Rt, $Rt2, $addr">,
3075       Sched<[WriteSTX]> {
3076   bits<5> status;
3077   bits<5> dst1;
3078   bits<5> dst2;
3079   bits<5> base;
3080   let Inst{20-16} = status;
3081   let Inst{14-10} = dst2;
3082   let Inst{9-5} = base;
3083   let Inst{4-0} = dst1;
3084
3085   let Constraints = "@earlyclobber $Ws";
3086 }
3087
3088 //---
3089 // Exception generation
3090 //---
3091
3092 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3093 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3094     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3095       Sched<[WriteSys]> {
3096   bits<16> imm;
3097   let Inst{31-24} = 0b11010100;
3098   let Inst{23-21} = op1;
3099   let Inst{20-5}  = imm;
3100   let Inst{4-2}   = 0b000;
3101   let Inst{1-0}   = ll;
3102 }
3103
3104 let Predicates = [HasFPARMv8] in {
3105
3106 //---
3107 // Floating point to integer conversion
3108 //---
3109
3110 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3111                       RegisterClass srcType, RegisterClass dstType,
3112                       string asm, list<dag> pattern>
3113     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3114          asm, "\t$Rd, $Rn", "", pattern>,
3115       Sched<[WriteFCvt]> {
3116   bits<5> Rd;
3117   bits<5> Rn;
3118   let Inst{30-29} = 0b00;
3119   let Inst{28-24} = 0b11110;
3120   let Inst{23-22} = type;
3121   let Inst{21}    = 1;
3122   let Inst{20-19} = rmode;
3123   let Inst{18-16} = opcode;
3124   let Inst{15-10} = 0;
3125   let Inst{9-5}   = Rn;
3126   let Inst{4-0}   = Rd;
3127 }
3128
3129 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3130 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3131                       RegisterClass srcType, RegisterClass dstType,
3132                       Operand immType, string asm, list<dag> pattern>
3133     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3134          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3135       Sched<[WriteFCvt]> {
3136   bits<5> Rd;
3137   bits<5> Rn;
3138   bits<6> scale;
3139   let Inst{30-29} = 0b00;
3140   let Inst{28-24} = 0b11110;
3141   let Inst{23-22} = type;
3142   let Inst{21}    = 0;
3143   let Inst{20-19} = rmode;
3144   let Inst{18-16} = opcode;
3145   let Inst{15-10} = scale;
3146   let Inst{9-5}   = Rn;
3147   let Inst{4-0}   = Rd;
3148 }
3149
3150 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3151            SDPatternOperator OpN> {
3152   // Unscaled single-precision to 32-bit
3153   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3154                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3155     let Inst{31} = 0; // 32-bit GPR flag
3156   }
3157
3158   // Unscaled single-precision to 64-bit
3159   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3160                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3161     let Inst{31} = 1; // 64-bit GPR flag
3162   }
3163
3164   // Unscaled double-precision to 32-bit
3165   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3166                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3167     let Inst{31} = 0; // 32-bit GPR flag
3168   }
3169
3170   // Unscaled double-precision to 64-bit
3171   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3172                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3173     let Inst{31} = 1; // 64-bit GPR flag
3174   }
3175 }
3176
3177 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3178                              SDPatternOperator OpN> {
3179   // Scaled single-precision to 32-bit
3180   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3181                               fixedpoint_f32_i32, asm,
3182               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3183                                           fixedpoint_f32_i32:$scale)))]> {
3184     let Inst{31} = 0; // 32-bit GPR flag
3185     let scale{5} = 1;
3186   }
3187
3188   // Scaled single-precision to 64-bit
3189   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3190                               fixedpoint_f32_i64, asm,
3191               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3192                                           fixedpoint_f32_i64:$scale)))]> {
3193     let Inst{31} = 1; // 64-bit GPR flag
3194   }
3195
3196   // Scaled double-precision to 32-bit
3197   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3198                               fixedpoint_f64_i32, asm,
3199               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3200                                           fixedpoint_f64_i32:$scale)))]> {
3201     let Inst{31} = 0; // 32-bit GPR flag
3202     let scale{5} = 1;
3203   }
3204
3205   // Scaled double-precision to 64-bit
3206   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3207                               fixedpoint_f64_i64, asm,
3208               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3209                                           fixedpoint_f64_i64:$scale)))]> {
3210     let Inst{31} = 1; // 64-bit GPR flag
3211   }
3212 }
3213
3214 //---
3215 // Integer to floating point conversion
3216 //---
3217
3218 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3219 class BaseIntegerToFP<bit isUnsigned,
3220                       RegisterClass srcType, RegisterClass dstType,
3221                       Operand immType, string asm, list<dag> pattern>
3222     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3223          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3224       Sched<[WriteFCvt]> {
3225   bits<5> Rd;
3226   bits<5> Rn;
3227   bits<6> scale;
3228   let Inst{30-23} = 0b00111100;
3229   let Inst{21-17} = 0b00001;
3230   let Inst{16}    = isUnsigned;
3231   let Inst{15-10} = scale;
3232   let Inst{9-5}   = Rn;
3233   let Inst{4-0}   = Rd;
3234 }
3235
3236 class BaseIntegerToFPUnscaled<bit isUnsigned,
3237                       RegisterClass srcType, RegisterClass dstType,
3238                       ValueType dvt, string asm, SDNode node>
3239     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3240          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3241       Sched<[WriteFCvt]> {
3242   bits<5> Rd;
3243   bits<5> Rn;
3244   bits<6> scale;
3245   let Inst{30-23} = 0b00111100;
3246   let Inst{21-17} = 0b10001;
3247   let Inst{16}    = isUnsigned;
3248   let Inst{15-10} = 0b000000;
3249   let Inst{9-5}   = Rn;
3250   let Inst{4-0}   = Rd;
3251 }
3252
3253 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3254   // Unscaled
3255   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3256     let Inst{31} = 0; // 32-bit GPR flag
3257     let Inst{22} = 0; // 32-bit FPR flag
3258   }
3259
3260   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3261     let Inst{31} = 0; // 32-bit GPR flag
3262     let Inst{22} = 1; // 64-bit FPR flag
3263   }
3264
3265   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3266     let Inst{31} = 1; // 64-bit GPR flag
3267     let Inst{22} = 0; // 32-bit FPR flag
3268   }
3269
3270   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3271     let Inst{31} = 1; // 64-bit GPR flag
3272     let Inst{22} = 1; // 64-bit FPR flag
3273   }
3274
3275   // Scaled
3276   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3277                              [(set FPR32:$Rd,
3278                                    (fdiv (node GPR32:$Rn),
3279                                          fixedpoint_f32_i32:$scale))]> {
3280     let Inst{31} = 0; // 32-bit GPR flag
3281     let Inst{22} = 0; // 32-bit FPR flag
3282     let scale{5} = 1;
3283   }
3284
3285   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3286                              [(set FPR64:$Rd,
3287                                    (fdiv (node GPR32:$Rn),
3288                                          fixedpoint_f64_i32:$scale))]> {
3289     let Inst{31} = 0; // 32-bit GPR flag
3290     let Inst{22} = 1; // 64-bit FPR flag
3291     let scale{5} = 1;
3292   }
3293
3294   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3295                              [(set FPR32:$Rd,
3296                                    (fdiv (node GPR64:$Rn),
3297                                          fixedpoint_f32_i64:$scale))]> {
3298     let Inst{31} = 1; // 64-bit GPR flag
3299     let Inst{22} = 0; // 32-bit FPR flag
3300   }
3301
3302   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3303                              [(set FPR64:$Rd,
3304                                    (fdiv (node GPR64:$Rn),
3305                                          fixedpoint_f64_i64:$scale))]> {
3306     let Inst{31} = 1; // 64-bit GPR flag
3307     let Inst{22} = 1; // 64-bit FPR flag
3308   }
3309 }
3310
3311 //---
3312 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3313 //---
3314
3315 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3316 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3317                       RegisterClass srcType, RegisterClass dstType,
3318                       string asm>
3319     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3320         // We use COPY_TO_REGCLASS for these bitconvert operations.
3321         // copyPhysReg() expands the resultant COPY instructions after
3322         // regalloc is done. This gives greater freedom for the allocator
3323         // and related passes (coalescing, copy propagation, et. al.) to
3324         // be more effective.
3325         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3326       Sched<[WriteFCopy]> {
3327   bits<5> Rd;
3328   bits<5> Rn;
3329   let Inst{30-23} = 0b00111100;
3330   let Inst{21}    = 1;
3331   let Inst{20-19} = rmode;
3332   let Inst{18-16} = opcode;
3333   let Inst{15-10} = 0b000000;
3334   let Inst{9-5}   = Rn;
3335   let Inst{4-0}   = Rd;
3336 }
3337
3338 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3339 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3340                      RegisterClass srcType, RegisterOperand dstType, string asm,
3341                      string kind>
3342     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3343         "{\t$Rd"#kind#"[1], $Rn|"#kind#"\t$Rd[1], $Rn}", "", []>,
3344       Sched<[WriteFCopy]> {
3345   bits<5> Rd;
3346   bits<5> Rn;
3347   let Inst{30-23} = 0b00111101;
3348   let Inst{21}    = 1;
3349   let Inst{20-19} = rmode;
3350   let Inst{18-16} = opcode;
3351   let Inst{15-10} = 0b000000;
3352   let Inst{9-5}   = Rn;
3353   let Inst{4-0}   = Rd;
3354 }
3355
3356 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3357 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3358                      RegisterOperand srcType, RegisterClass dstType, string asm,
3359                      string kind>
3360     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3361         "{\t$Rd, $Rn"#kind#"[1]|"#kind#"\t$Rd, $Rn[1]}", "", []>,
3362       Sched<[WriteFCopy]> {
3363   bits<5> Rd;
3364   bits<5> Rn;
3365   let Inst{30-23} = 0b00111101;
3366   let Inst{21}    = 1;
3367   let Inst{20-19} = rmode;
3368   let Inst{18-16} = opcode;
3369   let Inst{15-10} = 0b000000;
3370   let Inst{9-5}   = Rn;
3371   let Inst{4-0}   = Rd;
3372 }
3373
3374
3375
3376 multiclass UnscaledConversion<string asm> {
3377   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3378     let Inst{31} = 0; // 32-bit GPR flag
3379     let Inst{22} = 0; // 32-bit FPR flag
3380   }
3381
3382   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3383     let Inst{31} = 1; // 64-bit GPR flag
3384     let Inst{22} = 1; // 64-bit FPR flag
3385   }
3386
3387   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3388     let Inst{31} = 0; // 32-bit GPR flag
3389     let Inst{22} = 0; // 32-bit FPR flag
3390   }
3391
3392   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3393     let Inst{31} = 1; // 64-bit GPR flag
3394     let Inst{22} = 1; // 64-bit FPR flag
3395   }
3396
3397   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3398                                              asm, ".d"> {
3399     let Inst{31} = 1;
3400     let Inst{22} = 0;
3401   }
3402
3403   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3404                                                asm, ".d"> {
3405     let Inst{31} = 1;
3406     let Inst{22} = 0;
3407   }
3408 }
3409
3410 //---
3411 // Floating point conversion
3412 //---
3413
3414 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3415                        RegisterClass srcType, string asm, list<dag> pattern>
3416     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3417       Sched<[WriteFCvt]> {
3418   bits<5> Rd;
3419   bits<5> Rn;
3420   let Inst{31-24} = 0b00011110;
3421   let Inst{23-22} = type;
3422   let Inst{21-17} = 0b10001;
3423   let Inst{16-15} = opcode;
3424   let Inst{14-10} = 0b10000;
3425   let Inst{9-5}   = Rn;
3426   let Inst{4-0}   = Rd;
3427 }
3428
3429 multiclass FPConversion<string asm> {
3430   // Double-precision to Half-precision
3431   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3432                              [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3433
3434   // Double-precision to Single-precision
3435   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3436                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3437
3438   // Half-precision to Double-precision
3439   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3440                              [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3441
3442   // Half-precision to Single-precision
3443   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3444                              [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3445
3446   // Single-precision to Double-precision
3447   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3448                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3449
3450   // Single-precision to Half-precision
3451   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3452                              [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3453 }
3454
3455 //---
3456 // Single operand floating point data processing
3457 //---
3458
3459 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3460 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3461                               ValueType vt, string asm, SDPatternOperator node>
3462     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3463          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3464       Sched<[WriteF]> {
3465   bits<5> Rd;
3466   bits<5> Rn;
3467   let Inst{31-23} = 0b000111100;
3468   let Inst{21-19} = 0b100;
3469   let Inst{18-15} = opcode;
3470   let Inst{14-10} = 0b10000;
3471   let Inst{9-5}   = Rn;
3472   let Inst{4-0}   = Rd;
3473 }
3474
3475 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3476                                SDPatternOperator node = null_frag> {
3477   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3478     let Inst{22} = 0; // 32-bit size flag
3479   }
3480
3481   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3482     let Inst{22} = 1; // 64-bit size flag
3483   }
3484 }
3485
3486 //---
3487 // Two operand floating point data processing
3488 //---
3489
3490 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3491 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3492                            string asm, list<dag> pat>
3493     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3494          asm, "\t$Rd, $Rn, $Rm", "", pat>,
3495       Sched<[WriteF]> {
3496   bits<5> Rd;
3497   bits<5> Rn;
3498   bits<5> Rm;
3499   let Inst{31-23} = 0b000111100;
3500   let Inst{21}    = 1;
3501   let Inst{20-16} = Rm;
3502   let Inst{15-12} = opcode;
3503   let Inst{11-10} = 0b10;
3504   let Inst{9-5}   = Rn;
3505   let Inst{4-0}   = Rd;
3506 }
3507
3508 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3509                             SDPatternOperator node = null_frag> {
3510   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3511                          [(set (f32 FPR32:$Rd),
3512                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3513     let Inst{22} = 0; // 32-bit size flag
3514   }
3515
3516   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3517                          [(set (f64 FPR64:$Rd),
3518                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3519     let Inst{22} = 1; // 64-bit size flag
3520   }
3521 }
3522
3523 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3524   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3525                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3526     let Inst{22} = 0; // 32-bit size flag
3527   }
3528
3529   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3530                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3531     let Inst{22} = 1; // 64-bit size flag
3532   }
3533 }
3534
3535
3536 //---
3537 // Three operand floating point data processing
3538 //---
3539
3540 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3541                              RegisterClass regtype, string asm, list<dag> pat>
3542     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3543          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3544       Sched<[WriteFMul]> {
3545   bits<5> Rd;
3546   bits<5> Rn;
3547   bits<5> Rm;
3548   bits<5> Ra;
3549   let Inst{31-23} = 0b000111110;
3550   let Inst{21}    = isNegated;
3551   let Inst{20-16} = Rm;
3552   let Inst{15}    = isSub;
3553   let Inst{14-10} = Ra;
3554   let Inst{9-5}   = Rn;
3555   let Inst{4-0}   = Rd;
3556 }
3557
3558 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3559                               SDPatternOperator node> {
3560   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3561             [(set FPR32:$Rd,
3562                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3563     let Inst{22} = 0; // 32-bit size flag
3564   }
3565
3566   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3567             [(set FPR64:$Rd,
3568                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3569     let Inst{22} = 1; // 64-bit size flag
3570   }
3571 }
3572
3573 //---
3574 // Floating point data comparisons
3575 //---
3576
3577 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3578 class BaseOneOperandFPComparison<bit signalAllNans,
3579                                  RegisterClass regtype, string asm,
3580                                  list<dag> pat>
3581     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3582       Sched<[WriteFCmp]> {
3583   bits<5> Rn;
3584   let Inst{31-23} = 0b000111100;
3585   let Inst{21}    = 1;
3586
3587   let Inst{15-10} = 0b001000;
3588   let Inst{9-5}   = Rn;
3589   let Inst{4}     = signalAllNans;
3590   let Inst{3-0}   = 0b1000;
3591
3592   // Rm should be 0b00000 canonically, but we need to accept any value.
3593   let PostEncoderMethod = "fixOneOperandFPComparison";
3594 }
3595
3596 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3597 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3598                                 string asm, list<dag> pat>
3599     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3600       Sched<[WriteFCmp]> {
3601   bits<5> Rm;
3602   bits<5> Rn;
3603   let Inst{31-23} = 0b000111100;
3604   let Inst{21}    = 1;
3605   let Inst{20-16} = Rm;
3606   let Inst{15-10} = 0b001000;
3607   let Inst{9-5}   = Rn;
3608   let Inst{4}     = signalAllNans;
3609   let Inst{3-0}   = 0b0000;
3610 }
3611
3612 multiclass FPComparison<bit signalAllNans, string asm,
3613                         SDPatternOperator OpNode = null_frag> {
3614   let Defs = [NZCV] in {
3615   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3616       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
3617     let Inst{22} = 0;
3618   }
3619
3620   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3621       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
3622     let Inst{22} = 0;
3623   }
3624
3625   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3626       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
3627     let Inst{22} = 1;
3628   }
3629
3630   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3631       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
3632     let Inst{22} = 1;
3633   }
3634   } // Defs = [NZCV]
3635 }
3636
3637 //---
3638 // Floating point conditional comparisons
3639 //---
3640
3641 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3642 class BaseFPCondComparison<bit signalAllNans,
3643                               RegisterClass regtype, string asm>
3644     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3645          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3646       Sched<[WriteFCmp]> {
3647   bits<5> Rn;
3648   bits<5> Rm;
3649   bits<4> nzcv;
3650   bits<4> cond;
3651
3652   let Inst{31-23} = 0b000111100;
3653   let Inst{21}    = 1;
3654   let Inst{20-16} = Rm;
3655   let Inst{15-12} = cond;
3656   let Inst{11-10} = 0b01;
3657   let Inst{9-5}   = Rn;
3658   let Inst{4}     = signalAllNans;
3659   let Inst{3-0}   = nzcv;
3660 }
3661
3662 multiclass FPCondComparison<bit signalAllNans, string asm> {
3663   let Defs = [NZCV], Uses = [NZCV] in {
3664   def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3665     let Inst{22} = 0;
3666   }
3667
3668   def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3669     let Inst{22} = 1;
3670   }
3671   } // Defs = [NZCV], Uses = [NZCV]
3672 }
3673
3674 //---
3675 // Floating point conditional select
3676 //---
3677
3678 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3679     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3680          asm, "\t$Rd, $Rn, $Rm, $cond", "",
3681          [(set regtype:$Rd,
3682                (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3683                           (i32 imm:$cond), NZCV))]>,
3684       Sched<[WriteF]> {
3685   bits<5> Rd;
3686   bits<5> Rn;
3687   bits<5> Rm;
3688   bits<4> cond;
3689
3690   let Inst{31-23} = 0b000111100;
3691   let Inst{21}    = 1;
3692   let Inst{20-16} = Rm;
3693   let Inst{15-12} = cond;
3694   let Inst{11-10} = 0b11;
3695   let Inst{9-5}   = Rn;
3696   let Inst{4-0}   = Rd;
3697 }
3698
3699 multiclass FPCondSelect<string asm> {
3700   let Uses = [NZCV] in {
3701   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3702     let Inst{22} = 0;
3703   }
3704
3705   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3706     let Inst{22} = 1;
3707   }
3708   } // Uses = [NZCV]
3709 }
3710
3711 //---
3712 // Floating move immediate
3713 //---
3714
3715 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3716   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3717       [(set regtype:$Rd, fpimmtype:$imm)]>,
3718     Sched<[WriteFImm]> {
3719   bits<5> Rd;
3720   bits<8> imm;
3721   let Inst{31-23} = 0b000111100;
3722   let Inst{21}    = 1;
3723   let Inst{20-13} = imm;
3724   let Inst{12-5}  = 0b10000000;
3725   let Inst{4-0}   = Rd;
3726 }
3727
3728 multiclass FPMoveImmediate<string asm> {
3729   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3730     let Inst{22} = 0;
3731   }
3732
3733   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3734     let Inst{22} = 1;
3735   }
3736 }
3737 } // end of 'let Predicates = [HasFPARMv8]'
3738
3739 //----------------------------------------------------------------------------
3740 // AdvSIMD
3741 //----------------------------------------------------------------------------
3742
3743 class AsmVectorIndex<string Suffix> : AsmOperandClass {
3744   let Name = "VectorIndex" # Suffix;
3745   let DiagnosticType = "InvalidIndex" # Suffix;
3746 }
3747 def VectorIndexBOperand : AsmVectorIndex<"B">;
3748 def VectorIndexHOperand : AsmVectorIndex<"H">;
3749 def VectorIndexSOperand : AsmVectorIndex<"S">;
3750 def VectorIndexDOperand : AsmVectorIndex<"D">;
3751
3752 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3753   return ((uint64_t)Imm) < 16;
3754 }]> {
3755   let ParserMatchClass = VectorIndexBOperand;
3756   let PrintMethod = "printVectorIndex";
3757   let MIOperandInfo = (ops i64imm);
3758 }
3759 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3760   return ((uint64_t)Imm) < 8;
3761 }]> {
3762   let ParserMatchClass = VectorIndexHOperand;
3763   let PrintMethod = "printVectorIndex";
3764   let MIOperandInfo = (ops i64imm);
3765 }
3766 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3767   return ((uint64_t)Imm) < 4;
3768 }]> {
3769   let ParserMatchClass = VectorIndexSOperand;
3770   let PrintMethod = "printVectorIndex";
3771   let MIOperandInfo = (ops i64imm);
3772 }
3773 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3774   return ((uint64_t)Imm) < 2;
3775 }]> {
3776   let ParserMatchClass = VectorIndexDOperand;
3777   let PrintMethod = "printVectorIndex";
3778   let MIOperandInfo = (ops i64imm);
3779 }
3780
3781 def MemorySIMDNoIndexOperand : AsmOperandClass {
3782   let Name = "MemorySIMDNoIndex";
3783   let ParserMethod = "tryParseNoIndexMemory";
3784 }
3785 def am_simdnoindex : Operand<i64>,
3786                      ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
3787   let PrintMethod = "printAMNoIndex";
3788   let ParserMatchClass = MemorySIMDNoIndexOperand;
3789   let MIOperandInfo = (ops GPR64sp:$base);
3790   let DecoderMethod = "DecodeGPR64spRegisterClass";
3791 }
3792
3793 let Predicates = [HasNEON] in {
3794
3795 //----------------------------------------------------------------------------
3796 // AdvSIMD three register vector instructions
3797 //----------------------------------------------------------------------------
3798
3799 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3800 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3801                         RegisterOperand regtype, string asm, string kind,
3802                         list<dag> pattern>
3803   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3804       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3805       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3806     Sched<[WriteV]> {
3807   bits<5> Rd;
3808   bits<5> Rn;
3809   bits<5> Rm;
3810   let Inst{31}    = 0;
3811   let Inst{30}    = Q;
3812   let Inst{29}    = U;
3813   let Inst{28-24} = 0b01110;
3814   let Inst{23-22} = size;
3815   let Inst{21}    = 1;
3816   let Inst{20-16} = Rm;
3817   let Inst{15-11} = opcode;
3818   let Inst{10}    = 1;
3819   let Inst{9-5}   = Rn;
3820   let Inst{4-0}   = Rd;
3821 }
3822
3823 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3824 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3825                         RegisterOperand regtype, string asm, string kind,
3826                         list<dag> pattern>
3827   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3828       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3829       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3830     Sched<[WriteV]> {
3831   bits<5> Rd;
3832   bits<5> Rn;
3833   bits<5> Rm;
3834   let Inst{31}    = 0;
3835   let Inst{30}    = Q;
3836   let Inst{29}    = U;
3837   let Inst{28-24} = 0b01110;
3838   let Inst{23-22} = size;
3839   let Inst{21}    = 1;
3840   let Inst{20-16} = Rm;
3841   let Inst{15-11} = opcode;
3842   let Inst{10}    = 1;
3843   let Inst{9-5}   = Rn;
3844   let Inst{4-0}   = Rd;
3845 }
3846
3847 // All operand sizes distinguished in the encoding.
3848 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3849                                SDPatternOperator OpNode> {
3850   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3851                                       asm, ".8b",
3852          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3853   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3854                                       asm, ".16b",
3855          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3856   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3857                                       asm, ".4h",
3858          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3859   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3860                                       asm, ".8h",
3861          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3862   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3863                                       asm, ".2s",
3864          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3865   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3866                                       asm, ".4s",
3867          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3868   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3869                                       asm, ".2d",
3870          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3871 }
3872
3873 // As above, but D sized elements unsupported.
3874 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3875                                   SDPatternOperator OpNode> {
3876   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3877                                       asm, ".8b",
3878         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3879   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3880                                       asm, ".16b",
3881         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3882   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3883                                       asm, ".4h",
3884         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3885   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3886                                       asm, ".8h",
3887         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3888   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3889                                       asm, ".2s",
3890         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3891   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3892                                       asm, ".4s",
3893         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3894 }
3895
3896 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3897                                   SDPatternOperator OpNode> {
3898   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3899                                       asm, ".8b",
3900       [(set (v8i8 V64:$dst),
3901             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3902   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3903                                       asm, ".16b",
3904       [(set (v16i8 V128:$dst),
3905             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3906   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3907                                       asm, ".4h",
3908       [(set (v4i16 V64:$dst),
3909             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3910   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3911                                       asm, ".8h",
3912       [(set (v8i16 V128:$dst),
3913             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3914   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3915                                       asm, ".2s",
3916       [(set (v2i32 V64:$dst),
3917             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3918   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3919                                       asm, ".4s",
3920       [(set (v4i32 V128:$dst),
3921             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3922 }
3923
3924 // As above, but only B sized elements supported.
3925 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3926                                 SDPatternOperator OpNode> {
3927   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3928                                       asm, ".8b",
3929     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3930   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3931                                       asm, ".16b",
3932     [(set (v16i8 V128:$Rd),
3933           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3934 }
3935
3936 // As above, but only S and D sized floating point elements supported.
3937 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
3938                                  string asm, SDPatternOperator OpNode> {
3939   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3940                                       asm, ".2s",
3941         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3942   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3943                                       asm, ".4s",
3944         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3945   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3946                                       asm, ".2d",
3947         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3948 }
3949
3950 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
3951                                     string asm,
3952                                     SDPatternOperator OpNode> {
3953   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3954                                       asm, ".2s",
3955         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3956   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3957                                       asm, ".4s",
3958         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3959   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3960                                       asm, ".2d",
3961         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3962 }
3963
3964 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
3965                                  string asm, SDPatternOperator OpNode> {
3966   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
3967                                       asm, ".2s",
3968      [(set (v2f32 V64:$dst),
3969            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3970   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
3971                                       asm, ".4s",
3972      [(set (v4f32 V128:$dst),
3973            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3974   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
3975                                       asm, ".2d",
3976      [(set (v2f64 V128:$dst),
3977            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3978 }
3979
3980 // As above, but D and B sized elements unsupported.
3981 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
3982                                 SDPatternOperator OpNode> {
3983   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3984                                       asm, ".4h",
3985         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3986   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3987                                       asm, ".8h",
3988         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3989   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3990                                       asm, ".2s",
3991         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3992   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3993                                       asm, ".4s",
3994         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3995 }
3996
3997 // Logical three vector ops share opcode bits, and only use B sized elements.
3998 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
3999                                   SDPatternOperator OpNode = null_frag> {
4000   def v8i8  : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4001                                      asm, ".8b",
4002                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4003   def v16i8  : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4004                                      asm, ".16b",
4005                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4006
4007   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4008           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4009   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4010           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4011   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4012           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4013
4014   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4015       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4016   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4017       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4018   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4019       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4020 }
4021
4022 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4023                                   string asm, SDPatternOperator OpNode> {
4024   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4025                                      asm, ".8b",
4026              [(set (v8i8 V64:$dst),
4027                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4028   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4029                                      asm, ".16b",
4030              [(set (v16i8 V128:$dst),
4031                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4032                            (v16i8 V128:$Rm)))]>;
4033
4034   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4035                            (v4i16 V64:$RHS))),
4036           (!cast<Instruction>(NAME#"v8i8")
4037             V64:$LHS, V64:$MHS, V64:$RHS)>;
4038   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4039                            (v2i32 V64:$RHS))),
4040           (!cast<Instruction>(NAME#"v8i8")
4041             V64:$LHS, V64:$MHS, V64:$RHS)>;
4042   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4043                            (v1i64 V64:$RHS))),
4044           (!cast<Instruction>(NAME#"v8i8")
4045             V64:$LHS, V64:$MHS, V64:$RHS)>;
4046
4047   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4048                            (v8i16 V128:$RHS))),
4049       (!cast<Instruction>(NAME#"v16i8")
4050         V128:$LHS, V128:$MHS, V128:$RHS)>;
4051   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4052                            (v4i32 V128:$RHS))),
4053       (!cast<Instruction>(NAME#"v16i8")
4054         V128:$LHS, V128:$MHS, V128:$RHS)>;
4055   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4056                            (v2i64 V128:$RHS))),
4057       (!cast<Instruction>(NAME#"v16i8")
4058         V128:$LHS, V128:$MHS, V128:$RHS)>;
4059 }
4060
4061
4062 //----------------------------------------------------------------------------
4063 // AdvSIMD two register vector instructions.
4064 //----------------------------------------------------------------------------
4065
4066 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4067 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4068                         RegisterOperand regtype, string asm, string dstkind,
4069                         string srckind, list<dag> pattern>
4070   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4071       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4072       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4073     Sched<[WriteV]> {
4074   bits<5> Rd;
4075   bits<5> Rn;
4076   let Inst{31}    = 0;
4077   let Inst{30}    = Q;
4078   let Inst{29}    = U;
4079   let Inst{28-24} = 0b01110;
4080   let Inst{23-22} = size;
4081   let Inst{21-17} = 0b10000;
4082   let Inst{16-12} = opcode;
4083   let Inst{11-10} = 0b10;
4084   let Inst{9-5}   = Rn;
4085   let Inst{4-0}   = Rd;
4086 }
4087
4088 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4089 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4090                             RegisterOperand regtype, string asm, string dstkind,
4091                             string srckind, list<dag> pattern>
4092   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4093       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4094       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4095     Sched<[WriteV]> {
4096   bits<5> Rd;
4097   bits<5> Rn;
4098   let Inst{31}    = 0;
4099   let Inst{30}    = Q;
4100   let Inst{29}    = U;
4101   let Inst{28-24} = 0b01110;
4102   let Inst{23-22} = size;
4103   let Inst{21-17} = 0b10000;
4104   let Inst{16-12} = opcode;
4105   let Inst{11-10} = 0b10;
4106   let Inst{9-5}   = Rn;
4107   let Inst{4-0}   = Rd;
4108 }
4109
4110 // Supports B, H, and S element sizes.
4111 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4112                             SDPatternOperator OpNode> {
4113   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4114                                       asm, ".8b", ".8b",
4115                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4116   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4117                                       asm, ".16b", ".16b",
4118                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4119   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4120                                       asm, ".4h", ".4h",
4121                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4122   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4123                                       asm, ".8h", ".8h",
4124                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4125   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4126                                       asm, ".2s", ".2s",
4127                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4128   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4129                                       asm, ".4s", ".4s",
4130                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4131 }
4132
4133 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4134                             RegisterOperand regtype, string asm, string dstkind,
4135                             string srckind, string amount>
4136   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4137       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4138       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4139     Sched<[WriteV]> {
4140   bits<5> Rd;
4141   bits<5> Rn;
4142   let Inst{31}    = 0;
4143   let Inst{30}    = Q;
4144   let Inst{29-24} = 0b101110;
4145   let Inst{23-22} = size;
4146   let Inst{21-10} = 0b100001001110;
4147   let Inst{9-5}   = Rn;
4148   let Inst{4-0}   = Rd;
4149 }
4150
4151 multiclass SIMDVectorLShiftLongBySizeBHS {
4152   let neverHasSideEffects = 1 in {
4153   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4154                                              "shll", ".8h",  ".8b", "8">;
4155   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4156                                              "shll2", ".8h", ".16b", "8">;
4157   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4158                                              "shll", ".4s",  ".4h", "16">;
4159   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4160                                              "shll2", ".4s", ".8h", "16">;
4161   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4162                                              "shll", ".2d",  ".2s", "32">;
4163   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4164                                              "shll2", ".2d", ".4s", "32">;
4165   }
4166 }
4167
4168 // Supports all element sizes.
4169 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4170                              SDPatternOperator OpNode> {
4171   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4172                                       asm, ".4h", ".8b",
4173                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4174   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4175                                       asm, ".8h", ".16b",
4176                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4177   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4178                                       asm, ".2s", ".4h",
4179                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4180   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4181                                       asm, ".4s", ".8h",
4182                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4183   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4184                                       asm, ".1d", ".2s",
4185                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4186   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4187                                       asm, ".2d", ".4s",
4188                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4189 }
4190
4191 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4192                                  SDPatternOperator OpNode> {
4193   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4194                                           asm, ".4h", ".8b",
4195       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4196                                       (v8i8 V64:$Rn)))]>;
4197   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4198                                           asm, ".8h", ".16b",
4199       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4200                                       (v16i8 V128:$Rn)))]>;
4201   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4202                                           asm, ".2s", ".4h",
4203       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4204                                       (v4i16 V64:$Rn)))]>;
4205   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4206                                           asm, ".4s", ".8h",
4207       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4208                                       (v8i16 V128:$Rn)))]>;
4209   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4210                                           asm, ".1d", ".2s",
4211       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4212                                       (v2i32 V64:$Rn)))]>;
4213   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4214                                           asm, ".2d", ".4s",
4215       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4216                                       (v4i32 V128:$Rn)))]>;
4217 }
4218
4219 // Supports all element sizes, except 1xD.
4220 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4221                                   SDPatternOperator OpNode> {
4222   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4223                                     asm, ".8b", ".8b",
4224     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4225   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4226                                     asm, ".16b", ".16b",
4227     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4228   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4229                                     asm, ".4h", ".4h",
4230     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4231   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4232                                     asm, ".8h", ".8h",
4233     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4234   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4235                                     asm, ".2s", ".2s",
4236     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4237   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4238                                     asm, ".4s", ".4s",
4239     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4240   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4241                                     asm, ".2d", ".2d",
4242     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4243 }
4244
4245 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4246                              SDPatternOperator OpNode = null_frag> {
4247   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4248                                 asm, ".8b", ".8b",
4249     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4250   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4251                                 asm, ".16b", ".16b",
4252     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4253   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4254                                 asm, ".4h", ".4h",
4255     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4256   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4257                                 asm, ".8h", ".8h",
4258     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4259   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4260                                 asm, ".2s", ".2s",
4261     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4262   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4263                                 asm, ".4s", ".4s",
4264     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4265   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4266                                 asm, ".2d", ".2d",
4267     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4268 }
4269
4270
4271 // Supports only B element sizes.
4272 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4273                           SDPatternOperator OpNode> {
4274   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4275                                 asm, ".8b", ".8b",
4276                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4277   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4278                                 asm, ".16b", ".16b",
4279                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4280
4281 }
4282
4283 // Supports only B and H element sizes.
4284 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4285                                 SDPatternOperator OpNode> {
4286   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4287                                 asm, ".8b", ".8b",
4288                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4289   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4290                                 asm, ".16b", ".16b",
4291                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4292   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4293                                 asm, ".4h", ".4h",
4294                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4295   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4296                                 asm, ".8h", ".8h",
4297                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4298 }
4299
4300 // Supports only S and D element sizes, uses high bit of the size field
4301 // as an extra opcode bit.
4302 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4303                            SDPatternOperator OpNode> {
4304   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4305                                 asm, ".2s", ".2s",
4306                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4307   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4308                                 asm, ".4s", ".4s",
4309                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4310   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4311                                 asm, ".2d", ".2d",
4312                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4313 }
4314
4315 // Supports only S element size.
4316 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4317                            SDPatternOperator OpNode> {
4318   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4319                                 asm, ".2s", ".2s",
4320                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4321   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4322                                 asm, ".4s", ".4s",
4323                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4324 }
4325
4326
4327 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4328                            SDPatternOperator OpNode> {
4329   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4330                                 asm, ".2s", ".2s",
4331                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4332   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4333                                 asm, ".4s", ".4s",
4334                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4335   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4336                                 asm, ".2d", ".2d",
4337                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4338 }
4339
4340 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4341                            SDPatternOperator OpNode> {
4342   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4343                                 asm, ".2s", ".2s",
4344                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4345   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4346                                 asm, ".4s", ".4s",
4347                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4348   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4349                                 asm, ".2d", ".2d",
4350                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4351 }
4352
4353
4354 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4355                            RegisterOperand inreg, RegisterOperand outreg,
4356                            string asm, string outkind, string inkind,
4357                            list<dag> pattern>
4358   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4359       "{\t$Rd" # outkind # ", $Rn" # inkind #
4360       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4361     Sched<[WriteV]> {
4362   bits<5> Rd;
4363   bits<5> Rn;
4364   let Inst{31}    = 0;
4365   let Inst{30}    = Q;
4366   let Inst{29}    = U;
4367   let Inst{28-24} = 0b01110;
4368   let Inst{23-22} = size;
4369   let Inst{21-17} = 0b10000;
4370   let Inst{16-12} = opcode;
4371   let Inst{11-10} = 0b10;
4372   let Inst{9-5}   = Rn;
4373   let Inst{4-0}   = Rd;
4374 }
4375
4376 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4377                            RegisterOperand inreg, RegisterOperand outreg,
4378                            string asm, string outkind, string inkind,
4379                            list<dag> pattern>
4380   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4381       "{\t$Rd" # outkind # ", $Rn" # inkind #
4382       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4383     Sched<[WriteV]> {
4384   bits<5> Rd;
4385   bits<5> Rn;
4386   let Inst{31}    = 0;
4387   let Inst{30}    = Q;
4388   let Inst{29}    = U;
4389   let Inst{28-24} = 0b01110;
4390   let Inst{23-22} = size;
4391   let Inst{21-17} = 0b10000;
4392   let Inst{16-12} = opcode;
4393   let Inst{11-10} = 0b10;
4394   let Inst{9-5}   = Rn;
4395   let Inst{4-0}   = Rd;
4396 }
4397
4398 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4399                               SDPatternOperator OpNode> {
4400   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4401                                       asm, ".8b", ".8h",
4402         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4403   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4404                                       asm#"2", ".16b", ".8h", []>;
4405   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4406                                       asm, ".4h", ".4s",
4407         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4408   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4409                                       asm#"2", ".8h", ".4s", []>;
4410   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4411                                       asm, ".2s", ".2d",
4412         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4413   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4414                                       asm#"2", ".4s", ".2d", []>;
4415
4416   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4417             (!cast<Instruction>(NAME # "v16i8")
4418                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4419   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4420             (!cast<Instruction>(NAME # "v8i16")
4421                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4422   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4423             (!cast<Instruction>(NAME # "v4i32")
4424                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4425 }
4426
4427 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4428                            RegisterOperand regtype,
4429                            string asm, string kind, string zero,
4430                            ValueType dty, ValueType sty, SDNode OpNode>
4431   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4432       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4433       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4434       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4435     Sched<[WriteV]> {
4436   bits<5> Rd;
4437   bits<5> Rn;
4438   let Inst{31}    = 0;
4439   let Inst{30}    = Q;
4440   let Inst{29}    = U;
4441   let Inst{28-24} = 0b01110;
4442   let Inst{23-22} = size;
4443   let Inst{21-17} = 0b10000;
4444   let Inst{16-12} = opcode;
4445   let Inst{11-10} = 0b10;
4446   let Inst{9-5}   = Rn;
4447   let Inst{4-0}   = Rd;
4448 }
4449
4450 // Comparisons support all element sizes, except 1xD.
4451 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4452                             SDNode OpNode> {
4453   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4454                                      asm, ".8b", "0",
4455                                      v8i8, v8i8, OpNode>;
4456   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4457                                      asm, ".16b", "0",
4458                                      v16i8, v16i8, OpNode>;
4459   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4460                                      asm, ".4h", "0",
4461                                      v4i16, v4i16, OpNode>;
4462   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4463                                      asm, ".8h", "0",
4464                                      v8i16, v8i16, OpNode>;
4465   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4466                                      asm, ".2s", "0",
4467                                      v2i32, v2i32, OpNode>;
4468   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4469                                      asm, ".4s", "0",
4470                                      v4i32, v4i32, OpNode>;
4471   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4472                                      asm, ".2d", "0",
4473                                      v2i64, v2i64, OpNode>;
4474 }
4475
4476 // FP Comparisons support only S and D element sizes.
4477 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4478                               string asm, SDNode OpNode> {
4479
4480   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4481                                      asm, ".2s", "0.0",
4482                                      v2i32, v2f32, OpNode>;
4483   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4484                                      asm, ".4s", "0.0",
4485                                      v4i32, v4f32, OpNode>;
4486   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4487                                      asm, ".2d", "0.0",
4488                                      v2i64, v2f64, OpNode>;
4489
4490   def : InstAlias<asm # " $Vd.2s, $Vn.2s, #0",
4491                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4492   def : InstAlias<asm # " $Vd.4s, $Vn.4s, #0",
4493                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4494   def : InstAlias<asm # " $Vd.2d, $Vn.2d, #0",
4495                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4496   def : InstAlias<asm # ".2s $Vd, $Vn, #0",
4497                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4498   def : InstAlias<asm # ".4s $Vd, $Vn, #0",
4499                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4500   def : InstAlias<asm # ".2d $Vd, $Vn, #0",
4501                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4502 }
4503
4504 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4505 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4506                              RegisterOperand outtype, RegisterOperand intype,
4507                              string asm, string VdTy, string VnTy,
4508                              list<dag> pattern>
4509   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4510       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4511     Sched<[WriteV]> {
4512   bits<5> Rd;
4513   bits<5> Rn;
4514   let Inst{31}    = 0;
4515   let Inst{30}    = Q;
4516   let Inst{29}    = U;
4517   let Inst{28-24} = 0b01110;
4518   let Inst{23-22} = size;
4519   let Inst{21-17} = 0b10000;
4520   let Inst{16-12} = opcode;
4521   let Inst{11-10} = 0b10;
4522   let Inst{9-5}   = Rn;
4523   let Inst{4-0}   = Rd;
4524 }
4525
4526 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4527                              RegisterOperand outtype, RegisterOperand intype,
4528                              string asm, string VdTy, string VnTy,
4529                              list<dag> pattern>
4530   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4531       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4532     Sched<[WriteV]> {
4533   bits<5> Rd;
4534   bits<5> Rn;
4535   let Inst{31}    = 0;
4536   let Inst{30}    = Q;
4537   let Inst{29}    = U;
4538   let Inst{28-24} = 0b01110;
4539   let Inst{23-22} = size;
4540   let Inst{21-17} = 0b10000;
4541   let Inst{16-12} = opcode;
4542   let Inst{11-10} = 0b10;
4543   let Inst{9-5}   = Rn;
4544   let Inst{4-0}   = Rd;
4545 }
4546
4547 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4548   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4549                                     asm, ".4s", ".4h", []>;
4550   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4551                                     asm#"2", ".4s", ".8h", []>;
4552   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4553                                     asm, ".2d", ".2s", []>;
4554   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4555                                     asm#"2", ".2d", ".4s", []>;
4556 }
4557
4558 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4559   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4560                                     asm, ".4h", ".4s", []>;
4561   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4562                                     asm#"2", ".8h", ".4s", []>;
4563   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4564                                     asm, ".2s", ".2d", []>;
4565   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4566                                     asm#"2", ".4s", ".2d", []>;
4567 }
4568
4569 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4570                                      Intrinsic OpNode> {
4571   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4572                                      asm, ".2s", ".2d",
4573                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4574   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4575                                     asm#"2", ".4s", ".2d", []>;
4576
4577   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4578             (!cast<Instruction>(NAME # "v4f32")
4579                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4580 }
4581
4582 //----------------------------------------------------------------------------
4583 // AdvSIMD three register different-size vector instructions.
4584 //----------------------------------------------------------------------------
4585
4586 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4587 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4588                       RegisterOperand outtype, RegisterOperand intype1,
4589                       RegisterOperand intype2, string asm,
4590                       string outkind, string inkind1, string inkind2,
4591                       list<dag> pattern>
4592   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4593       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4594       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4595     Sched<[WriteV]> {
4596   bits<5> Rd;
4597   bits<5> Rn;
4598   bits<5> Rm;
4599   let Inst{31}    = 0;
4600   let Inst{30}    = size{0};
4601   let Inst{29}    = U;
4602   let Inst{28-24} = 0b01110;
4603   let Inst{23-22} = size{2-1};
4604   let Inst{21}    = 1;
4605   let Inst{20-16} = Rm;
4606   let Inst{15-12} = opcode;
4607   let Inst{11-10} = 0b00;
4608   let Inst{9-5}   = Rn;
4609   let Inst{4-0}   = Rd;
4610 }
4611
4612 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4613 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4614                       RegisterOperand outtype, RegisterOperand intype1,
4615                       RegisterOperand intype2, string asm,
4616                       string outkind, string inkind1, string inkind2,
4617                       list<dag> pattern>
4618   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4619       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4620       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4621     Sched<[WriteV]> {
4622   bits<5> Rd;
4623   bits<5> Rn;
4624   bits<5> Rm;
4625   let Inst{31}    = 0;
4626   let Inst{30}    = size{0};
4627   let Inst{29}    = U;
4628   let Inst{28-24} = 0b01110;
4629   let Inst{23-22} = size{2-1};
4630   let Inst{21}    = 1;
4631   let Inst{20-16} = Rm;
4632   let Inst{15-12} = opcode;
4633   let Inst{11-10} = 0b00;
4634   let Inst{9-5}   = Rn;
4635   let Inst{4-0}   = Rd;
4636 }
4637
4638 // FIXME: TableGen doesn't know how to deal with expanded types that also
4639 //        change the element count (in this case, placing the results in
4640 //        the high elements of the result register rather than the low
4641 //        elements). Until that's fixed, we can't code-gen those.
4642 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4643                                     Intrinsic IntOp> {
4644   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4645                                                   V64, V128, V128,
4646                                                   asm, ".8b", ".8h", ".8h",
4647      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4648   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4649                                                   V128, V128, V128,
4650                                                   asm#"2", ".16b", ".8h", ".8h",
4651      []>;
4652   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4653                                                   V64, V128, V128,
4654                                                   asm, ".4h", ".4s", ".4s",
4655      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4656   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4657                                                   V128, V128, V128,
4658                                                   asm#"2", ".8h", ".4s", ".4s",
4659      []>;
4660   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4661                                                   V64, V128, V128,
4662                                                   asm, ".2s", ".2d", ".2d",
4663      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4664   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4665                                                   V128, V128, V128,
4666                                                   asm#"2", ".4s", ".2d", ".2d",
4667      []>;
4668
4669
4670   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4671   // a version attached to an instruction.
4672   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4673                                                    (v8i16 V128:$Rm))),
4674             (!cast<Instruction>(NAME # "v8i16_v16i8")
4675                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4676                 V128:$Rn, V128:$Rm)>;
4677   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4678                                                     (v4i32 V128:$Rm))),
4679             (!cast<Instruction>(NAME # "v4i32_v8i16")
4680                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4681                 V128:$Rn, V128:$Rm)>;
4682   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4683                                                     (v2i64 V128:$Rm))),
4684             (!cast<Instruction>(NAME # "v2i64_v4i32")
4685                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4686                 V128:$Rn, V128:$Rm)>;
4687 }
4688
4689 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4690                                       Intrinsic IntOp> {
4691   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4692                                             V128, V64, V64,
4693                                             asm, ".8h", ".8b", ".8b",
4694       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4695   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4696                                             V128, V128, V128,
4697                                             asm#"2", ".8h", ".16b", ".16b", []>;
4698   let Predicates = [HasCrypto] in {
4699     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4700                                               V128, V64, V64,
4701                                               asm, ".1q", ".1d", ".1d", []>;
4702     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4703                                               V128, V128, V128,
4704                                               asm#"2", ".1q", ".2d", ".2d", []>;
4705   }
4706
4707   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4708                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
4709       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4710 }
4711
4712 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4713                                  SDPatternOperator OpNode> {
4714   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4715                                                   V128, V64, V64,
4716                                                   asm, ".4s", ".4h", ".4h",
4717       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4718   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4719                                                   V128, V128, V128,
4720                                                   asm#"2", ".4s", ".8h", ".8h",
4721       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4722                                       (extract_high_v8i16 V128:$Rm)))]>;
4723   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4724                                                   V128, V64, V64,
4725                                                   asm, ".2d", ".2s", ".2s",
4726       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4727   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4728                                                   V128, V128, V128,
4729                                                   asm#"2", ".2d", ".4s", ".4s",
4730       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4731                                       (extract_high_v4i32 V128:$Rm)))]>;
4732 }
4733
4734 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4735                                   SDPatternOperator OpNode = null_frag> {
4736   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4737                                                   V128, V64, V64,
4738                                                   asm, ".8h", ".8b", ".8b",
4739       [(set (v8i16 V128:$Rd),
4740             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4741   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4742                                                  V128, V128, V128,
4743                                                  asm#"2", ".8h", ".16b", ".16b",
4744       [(set (v8i16 V128:$Rd),
4745             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4746                                 (extract_high_v16i8 V128:$Rm)))))]>;
4747   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4748                                                   V128, V64, V64,
4749                                                   asm, ".4s", ".4h", ".4h",
4750       [(set (v4i32 V128:$Rd),
4751             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4752   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4753                                                   V128, V128, V128,
4754                                                   asm#"2", ".4s", ".8h", ".8h",
4755       [(set (v4i32 V128:$Rd),
4756             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4757                                   (extract_high_v8i16 V128:$Rm)))))]>;
4758   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4759                                                   V128, V64, V64,
4760                                                   asm, ".2d", ".2s", ".2s",
4761       [(set (v2i64 V128:$Rd),
4762             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4763   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4764                                                   V128, V128, V128,
4765                                                   asm#"2", ".2d", ".4s", ".4s",
4766       [(set (v2i64 V128:$Rd),
4767             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4768                                  (extract_high_v4i32 V128:$Rm)))))]>;
4769 }
4770
4771 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4772                                           string asm,
4773                                           SDPatternOperator OpNode> {
4774   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4775                                                   V128, V64, V64,
4776                                                   asm, ".8h", ".8b", ".8b",
4777     [(set (v8i16 V128:$dst),
4778           (add (v8i16 V128:$Rd),
4779                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4780   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4781                                                  V128, V128, V128,
4782                                                  asm#"2", ".8h", ".16b", ".16b",
4783     [(set (v8i16 V128:$dst),
4784           (add (v8i16 V128:$Rd),
4785                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4786                                    (extract_high_v16i8 V128:$Rm))))))]>;
4787   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4788                                                   V128, V64, V64,
4789                                                   asm, ".4s", ".4h", ".4h",
4790     [(set (v4i32 V128:$dst),
4791           (add (v4i32 V128:$Rd),
4792                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4793   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4794                                                   V128, V128, V128,
4795                                                   asm#"2", ".4s", ".8h", ".8h",
4796     [(set (v4i32 V128:$dst),
4797           (add (v4i32 V128:$Rd),
4798                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4799                                     (extract_high_v8i16 V128:$Rm))))))]>;
4800   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4801                                                   V128, V64, V64,
4802                                                   asm, ".2d", ".2s", ".2s",
4803     [(set (v2i64 V128:$dst),
4804           (add (v2i64 V128:$Rd),
4805                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4806   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4807                                                   V128, V128, V128,
4808                                                   asm#"2", ".2d", ".4s", ".4s",
4809     [(set (v2i64 V128:$dst),
4810           (add (v2i64 V128:$Rd),
4811                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4812                                     (extract_high_v4i32 V128:$Rm))))))]>;
4813 }
4814
4815 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4816                                   SDPatternOperator OpNode = null_frag> {
4817   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4818                                                   V128, V64, V64,
4819                                                   asm, ".8h", ".8b", ".8b",
4820       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4821   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4822                                                  V128, V128, V128,
4823                                                  asm#"2", ".8h", ".16b", ".16b",
4824       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4825                                       (extract_high_v16i8 V128:$Rm)))]>;
4826   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4827                                                   V128, V64, V64,
4828                                                   asm, ".4s", ".4h", ".4h",
4829       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4830   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4831                                                   V128, V128, V128,
4832                                                   asm#"2", ".4s", ".8h", ".8h",
4833       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4834                                       (extract_high_v8i16 V128:$Rm)))]>;
4835   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4836                                                   V128, V64, V64,
4837                                                   asm, ".2d", ".2s", ".2s",
4838       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4839   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4840                                                   V128, V128, V128,
4841                                                   asm#"2", ".2d", ".4s", ".4s",
4842       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4843                                       (extract_high_v4i32 V128:$Rm)))]>;
4844 }
4845
4846 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4847                                       string asm,
4848                                       SDPatternOperator OpNode> {
4849   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4850                                                   V128, V64, V64,
4851                                                   asm, ".8h", ".8b", ".8b",
4852     [(set (v8i16 V128:$dst),
4853           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4854   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4855                                                  V128, V128, V128,
4856                                                  asm#"2", ".8h", ".16b", ".16b",
4857     [(set (v8i16 V128:$dst),
4858           (OpNode (v8i16 V128:$Rd),
4859                   (extract_high_v16i8 V128:$Rn),
4860                   (extract_high_v16i8 V128:$Rm)))]>;
4861   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4862                                                   V128, V64, V64,
4863                                                   asm, ".4s", ".4h", ".4h",
4864     [(set (v4i32 V128:$dst),
4865           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4866   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4867                                                   V128, V128, V128,
4868                                                   asm#"2", ".4s", ".8h", ".8h",
4869     [(set (v4i32 V128:$dst),
4870           (OpNode (v4i32 V128:$Rd),
4871                   (extract_high_v8i16 V128:$Rn),
4872                   (extract_high_v8i16 V128:$Rm)))]>;
4873   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4874                                                   V128, V64, V64,
4875                                                   asm, ".2d", ".2s", ".2s",
4876     [(set (v2i64 V128:$dst),
4877           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4878   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4879                                                   V128, V128, V128,
4880                                                   asm#"2", ".2d", ".4s", ".4s",
4881     [(set (v2i64 V128:$dst),
4882           (OpNode (v2i64 V128:$Rd),
4883                   (extract_high_v4i32 V128:$Rn),
4884                   (extract_high_v4i32 V128:$Rm)))]>;
4885 }
4886
4887 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4888                                            SDPatternOperator Accum> {
4889   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4890                                                   V128, V64, V64,
4891                                                   asm, ".4s", ".4h", ".4h",
4892     [(set (v4i32 V128:$dst),
4893           (Accum (v4i32 V128:$Rd),
4894                  (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4895                                                 (v4i16 V64:$Rm)))))]>;
4896   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4897                                                   V128, V128, V128,
4898                                                   asm#"2", ".4s", ".8h", ".8h",
4899     [(set (v4i32 V128:$dst),
4900           (Accum (v4i32 V128:$Rd),
4901                  (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4902                                             (extract_high_v8i16 V128:$Rm)))))]>;
4903   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4904                                                   V128, V64, V64,
4905                                                   asm, ".2d", ".2s", ".2s",
4906     [(set (v2i64 V128:$dst),
4907           (Accum (v2i64 V128:$Rd),
4908                  (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4909                                                 (v2i32 V64:$Rm)))))]>;
4910   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4911                                                   V128, V128, V128,
4912                                                   asm#"2", ".2d", ".4s", ".4s",
4913     [(set (v2i64 V128:$dst),
4914           (Accum (v2i64 V128:$Rd),
4915                  (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4916                                             (extract_high_v4i32 V128:$Rm)))))]>;
4917 }
4918
4919 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4920                                   SDPatternOperator OpNode> {
4921   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4922                                                   V128, V128, V64,
4923                                                   asm, ".8h", ".8h", ".8b",
4924        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4925   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4926                                                   V128, V128, V128,
4927                                                   asm#"2", ".8h", ".8h", ".16b",
4928        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4929                                        (extract_high_v16i8 V128:$Rm)))]>;
4930   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4931                                                   V128, V128, V64,
4932                                                   asm, ".4s", ".4s", ".4h",
4933        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
4934   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4935                                                   V128, V128, V128,
4936                                                   asm#"2", ".4s", ".4s", ".8h",
4937        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
4938                                        (extract_high_v8i16 V128:$Rm)))]>;
4939   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4940                                                   V128, V128, V64,
4941                                                   asm, ".2d", ".2d", ".2s",
4942        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
4943   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4944                                                   V128, V128, V128,
4945                                                   asm#"2", ".2d", ".2d", ".4s",
4946        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
4947                                        (extract_high_v4i32 V128:$Rm)))]>;
4948 }
4949
4950 //----------------------------------------------------------------------------
4951 // AdvSIMD bitwise extract from vector
4952 //----------------------------------------------------------------------------
4953
4954 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
4955                              string asm, string kind>
4956   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
4957       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
4958       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
4959       [(set (vty regtype:$Rd),
4960             (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
4961     Sched<[WriteV]> {
4962   bits<5> Rd;
4963   bits<5> Rn;
4964   bits<5> Rm;
4965   bits<4> imm;
4966   let Inst{31}    = 0;
4967   let Inst{30}    = size;
4968   let Inst{29-21} = 0b101110000;
4969   let Inst{20-16} = Rm;
4970   let Inst{15}    = 0;
4971   let Inst{14-11} = imm;
4972   let Inst{10}    = 0;
4973   let Inst{9-5}   = Rn;
4974   let Inst{4-0}   = Rd;
4975 }
4976
4977
4978 multiclass SIMDBitwiseExtract<string asm> {
4979   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
4980     let imm{3} = 0;
4981   }
4982   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
4983 }
4984
4985 //----------------------------------------------------------------------------
4986 // AdvSIMD zip vector
4987 //----------------------------------------------------------------------------
4988
4989 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
4990                         string asm, string kind, SDNode OpNode, ValueType valty>
4991   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4992       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4993       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
4994       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
4995     Sched<[WriteV]> {
4996   bits<5> Rd;
4997   bits<5> Rn;
4998   bits<5> Rm;
4999   let Inst{31}    = 0;
5000   let Inst{30}    = size{0};
5001   let Inst{29-24} = 0b001110;
5002   let Inst{23-22} = size{2-1};
5003   let Inst{21}    = 0;
5004   let Inst{20-16} = Rm;
5005   let Inst{15}    = 0;
5006   let Inst{14-12} = opc;
5007   let Inst{11-10} = 0b10;
5008   let Inst{9-5}   = Rn;
5009   let Inst{4-0}   = Rd;
5010 }
5011
5012 multiclass SIMDZipVector<bits<3>opc, string asm,
5013                          SDNode OpNode> {
5014   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5015       asm, ".8b", OpNode, v8i8>;
5016   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5017       asm, ".16b", OpNode, v16i8>;
5018   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5019       asm, ".4h", OpNode, v4i16>;
5020   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5021       asm, ".8h", OpNode, v8i16>;
5022   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5023       asm, ".2s", OpNode, v2i32>;
5024   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5025       asm, ".4s", OpNode, v4i32>;
5026   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5027       asm, ".2d", OpNode, v2i64>;
5028
5029   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5030         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5031   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5032         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5033   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5034         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5035 }
5036
5037 //----------------------------------------------------------------------------
5038 // AdvSIMD three register scalar instructions
5039 //----------------------------------------------------------------------------
5040
5041 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5042 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5043                         RegisterClass regtype, string asm,
5044                         list<dag> pattern>
5045   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5046       "\t$Rd, $Rn, $Rm", "", pattern>,
5047     Sched<[WriteV]> {
5048   bits<5> Rd;
5049   bits<5> Rn;
5050   bits<5> Rm;
5051   let Inst{31-30} = 0b01;
5052   let Inst{29}    = U;
5053   let Inst{28-24} = 0b11110;
5054   let Inst{23-22} = size;
5055   let Inst{21}    = 1;
5056   let Inst{20-16} = Rm;
5057   let Inst{15-11} = opcode;
5058   let Inst{10}    = 1;
5059   let Inst{9-5}   = Rn;
5060   let Inst{4-0}   = Rd;
5061 }
5062
5063 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5064                             SDPatternOperator OpNode> {
5065   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5066     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5067 }
5068
5069 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5070                                SDPatternOperator OpNode> {
5071   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5072     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5073   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5074   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5075   def v1i8   : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5076
5077   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5078             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5079   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5080             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5081 }
5082
5083 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5084                              SDPatternOperator OpNode> {
5085   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5086                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5087   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5088 }
5089
5090 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5091                              SDPatternOperator OpNode = null_frag> {
5092   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5093     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5094       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5095     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5096       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5097   }
5098
5099   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5100             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5101 }
5102
5103 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5104                                 SDPatternOperator OpNode = null_frag> {
5105   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5106     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5107       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5108     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5109       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5110   }
5111
5112   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5113             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5114 }
5115
5116 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5117               dag oops, dag iops, string asm, string cstr, list<dag> pat>
5118   : I<oops, iops, asm,
5119       "\t$Rd, $Rn, $Rm", cstr, pat>,
5120     Sched<[WriteV]> {
5121   bits<5> Rd;
5122   bits<5> Rn;
5123   bits<5> Rm;
5124   let Inst{31-30} = 0b01;
5125   let Inst{29}    = U;
5126   let Inst{28-24} = 0b11110;
5127   let Inst{23-22} = size;
5128   let Inst{21}    = 1;
5129   let Inst{20-16} = Rm;
5130   let Inst{15-11} = opcode;
5131   let Inst{10}    = 0;
5132   let Inst{9-5}   = Rn;
5133   let Inst{4-0}   = Rd;
5134 }
5135
5136 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5137 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5138                                   SDPatternOperator OpNode = null_frag> {
5139   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5140                                       (outs FPR32:$Rd),
5141                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5142   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5143                                       (outs FPR64:$Rd),
5144                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5145             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5146 }
5147
5148 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5149 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5150                                   SDPatternOperator OpNode = null_frag> {
5151   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5152                                       (outs FPR32:$dst),
5153                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5154                                       asm, "$Rd = $dst", []>;
5155   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5156                                       (outs FPR64:$dst),
5157                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5158                                       asm, "$Rd = $dst",
5159             [(set (i64 FPR64:$dst),
5160                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5161 }
5162
5163 //----------------------------------------------------------------------------
5164 // AdvSIMD two register scalar instructions
5165 //----------------------------------------------------------------------------
5166
5167 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5168 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5169                         RegisterClass regtype, RegisterClass regtype2,
5170                         string asm, list<dag> pat>
5171   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5172       "\t$Rd, $Rn", "", pat>,
5173     Sched<[WriteV]> {
5174   bits<5> Rd;
5175   bits<5> Rn;
5176   let Inst{31-30} = 0b01;
5177   let Inst{29}    = U;
5178   let Inst{28-24} = 0b11110;
5179   let Inst{23-22} = size;
5180   let Inst{21-17} = 0b10000;
5181   let Inst{16-12} = opcode;
5182   let Inst{11-10} = 0b10;
5183   let Inst{9-5}   = Rn;
5184   let Inst{4-0}   = Rd;
5185 }
5186
5187 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5188 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5189                         RegisterClass regtype, RegisterClass regtype2,
5190                         string asm, list<dag> pat>
5191   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5192       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5193     Sched<[WriteV]> {
5194   bits<5> Rd;
5195   bits<5> Rn;
5196   let Inst{31-30} = 0b01;
5197   let Inst{29}    = U;
5198   let Inst{28-24} = 0b11110;
5199   let Inst{23-22} = size;
5200   let Inst{21-17} = 0b10000;
5201   let Inst{16-12} = opcode;
5202   let Inst{11-10} = 0b10;
5203   let Inst{9-5}   = Rn;
5204   let Inst{4-0}   = Rd;
5205 }
5206
5207
5208 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5209 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5210                         RegisterClass regtype, string asm, string zero>
5211   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5212       "\t$Rd, $Rn, #" # zero, "", []>,
5213     Sched<[WriteV]> {
5214   bits<5> Rd;
5215   bits<5> Rn;
5216   let Inst{31-30} = 0b01;
5217   let Inst{29}    = U;
5218   let Inst{28-24} = 0b11110;
5219   let Inst{23-22} = size;
5220   let Inst{21-17} = 0b10000;
5221   let Inst{16-12} = opcode;
5222   let Inst{11-10} = 0b10;
5223   let Inst{9-5}   = Rn;
5224   let Inst{4-0}   = Rd;
5225 }
5226
5227 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5228   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5229      [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5230     Sched<[WriteV]> {
5231   bits<5> Rd;
5232   bits<5> Rn;
5233   let Inst{31-17} = 0b011111100110000;
5234   let Inst{16-12} = opcode;
5235   let Inst{11-10} = 0b10;
5236   let Inst{9-5}   = Rn;
5237   let Inst{4-0}   = Rd;
5238 }
5239
5240 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5241                              SDPatternOperator OpNode> {
5242   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5243
5244   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5245             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5246 }
5247
5248 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5249                               SDPatternOperator OpNode> {
5250   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5251   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5252
5253   def : InstAlias<asm # " $Rd, $Rn, #0",
5254                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn)>;
5255   def : InstAlias<asm # " $Rd, $Rn, #0",
5256                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn)>;
5257
5258   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5259             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5260 }
5261
5262 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5263                           SDPatternOperator OpNode = null_frag> {
5264   def v1i64       : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5265     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5266
5267   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5268             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5269 }
5270
5271 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5272   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5273   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5274 }
5275
5276 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5277                               SDPatternOperator OpNode> {
5278   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5279                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5280   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5281                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5282 }
5283
5284 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5285                              SDPatternOperator OpNode = null_frag> {
5286   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5287     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5288            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5289     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5290            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5291     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5292     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5293   }
5294
5295   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5296             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5297 }
5298
5299 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5300                                  Intrinsic OpNode> {
5301   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5302     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5303         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5304     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5305         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5306     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5307     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5308   }
5309
5310   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5311             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5312 }
5313
5314
5315
5316 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5317 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5318                                  SDPatternOperator OpNode = null_frag> {
5319   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5320         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5321   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5322   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5323 }
5324
5325 //----------------------------------------------------------------------------
5326 // AdvSIMD scalar pairwise instructions
5327 //----------------------------------------------------------------------------
5328
5329 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5330 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5331                         RegisterOperand regtype, RegisterOperand vectype,
5332                         string asm, string kind>
5333   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5334       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5335     Sched<[WriteV]> {
5336   bits<5> Rd;
5337   bits<5> Rn;
5338   let Inst{31-30} = 0b01;
5339   let Inst{29}    = U;
5340   let Inst{28-24} = 0b11110;
5341   let Inst{23-22} = size;
5342   let Inst{21-17} = 0b11000;
5343   let Inst{16-12} = opcode;
5344   let Inst{11-10} = 0b10;
5345   let Inst{9-5}   = Rn;
5346   let Inst{4-0}   = Rd;
5347 }
5348
5349 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5350   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5351                                       asm, ".2d">;
5352 }
5353
5354 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5355   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5356                                       asm, ".2s">;
5357   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5358                                       asm, ".2d">;
5359 }
5360
5361 //----------------------------------------------------------------------------
5362 // AdvSIMD across lanes instructions
5363 //----------------------------------------------------------------------------
5364
5365 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5366 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5367                           RegisterClass regtype, RegisterOperand vectype,
5368                           string asm, string kind, list<dag> pattern>
5369   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5370       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5371     Sched<[WriteV]> {
5372   bits<5> Rd;
5373   bits<5> Rn;
5374   let Inst{31}    = 0;
5375   let Inst{30}    = Q;
5376   let Inst{29}    = U;
5377   let Inst{28-24} = 0b01110;
5378   let Inst{23-22} = size;
5379   let Inst{21-17} = 0b11000;
5380   let Inst{16-12} = opcode;
5381   let Inst{11-10} = 0b10;
5382   let Inst{9-5}   = Rn;
5383   let Inst{4-0}   = Rd;
5384 }
5385
5386 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5387                               string asm> {
5388   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5389                                    asm, ".8b", []>;
5390   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5391                                    asm, ".16b", []>;
5392   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5393                                    asm, ".4h", []>;
5394   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5395                                    asm, ".8h", []>;
5396   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5397                                    asm, ".4s", []>;
5398 }
5399
5400 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5401   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5402                                    asm, ".8b", []>;
5403   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5404                                    asm, ".16b", []>;
5405   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5406                                    asm, ".4h", []>;
5407   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5408                                    asm, ".8h", []>;
5409   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5410                                    asm, ".4s", []>;
5411 }
5412
5413 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5414                             Intrinsic intOp> {
5415   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5416                                    asm, ".4s",
5417         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5418 }
5419
5420 //----------------------------------------------------------------------------
5421 // AdvSIMD INS/DUP instructions
5422 //----------------------------------------------------------------------------
5423
5424 // FIXME: There has got to be a better way to factor these. ugh.
5425
5426 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5427                      string operands, string constraints, list<dag> pattern>
5428   : I<outs, ins, asm, operands, constraints, pattern>,
5429     Sched<[WriteV]> {
5430   bits<5> Rd;
5431   bits<5> Rn;
5432   let Inst{31} = 0;
5433   let Inst{30} = Q;
5434   let Inst{29} = op;
5435   let Inst{28-21} = 0b01110000;
5436   let Inst{15} = 0;
5437   let Inst{10} = 1;
5438   let Inst{9-5} = Rn;
5439   let Inst{4-0} = Rd;
5440 }
5441
5442 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5443                       RegisterOperand vecreg, RegisterClass regtype>
5444   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5445                    "{\t$Rd" # size # ", $Rn" #
5446                    "|" # size # "\t$Rd, $Rn}", "",
5447                    [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5448   let Inst{20-16} = imm5;
5449   let Inst{14-11} = 0b0001;
5450 }
5451
5452 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5453                          ValueType vectype, ValueType insreg,
5454                          RegisterOperand vecreg, Operand idxtype,
5455                          ValueType elttype, SDNode OpNode>
5456   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5457                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5458                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5459                  [(set (vectype vecreg:$Rd),
5460                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5461   let Inst{14-11} = 0b0000;
5462 }
5463
5464 class SIMDDup64FromElement
5465   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5466                        VectorIndexD, i64, ARM64duplane64> {
5467   bits<1> idx;
5468   let Inst{20} = idx;
5469   let Inst{19-16} = 0b1000;
5470 }
5471
5472 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5473                            RegisterOperand vecreg>
5474   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5475                        VectorIndexS, i64, ARM64duplane32> {
5476   bits<2> idx;
5477   let Inst{20-19} = idx;
5478   let Inst{18-16} = 0b100;
5479 }
5480
5481 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5482                            RegisterOperand vecreg>
5483   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5484                        VectorIndexH, i64, ARM64duplane16> {
5485   bits<3> idx;
5486   let Inst{20-18} = idx;
5487   let Inst{17-16} = 0b10;
5488 }
5489
5490 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5491                           RegisterOperand vecreg>
5492   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5493                        VectorIndexB, i64, ARM64duplane8> {
5494   bits<4> idx;
5495   let Inst{20-17} = idx;
5496   let Inst{16} = 1;
5497 }
5498
5499 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5500                   Operand idxtype, string asm, list<dag> pattern>
5501   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5502                    "{\t$Rd, $Rn" # size # "$idx" #
5503                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5504   let Inst{14-11} = imm4;
5505 }
5506
5507 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5508                Operand idxtype>
5509   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5510 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5511                Operand idxtype>
5512   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5513       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5514
5515 class SIMDMovAlias<string asm, string size, Instruction inst,
5516                    RegisterClass regtype, Operand idxtype>
5517     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5518                     "|" # size # "\t$dst, $src$idx}",
5519                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5520
5521 multiclass SMov {
5522   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5523     bits<4> idx;
5524     let Inst{20-17} = idx;
5525     let Inst{16} = 1;
5526   }
5527   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5528     bits<4> idx;
5529     let Inst{20-17} = idx;
5530     let Inst{16} = 1;
5531   }
5532   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5533     bits<3> idx;
5534     let Inst{20-18} = idx;
5535     let Inst{17-16} = 0b10;
5536   }
5537   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5538     bits<3> idx;
5539     let Inst{20-18} = idx;
5540     let Inst{17-16} = 0b10;
5541   }
5542   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5543     bits<2> idx;
5544     let Inst{20-19} = idx;
5545     let Inst{18-16} = 0b100;
5546   }
5547 }
5548
5549 multiclass UMov {
5550   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5551     bits<4> idx;
5552     let Inst{20-17} = idx;
5553     let Inst{16} = 1;
5554   }
5555   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5556     bits<3> idx;
5557     let Inst{20-18} = idx;
5558     let Inst{17-16} = 0b10;
5559   }
5560   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5561     bits<2> idx;
5562     let Inst{20-19} = idx;
5563     let Inst{18-16} = 0b100;
5564   }
5565   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5566     bits<1> idx;
5567     let Inst{20} = idx;
5568     let Inst{19-16} = 0b1000;
5569   }
5570   def : SIMDMovAlias<"mov", ".s",
5571                      !cast<Instruction>(NAME#"vi32"),
5572                      GPR32, VectorIndexS>;
5573   def : SIMDMovAlias<"mov", ".d",
5574                      !cast<Instruction>(NAME#"vi64"),
5575                      GPR64, VectorIndexD>;
5576 }
5577
5578 class SIMDInsFromMain<string size, ValueType vectype,
5579                       RegisterClass regtype, Operand idxtype>
5580   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5581                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5582                    "{\t$Rd" # size # "$idx, $Rn" #
5583                    "|" # size # "\t$Rd$idx, $Rn}",
5584                    "$Rd = $dst",
5585             [(set V128:$dst,
5586               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5587   let Inst{14-11} = 0b0011;
5588 }
5589
5590 class SIMDInsFromElement<string size, ValueType vectype,
5591                          ValueType elttype, Operand idxtype>
5592   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5593                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5594                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5595                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
5596                    "$Rd = $dst",
5597          [(set V128:$dst,
5598                (vector_insert
5599                  (vectype V128:$Rd),
5600                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5601                  idxtype:$idx))]>;
5602
5603 class SIMDInsMainMovAlias<string size, Instruction inst,
5604                           RegisterClass regtype, Operand idxtype>
5605     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5606                         "|" # size #"\t$dst$idx, $src}",
5607                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5608 class SIMDInsElementMovAlias<string size, Instruction inst,
5609                              Operand idxtype>
5610     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5611                       # "|" # size #" $dst$idx, $src$idx2}",
5612                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5613
5614
5615 multiclass SIMDIns {
5616   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5617     bits<4> idx;
5618     let Inst{20-17} = idx;
5619     let Inst{16} = 1;
5620   }
5621   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5622     bits<3> idx;
5623     let Inst{20-18} = idx;
5624     let Inst{17-16} = 0b10;
5625   }
5626   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5627     bits<2> idx;
5628     let Inst{20-19} = idx;
5629     let Inst{18-16} = 0b100;
5630   }
5631   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5632     bits<1> idx;
5633     let Inst{20} = idx;
5634     let Inst{19-16} = 0b1000;
5635   }
5636
5637   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5638     bits<4> idx;
5639     bits<4> idx2;
5640     let Inst{20-17} = idx;
5641     let Inst{16} = 1;
5642     let Inst{14-11} = idx2;
5643   }
5644   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5645     bits<3> idx;
5646     bits<3> idx2;
5647     let Inst{20-18} = idx;
5648     let Inst{17-16} = 0b10;
5649     let Inst{14-12} = idx2;
5650     let Inst{11} = 0;
5651   }
5652   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5653     bits<2> idx;
5654     bits<2> idx2;
5655     let Inst{20-19} = idx;
5656     let Inst{18-16} = 0b100;
5657     let Inst{14-13} = idx2;
5658     let Inst{12-11} = 0;
5659   }
5660   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5661     bits<1> idx;
5662     bits<1> idx2;
5663     let Inst{20} = idx;
5664     let Inst{19-16} = 0b1000;
5665     let Inst{14} = idx2;
5666     let Inst{13-11} = 0;
5667   }
5668
5669   // For all forms of the INS instruction, the "mov" mnemonic is the
5670   // preferred alias. Why they didn't just call the instruction "mov" in
5671   // the first place is a very good question indeed...
5672   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5673                          GPR32, VectorIndexB>;
5674   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5675                          GPR32, VectorIndexH>;
5676   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5677                          GPR32, VectorIndexS>;
5678   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5679                          GPR64, VectorIndexD>;
5680
5681   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5682                          VectorIndexB>;
5683   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5684                          VectorIndexH>;
5685   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5686                          VectorIndexS>;
5687   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5688                          VectorIndexD>;
5689 }
5690
5691 //----------------------------------------------------------------------------
5692 // AdvSIMD TBL/TBX
5693 //----------------------------------------------------------------------------
5694
5695 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5696 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5697                           RegisterOperand listtype, string asm, string kind>
5698   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5699        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5700     Sched<[WriteV]> {
5701   bits<5> Vd;
5702   bits<5> Vn;
5703   bits<5> Vm;
5704   let Inst{31}    = 0;
5705   let Inst{30}    = Q;
5706   let Inst{29-21} = 0b001110000;
5707   let Inst{20-16} = Vm;
5708   let Inst{15}    = 0;
5709   let Inst{14-13} = len;
5710   let Inst{12}    = op;
5711   let Inst{11-10} = 0b00;
5712   let Inst{9-5}   = Vn;
5713   let Inst{4-0}   = Vd;
5714 }
5715
5716 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5717 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5718                           RegisterOperand listtype, string asm, string kind>
5719   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5720        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5721     Sched<[WriteV]> {
5722   bits<5> Vd;
5723   bits<5> Vn;
5724   bits<5> Vm;
5725   let Inst{31}    = 0;
5726   let Inst{30}    = Q;
5727   let Inst{29-21} = 0b001110000;
5728   let Inst{20-16} = Vm;
5729   let Inst{15}    = 0;
5730   let Inst{14-13} = len;
5731   let Inst{12}    = op;
5732   let Inst{11-10} = 0b00;
5733   let Inst{9-5}   = Vn;
5734   let Inst{4-0}   = Vd;
5735 }
5736
5737 class SIMDTableLookupAlias<string asm, Instruction inst,
5738                           RegisterOperand vectype, RegisterOperand listtype>
5739     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5740                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5741
5742 multiclass SIMDTableLookup<bit op, string asm> {
5743   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5744                                       asm, ".8b">;
5745   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5746                                       asm, ".8b">;
5747   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5748                                       asm, ".8b">;
5749   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5750                                       asm, ".8b">;
5751   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5752                                       asm, ".16b">;
5753   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5754                                       asm, ".16b">;
5755   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5756                                       asm, ".16b">;
5757   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5758                                       asm, ".16b">;
5759
5760   def : SIMDTableLookupAlias<asm # ".8b",
5761                          !cast<Instruction>(NAME#"v8i8One"),
5762                          V64, VecListOne128>;
5763   def : SIMDTableLookupAlias<asm # ".8b",
5764                          !cast<Instruction>(NAME#"v8i8Two"),
5765                          V64, VecListTwo128>;
5766   def : SIMDTableLookupAlias<asm # ".8b",
5767                          !cast<Instruction>(NAME#"v8i8Three"),
5768                          V64, VecListThree128>;
5769   def : SIMDTableLookupAlias<asm # ".8b",
5770                          !cast<Instruction>(NAME#"v8i8Four"),
5771                          V64, VecListFour128>;
5772   def : SIMDTableLookupAlias<asm # ".16b",
5773                          !cast<Instruction>(NAME#"v16i8One"),
5774                          V128, VecListOne128>;
5775   def : SIMDTableLookupAlias<asm # ".16b",
5776                          !cast<Instruction>(NAME#"v16i8Two"),
5777                          V128, VecListTwo128>;
5778   def : SIMDTableLookupAlias<asm # ".16b",
5779                          !cast<Instruction>(NAME#"v16i8Three"),
5780                          V128, VecListThree128>;
5781   def : SIMDTableLookupAlias<asm # ".16b",
5782                          !cast<Instruction>(NAME#"v16i8Four"),
5783                          V128, VecListFour128>;
5784 }
5785
5786 multiclass SIMDTableLookupTied<bit op, string asm> {
5787   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5788                                       asm, ".8b">;
5789   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5790                                       asm, ".8b">;
5791   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5792                                       asm, ".8b">;
5793   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5794                                       asm, ".8b">;
5795   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5796                                       asm, ".16b">;
5797   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5798                                       asm, ".16b">;
5799   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5800                                       asm, ".16b">;
5801   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5802                                       asm, ".16b">;
5803
5804   def : SIMDTableLookupAlias<asm # ".8b",
5805                          !cast<Instruction>(NAME#"v8i8One"),
5806                          V64, VecListOne128>;
5807   def : SIMDTableLookupAlias<asm # ".8b",
5808                          !cast<Instruction>(NAME#"v8i8Two"),
5809                          V64, VecListTwo128>;
5810   def : SIMDTableLookupAlias<asm # ".8b",
5811                          !cast<Instruction>(NAME#"v8i8Three"),
5812                          V64, VecListThree128>;
5813   def : SIMDTableLookupAlias<asm # ".8b",
5814                          !cast<Instruction>(NAME#"v8i8Four"),
5815                          V64, VecListFour128>;
5816   def : SIMDTableLookupAlias<asm # ".16b",
5817                          !cast<Instruction>(NAME#"v16i8One"),
5818                          V128, VecListOne128>;
5819   def : SIMDTableLookupAlias<asm # ".16b",
5820                          !cast<Instruction>(NAME#"v16i8Two"),
5821                          V128, VecListTwo128>;
5822   def : SIMDTableLookupAlias<asm # ".16b",
5823                          !cast<Instruction>(NAME#"v16i8Three"),
5824                          V128, VecListThree128>;
5825   def : SIMDTableLookupAlias<asm # ".16b",
5826                          !cast<Instruction>(NAME#"v16i8Four"),
5827                          V128, VecListFour128>;
5828 }
5829
5830
5831 //----------------------------------------------------------------------------
5832 // AdvSIMD scalar CPY
5833 //----------------------------------------------------------------------------
5834 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5835 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5836                         string kind, Operand idxtype>
5837   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5838        "{\t$dst, $src" # kind # "$idx" #
5839        "|\t$dst, $src$idx}", "", []>,
5840     Sched<[WriteV]> {
5841   bits<5> dst;
5842   bits<5> src;
5843   let Inst{31-21} = 0b01011110000;
5844   let Inst{15-10} = 0b000001;
5845   let Inst{9-5}   = src;
5846   let Inst{4-0}   = dst;
5847 }
5848
5849 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5850       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5851     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5852                     # "|\t$dst, $src$index}",
5853                 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5854
5855
5856 multiclass SIMDScalarCPY<string asm> {
5857   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
5858     bits<4> idx;
5859     let Inst{20-17} = idx;
5860     let Inst{16} = 1;
5861   }
5862   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5863     bits<3> idx;
5864     let Inst{20-18} = idx;
5865     let Inst{17-16} = 0b10;
5866   }
5867   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5868     bits<2> idx;
5869     let Inst{20-19} = idx;
5870     let Inst{18-16} = 0b100;
5871   }
5872   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5873     bits<1> idx;
5874     let Inst{20} = idx;
5875     let Inst{19-16} = 0b1000;
5876   }
5877
5878   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
5879                                                           VectorIndexD:$idx)))),
5880             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
5881
5882   // 'DUP' mnemonic aliases.
5883   def : SIMDScalarCPYAlias<"dup", ".b",
5884                            !cast<Instruction>(NAME#"i8"),
5885                            FPR8, V128, VectorIndexB>;
5886   def : SIMDScalarCPYAlias<"dup", ".h",
5887                            !cast<Instruction>(NAME#"i16"),
5888                            FPR16, V128, VectorIndexH>;
5889   def : SIMDScalarCPYAlias<"dup", ".s",
5890                            !cast<Instruction>(NAME#"i32"),
5891                            FPR32, V128, VectorIndexS>;
5892   def : SIMDScalarCPYAlias<"dup", ".d",
5893                            !cast<Instruction>(NAME#"i64"),
5894                            FPR64, V128, VectorIndexD>;
5895 }
5896
5897 //----------------------------------------------------------------------------
5898 // AdvSIMD modified immediate instructions
5899 //----------------------------------------------------------------------------
5900
5901 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5902                           string asm, string op_string,
5903                           string cstr, list<dag> pattern>
5904   : I<oops, iops, asm, op_string, cstr, pattern>,
5905     Sched<[WriteV]> {
5906   bits<5> Rd;
5907   bits<8> imm8;
5908   let Inst{31}    = 0;
5909   let Inst{30}    = Q;
5910   let Inst{29}    = op;
5911   let Inst{28-19} = 0b0111100000;
5912   let Inst{18-16} = imm8{7-5};
5913   let Inst{11-10} = 0b01;
5914   let Inst{9-5}   = imm8{4-0};
5915   let Inst{4-0}   = Rd;
5916 }
5917
5918 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5919                                 Operand immtype, dag opt_shift_iop,
5920                                 string opt_shift, string asm, string kind,
5921                                 list<dag> pattern>
5922   : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5923                         !con((ins immtype:$imm8), opt_shift_iop), asm,
5924                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
5925                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5926                         "", pattern> {
5927   let DecoderMethod = "DecodeModImmInstruction";
5928 }
5929
5930 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5931                                 Operand immtype, dag opt_shift_iop,
5932                                 string opt_shift, string asm, string kind,
5933                                 list<dag> pattern>
5934   : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5935                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5936                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5937                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5938                         "$Rd = $dst", pattern> {
5939   let DecoderMethod = "DecodeModImmTiedInstruction";
5940 }
5941
5942 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5943                                      RegisterOperand vectype, string asm,
5944                                      string kind, list<dag> pattern>
5945   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5946                               (ins logical_vec_shift:$shift),
5947                               "$shift", asm, kind, pattern> {
5948   bits<2> shift;
5949   let Inst{15}    = b15_b12{1};
5950   let Inst{14-13} = shift;
5951   let Inst{12}    = b15_b12{0};
5952 }
5953
5954 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5955                                      RegisterOperand vectype, string asm,
5956                                      string kind, list<dag> pattern>
5957   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5958                               (ins logical_vec_shift:$shift),
5959                               "$shift", asm, kind, pattern> {
5960   bits<2> shift;
5961   let Inst{15}    = b15_b12{1};
5962   let Inst{14-13} = shift;
5963   let Inst{12}    = b15_b12{0};
5964 }
5965
5966
5967 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5968                                          RegisterOperand vectype, string asm,
5969                                          string kind, list<dag> pattern>
5970   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5971                               (ins logical_vec_hw_shift:$shift),
5972                               "$shift", asm, kind, pattern> {
5973   bits<2> shift;
5974   let Inst{15} = b15_b12{1};
5975   let Inst{14} = 0;
5976   let Inst{13} = shift{0};
5977   let Inst{12} = b15_b12{0};
5978 }
5979
5980 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5981                                          RegisterOperand vectype, string asm,
5982                                          string kind, list<dag> pattern>
5983   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5984                               (ins logical_vec_hw_shift:$shift),
5985                               "$shift", asm, kind, pattern> {
5986   bits<2> shift;
5987   let Inst{15} = b15_b12{1};
5988   let Inst{14} = 0;
5989   let Inst{13} = shift{0};
5990   let Inst{12} = b15_b12{0};
5991 }
5992
5993 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5994                                       string asm> {
5995   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5996                                                  asm, ".4h", []>;
5997   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
5998                                                  asm, ".8h", []>;
5999
6000   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6001                                              asm, ".2s", []>;
6002   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6003                                              asm, ".4s", []>;
6004 }
6005
6006 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6007                                       bits<2> w_cmode, string asm,
6008                                       SDNode OpNode> {
6009   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6010                                                  asm, ".4h",
6011              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6012                                              imm0_255:$imm8,
6013                                              (i32 imm:$shift)))]>;
6014   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6015                                                  asm, ".8h",
6016              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6017                                               imm0_255:$imm8,
6018                                               (i32 imm:$shift)))]>;
6019
6020   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6021                                              asm, ".2s",
6022              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6023                                              imm0_255:$imm8,
6024                                              (i32 imm:$shift)))]>;
6025   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6026                                              asm, ".4s",
6027              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6028                                               imm0_255:$imm8,
6029                                               (i32 imm:$shift)))]>;
6030 }
6031
6032 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6033                              RegisterOperand vectype, string asm,
6034                              string kind, list<dag> pattern>
6035   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6036                               (ins move_vec_shift:$shift),
6037                               "$shift", asm, kind, pattern> {
6038   bits<1> shift;
6039   let Inst{15-13} = cmode{3-1};
6040   let Inst{12}    = shift;
6041 }
6042
6043 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
6044                                    RegisterOperand vectype,
6045                                    Operand imm_type, string asm,
6046                                    string kind, list<dag> pattern>
6047   : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
6048                               asm, kind, pattern> {
6049   let Inst{15-12} = cmode;
6050 }
6051
6052 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6053                                    list<dag> pattern>
6054   : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6055                         "\t$Rd, $imm8", "", pattern> {
6056   let Inst{15-12} = cmode;
6057   let DecoderMethod = "DecodeModImmInstruction";
6058 }
6059
6060 //----------------------------------------------------------------------------
6061 // AdvSIMD indexed element
6062 //----------------------------------------------------------------------------
6063
6064 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6065 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6066                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6067                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6068                       string apple_kind, string dst_kind, string lhs_kind,
6069                       string rhs_kind, list<dag> pattern>
6070   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6071       asm,
6072       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6073       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6074     Sched<[WriteV]> {
6075   bits<5> Rd;
6076   bits<5> Rn;
6077   bits<5> Rm;
6078
6079   let Inst{31}    = 0;
6080   let Inst{30}    = Q;
6081   let Inst{29}    = U;
6082   let Inst{28}    = Scalar;
6083   let Inst{27-24} = 0b1111;
6084   let Inst{23-22} = size;
6085   // Bit 21 must be set by the derived class.
6086   let Inst{20-16} = Rm;
6087   let Inst{15-12} = opc;
6088   // Bit 11 must be set by the derived class.
6089   let Inst{10}    = 0;
6090   let Inst{9-5}   = Rn;
6091   let Inst{4-0}   = Rd;
6092 }
6093
6094 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6095 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6096                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6097                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6098                       string apple_kind, string dst_kind, string lhs_kind,
6099                       string rhs_kind, list<dag> pattern>
6100   : I<(outs dst_reg:$dst),
6101       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6102       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6103       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6104     Sched<[WriteV]> {
6105   bits<5> Rd;
6106   bits<5> Rn;
6107   bits<5> Rm;
6108
6109   let Inst{31}    = 0;
6110   let Inst{30}    = Q;
6111   let Inst{29}    = U;
6112   let Inst{28}    = Scalar;
6113   let Inst{27-24} = 0b1111;
6114   let Inst{23-22} = size;
6115   // Bit 21 must be set by the derived class.
6116   let Inst{20-16} = Rm;
6117   let Inst{15-12} = opc;
6118   // Bit 11 must be set by the derived class.
6119   let Inst{10}    = 0;
6120   let Inst{9-5}   = Rn;
6121   let Inst{4-0}   = Rd;
6122 }
6123
6124 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
6125                            SDPatternOperator OpNode> {
6126   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6127                                       V64, V64,
6128                                       V128, VectorIndexS,
6129                                       asm, ".2s", ".2s", ".2s", ".s",
6130     [(set (v2f32 V64:$Rd),
6131         (OpNode (v2f32 V64:$Rn),
6132          (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6133     bits<2> idx;
6134     let Inst{11} = idx{1};
6135     let Inst{21} = idx{0};
6136   }
6137
6138   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6139                                       V128, V128,
6140                                       V128, VectorIndexS,
6141                                       asm, ".4s", ".4s", ".4s", ".s",
6142     [(set (v4f32 V128:$Rd),
6143         (OpNode (v4f32 V128:$Rn),
6144          (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6145     bits<2> idx;
6146     let Inst{11} = idx{1};
6147     let Inst{21} = idx{0};
6148   }
6149
6150   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6151                                       V128, V128,
6152                                       V128, VectorIndexD,
6153                                       asm, ".2d", ".2d", ".2d", ".d",
6154     [(set (v2f64 V128:$Rd),
6155         (OpNode (v2f64 V128:$Rn),
6156          (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6157     bits<1> idx;
6158     let Inst{11} = idx{0};
6159     let Inst{21} = 0;
6160   }
6161
6162   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6163                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6164                                       asm, ".s", "", "", ".s",
6165     [(set (f32 FPR32Op:$Rd),
6166           (OpNode (f32 FPR32Op:$Rn),
6167                   (f32 (vector_extract (v4f32 V128:$Rm),
6168                                        VectorIndexS:$idx))))]> {
6169     bits<2> idx;
6170     let Inst{11} = idx{1};
6171     let Inst{21} = idx{0};
6172   }
6173
6174   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6175                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6176                                       asm, ".d", "", "", ".d",
6177     [(set (f64 FPR64Op:$Rd),
6178           (OpNode (f64 FPR64Op:$Rn),
6179                   (f64 (vector_extract (v2f64 V128:$Rm),
6180                                        VectorIndexD:$idx))))]> {
6181     bits<1> idx;
6182     let Inst{11} = idx{0};
6183     let Inst{21} = 0;
6184   }
6185 }
6186
6187 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6188   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6189   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6190                            (ARM64duplane32 (v4f32 V128:$Rm),
6191                                            VectorIndexS:$idx))),
6192             (!cast<Instruction>(INST # v2i32_indexed)
6193                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6194   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6195                            (ARM64dup (f32 FPR32Op:$Rm)))),
6196             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6197                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6198
6199
6200   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6201   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6202                            (ARM64duplane32 (v4f32 V128:$Rm),
6203                                            VectorIndexS:$idx))),
6204             (!cast<Instruction>(INST # "v4i32_indexed")
6205                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6206   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6207                            (ARM64dup (f32 FPR32Op:$Rm)))),
6208             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6209                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6210
6211   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6212   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6213                            (ARM64duplane64 (v2f64 V128:$Rm),
6214                                            VectorIndexD:$idx))),
6215             (!cast<Instruction>(INST # "v2i64_indexed")
6216                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6217   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6218                            (ARM64dup (f64 FPR64Op:$Rm)))),
6219             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6220                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6221
6222   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6223   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6224                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6225             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6226                 V128:$Rm, VectorIndexS:$idx)>;
6227   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6228                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6229             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6230                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6231
6232   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6233   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6234                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6235             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6236                 V128:$Rm, VectorIndexD:$idx)>;
6237 }
6238
6239 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6240   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6241                                           V128, VectorIndexS,
6242                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6243     bits<2> idx;
6244     let Inst{11} = idx{1};
6245     let Inst{21} = idx{0};
6246   }
6247
6248   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6249                                       V128, V128,
6250                                       V128, VectorIndexS,
6251                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6252     bits<2> idx;
6253     let Inst{11} = idx{1};
6254     let Inst{21} = idx{0};
6255   }
6256
6257   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6258                                       V128, V128,
6259                                       V128, VectorIndexD,
6260                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6261     bits<1> idx;
6262     let Inst{11} = idx{0};
6263     let Inst{21} = 0;
6264   }
6265
6266
6267   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6268                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6269                                       asm, ".s", "", "", ".s", []> {
6270     bits<2> idx;
6271     let Inst{11} = idx{1};
6272     let Inst{21} = idx{0};
6273   }
6274
6275   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6276                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6277                                       asm, ".d", "", "", ".d", []> {
6278     bits<1> idx;
6279     let Inst{11} = idx{0};
6280     let Inst{21} = 0;
6281   }
6282 }
6283
6284 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6285                          SDPatternOperator OpNode> {
6286   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6287                                       V128_lo, VectorIndexH,
6288                                       asm, ".4h", ".4h", ".4h", ".h",
6289     [(set (v4i16 V64:$Rd),
6290         (OpNode (v4i16 V64:$Rn),
6291          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6292     bits<3> idx;
6293     let Inst{11} = idx{2};
6294     let Inst{21} = idx{1};
6295     let Inst{20} = idx{0};
6296   }
6297
6298   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6299                                       V128, V128,
6300                                       V128_lo, VectorIndexH,
6301                                       asm, ".8h", ".8h", ".8h", ".h",
6302     [(set (v8i16 V128:$Rd),
6303        (OpNode (v8i16 V128:$Rn),
6304          (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6305     bits<3> idx;
6306     let Inst{11} = idx{2};
6307     let Inst{21} = idx{1};
6308     let Inst{20} = idx{0};
6309   }
6310
6311   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6312                                       V64, V64,
6313                                       V128, VectorIndexS,
6314                                       asm, ".2s", ".2s", ".2s",  ".s",
6315     [(set (v2i32 V64:$Rd),
6316        (OpNode (v2i32 V64:$Rn),
6317           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6318     bits<2> idx;
6319     let Inst{11} = idx{1};
6320     let Inst{21} = idx{0};
6321   }
6322
6323   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6324                                       V128, V128,
6325                                       V128, VectorIndexS,
6326                                       asm, ".4s", ".4s", ".4s", ".s",
6327     [(set (v4i32 V128:$Rd),
6328        (OpNode (v4i32 V128:$Rn),
6329           (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6330     bits<2> idx;
6331     let Inst{11} = idx{1};
6332     let Inst{21} = idx{0};
6333   }
6334
6335   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6336                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6337                                       asm, ".h", "", "", ".h", []> {
6338     bits<3> idx;
6339     let Inst{11} = idx{2};
6340     let Inst{21} = idx{1};
6341     let Inst{20} = idx{0};
6342   }
6343
6344   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6345                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6346                                       asm, ".s", "", "", ".s",
6347       [(set (i32 FPR32Op:$Rd),
6348             (OpNode FPR32Op:$Rn,
6349                     (i32 (vector_extract (v4i32 V128:$Rm),
6350                                          VectorIndexS:$idx))))]> {
6351     bits<2> idx;
6352     let Inst{11} = idx{1};
6353     let Inst{21} = idx{0};
6354   }
6355 }
6356
6357 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6358                                SDPatternOperator OpNode> {
6359   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6360                                       V64, V64,
6361                                       V128_lo, VectorIndexH,
6362                                       asm, ".4h", ".4h", ".4h", ".h",
6363     [(set (v4i16 V64:$Rd),
6364         (OpNode (v4i16 V64:$Rn),
6365          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6366     bits<3> idx;
6367     let Inst{11} = idx{2};
6368     let Inst{21} = idx{1};
6369     let Inst{20} = idx{0};
6370   }
6371
6372   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6373                                       V128, V128,
6374                                       V128_lo, VectorIndexH,
6375                                       asm, ".8h", ".8h", ".8h", ".h",
6376     [(set (v8i16 V128:$Rd),
6377        (OpNode (v8i16 V128:$Rn),
6378          (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6379     bits<3> idx;
6380     let Inst{11} = idx{2};
6381     let Inst{21} = idx{1};
6382     let Inst{20} = idx{0};
6383   }
6384
6385   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6386                                       V64, V64,
6387                                       V128, VectorIndexS,
6388                                       asm, ".2s", ".2s", ".2s", ".s",
6389     [(set (v2i32 V64:$Rd),
6390        (OpNode (v2i32 V64:$Rn),
6391           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6392     bits<2> idx;
6393     let Inst{11} = idx{1};
6394     let Inst{21} = idx{0};
6395   }
6396
6397   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6398                                       V128, V128,
6399                                       V128, VectorIndexS,
6400                                       asm, ".4s", ".4s", ".4s", ".s",
6401     [(set (v4i32 V128:$Rd),
6402        (OpNode (v4i32 V128:$Rn),
6403           (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6404     bits<2> idx;
6405     let Inst{11} = idx{1};
6406     let Inst{21} = idx{0};
6407   }
6408 }
6409
6410 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6411                                    SDPatternOperator OpNode> {
6412   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6413                                           V128_lo, VectorIndexH,
6414                                           asm, ".4h", ".4h", ".4h", ".h",
6415     [(set (v4i16 V64:$dst),
6416         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6417          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6418     bits<3> idx;
6419     let Inst{11} = idx{2};
6420     let Inst{21} = idx{1};
6421     let Inst{20} = idx{0};
6422   }
6423
6424   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6425                                       V128, V128,
6426                                       V128_lo, VectorIndexH,
6427                                       asm, ".8h", ".8h", ".8h", ".h",
6428     [(set (v8i16 V128:$dst),
6429        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6430          (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6431     bits<3> idx;
6432     let Inst{11} = idx{2};
6433     let Inst{21} = idx{1};
6434     let Inst{20} = idx{0};
6435   }
6436
6437   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6438                                       V64, V64,
6439                                       V128, VectorIndexS,
6440                                       asm, ".2s", ".2s", ".2s", ".s",
6441     [(set (v2i32 V64:$dst),
6442        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6443           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6444     bits<2> idx;
6445     let Inst{11} = idx{1};
6446     let Inst{21} = idx{0};
6447   }
6448
6449   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6450                                       V128, V128,
6451                                       V128, VectorIndexS,
6452                                       asm, ".4s", ".4s", ".4s", ".s",
6453     [(set (v4i32 V128:$dst),
6454        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6455           (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6456     bits<2> idx;
6457     let Inst{11} = idx{1};
6458     let Inst{21} = idx{0};
6459   }
6460 }
6461
6462 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6463                              SDPatternOperator OpNode> {
6464   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6465                                       V128, V64,
6466                                       V128_lo, VectorIndexH,
6467                                       asm, ".4s", ".4s", ".4h", ".h",
6468     [(set (v4i32 V128:$Rd),
6469         (OpNode (v4i16 V64:$Rn),
6470          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6471     bits<3> idx;
6472     let Inst{11} = idx{2};
6473     let Inst{21} = idx{1};
6474     let Inst{20} = idx{0};
6475   }
6476
6477   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6478                                       V128, V128,
6479                                       V128_lo, VectorIndexH,
6480                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6481     [(set (v4i32 V128:$Rd),
6482           (OpNode (extract_high_v8i16 V128:$Rn),
6483                   (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6484                                                       VectorIndexH:$idx))))]> {
6485
6486     bits<3> idx;
6487     let Inst{11} = idx{2};
6488     let Inst{21} = idx{1};
6489     let Inst{20} = idx{0};
6490   }
6491
6492   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6493                                       V128, V64,
6494                                       V128, VectorIndexS,
6495                                       asm, ".2d", ".2d", ".2s", ".s",
6496     [(set (v2i64 V128:$Rd),
6497         (OpNode (v2i32 V64:$Rn),
6498          (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6499     bits<2> idx;
6500     let Inst{11} = idx{1};
6501     let Inst{21} = idx{0};
6502   }
6503
6504   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6505                                       V128, V128,
6506                                       V128, VectorIndexS,
6507                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6508     [(set (v2i64 V128:$Rd),
6509           (OpNode (extract_high_v4i32 V128:$Rn),
6510                   (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6511                                                       VectorIndexS:$idx))))]> {
6512     bits<2> idx;
6513     let Inst{11} = idx{1};
6514     let Inst{21} = idx{0};
6515   }
6516
6517   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6518                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6519                                       asm, ".h", "", "", ".h", []> {
6520     bits<3> idx;
6521     let Inst{11} = idx{2};
6522     let Inst{21} = idx{1};
6523     let Inst{20} = idx{0};
6524   }
6525
6526   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6527                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6528                                       asm, ".s", "", "", ".s", []> {
6529     bits<2> idx;
6530     let Inst{11} = idx{1};
6531     let Inst{21} = idx{0};
6532   }
6533 }
6534
6535 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6536                                        SDPatternOperator Accum> {
6537   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6538                                       V128, V64,
6539                                       V128_lo, VectorIndexH,
6540                                       asm, ".4s", ".4s", ".4h", ".h",
6541     [(set (v4i32 V128:$dst),
6542           (Accum (v4i32 V128:$Rd),
6543                  (v4i32 (int_arm64_neon_sqdmull
6544                              (v4i16 V64:$Rn),
6545                              (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6546                                                     VectorIndexH:$idx))))))]> {
6547     bits<3> idx;
6548     let Inst{11} = idx{2};
6549     let Inst{21} = idx{1};
6550     let Inst{20} = idx{0};
6551   }
6552
6553   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6554   // intermediate EXTRACT_SUBREG would be untyped.
6555   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6556                 (i32 (vector_extract (v4i32
6557                          (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6558                              (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6559                                                     VectorIndexH:$idx)))),
6560                          (i64 0))))),
6561             (EXTRACT_SUBREG
6562                 (!cast<Instruction>(NAME # v4i16_indexed)
6563                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6564                     V128_lo:$Rm, VectorIndexH:$idx),
6565                 ssub)>;
6566
6567   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6568                                       V128, V128,
6569                                       V128_lo, VectorIndexH,
6570                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6571     [(set (v4i32 V128:$dst),
6572           (Accum (v4i32 V128:$Rd),
6573                  (v4i32 (int_arm64_neon_sqdmull
6574                             (extract_high_v8i16 V128:$Rn),
6575                             (extract_high_v8i16
6576                                 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6577                                                 VectorIndexH:$idx))))))]> {
6578     bits<3> idx;
6579     let Inst{11} = idx{2};
6580     let Inst{21} = idx{1};
6581     let Inst{20} = idx{0};
6582   }
6583
6584   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6585                                       V128, V64,
6586                                       V128, VectorIndexS,
6587                                       asm, ".2d", ".2d", ".2s", ".s",
6588     [(set (v2i64 V128:$dst),
6589         (Accum (v2i64 V128:$Rd),
6590                (v2i64 (int_arm64_neon_sqdmull
6591                           (v2i32 V64:$Rn),
6592                           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6593                                                  VectorIndexS:$idx))))))]> {
6594     bits<2> idx;
6595     let Inst{11} = idx{1};
6596     let Inst{21} = idx{0};
6597   }
6598
6599   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6600                                       V128, V128,
6601                                       V128, VectorIndexS,
6602                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6603     [(set (v2i64 V128:$dst),
6604           (Accum (v2i64 V128:$Rd),
6605                  (v2i64 (int_arm64_neon_sqdmull
6606                             (extract_high_v4i32 V128:$Rn),
6607                             (extract_high_v4i32
6608                                 (ARM64duplane32 (v4i32 V128:$Rm),
6609                                                 VectorIndexS:$idx))))))]> {
6610     bits<2> idx;
6611     let Inst{11} = idx{1};
6612     let Inst{21} = idx{0};
6613   }
6614
6615   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6616                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6617                                       asm, ".h", "", "", ".h", []> {
6618     bits<3> idx;
6619     let Inst{11} = idx{2};
6620     let Inst{21} = idx{1};
6621     let Inst{20} = idx{0};
6622   }
6623
6624
6625   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6626                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6627                                       asm, ".s", "", "", ".s",
6628     [(set (i64 FPR64Op:$dst),
6629           (Accum (i64 FPR64Op:$Rd),
6630                  (i64 (int_arm64_neon_sqdmulls_scalar
6631                             (i32 FPR32Op:$Rn),
6632                             (i32 (vector_extract (v4i32 V128:$Rm),
6633                                                  VectorIndexS:$idx))))))]> {
6634
6635     bits<2> idx;
6636     let Inst{11} = idx{1};
6637     let Inst{21} = idx{0};
6638   }
6639 }
6640
6641 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6642                                    SDPatternOperator OpNode> {
6643   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6644   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6645                                       V128, V64,
6646                                       V128_lo, VectorIndexH,
6647                                       asm, ".4s", ".4s", ".4h", ".h",
6648     [(set (v4i32 V128:$Rd),
6649         (OpNode (v4i16 V64:$Rn),
6650          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6651     bits<3> idx;
6652     let Inst{11} = idx{2};
6653     let Inst{21} = idx{1};
6654     let Inst{20} = idx{0};
6655   }
6656
6657   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6658                                       V128, V128,
6659                                       V128_lo, VectorIndexH,
6660                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6661     [(set (v4i32 V128:$Rd),
6662           (OpNode (extract_high_v8i16 V128:$Rn),
6663                   (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6664                                                       VectorIndexH:$idx))))]> {
6665
6666     bits<3> idx;
6667     let Inst{11} = idx{2};
6668     let Inst{21} = idx{1};
6669     let Inst{20} = idx{0};
6670   }
6671
6672   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6673                                       V128, V64,
6674                                       V128, VectorIndexS,
6675                                       asm, ".2d", ".2d", ".2s", ".s",
6676     [(set (v2i64 V128:$Rd),
6677         (OpNode (v2i32 V64:$Rn),
6678          (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6679     bits<2> idx;
6680     let Inst{11} = idx{1};
6681     let Inst{21} = idx{0};
6682   }
6683
6684   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6685                                       V128, V128,
6686                                       V128, VectorIndexS,
6687                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6688     [(set (v2i64 V128:$Rd),
6689           (OpNode (extract_high_v4i32 V128:$Rn),
6690                   (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6691                                                       VectorIndexS:$idx))))]> {
6692     bits<2> idx;
6693     let Inst{11} = idx{1};
6694     let Inst{21} = idx{0};
6695   }
6696   }
6697 }
6698
6699 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6700                                        SDPatternOperator OpNode> {
6701   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6702   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6703                                       V128, V64,
6704                                       V128_lo, VectorIndexH,
6705                                       asm, ".4s", ".4s", ".4h", ".h",
6706     [(set (v4i32 V128:$dst),
6707         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6708          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6709     bits<3> idx;
6710     let Inst{11} = idx{2};
6711     let Inst{21} = idx{1};
6712     let Inst{20} = idx{0};
6713   }
6714
6715   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6716                                       V128, V128,
6717                                       V128_lo, VectorIndexH,
6718                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6719     [(set (v4i32 V128:$dst),
6720           (OpNode (v4i32 V128:$Rd),
6721                   (extract_high_v8i16 V128:$Rn),
6722                   (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6723                                                       VectorIndexH:$idx))))]> {
6724     bits<3> idx;
6725     let Inst{11} = idx{2};
6726     let Inst{21} = idx{1};
6727     let Inst{20} = idx{0};
6728   }
6729
6730   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6731                                       V128, V64,
6732                                       V128, VectorIndexS,
6733                                       asm, ".2d", ".2d", ".2s", ".s",
6734     [(set (v2i64 V128:$dst),
6735         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6736          (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6737     bits<2> idx;
6738     let Inst{11} = idx{1};
6739     let Inst{21} = idx{0};
6740   }
6741
6742   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6743                                       V128, V128,
6744                                       V128, VectorIndexS,
6745                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6746     [(set (v2i64 V128:$dst),
6747           (OpNode (v2i64 V128:$Rd),
6748                   (extract_high_v4i32 V128:$Rn),
6749                   (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6750                                                       VectorIndexS:$idx))))]> {
6751     bits<2> idx;
6752     let Inst{11} = idx{1};
6753     let Inst{21} = idx{0};
6754   }
6755   }
6756 }
6757
6758 //----------------------------------------------------------------------------
6759 // AdvSIMD scalar shift by immediate
6760 //----------------------------------------------------------------------------
6761
6762 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6763 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6764                      RegisterClass regtype1, RegisterClass regtype2,
6765                      Operand immtype, string asm, list<dag> pattern>
6766   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6767       asm, "\t$Rd, $Rn, $imm", "", pattern>,
6768     Sched<[WriteV]> {
6769   bits<5> Rd;
6770   bits<5> Rn;
6771   bits<7> imm;
6772   let Inst{31-30} = 0b01;
6773   let Inst{29}    = U;
6774   let Inst{28-23} = 0b111110;
6775   let Inst{22-16} = fixed_imm;
6776   let Inst{15-11} = opc;
6777   let Inst{10}    = 1;
6778   let Inst{9-5} = Rn;
6779   let Inst{4-0} = Rd;
6780 }
6781
6782 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6783 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6784                      RegisterClass regtype1, RegisterClass regtype2,
6785                      Operand immtype, string asm, list<dag> pattern>
6786   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6787       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6788     Sched<[WriteV]> {
6789   bits<5> Rd;
6790   bits<5> Rn;
6791   bits<7> imm;
6792   let Inst{31-30} = 0b01;
6793   let Inst{29}    = U;
6794   let Inst{28-23} = 0b111110;
6795   let Inst{22-16} = fixed_imm;
6796   let Inst{15-11} = opc;
6797   let Inst{10}    = 1;
6798   let Inst{9-5} = Rn;
6799   let Inst{4-0} = Rd;
6800 }
6801
6802
6803 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6804   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6805                               FPR32, FPR32, vecshiftR32, asm, []> {
6806     let Inst{20-16} = imm{4-0};
6807   }
6808
6809   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6810                               FPR64, FPR64, vecshiftR64, asm, []> {
6811     let Inst{21-16} = imm{5-0};
6812   }
6813 }
6814
6815 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6816                              SDPatternOperator OpNode> {
6817   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6818                               FPR64, FPR64, vecshiftR64, asm,
6819   [(set (i64 FPR64:$Rd),
6820      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
6821     let Inst{21-16} = imm{5-0};
6822   }
6823
6824   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
6825             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
6826 }
6827
6828 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6829                                  SDPatternOperator OpNode = null_frag> {
6830   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6831                               FPR64, FPR64, vecshiftR64, asm,
6832   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
6833                                                    (i32 vecshiftR64:$imm)))]> {
6834     let Inst{21-16} = imm{5-0};
6835   }
6836
6837   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6838                            (i32 vecshiftR64:$imm))),
6839             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
6840                                             vecshiftR64:$imm)>;
6841 }
6842
6843 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6844                              SDPatternOperator OpNode> {
6845   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6846                               FPR64, FPR64, vecshiftL64, asm,
6847     [(set (v1i64 FPR64:$Rd),
6848        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6849     let Inst{21-16} = imm{5-0};
6850   }
6851 }
6852
6853 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6854 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6855   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6856                               FPR64, FPR64, vecshiftL64, asm, []> {
6857     let Inst{21-16} = imm{5-0};
6858   }
6859 }
6860
6861 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6862 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6863                                SDPatternOperator OpNode = null_frag> {
6864   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6865                               FPR8, FPR16, vecshiftR8, asm, []> {
6866     let Inst{18-16} = imm{2-0};
6867   }
6868
6869   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6870                               FPR16, FPR32, vecshiftR16, asm, []> {
6871     let Inst{19-16} = imm{3-0};
6872   }
6873
6874   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6875                               FPR32, FPR64, vecshiftR32, asm,
6876     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6877     let Inst{20-16} = imm{4-0};
6878   }
6879 }
6880
6881 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6882                                 SDPatternOperator OpNode> {
6883   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6884                               FPR8, FPR8, vecshiftL8, asm, []> {
6885     let Inst{18-16} = imm{2-0};
6886   }
6887
6888   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6889                               FPR16, FPR16, vecshiftL16, asm, []> {
6890     let Inst{19-16} = imm{3-0};
6891   }
6892
6893   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6894                               FPR32, FPR32, vecshiftL32, asm,
6895     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6896     let Inst{20-16} = imm{4-0};
6897   }
6898
6899   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6900                               FPR64, FPR64, vecshiftL64, asm,
6901     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6902     let Inst{21-16} = imm{5-0};
6903   }
6904
6905   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
6906             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
6907 }
6908
6909 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6910   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6911                               FPR8, FPR8, vecshiftR8, asm, []> {
6912     let Inst{18-16} = imm{2-0};
6913   }
6914
6915   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6916                               FPR16, FPR16, vecshiftR16, asm, []> {
6917     let Inst{19-16} = imm{3-0};
6918   }
6919
6920   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6921                               FPR32, FPR32, vecshiftR32, asm, []> {
6922     let Inst{20-16} = imm{4-0};
6923   }
6924
6925   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6926                               FPR64, FPR64, vecshiftR64, asm, []> {
6927     let Inst{21-16} = imm{5-0};
6928   }
6929 }
6930
6931 //----------------------------------------------------------------------------
6932 // AdvSIMD vector x indexed element
6933 //----------------------------------------------------------------------------
6934
6935 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6936 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6937                      RegisterOperand dst_reg, RegisterOperand src_reg,
6938                      Operand immtype,
6939                      string asm, string dst_kind, string src_kind,
6940                      list<dag> pattern>
6941   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6942       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6943            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6944     Sched<[WriteV]> {
6945   bits<5> Rd;
6946   bits<5> Rn;
6947   let Inst{31}    = 0;
6948   let Inst{30}    = Q;
6949   let Inst{29}    = U;
6950   let Inst{28-23} = 0b011110;
6951   let Inst{22-16} = fixed_imm;
6952   let Inst{15-11} = opc;
6953   let Inst{10}    = 1;
6954   let Inst{9-5}   = Rn;
6955   let Inst{4-0}   = Rd;
6956 }
6957
6958 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6959 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6960                      RegisterOperand vectype1, RegisterOperand vectype2,
6961                      Operand immtype,
6962                      string asm, string dst_kind, string src_kind,
6963                      list<dag> pattern>
6964   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6965       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6966            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6967     Sched<[WriteV]> {
6968   bits<5> Rd;
6969   bits<5> Rn;
6970   let Inst{31}    = 0;
6971   let Inst{30}    = Q;
6972   let Inst{29}    = U;
6973   let Inst{28-23} = 0b011110;
6974   let Inst{22-16} = fixed_imm;
6975   let Inst{15-11} = opc;
6976   let Inst{10}    = 1;
6977   let Inst{9-5}   = Rn;
6978   let Inst{4-0}   = Rd;
6979 }
6980
6981 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6982                               Intrinsic OpNode> {
6983   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6984                                   V64, V64, vecshiftR32,
6985                                   asm, ".2s", ".2s",
6986       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6987     bits<5> imm;
6988     let Inst{20-16} = imm;
6989   }
6990
6991   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6992                                   V128, V128, vecshiftR32,
6993                                   asm, ".4s", ".4s",
6994       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6995     bits<5> imm;
6996     let Inst{20-16} = imm;
6997   }
6998
6999   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7000                                   V128, V128, vecshiftR64,
7001                                   asm, ".2d", ".2d",
7002       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7003     bits<6> imm;
7004     let Inst{21-16} = imm;
7005   }
7006 }
7007
7008 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
7009                                   Intrinsic OpNode> {
7010   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7011                                   V64, V64, vecshiftR32,
7012                                   asm, ".2s", ".2s",
7013       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7014     bits<5> imm;
7015     let Inst{20-16} = imm;
7016   }
7017
7018   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7019                                   V128, V128, vecshiftR32,
7020                                   asm, ".4s", ".4s",
7021       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7022     bits<5> imm;
7023     let Inst{20-16} = imm;
7024   }
7025
7026   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7027                                   V128, V128, vecshiftR64,
7028                                   asm, ".2d", ".2d",
7029       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7030     bits<6> imm;
7031     let Inst{21-16} = imm;
7032   }
7033 }
7034
7035 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7036                                      SDPatternOperator OpNode> {
7037   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7038                                   V64, V128, vecshiftR16Narrow,
7039                                   asm, ".8b", ".8h",
7040       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7041     bits<3> imm;
7042     let Inst{18-16} = imm;
7043   }
7044
7045   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7046                                   V128, V128, vecshiftR16Narrow,
7047                                   asm#"2", ".16b", ".8h", []> {
7048     bits<3> imm;
7049     let Inst{18-16} = imm;
7050     let hasSideEffects = 0;
7051   }
7052
7053   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7054                                   V64, V128, vecshiftR32Narrow,
7055                                   asm, ".4h", ".4s",
7056       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7057     bits<4> imm;
7058     let Inst{19-16} = imm;
7059   }
7060
7061   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7062                                   V128, V128, vecshiftR32Narrow,
7063                                   asm#"2", ".8h", ".4s", []> {
7064     bits<4> imm;
7065     let Inst{19-16} = imm;
7066     let hasSideEffects = 0;
7067   }
7068
7069   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7070                                   V64, V128, vecshiftR64Narrow,
7071                                   asm, ".2s", ".2d",
7072       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7073     bits<5> imm;
7074     let Inst{20-16} = imm;
7075   }
7076
7077   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7078                                   V128, V128, vecshiftR64Narrow,
7079                                   asm#"2", ".4s", ".2d", []> {
7080     bits<5> imm;
7081     let Inst{20-16} = imm;
7082     let hasSideEffects = 0;
7083   }
7084
7085   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7086   // themselves, so put them here instead.
7087
7088   // Patterns involving what's effectively an insert high and a normal
7089   // intrinsic, represented by CONCAT_VECTORS.
7090   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7091                                                    vecshiftR16Narrow:$imm)),
7092             (!cast<Instruction>(NAME # "v16i8_shift")
7093                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7094                 V128:$Rn, vecshiftR16Narrow:$imm)>;
7095   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7096                                                      vecshiftR32Narrow:$imm)),
7097             (!cast<Instruction>(NAME # "v8i16_shift")
7098                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7099                 V128:$Rn, vecshiftR32Narrow:$imm)>;
7100   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7101                                                      vecshiftR64Narrow:$imm)),
7102             (!cast<Instruction>(NAME # "v4i32_shift")
7103                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7104                 V128:$Rn, vecshiftR64Narrow:$imm)>;
7105 }
7106
7107 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7108                                 SDPatternOperator OpNode> {
7109   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7110                                   V64, V64, vecshiftL8,
7111                                   asm, ".8b", ".8b",
7112                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7113                        (i32 vecshiftL8:$imm)))]> {
7114     bits<3> imm;
7115     let Inst{18-16} = imm;
7116   }
7117
7118   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7119                                   V128, V128, vecshiftL8,
7120                                   asm, ".16b", ".16b",
7121              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7122                    (i32 vecshiftL8:$imm)))]> {
7123     bits<3> imm;
7124     let Inst{18-16} = imm;
7125   }
7126
7127   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7128                                   V64, V64, vecshiftL16,
7129                                   asm, ".4h", ".4h",
7130               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7131                     (i32 vecshiftL16:$imm)))]> {
7132     bits<4> imm;
7133     let Inst{19-16} = imm;
7134   }
7135
7136   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7137                                   V128, V128, vecshiftL16,
7138                                   asm, ".8h", ".8h",
7139             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7140                   (i32 vecshiftL16:$imm)))]> {
7141     bits<4> imm;
7142     let Inst{19-16} = imm;
7143   }
7144
7145   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7146                                   V64, V64, vecshiftL32,
7147                                   asm, ".2s", ".2s",
7148               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7149                     (i32 vecshiftL32:$imm)))]> {
7150     bits<5> imm;
7151     let Inst{20-16} = imm;
7152   }
7153
7154   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7155                                   V128, V128, vecshiftL32,
7156                                   asm, ".4s", ".4s",
7157             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7158                   (i32 vecshiftL32:$imm)))]> {
7159     bits<5> imm;
7160     let Inst{20-16} = imm;
7161   }
7162
7163   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7164                                   V128, V128, vecshiftL64,
7165                                   asm, ".2d", ".2d",
7166             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7167                   (i32 vecshiftL64:$imm)))]> {
7168     bits<6> imm;
7169     let Inst{21-16} = imm;
7170   }
7171 }
7172
7173 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7174                                 SDPatternOperator OpNode> {
7175   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7176                                   V64, V64, vecshiftR8,
7177                                   asm, ".8b", ".8b",
7178                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7179                        (i32 vecshiftR8:$imm)))]> {
7180     bits<3> imm;
7181     let Inst{18-16} = imm;
7182   }
7183
7184   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7185                                   V128, V128, vecshiftR8,
7186                                   asm, ".16b", ".16b",
7187              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7188                    (i32 vecshiftR8:$imm)))]> {
7189     bits<3> imm;
7190     let Inst{18-16} = imm;
7191   }
7192
7193   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7194                                   V64, V64, vecshiftR16,
7195                                   asm, ".4h", ".4h",
7196               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7197                     (i32 vecshiftR16:$imm)))]> {
7198     bits<4> imm;
7199     let Inst{19-16} = imm;
7200   }
7201
7202   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7203                                   V128, V128, vecshiftR16,
7204                                   asm, ".8h", ".8h",
7205             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7206                   (i32 vecshiftR16:$imm)))]> {
7207     bits<4> imm;
7208     let Inst{19-16} = imm;
7209   }
7210
7211   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7212                                   V64, V64, vecshiftR32,
7213                                   asm, ".2s", ".2s",
7214               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7215                     (i32 vecshiftR32:$imm)))]> {
7216     bits<5> imm;
7217     let Inst{20-16} = imm;
7218   }
7219
7220   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7221                                   V128, V128, vecshiftR32,
7222                                   asm, ".4s", ".4s",
7223             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7224                   (i32 vecshiftR32:$imm)))]> {
7225     bits<5> imm;
7226     let Inst{20-16} = imm;
7227   }
7228
7229   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7230                                   V128, V128, vecshiftR64,
7231                                   asm, ".2d", ".2d",
7232             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7233                   (i32 vecshiftR64:$imm)))]> {
7234     bits<6> imm;
7235     let Inst{21-16} = imm;
7236   }
7237 }
7238
7239 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7240 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7241                                     SDPatternOperator OpNode = null_frag> {
7242   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7243                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
7244                  [(set (v8i8 V64:$dst),
7245                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7246                            (i32 vecshiftR8:$imm)))]> {
7247     bits<3> imm;
7248     let Inst{18-16} = imm;
7249   }
7250
7251   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7252                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
7253              [(set (v16i8 V128:$dst),
7254                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7255                        (i32 vecshiftR8:$imm)))]> {
7256     bits<3> imm;
7257     let Inst{18-16} = imm;
7258   }
7259
7260   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7261                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
7262               [(set (v4i16 V64:$dst),
7263                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7264                         (i32 vecshiftR16:$imm)))]> {
7265     bits<4> imm;
7266     let Inst{19-16} = imm;
7267   }
7268
7269   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7270                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
7271             [(set (v8i16 V128:$dst),
7272               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7273                       (i32 vecshiftR16:$imm)))]> {
7274     bits<4> imm;
7275     let Inst{19-16} = imm;
7276   }
7277
7278   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7279                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
7280               [(set (v2i32 V64:$dst),
7281                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7282                         (i32 vecshiftR32:$imm)))]> {
7283     bits<5> imm;
7284     let Inst{20-16} = imm;
7285   }
7286
7287   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7288                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
7289             [(set (v4i32 V128:$dst),
7290               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7291                       (i32 vecshiftR32:$imm)))]> {
7292     bits<5> imm;
7293     let Inst{20-16} = imm;
7294   }
7295
7296   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7297                                   V128, V128, vecshiftR64,
7298                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7299               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7300                       (i32 vecshiftR64:$imm)))]> {
7301     bits<6> imm;
7302     let Inst{21-16} = imm;
7303   }
7304 }
7305
7306 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7307                                     SDPatternOperator OpNode = null_frag> {
7308   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7309                                   V64, V64, vecshiftL8,
7310                                   asm, ".8b", ".8b",
7311                     [(set (v8i8 V64:$dst),
7312                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7313                                   (i32 vecshiftL8:$imm)))]> {
7314     bits<3> imm;
7315     let Inst{18-16} = imm;
7316   }
7317
7318   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7319                                   V128, V128, vecshiftL8,
7320                                   asm, ".16b", ".16b",
7321                     [(set (v16i8 V128:$dst),
7322                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7323                                   (i32 vecshiftL8:$imm)))]> {
7324     bits<3> imm;
7325     let Inst{18-16} = imm;
7326   }
7327
7328   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7329                                   V64, V64, vecshiftL16,
7330                                   asm, ".4h", ".4h",
7331                     [(set (v4i16 V64:$dst),
7332                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7333                                    (i32 vecshiftL16:$imm)))]> {
7334     bits<4> imm;
7335     let Inst{19-16} = imm;
7336   }
7337
7338   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7339                                   V128, V128, vecshiftL16,
7340                                   asm, ".8h", ".8h",
7341                     [(set (v8i16 V128:$dst),
7342                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7343                                   (i32 vecshiftL16:$imm)))]> {
7344     bits<4> imm;
7345     let Inst{19-16} = imm;
7346   }
7347
7348   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7349                                   V64, V64, vecshiftL32,
7350                                   asm, ".2s", ".2s",
7351                     [(set (v2i32 V64:$dst),
7352                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7353                                   (i32 vecshiftL32:$imm)))]> {
7354     bits<5> imm;
7355     let Inst{20-16} = imm;
7356   }
7357
7358   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7359                                   V128, V128, vecshiftL32,
7360                                   asm, ".4s", ".4s",
7361                     [(set (v4i32 V128:$dst),
7362                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7363                                   (i32 vecshiftL32:$imm)))]> {
7364     bits<5> imm;
7365     let Inst{20-16} = imm;
7366   }
7367
7368   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7369                                   V128, V128, vecshiftL64,
7370                                   asm, ".2d", ".2d",
7371                     [(set (v2i64 V128:$dst),
7372                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7373                                   (i32 vecshiftL64:$imm)))]> {
7374     bits<6> imm;
7375     let Inst{21-16} = imm;
7376   }
7377 }
7378
7379 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7380                                    SDPatternOperator OpNode> {
7381   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7382                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
7383       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7384     bits<3> imm;
7385     let Inst{18-16} = imm;
7386   }
7387
7388   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7389                                   V128, V128, vecshiftL8,
7390                                   asm#"2", ".8h", ".16b",
7391       [(set (v8i16 V128:$Rd),
7392             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7393     bits<3> imm;
7394     let Inst{18-16} = imm;
7395   }
7396
7397   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7398                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
7399       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7400     bits<4> imm;
7401     let Inst{19-16} = imm;
7402   }
7403
7404   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7405                                   V128, V128, vecshiftL16,
7406                                   asm#"2", ".4s", ".8h",
7407       [(set (v4i32 V128:$Rd),
7408             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7409
7410     bits<4> imm;
7411     let Inst{19-16} = imm;
7412   }
7413
7414   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7415                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
7416       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7417     bits<5> imm;
7418     let Inst{20-16} = imm;
7419   }
7420
7421   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7422                                   V128, V128, vecshiftL32,
7423                                   asm#"2", ".2d", ".4s",
7424       [(set (v2i64 V128:$Rd),
7425             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7426     bits<5> imm;
7427     let Inst{20-16} = imm;
7428   }
7429 }
7430
7431
7432 //---
7433 // Vector load/store
7434 //---
7435 // SIMD ldX/stX no-index memory references don't allow the optional
7436 // ", #0" constant and handle post-indexing explicitly, so we use
7437 // a more specialized parse method for them. Otherwise, it's the same as
7438 // the general am_noindex handling.
7439
7440 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7441                    string asm, dag oops, dag iops, list<dag> pattern>
7442   : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7443   bits<5> Vt;
7444   bits<5> vaddr;
7445   let Inst{31} = 0;
7446   let Inst{30} = Q;
7447   let Inst{29-23} = 0b0011000;
7448   let Inst{22} = L;
7449   let Inst{21-16} = 0b000000;
7450   let Inst{15-12} = opcode;
7451   let Inst{11-10} = size;
7452   let Inst{9-5} = vaddr;
7453   let Inst{4-0} = Vt;
7454 }
7455
7456 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7457                        string asm, dag oops, dag iops>
7458   : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "$vaddr = $wback", []> {
7459   bits<5> Vt;
7460   bits<5> vaddr;
7461   bits<5> Xm;
7462   let Inst{31} = 0;
7463   let Inst{30} = Q;
7464   let Inst{29-23} = 0b0011001;
7465   let Inst{22} = L;
7466   let Inst{21} = 0;
7467   let Inst{20-16} = Xm;
7468   let Inst{15-12} = opcode;
7469   let Inst{11-10} = size;
7470   let Inst{9-5} = vaddr;
7471   let Inst{4-0} = Vt;
7472 }
7473
7474 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7475 // register post-index addressing from the zero register.
7476 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7477                            int Offset, int Size> {
7478   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7479   //      "ld1\t$Vt, $vaddr, #16"
7480   // may get mapped to
7481   //      (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7482   def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7483                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7484                       am_simdnoindex:$vaddr,
7485                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7486                       XZR), 1>;
7487
7488   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7489   //      "ld1.8b\t$Vt, $vaddr, #16"
7490   // may get mapped to
7491   //      (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7492   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7493                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7494                       am_simdnoindex:$vaddr,
7495                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7496                       XZR), 0>;
7497
7498   // E.g. "ld1.8b { v0, v1 }, [x1]"
7499   //      "ld1\t$Vt, $vaddr"
7500   // may get mapped to
7501   //      (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7502   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7503                   (!cast<Instruction>(NAME # Count # "v" # layout)
7504                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7505                       am_simdnoindex:$vaddr), 0>;
7506
7507   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7508   //      "ld1\t$Vt, $vaddr, $Xm"
7509   // may get mapped to
7510   //      (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7511   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7512                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7513                       am_simdnoindex:$vaddr,
7514                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7515                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7516 }
7517
7518 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7519                        int Offset64, bits<4> opcode> {
7520   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7521     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7522                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7523                            (ins am_simdnoindex:$vaddr), []>;
7524     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7525                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7526                            (ins am_simdnoindex:$vaddr), []>;
7527     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7528                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7529                            (ins am_simdnoindex:$vaddr), []>;
7530     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7531                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7532                            (ins am_simdnoindex:$vaddr), []>;
7533     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7534                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7535                            (ins am_simdnoindex:$vaddr), []>;
7536     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7537                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7538                            (ins am_simdnoindex:$vaddr), []>;
7539     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7540                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7541                            (ins am_simdnoindex:$vaddr), []>;
7542
7543
7544     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7545                        (outs am_simdnoindex:$wback,
7546                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
7547                        (ins am_simdnoindex:$vaddr,
7548                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7549     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7550                        (outs am_simdnoindex:$wback,
7551                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
7552                        (ins am_simdnoindex:$vaddr,
7553                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7554     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7555                        (outs am_simdnoindex:$wback,
7556                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
7557                        (ins am_simdnoindex:$vaddr,
7558                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7559     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7560                        (outs am_simdnoindex:$wback,
7561                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
7562                        (ins am_simdnoindex:$vaddr,
7563                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7564     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7565                        (outs am_simdnoindex:$wback,
7566                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
7567                        (ins am_simdnoindex:$vaddr,
7568                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7569     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7570                        (outs am_simdnoindex:$wback,
7571                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
7572                        (ins am_simdnoindex:$vaddr,
7573                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7574     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7575                        (outs am_simdnoindex:$wback,
7576                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
7577                        (ins am_simdnoindex:$vaddr,
7578                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7579   }
7580
7581   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7582   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7583   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7584   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7585   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7586   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7587   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7588 }
7589
7590 // Only ld1/st1 has a v1d version.
7591 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7592                        int Offset64, bits<4> opcode> {
7593   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7594     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7595                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7596                                  am_simdnoindex:$vaddr), []>;
7597     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7598                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7599                                 am_simdnoindex:$vaddr), []>;
7600     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7601                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7602                                 am_simdnoindex:$vaddr), []>;
7603     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7604                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7605                                 am_simdnoindex:$vaddr), []>;
7606     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7607                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7608                                 am_simdnoindex:$vaddr), []>;
7609     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7610                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7611                                 am_simdnoindex:$vaddr), []>;
7612     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7613                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7614                                 am_simdnoindex:$vaddr), []>;
7615
7616     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
7617                        (outs am_simdnoindex:$wback),
7618                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7619                             am_simdnoindex:$vaddr,
7620                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7621     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
7622                        (outs am_simdnoindex:$wback),
7623                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7624                             am_simdnoindex:$vaddr,
7625                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7626     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
7627                        (outs am_simdnoindex:$wback),
7628                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7629                             am_simdnoindex:$vaddr,
7630                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7631     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
7632                        (outs am_simdnoindex:$wback),
7633                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7634                             am_simdnoindex:$vaddr,
7635                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7636     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
7637                        (outs am_simdnoindex:$wback),
7638                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7639                             am_simdnoindex:$vaddr,
7640                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7641     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
7642                        (outs am_simdnoindex:$wback),
7643                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7644                             am_simdnoindex:$vaddr,
7645                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7646     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
7647                        (outs am_simdnoindex:$wback),
7648                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7649                             am_simdnoindex:$vaddr,
7650                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7651   }
7652
7653   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7654   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7655   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7656   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7657   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7658   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7659   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7660 }
7661
7662 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7663                        int Offset128, int Offset64, bits<4> opcode>
7664   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7665
7666   // LD1 instructions have extra "1d" variants.
7667   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7668     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7669                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7670                            (ins am_simdnoindex:$vaddr), []>;
7671
7672     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7673                        (outs am_simdnoindex:$wback,
7674                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
7675                        (ins am_simdnoindex:$vaddr,
7676                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7677   }
7678
7679   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7680 }
7681
7682 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7683                        int Offset128, int Offset64, bits<4> opcode>
7684   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7685
7686   // ST1 instructions have extra "1d" variants.
7687   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7688     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7689                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7690                                 am_simdnoindex:$vaddr), []>;
7691
7692     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
7693                        (outs am_simdnoindex:$wback),
7694                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7695                             am_simdnoindex:$vaddr,
7696                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7697   }
7698
7699   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7700 }
7701
7702 multiclass SIMDLd1Multiple<string asm> {
7703   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
7704   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7705   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7706   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7707 }
7708
7709 multiclass SIMDSt1Multiple<string asm> {
7710   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
7711   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7712   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7713   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7714 }
7715
7716 multiclass SIMDLd2Multiple<string asm> {
7717   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7718 }
7719
7720 multiclass SIMDSt2Multiple<string asm> {
7721   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7722 }
7723
7724 multiclass SIMDLd3Multiple<string asm> {
7725   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7726 }
7727
7728 multiclass SIMDSt3Multiple<string asm> {
7729   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7730 }
7731
7732 multiclass SIMDLd4Multiple<string asm> {
7733   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7734 }
7735
7736 multiclass SIMDSt4Multiple<string asm> {
7737   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7738 }
7739
7740 //---
7741 // AdvSIMD Load/store single-element
7742 //---
7743
7744 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7745                          string asm, string operands, string cst,
7746                          dag oops, dag iops, list<dag> pattern>
7747   : I<oops, iops, asm, operands, cst, pattern> {
7748   bits<5> Vt;
7749   bits<5> vaddr;
7750   let Inst{31} = 0;
7751   let Inst{29-24} = 0b001101;
7752   let Inst{22} = L;
7753   let Inst{21} = R;
7754   let Inst{15-13} = opcode;
7755   let Inst{9-5} = vaddr;
7756   let Inst{4-0} = Vt;
7757 }
7758
7759 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7760                          string asm, string operands, string cst,
7761                          dag oops, dag iops, list<dag> pattern>
7762   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
7763   bits<5> Vt;
7764   bits<5> vaddr;
7765   let Inst{31} = 0;
7766   let Inst{29-24} = 0b001101;
7767   let Inst{22} = L;
7768   let Inst{21} = R;
7769   let Inst{15-13} = opcode;
7770   let Inst{9-5} = vaddr;
7771   let Inst{4-0} = Vt;
7772 }
7773
7774
7775 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7776 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7777                   Operand listtype>
7778   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr", "",
7779                        (outs listtype:$Vt), (ins am_simdnoindex:$vaddr),
7780                        []> {
7781   let Inst{30} = Q;
7782   let Inst{23} = 0;
7783   let Inst{20-16} = 0b00000;
7784   let Inst{12} = S;
7785   let Inst{11-10} = size;
7786 }
7787 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7788 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7789                       string asm, Operand listtype, Operand GPR64pi>
7790   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7791                        "$vaddr = $wback",
7792                        (outs am_simdnoindex:$wback, listtype:$Vt),
7793                        (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7794   bits<5> Xm;
7795   let Inst{30} = Q;
7796   let Inst{23} = 1;
7797   let Inst{20-16} = Xm;
7798   let Inst{12} = S;
7799   let Inst{11-10} = size;
7800 }
7801
7802 multiclass SIMDLdrAliases<string asm, string layout, string Count,
7803                           int Offset, int Size> {
7804   // E.g. "ld1r { v0.8b }, [x1], #1"
7805   //      "ld1r.8b\t$Vt, $vaddr, #1"
7806   // may get mapped to
7807   //      (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7808   def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7809                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
7810                       am_simdnoindex:$vaddr,
7811                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7812                       XZR), 1>;
7813
7814   // E.g. "ld1r.8b { v0 }, [x1], #1"
7815   //      "ld1r.8b\t$Vt, $vaddr, #1"
7816   // may get mapped to
7817   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7818   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7819                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
7820                       am_simdnoindex:$vaddr,
7821                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7822                       XZR), 0>;
7823
7824   // E.g. "ld1r.8b { v0 }, [x1]"
7825   //      "ld1r.8b\t$Vt, $vaddr"
7826   // may get mapped to
7827   //      (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7828   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7829                   (!cast<Instruction>(NAME # "v" # layout)
7830                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7831                       am_simdnoindex:$vaddr), 0>;
7832
7833   // E.g. "ld1r.8b { v0 }, [x1], x2"
7834   //      "ld1r.8b\t$Vt, $vaddr, $Xm"
7835   // may get mapped to
7836   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7837   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7838                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
7839                       am_simdnoindex:$vaddr,
7840                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7841                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7842 }
7843
7844 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7845   int Offset1, int Offset2, int Offset4, int Offset8> {
7846   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7847                         !cast<Operand>("VecList" # Count # "8b")>;
7848   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7849                         !cast<Operand>("VecList" # Count #"16b")>;
7850   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7851                         !cast<Operand>("VecList" # Count #"4h")>;
7852   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7853                         !cast<Operand>("VecList" # Count #"8h")>;
7854   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7855                         !cast<Operand>("VecList" # Count #"2s")>;
7856   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7857                         !cast<Operand>("VecList" # Count #"4s")>;
7858   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7859                         !cast<Operand>("VecList" # Count #"1d")>;
7860   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7861                         !cast<Operand>("VecList" # Count #"2d")>;
7862
7863   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7864                                  !cast<Operand>("VecList" # Count # "8b"),
7865                                  !cast<Operand>("GPR64pi" # Offset1)>;
7866   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7867                                  !cast<Operand>("VecList" # Count # "16b"),
7868                                  !cast<Operand>("GPR64pi" # Offset1)>;
7869   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7870                                  !cast<Operand>("VecList" # Count # "4h"),
7871                                  !cast<Operand>("GPR64pi" # Offset2)>;
7872   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7873                                  !cast<Operand>("VecList" # Count # "8h"),
7874                                  !cast<Operand>("GPR64pi" # Offset2)>;
7875   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7876                                  !cast<Operand>("VecList" # Count # "2s"),
7877                                  !cast<Operand>("GPR64pi" # Offset4)>;
7878   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7879                                  !cast<Operand>("VecList" # Count # "4s"),
7880                                  !cast<Operand>("GPR64pi" # Offset4)>;
7881   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7882                                  !cast<Operand>("VecList" # Count # "1d"),
7883                                  !cast<Operand>("GPR64pi" # Offset8)>;
7884   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7885                                  !cast<Operand>("VecList" # Count # "2d"),
7886                                  !cast<Operand>("GPR64pi" # Offset8)>;
7887
7888   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
7889   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7890   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
7891   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
7892   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
7893   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
7894   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
7895   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
7896 }
7897
7898 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7899                       dag oops, dag iops, list<dag> pattern>
7900   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "", oops, iops,
7901                        pattern> {
7902   // idx encoded in Q:S:size fields.
7903   bits<4> idx;
7904   let Inst{30} = idx{3};
7905   let Inst{23} = 0;
7906   let Inst{20-16} = 0b00000;
7907   let Inst{12} = idx{2};
7908   let Inst{11-10} = idx{1-0};
7909 }
7910 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7911                       dag oops, dag iops, list<dag> pattern>
7912   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "",
7913                            oops, iops, pattern> {
7914   // idx encoded in Q:S:size fields.
7915   bits<4> idx;
7916   let Inst{30} = idx{3};
7917   let Inst{23} = 0;
7918   let Inst{20-16} = 0b00000;
7919   let Inst{12} = idx{2};
7920   let Inst{11-10} = idx{1-0};
7921 }
7922 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7923                           dag oops, dag iops>
7924   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7925                        "$vaddr = $wback", oops, iops, []> {
7926   // idx encoded in Q:S:size fields.
7927   bits<4> idx;
7928   bits<5> Xm;
7929   let Inst{30} = idx{3};
7930   let Inst{23} = 1;
7931   let Inst{20-16} = Xm;
7932   let Inst{12} = idx{2};
7933   let Inst{11-10} = idx{1-0};
7934 }
7935 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7936                           dag oops, dag iops>
7937   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7938                            "$vaddr = $wback", oops, iops, []> {
7939   // idx encoded in Q:S:size fields.
7940   bits<4> idx;
7941   bits<5> Xm;
7942   let Inst{30} = idx{3};
7943   let Inst{23} = 1;
7944   let Inst{20-16} = Xm;
7945   let Inst{12} = idx{2};
7946   let Inst{11-10} = idx{1-0};
7947 }
7948
7949 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7950                       dag oops, dag iops, list<dag> pattern>
7951   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "", oops, iops,
7952                        pattern> {
7953   // idx encoded in Q:S:size<1> fields.
7954   bits<3> idx;
7955   let Inst{30} = idx{2};
7956   let Inst{23} = 0;
7957   let Inst{20-16} = 0b00000;
7958   let Inst{12} = idx{1};
7959   let Inst{11} = idx{0};
7960   let Inst{10} = size;
7961 }
7962 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7963                       dag oops, dag iops, list<dag> pattern>
7964   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "",
7965                            oops, iops, pattern> {
7966   // idx encoded in Q:S:size<1> fields.
7967   bits<3> idx;
7968   let Inst{30} = idx{2};
7969   let Inst{23} = 0;
7970   let Inst{20-16} = 0b00000;
7971   let Inst{12} = idx{1};
7972   let Inst{11} = idx{0};
7973   let Inst{10} = size;
7974 }
7975
7976 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7977                           dag oops, dag iops>
7978   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7979                        "$vaddr = $wback", oops, iops, []> {
7980   // idx encoded in Q:S:size<1> fields.
7981   bits<3> idx;
7982   bits<5> Xm;
7983   let Inst{30} = idx{2};
7984   let Inst{23} = 1;
7985   let Inst{20-16} = Xm;
7986   let Inst{12} = idx{1};
7987   let Inst{11} = idx{0};
7988   let Inst{10} = size;
7989 }
7990 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7991                           dag oops, dag iops>
7992   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7993                            "$vaddr = $wback", oops, iops, []> {
7994   // idx encoded in Q:S:size<1> fields.
7995   bits<3> idx;
7996   bits<5> Xm;
7997   let Inst{30} = idx{2};
7998   let Inst{23} = 1;
7999   let Inst{20-16} = Xm;
8000   let Inst{12} = idx{1};
8001   let Inst{11} = idx{0};
8002   let Inst{10} = size;
8003 }
8004 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8005                       dag oops, dag iops, list<dag> pattern>
8006   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "", oops, iops,
8007                        pattern> {
8008   // idx encoded in Q:S fields.
8009   bits<2> idx;
8010   let Inst{30} = idx{1};
8011   let Inst{23} = 0;
8012   let Inst{20-16} = 0b00000;
8013   let Inst{12} = idx{0};
8014   let Inst{11-10} = size;
8015 }
8016 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8017                       dag oops, dag iops, list<dag> pattern>
8018   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "",
8019                            oops, iops, pattern> {
8020   // idx encoded in Q:S fields.
8021   bits<2> idx;
8022   let Inst{30} = idx{1};
8023   let Inst{23} = 0;
8024   let Inst{20-16} = 0b00000;
8025   let Inst{12} = idx{0};
8026   let Inst{11-10} = size;
8027 }
8028 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8029                           string asm, dag oops, dag iops>
8030   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8031                        "$vaddr = $wback", oops, iops, []> {
8032   // idx encoded in Q:S fields.
8033   bits<2> idx;
8034   bits<5> Xm;
8035   let Inst{30} = idx{1};
8036   let Inst{23} = 1;
8037   let Inst{20-16} = Xm;
8038   let Inst{12} = idx{0};
8039   let Inst{11-10} = size;
8040 }
8041 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8042                           string asm, dag oops, dag iops>
8043   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8044                            "$vaddr = $wback", oops, iops, []> {
8045   // idx encoded in Q:S fields.
8046   bits<2> idx;
8047   bits<5> Xm;
8048   let Inst{30} = idx{1};
8049   let Inst{23} = 1;
8050   let Inst{20-16} = Xm;
8051   let Inst{12} = idx{0};
8052   let Inst{11-10} = size;
8053 }
8054 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8055                       dag oops, dag iops, list<dag> pattern>
8056   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "", oops, iops,
8057                        pattern> {
8058   // idx encoded in Q field.
8059   bits<1> idx;
8060   let Inst{30} = idx;
8061   let Inst{23} = 0;
8062   let Inst{20-16} = 0b00000;
8063   let Inst{12} = 0;
8064   let Inst{11-10} = size;
8065 }
8066 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8067                       dag oops, dag iops, list<dag> pattern>
8068   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", "",
8069                            oops, iops, pattern> {
8070   // idx encoded in Q field.
8071   bits<1> idx;
8072   let Inst{30} = idx;
8073   let Inst{23} = 0;
8074   let Inst{20-16} = 0b00000;
8075   let Inst{12} = 0;
8076   let Inst{11-10} = size;
8077 }
8078 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8079                           string asm, dag oops, dag iops>
8080   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8081                        "$vaddr = $wback", oops, iops, []> {
8082   // idx encoded in Q field.
8083   bits<1> idx;
8084   bits<5> Xm;
8085   let Inst{30} = idx;
8086   let Inst{23} = 1;
8087   let Inst{20-16} = Xm;
8088   let Inst{12} = 0;
8089   let Inst{11-10} = size;
8090 }
8091 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8092                           string asm, dag oops, dag iops>
8093   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
8094                            "$vaddr = $wback", oops, iops, []> {
8095   // idx encoded in Q field.
8096   bits<1> idx;
8097   bits<5> Xm;
8098   let Inst{30} = idx;
8099   let Inst{23} = 1;
8100   let Inst{20-16} = Xm;
8101   let Inst{12} = 0;
8102   let Inst{11-10} = size;
8103 }
8104
8105 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8106 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8107                          RegisterOperand listtype,
8108                          RegisterOperand GPR64pi> {
8109   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8110                            (outs listtype:$dst),
8111                            (ins listtype:$Vt, VectorIndexB:$idx,
8112                                 am_simdnoindex:$vaddr), []>;
8113
8114   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8115                             (outs am_simdnoindex:$wback, listtype:$dst),
8116                             (ins listtype:$Vt, VectorIndexB:$idx,
8117                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8118 }
8119 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8120 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8121                          RegisterOperand listtype,
8122                          RegisterOperand GPR64pi> {
8123   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8124                             (outs listtype:$dst),
8125                             (ins listtype:$Vt, VectorIndexH:$idx,
8126                                  am_simdnoindex:$vaddr), []>;
8127
8128   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8129                             (outs am_simdnoindex:$wback, listtype:$dst),
8130                             (ins listtype:$Vt, VectorIndexH:$idx,
8131                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8132 }
8133 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8134 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8135                          RegisterOperand listtype,
8136                          RegisterOperand GPR64pi> {
8137   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8138                             (outs listtype:$dst),
8139                             (ins listtype:$Vt, VectorIndexS:$idx,
8140                                  am_simdnoindex:$vaddr), []>;
8141
8142   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8143                             (outs am_simdnoindex:$wback, listtype:$dst),
8144                             (ins listtype:$Vt, VectorIndexS:$idx,
8145                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8146 }
8147 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8148 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8149                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8150   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8151                             (outs listtype:$dst),
8152                             (ins listtype:$Vt, VectorIndexD:$idx,
8153                                  am_simdnoindex:$vaddr), []>;
8154
8155   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8156                             (outs am_simdnoindex:$wback, listtype:$dst),
8157                             (ins listtype:$Vt, VectorIndexD:$idx,
8158                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8159 }
8160 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8161 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8162                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8163   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8164                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8165                                         am_simdnoindex:$vaddr), []>;
8166
8167   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8168                                     (outs am_simdnoindex:$wback),
8169                                     (ins listtype:$Vt, VectorIndexB:$idx,
8170                                          am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8171 }
8172 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8173 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8174                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8175   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8176                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8177                                          am_simdnoindex:$vaddr), []>;
8178
8179   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8180                             (outs am_simdnoindex:$wback),
8181                             (ins listtype:$Vt, VectorIndexH:$idx,
8182                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8183 }
8184 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8185 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8186                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8187   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8188                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8189                                          am_simdnoindex:$vaddr), []>;
8190
8191   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8192                             (outs am_simdnoindex:$wback),
8193                             (ins listtype:$Vt, VectorIndexS:$idx,
8194                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8195 }
8196 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8197 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8198                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8199   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8200                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8201                                          am_simdnoindex:$vaddr), []>;
8202
8203   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8204                             (outs am_simdnoindex:$wback),
8205                             (ins listtype:$Vt, VectorIndexD:$idx,
8206                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8207 }
8208
8209 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8210                                  string Count, int Offset, Operand idxtype> {
8211   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8212   //      "ld1\t$Vt, $vaddr, #1"
8213   // may get mapped to
8214   //      (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8215   def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8216                   (!cast<Instruction>(NAME # Type  # "_POST")
8217                       am_simdnoindex:$vaddr,
8218                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8219                       idxtype:$idx, XZR), 1>;
8220
8221   // E.g. "ld1.8b { v0 }[0], [x1], #1"
8222   //      "ld1.8b\t$Vt, $vaddr, #1"
8223   // may get mapped to
8224   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8225   def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8226                   (!cast<Instruction>(NAME # Type # "_POST")
8227                       am_simdnoindex:$vaddr,
8228                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8229                       idxtype:$idx, XZR), 0>;
8230
8231   // E.g. "ld1.8b { v0 }[0], [x1]"
8232   //      "ld1.8b\t$Vt, $vaddr"
8233   // may get mapped to
8234   //      (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8235   def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8236                       (!cast<Instruction>(NAME # Type)
8237                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8238                          idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8239
8240   // E.g. "ld1.8b { v0 }[0], [x1], x2"
8241   //      "ld1.8b\t$Vt, $vaddr, $Xm"
8242   // may get mapped to
8243   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8244   def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8245                       (!cast<Instruction>(NAME # Type # "_POST")
8246                          am_simdnoindex:$vaddr,
8247                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8248                          idxtype:$idx,
8249                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8250 }
8251
8252 multiclass SIMDLdSt1SingleAliases<string asm> {
8253   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
8254   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8255   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8256   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8257 }
8258
8259 multiclass SIMDLdSt2SingleAliases<string asm> {
8260   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
8261   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
8262   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
8263   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8264 }
8265
8266 multiclass SIMDLdSt3SingleAliases<string asm> {
8267   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
8268   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
8269   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8270   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8271 }
8272
8273 multiclass SIMDLdSt4SingleAliases<string asm> {
8274   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
8275   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
8276   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8277   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8278 }
8279 } // end of 'let Predicates = [HasNEON]'
8280
8281 //----------------------------------------------------------------------------
8282 // Crypto extensions
8283 //----------------------------------------------------------------------------
8284
8285 let Predicates = [HasCrypto] in {
8286 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8287 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8288               list<dag> pat>
8289   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8290     Sched<[WriteV]>{
8291   bits<5> Rd;
8292   bits<5> Rn;
8293   let Inst{31-16} = 0b0100111000101000;
8294   let Inst{15-12} = opc;
8295   let Inst{11-10} = 0b10;
8296   let Inst{9-5}   = Rn;
8297   let Inst{4-0}   = Rd;
8298 }
8299
8300 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8301   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8302             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8303
8304 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8305   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8306             "$Rd = $dst",
8307             [(set (v16i8 V128:$dst),
8308                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8309
8310 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8311 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8312                      dag oops, dag iops, list<dag> pat>
8313   : I<oops, iops, asm,
8314       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8315       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8316     Sched<[WriteV]>{
8317   bits<5> Rd;
8318   bits<5> Rn;
8319   bits<5> Rm;
8320   let Inst{31-21} = 0b01011110000;
8321   let Inst{20-16} = Rm;
8322   let Inst{15}    = 0;
8323   let Inst{14-12} = opc;
8324   let Inst{11-10} = 0b00;
8325   let Inst{9-5}   = Rn;
8326   let Inst{4-0}   = Rd;
8327 }
8328
8329 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8330   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8331                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8332                    [(set (v4i32 FPR128:$dst),
8333                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8334                                  (v4i32 V128:$Rm)))]>;
8335
8336 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8337   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8338                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
8339                    [(set (v4i32 V128:$dst),
8340                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8341                                  (v4i32 V128:$Rm)))]>;
8342
8343 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8344   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8345                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8346                    [(set (v4i32 FPR128:$dst),
8347                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8348                                  (v4i32 V128:$Rm)))]>;
8349
8350 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8351 class SHA2OpInst<bits<4> opc, string asm, string kind,
8352                  string cstr, dag oops, dag iops,
8353                  list<dag> pat>
8354   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8355                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8356     Sched<[WriteV]>{
8357   bits<5> Rd;
8358   bits<5> Rn;
8359   let Inst{31-16} = 0b0101111000101000;
8360   let Inst{15-12} = opc;
8361   let Inst{11-10} = 0b10;
8362   let Inst{9-5}   = Rn;
8363   let Inst{4-0}   = Rd;
8364 }
8365
8366 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8367   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8368                (ins V128:$Rd, V128:$Rn),
8369                [(set (v4i32 V128:$dst),
8370                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8371
8372 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8373   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8374                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8375 } // end of 'let Predicates = [HasCrypto]'
8376
8377 // Allow the size specifier tokens to be upper case, not just lower.
8378 def : TokenAlias<".8B", ".8b">;
8379 def : TokenAlias<".4H", ".4h">;
8380 def : TokenAlias<".2S", ".2s">;
8381 def : TokenAlias<".1D", ".1d">;
8382 def : TokenAlias<".16B", ".16b">;
8383 def : TokenAlias<".8H", ".8h">;
8384 def : TokenAlias<".4S", ".4s">;
8385 def : TokenAlias<".2D", ".2d">;
8386 def : TokenAlias<".1Q", ".1q">;
8387 def : TokenAlias<".B", ".b">;
8388 def : TokenAlias<".H", ".h">;
8389 def : TokenAlias<".S", ".s">;
8390 def : TokenAlias<".D", ".d">;
8391 def : TokenAlias<".Q", ".q">;