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