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