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