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