ARM64: initial backend import
[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
5107 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5108   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5109   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5110 }
5111
5112 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5113                               SDPatternOperator OpNode> {
5114   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5115                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5116   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5117                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5118 }
5119
5120 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5121                              SDPatternOperator OpNode = null_frag> {
5122   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5123     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5124            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5125     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5126            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5127     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5128     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5129   }
5130
5131   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5132             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5133 }
5134
5135 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5136 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5137                                  Intrinsic OpNode> {
5138   def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5139       [(set (v1i64 FPR64:$dst),
5140             (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn)))]>;
5141   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm, []>;
5142   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5143   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5144 }
5145
5146
5147
5148 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5149 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5150                                  SDPatternOperator OpNode = null_frag> {
5151   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5152         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5153   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5154   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5155 }
5156
5157 //----------------------------------------------------------------------------
5158 // AdvSIMD scalar pairwise instructions
5159 //----------------------------------------------------------------------------
5160
5161 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5162 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5163                         RegisterOperand regtype, RegisterOperand vectype,
5164                         string asm, string kind>
5165   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5166       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5167     Sched<[WriteV]> {
5168   bits<5> Rd;
5169   bits<5> Rn;
5170   let Inst{31-30} = 0b01;
5171   let Inst{29}    = U;
5172   let Inst{28-24} = 0b11110;
5173   let Inst{23-22} = size;
5174   let Inst{21-17} = 0b11000;
5175   let Inst{16-12} = opcode;
5176   let Inst{11-10} = 0b10;
5177   let Inst{9-5}   = Rn;
5178   let Inst{4-0}   = Rd;
5179 }
5180
5181 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5182   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5183                                       asm, ".2d">;
5184 }
5185
5186 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5187   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5188                                       asm, ".2s">;
5189   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5190                                       asm, ".2d">;
5191 }
5192
5193 //----------------------------------------------------------------------------
5194 // AdvSIMD across lanes instructions
5195 //----------------------------------------------------------------------------
5196
5197 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5198 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5199                           RegisterClass regtype, RegisterOperand vectype,
5200                           string asm, string kind, list<dag> pattern>
5201   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5202       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5203     Sched<[WriteV]> {
5204   bits<5> Rd;
5205   bits<5> Rn;
5206   let Inst{31}    = 0;
5207   let Inst{30}    = Q;
5208   let Inst{29}    = U;
5209   let Inst{28-24} = 0b01110;
5210   let Inst{23-22} = size;
5211   let Inst{21-17} = 0b11000;
5212   let Inst{16-12} = opcode;
5213   let Inst{11-10} = 0b10;
5214   let Inst{9-5}   = Rn;
5215   let Inst{4-0}   = Rd;
5216 }
5217
5218 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5219                               string asm> {
5220   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5221                                    asm, ".8b", []>;
5222   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5223                                    asm, ".16b", []>;
5224   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5225                                    asm, ".4h", []>;
5226   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5227                                    asm, ".8h", []>;
5228   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5229                                    asm, ".4s", []>;
5230 }
5231
5232 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5233   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5234                                    asm, ".8b", []>;
5235   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5236                                    asm, ".16b", []>;
5237   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5238                                    asm, ".4h", []>;
5239   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5240                                    asm, ".8h", []>;
5241   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5242                                    asm, ".4s", []>;
5243 }
5244
5245 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5246                             Intrinsic intOp> {
5247   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5248                                    asm, ".4s",
5249         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5250 }
5251
5252 //----------------------------------------------------------------------------
5253 // AdvSIMD INS/DUP instructions
5254 //----------------------------------------------------------------------------
5255
5256 // FIXME: There has got to be a better way to factor these. ugh.
5257
5258 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5259                      string operands, string constraints, list<dag> pattern>
5260   : I<outs, ins, asm, operands, constraints, pattern>,
5261     Sched<[WriteV]> {
5262   bits<5> Rd;
5263   bits<5> Rn;
5264   let Inst{31} = 0;
5265   let Inst{30} = Q;
5266   let Inst{29} = op;
5267   let Inst{28-21} = 0b01110000;
5268   let Inst{15} = 0;
5269   let Inst{10} = 1;
5270   let Inst{9-5} = Rn;
5271   let Inst{4-0} = Rd;
5272 }
5273
5274 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5275                       RegisterOperand vecreg, RegisterClass regtype>
5276   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5277                    "{\t$Rd" # size # ", $Rn" #
5278                    "|" # size # "\t$Rd, $Rn}", "",
5279                    [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5280   let Inst{20-16} = imm5;
5281   let Inst{14-11} = 0b0001;
5282 }
5283
5284 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5285                          ValueType vectype, ValueType insreg,
5286                          RegisterOperand vecreg, Operand idxtype,
5287                          ValueType elttype, SDNode OpNode>
5288   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5289                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5290                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5291                  [(set (vectype vecreg:$Rd),
5292                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5293   let Inst{14-11} = 0b0000;
5294 }
5295
5296 class SIMDDup64FromElement
5297   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5298                        VectorIndexD, i64, ARM64duplane64> {
5299   bits<1> idx;
5300   let Inst{20} = idx;
5301   let Inst{19-16} = 0b1000;
5302 }
5303
5304 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5305                            RegisterOperand vecreg>
5306   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5307                        VectorIndexS, i64, ARM64duplane32> {
5308   bits<2> idx;
5309   let Inst{20-19} = idx;
5310   let Inst{18-16} = 0b100;
5311 }
5312
5313 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5314                            RegisterOperand vecreg>
5315   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5316                        VectorIndexH, i64, ARM64duplane16> {
5317   bits<3> idx;
5318   let Inst{20-18} = idx;
5319   let Inst{17-16} = 0b10;
5320 }
5321
5322 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5323                           RegisterOperand vecreg>
5324   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5325                        VectorIndexB, i64, ARM64duplane8> {
5326   bits<4> idx;
5327   let Inst{20-17} = idx;
5328   let Inst{16} = 1;
5329 }
5330
5331 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5332                   Operand idxtype, string asm, list<dag> pattern>
5333   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5334                    "{\t$Rd, $Rn" # size # "$idx" #
5335                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5336   let Inst{14-11} = imm4;
5337 }
5338
5339 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5340                Operand idxtype>
5341   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5342 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5343                Operand idxtype>
5344   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5345       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5346
5347 class SIMDMovAlias<string asm, string size, Instruction inst,
5348                    RegisterClass regtype, Operand idxtype>
5349     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5350                     "|" # size # "\t$dst, $src$idx}",
5351                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5352
5353 multiclass SMov {
5354   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5355     bits<4> idx;
5356     let Inst{20-17} = idx;
5357     let Inst{16} = 1;
5358   }
5359   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5360     bits<4> idx;
5361     let Inst{20-17} = idx;
5362     let Inst{16} = 1;
5363   }
5364   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5365     bits<3> idx;
5366     let Inst{20-18} = idx;
5367     let Inst{17-16} = 0b10;
5368   }
5369   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5370     bits<3> idx;
5371     let Inst{20-18} = idx;
5372     let Inst{17-16} = 0b10;
5373   }
5374   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5375     bits<2> idx;
5376     let Inst{20-19} = idx;
5377     let Inst{18-16} = 0b100;
5378   }
5379 }
5380
5381 multiclass UMov {
5382   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5383     bits<4> idx;
5384     let Inst{20-17} = idx;
5385     let Inst{16} = 1;
5386   }
5387   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5388     bits<3> idx;
5389     let Inst{20-18} = idx;
5390     let Inst{17-16} = 0b10;
5391   }
5392   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5393     bits<2> idx;
5394     let Inst{20-19} = idx;
5395     let Inst{18-16} = 0b100;
5396   }
5397   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5398     bits<1> idx;
5399     let Inst{20} = idx;
5400     let Inst{19-16} = 0b1000;
5401   }
5402   def : SIMDMovAlias<"mov", ".s",
5403                      !cast<Instruction>(NAME#"vi32"),
5404                      GPR32, VectorIndexS>;
5405   def : SIMDMovAlias<"mov", ".d",
5406                      !cast<Instruction>(NAME#"vi64"),
5407                      GPR64, VectorIndexD>;
5408 }
5409
5410 class SIMDInsFromMain<string size, ValueType vectype,
5411                       RegisterClass regtype, Operand idxtype>
5412   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5413                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5414                    "{\t$Rd" # size # "$idx, $Rn" #
5415                    "|" # size # "\t$Rd$idx, $Rn}",
5416                    "$Rd = $dst",
5417             [(set V128:$dst,
5418               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5419   let Inst{14-11} = 0b0011;
5420 }
5421
5422 class SIMDInsFromElement<string size, ValueType vectype,
5423                          ValueType elttype, Operand idxtype>
5424   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5425                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5426                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5427                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
5428                    "$Rd = $dst",
5429          [(set V128:$dst,
5430                (vector_insert
5431                  (vectype V128:$Rd),
5432                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5433                  idxtype:$idx))]>;
5434
5435 class SIMDInsMainMovAlias<string size, Instruction inst,
5436                           RegisterClass regtype, Operand idxtype>
5437     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5438                         "|" # size #"\t$dst$idx, $src}",
5439                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5440 class SIMDInsElementMovAlias<string size, Instruction inst,
5441                              Operand idxtype>
5442     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5443                       # "|" # size #" $dst$idx, $src$idx2}",
5444                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5445
5446
5447 multiclass SIMDIns {
5448   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5449     bits<4> idx;
5450     let Inst{20-17} = idx;
5451     let Inst{16} = 1;
5452   }
5453   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5454     bits<3> idx;
5455     let Inst{20-18} = idx;
5456     let Inst{17-16} = 0b10;
5457   }
5458   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5459     bits<2> idx;
5460     let Inst{20-19} = idx;
5461     let Inst{18-16} = 0b100;
5462   }
5463   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5464     bits<1> idx;
5465     let Inst{20} = idx;
5466     let Inst{19-16} = 0b1000;
5467   }
5468
5469   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5470     bits<4> idx;
5471     bits<4> idx2;
5472     let Inst{20-17} = idx;
5473     let Inst{16} = 1;
5474     let Inst{14-11} = idx2;
5475   }
5476   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5477     bits<3> idx;
5478     bits<3> idx2;
5479     let Inst{20-18} = idx;
5480     let Inst{17-16} = 0b10;
5481     let Inst{14-12} = idx2;
5482     let Inst{11} = 0;
5483   }
5484   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5485     bits<2> idx;
5486     bits<2> idx2;
5487     let Inst{20-19} = idx;
5488     let Inst{18-16} = 0b100;
5489     let Inst{14-13} = idx2;
5490     let Inst{12-11} = 0;
5491   }
5492   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5493     bits<1> idx;
5494     bits<1> idx2;
5495     let Inst{20} = idx;
5496     let Inst{19-16} = 0b1000;
5497     let Inst{14} = idx2;
5498     let Inst{13-11} = 0;
5499   }
5500
5501   // For all forms of the INS instruction, the "mov" mnemonic is the
5502   // preferred alias. Why they didn't just call the instruction "mov" in
5503   // the first place is a very good question indeed...
5504   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5505                          GPR32, VectorIndexB>;
5506   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5507                          GPR32, VectorIndexH>;
5508   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5509                          GPR32, VectorIndexS>;
5510   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5511                          GPR64, VectorIndexD>;
5512
5513   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5514                          VectorIndexB>;
5515   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5516                          VectorIndexH>;
5517   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5518                          VectorIndexS>;
5519   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5520                          VectorIndexD>;
5521 }
5522
5523 //----------------------------------------------------------------------------
5524 // AdvSIMD TBL/TBX
5525 //----------------------------------------------------------------------------
5526
5527 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5528 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5529                           RegisterOperand listtype, string asm, string kind>
5530   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5531        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5532     Sched<[WriteV]> {
5533   bits<5> Vd;
5534   bits<5> Vn;
5535   bits<5> Vm;
5536   let Inst{31}    = 0;
5537   let Inst{30}    = Q;
5538   let Inst{29-21} = 0b001110000;
5539   let Inst{20-16} = Vm;
5540   let Inst{15}    = 0;
5541   let Inst{14-13} = len;
5542   let Inst{12}    = op;
5543   let Inst{11-10} = 0b00;
5544   let Inst{9-5}   = Vn;
5545   let Inst{4-0}   = Vd;
5546 }
5547
5548 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5549 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5550                           RegisterOperand listtype, string asm, string kind>
5551   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5552        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5553     Sched<[WriteV]> {
5554   bits<5> Vd;
5555   bits<5> Vn;
5556   bits<5> Vm;
5557   let Inst{31}    = 0;
5558   let Inst{30}    = Q;
5559   let Inst{29-21} = 0b001110000;
5560   let Inst{20-16} = Vm;
5561   let Inst{15}    = 0;
5562   let Inst{14-13} = len;
5563   let Inst{12}    = op;
5564   let Inst{11-10} = 0b00;
5565   let Inst{9-5}   = Vn;
5566   let Inst{4-0}   = Vd;
5567 }
5568
5569 class SIMDTableLookupAlias<string asm, Instruction inst,
5570                           RegisterOperand vectype, RegisterOperand listtype>
5571     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5572                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5573
5574 multiclass SIMDTableLookup<bit op, string asm> {
5575   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5576                                       asm, ".8b">;
5577   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5578                                       asm, ".8b">;
5579   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5580                                       asm, ".8b">;
5581   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5582                                       asm, ".8b">;
5583   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5584                                       asm, ".16b">;
5585   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5586                                       asm, ".16b">;
5587   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5588                                       asm, ".16b">;
5589   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5590                                       asm, ".16b">;
5591
5592   def : SIMDTableLookupAlias<asm # ".8b",
5593                          !cast<Instruction>(NAME#"v8i8One"),
5594                          V64, VecListOne128>;
5595   def : SIMDTableLookupAlias<asm # ".8b",
5596                          !cast<Instruction>(NAME#"v8i8Two"),
5597                          V64, VecListTwo128>;
5598   def : SIMDTableLookupAlias<asm # ".8b",
5599                          !cast<Instruction>(NAME#"v8i8Three"),
5600                          V64, VecListThree128>;
5601   def : SIMDTableLookupAlias<asm # ".8b",
5602                          !cast<Instruction>(NAME#"v8i8Four"),
5603                          V64, VecListFour128>;
5604   def : SIMDTableLookupAlias<asm # ".16b",
5605                          !cast<Instruction>(NAME#"v16i8One"),
5606                          V128, VecListOne128>;
5607   def : SIMDTableLookupAlias<asm # ".16b",
5608                          !cast<Instruction>(NAME#"v16i8Two"),
5609                          V128, VecListTwo128>;
5610   def : SIMDTableLookupAlias<asm # ".16b",
5611                          !cast<Instruction>(NAME#"v16i8Three"),
5612                          V128, VecListThree128>;
5613   def : SIMDTableLookupAlias<asm # ".16b",
5614                          !cast<Instruction>(NAME#"v16i8Four"),
5615                          V128, VecListFour128>;
5616 }
5617
5618 multiclass SIMDTableLookupTied<bit op, string asm> {
5619   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5620                                       asm, ".8b">;
5621   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5622                                       asm, ".8b">;
5623   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5624                                       asm, ".8b">;
5625   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5626                                       asm, ".8b">;
5627   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5628                                       asm, ".16b">;
5629   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5630                                       asm, ".16b">;
5631   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5632                                       asm, ".16b">;
5633   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5634                                       asm, ".16b">;
5635
5636   def : SIMDTableLookupAlias<asm # ".8b",
5637                          !cast<Instruction>(NAME#"v8i8One"),
5638                          V64, VecListOne128>;
5639   def : SIMDTableLookupAlias<asm # ".8b",
5640                          !cast<Instruction>(NAME#"v8i8Two"),
5641                          V64, VecListTwo128>;
5642   def : SIMDTableLookupAlias<asm # ".8b",
5643                          !cast<Instruction>(NAME#"v8i8Three"),
5644                          V64, VecListThree128>;
5645   def : SIMDTableLookupAlias<asm # ".8b",
5646                          !cast<Instruction>(NAME#"v8i8Four"),
5647                          V64, VecListFour128>;
5648   def : SIMDTableLookupAlias<asm # ".16b",
5649                          !cast<Instruction>(NAME#"v16i8One"),
5650                          V128, VecListOne128>;
5651   def : SIMDTableLookupAlias<asm # ".16b",
5652                          !cast<Instruction>(NAME#"v16i8Two"),
5653                          V128, VecListTwo128>;
5654   def : SIMDTableLookupAlias<asm # ".16b",
5655                          !cast<Instruction>(NAME#"v16i8Three"),
5656                          V128, VecListThree128>;
5657   def : SIMDTableLookupAlias<asm # ".16b",
5658                          !cast<Instruction>(NAME#"v16i8Four"),
5659                          V128, VecListFour128>;
5660 }
5661
5662
5663 //----------------------------------------------------------------------------
5664 // AdvSIMD scalar CPY
5665 //----------------------------------------------------------------------------
5666 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5667 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5668                         string kind, Operand idxtype>
5669   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5670        "{\t$dst, $src" # kind # "$idx" #
5671        "|\t$dst, $src$idx}", "", []>,
5672     Sched<[WriteV]> {
5673   bits<5> dst;
5674   bits<5> src;
5675   let Inst{31-21} = 0b01011110000;
5676   let Inst{15-10} = 0b000001;
5677   let Inst{9-5}   = src;
5678   let Inst{4-0}   = dst;
5679 }
5680
5681 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5682       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5683     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5684                     # "|\t$dst, $src$index}",
5685                 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5686
5687
5688 multiclass SIMDScalarCPY<string asm> {
5689   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
5690     bits<4> idx;
5691     let Inst{20-17} = idx;
5692     let Inst{16} = 1;
5693   }
5694   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5695     bits<3> idx;
5696     let Inst{20-18} = idx;
5697     let Inst{17-16} = 0b10;
5698   }
5699   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5700     bits<2> idx;
5701     let Inst{20-19} = idx;
5702     let Inst{18-16} = 0b100;
5703   }
5704   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5705     bits<1> idx;
5706     let Inst{20} = idx;
5707     let Inst{19-16} = 0b1000;
5708   }
5709
5710   // 'DUP' mnemonic aliases.
5711   def : SIMDScalarCPYAlias<"dup", ".b",
5712                            !cast<Instruction>(NAME#"i8"),
5713                            FPR8, V128, VectorIndexB>;
5714   def : SIMDScalarCPYAlias<"dup", ".h",
5715                            !cast<Instruction>(NAME#"i16"),
5716                            FPR16, V128, VectorIndexH>;
5717   def : SIMDScalarCPYAlias<"dup", ".s",
5718                            !cast<Instruction>(NAME#"i32"),
5719                            FPR32, V128, VectorIndexS>;
5720   def : SIMDScalarCPYAlias<"dup", ".d",
5721                            !cast<Instruction>(NAME#"i64"),
5722                            FPR64, V128, VectorIndexD>;
5723 }
5724
5725 //----------------------------------------------------------------------------
5726 // AdvSIMD modified immediate instructions
5727 //----------------------------------------------------------------------------
5728
5729 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5730                           string asm, string op_string,
5731                           string cstr, list<dag> pattern>
5732   : I<oops, iops, asm, op_string, cstr, pattern>,
5733     Sched<[WriteV]> {
5734   bits<5> Rd;
5735   bits<8> imm8;
5736   let Inst{31}    = 0;
5737   let Inst{30}    = Q;
5738   let Inst{29}    = op;
5739   let Inst{28-19} = 0b0111100000;
5740   let Inst{18-16} = imm8{7-5};
5741   let Inst{11-10} = 0b01;
5742   let Inst{9-5}   = imm8{4-0};
5743   let Inst{4-0}   = Rd;
5744 }
5745
5746 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5747                                 Operand immtype, dag opt_shift_iop,
5748                                 string opt_shift, string asm, string kind,
5749                                 list<dag> pattern>
5750   : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5751                         !con((ins immtype:$imm8), opt_shift_iop), asm,
5752                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
5753                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5754                         "", pattern> {
5755   let DecoderMethod = "DecodeModImmInstruction";
5756 }
5757
5758 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5759                                 Operand immtype, dag opt_shift_iop,
5760                                 string opt_shift, string asm, string kind,
5761                                 list<dag> pattern>
5762   : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5763                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5764                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5765                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5766                         "$Rd = $dst", pattern> {
5767   let DecoderMethod = "DecodeModImmTiedInstruction";
5768 }
5769
5770 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5771                                      RegisterOperand vectype, string asm,
5772                                      string kind, list<dag> pattern>
5773   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5774                               (ins logical_vec_shift:$shift),
5775                               "$shift", asm, kind, pattern> {
5776   bits<2> shift;
5777   let Inst{15}    = b15_b12{1};
5778   let Inst{14-13} = shift;
5779   let Inst{12}    = b15_b12{0};
5780 }
5781
5782 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5783                                      RegisterOperand vectype, string asm,
5784                                      string kind, list<dag> pattern>
5785   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5786                               (ins logical_vec_shift:$shift),
5787                               "$shift", asm, kind, pattern> {
5788   bits<2> shift;
5789   let Inst{15}    = b15_b12{1};
5790   let Inst{14-13} = shift;
5791   let Inst{12}    = b15_b12{0};
5792 }
5793
5794
5795 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5796                                          RegisterOperand vectype, string asm,
5797                                          string kind, list<dag> pattern>
5798   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5799                               (ins logical_vec_hw_shift:$shift),
5800                               "$shift", asm, kind, pattern> {
5801   bits<2> shift;
5802   let Inst{15} = b15_b12{1};
5803   let Inst{14} = 0;
5804   let Inst{13} = shift{0};
5805   let Inst{12} = b15_b12{0};
5806 }
5807
5808 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5809                                          RegisterOperand vectype, string asm,
5810                                          string kind, list<dag> pattern>
5811   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5812                               (ins logical_vec_hw_shift:$shift),
5813                               "$shift", asm, kind, pattern> {
5814   bits<2> shift;
5815   let Inst{15} = b15_b12{1};
5816   let Inst{14} = 0;
5817   let Inst{13} = shift{0};
5818   let Inst{12} = b15_b12{0};
5819 }
5820
5821 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5822                                       string asm> {
5823   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5824                                                  asm, ".4h", []>;
5825   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
5826                                                  asm, ".8h", []>;
5827
5828   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
5829                                              asm, ".2s", []>;
5830   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
5831                                              asm, ".4s", []>;
5832 }
5833
5834 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
5835                                       bits<2> w_cmode, string asm,
5836                                       SDNode OpNode> {
5837   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
5838                                                  asm, ".4h",
5839              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
5840                                              imm0_255:$imm8,
5841                                              (i32 imm:$shift)))]>;
5842   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
5843                                                  asm, ".8h",
5844              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
5845                                               imm0_255:$imm8,
5846                                               (i32 imm:$shift)))]>;
5847
5848   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
5849                                              asm, ".2s",
5850              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
5851                                              imm0_255:$imm8,
5852                                              (i32 imm:$shift)))]>;
5853   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
5854                                              asm, ".4s",
5855              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
5856                                               imm0_255:$imm8,
5857                                               (i32 imm:$shift)))]>;
5858 }
5859
5860 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
5861                              RegisterOperand vectype, string asm,
5862                              string kind, list<dag> pattern>
5863   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5864                               (ins move_vec_shift:$shift),
5865                               "$shift", asm, kind, pattern> {
5866   bits<1> shift;
5867   let Inst{15-13} = cmode{3-1};
5868   let Inst{12}    = shift;
5869 }
5870
5871 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
5872                                    RegisterOperand vectype,
5873                                    Operand imm_type, string asm,
5874                                    string kind, list<dag> pattern>
5875   : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
5876                               asm, kind, pattern> {
5877   let Inst{15-12} = cmode;
5878 }
5879
5880 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
5881                                    list<dag> pattern>
5882   : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
5883                         "\t$Rd, $imm8", "", pattern> {
5884   let Inst{15-12} = cmode;
5885   let DecoderMethod = "DecodeModImmInstruction";
5886 }
5887
5888 //----------------------------------------------------------------------------
5889 // AdvSIMD indexed element
5890 //----------------------------------------------------------------------------
5891
5892 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5893 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5894                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
5895                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
5896                       string apple_kind, string dst_kind, string lhs_kind,
5897                       string rhs_kind, list<dag> pattern>
5898   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
5899       asm,
5900       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5901       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
5902     Sched<[WriteV]> {
5903   bits<5> Rd;
5904   bits<5> Rn;
5905   bits<5> Rm;
5906
5907   let Inst{31}    = 0;
5908   let Inst{30}    = Q;
5909   let Inst{29}    = U;
5910   let Inst{28}    = Scalar;
5911   let Inst{27-24} = 0b1111;
5912   let Inst{23-22} = size;
5913   // Bit 21 must be set by the derived class.
5914   let Inst{20-16} = Rm;
5915   let Inst{15-12} = opc;
5916   // Bit 11 must be set by the derived class.
5917   let Inst{10}    = 0;
5918   let Inst{9-5}   = Rn;
5919   let Inst{4-0}   = Rd;
5920 }
5921
5922 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5923 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5924                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
5925                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
5926                       string apple_kind, string dst_kind, string lhs_kind,
5927                       string rhs_kind, list<dag> pattern>
5928   : I<(outs dst_reg:$dst),
5929       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
5930       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5931       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
5932     Sched<[WriteV]> {
5933   bits<5> Rd;
5934   bits<5> Rn;
5935   bits<5> Rm;
5936
5937   let Inst{31}    = 0;
5938   let Inst{30}    = Q;
5939   let Inst{29}    = U;
5940   let Inst{28}    = Scalar;
5941   let Inst{27-24} = 0b1111;
5942   let Inst{23-22} = size;
5943   // Bit 21 must be set by the derived class.
5944   let Inst{20-16} = Rm;
5945   let Inst{15-12} = opc;
5946   // Bit 11 must be set by the derived class.
5947   let Inst{10}    = 0;
5948   let Inst{9-5}   = Rn;
5949   let Inst{4-0}   = Rd;
5950 }
5951
5952 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
5953                            SDPatternOperator OpNode> {
5954   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
5955                                       V64, V64,
5956                                       V128, VectorIndexS,
5957                                       asm, ".2s", ".2s", ".2s", ".s",
5958     [(set (v2f32 V64:$Rd),
5959         (OpNode (v2f32 V64:$Rn),
5960          (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
5961     bits<2> idx;
5962     let Inst{11} = idx{1};
5963     let Inst{21} = idx{0};
5964   }
5965
5966   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
5967                                       V128, V128,
5968                                       V128, VectorIndexS,
5969                                       asm, ".4s", ".4s", ".4s", ".s",
5970     [(set (v4f32 V128:$Rd),
5971         (OpNode (v4f32 V128:$Rn),
5972          (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
5973     bits<2> idx;
5974     let Inst{11} = idx{1};
5975     let Inst{21} = idx{0};
5976   }
5977
5978   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
5979                                       V128, V128,
5980                                       V128, VectorIndexD,
5981                                       asm, ".2d", ".2d", ".2d", ".d",
5982     [(set (v2f64 V128:$Rd),
5983         (OpNode (v2f64 V128:$Rn),
5984          (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
5985     bits<1> idx;
5986     let Inst{11} = idx{0};
5987     let Inst{21} = 0;
5988   }
5989
5990   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
5991                                       FPR32Op, FPR32Op, V128, VectorIndexS,
5992                                       asm, ".s", "", "", ".s",
5993     [(set (f32 FPR32Op:$Rd),
5994           (OpNode (f32 FPR32Op:$Rn),
5995                   (f32 (vector_extract (v4f32 V128:$Rm),
5996                                        VectorIndexS:$idx))))]> {
5997     bits<2> idx;
5998     let Inst{11} = idx{1};
5999     let Inst{21} = idx{0};
6000   }
6001
6002   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6003                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6004                                       asm, ".d", "", "", ".d",
6005     [(set (f64 FPR64Op:$Rd),
6006           (OpNode (f64 FPR64Op:$Rn),
6007                   (f64 (vector_extract (v2f64 V128:$Rm),
6008                                        VectorIndexD:$idx))))]> {
6009     bits<1> idx;
6010     let Inst{11} = idx{0};
6011     let Inst{21} = 0;
6012   }
6013 }
6014
6015 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6016   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6017   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6018                            (ARM64duplane32 (v4f32 V128:$Rm),
6019                                            VectorIndexS:$idx))),
6020             (!cast<Instruction>(INST # v2i32_indexed)
6021                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6022   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6023                            (ARM64dup (f32 FPR32Op:$Rm)))),
6024             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6025                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6026
6027
6028   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6029   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6030                            (ARM64duplane32 (v4f32 V128:$Rm),
6031                                            VectorIndexS:$idx))),
6032             (!cast<Instruction>(INST # "v4i32_indexed")
6033                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6034   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6035                            (ARM64dup (f32 FPR32Op:$Rm)))),
6036             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6037                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6038
6039   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6040   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6041                            (ARM64duplane64 (v2f64 V128:$Rm),
6042                                            VectorIndexD:$idx))),
6043             (!cast<Instruction>(INST # "v2i64_indexed")
6044                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6045   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6046                            (ARM64dup (f64 FPR64Op:$Rm)))),
6047             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6048                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6049
6050   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6051   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6052                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6053             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6054                 V128:$Rm, VectorIndexS:$idx)>;
6055   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6056                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6057             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6058                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6059
6060   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6061   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6062                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6063             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6064                 V128:$Rm, VectorIndexD:$idx)>;
6065 }
6066
6067 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6068   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6069                                           V128, VectorIndexS,
6070                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6071     bits<2> idx;
6072     let Inst{11} = idx{1};
6073     let Inst{21} = idx{0};
6074   }
6075
6076   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6077                                       V128, V128,
6078                                       V128, VectorIndexS,
6079                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6080     bits<2> idx;
6081     let Inst{11} = idx{1};
6082     let Inst{21} = idx{0};
6083   }
6084
6085   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6086                                       V128, V128,
6087                                       V128, VectorIndexD,
6088                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6089     bits<1> idx;
6090     let Inst{11} = idx{0};
6091     let Inst{21} = 0;
6092   }
6093
6094
6095   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6096                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6097                                       asm, ".s", "", "", ".s", []> {
6098     bits<2> idx;
6099     let Inst{11} = idx{1};
6100     let Inst{21} = idx{0};
6101   }
6102
6103   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6104                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6105                                       asm, ".d", "", "", ".d", []> {
6106     bits<1> idx;
6107     let Inst{11} = idx{0};
6108     let Inst{21} = 0;
6109   }
6110 }
6111
6112 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6113                          SDPatternOperator OpNode> {
6114   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6115                                       V128_lo, VectorIndexH,
6116                                       asm, ".4h", ".4h", ".4h", ".h",
6117     [(set (v4i16 V64:$Rd),
6118         (OpNode (v4i16 V64:$Rn),
6119          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6120     bits<3> idx;
6121     let Inst{11} = idx{2};
6122     let Inst{21} = idx{1};
6123     let Inst{20} = idx{0};
6124   }
6125
6126   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6127                                       V128, V128,
6128                                       V128_lo, VectorIndexH,
6129                                       asm, ".8h", ".8h", ".8h", ".h",
6130     [(set (v8i16 V128:$Rd),
6131        (OpNode (v8i16 V128:$Rn),
6132          (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6133     bits<3> idx;
6134     let Inst{11} = idx{2};
6135     let Inst{21} = idx{1};
6136     let Inst{20} = idx{0};
6137   }
6138
6139   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6140                                       V64, V64,
6141                                       V128, VectorIndexS,
6142                                       asm, ".2s", ".2s", ".2s",  ".s",
6143     [(set (v2i32 V64:$Rd),
6144        (OpNode (v2i32 V64:$Rn),
6145           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6146     bits<2> idx;
6147     let Inst{11} = idx{1};
6148     let Inst{21} = idx{0};
6149   }
6150
6151   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6152                                       V128, V128,
6153                                       V128, VectorIndexS,
6154                                       asm, ".4s", ".4s", ".4s", ".s",
6155     [(set (v4i32 V128:$Rd),
6156        (OpNode (v4i32 V128:$Rn),
6157           (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6158     bits<2> idx;
6159     let Inst{11} = idx{1};
6160     let Inst{21} = idx{0};
6161   }
6162
6163   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6164                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6165                                       asm, ".h", "", "", ".h", []> {
6166     bits<3> idx;
6167     let Inst{11} = idx{2};
6168     let Inst{21} = idx{1};
6169     let Inst{20} = idx{0};
6170   }
6171
6172   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6173                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6174                                       asm, ".s", "", "", ".s",
6175       [(set (i32 FPR32Op:$Rd),
6176             (OpNode FPR32Op:$Rn,
6177                     (i32 (vector_extract (v4i32 V128:$Rm),
6178                                          VectorIndexS:$idx))))]> {
6179     bits<2> idx;
6180     let Inst{11} = idx{1};
6181     let Inst{21} = idx{0};
6182   }
6183 }
6184
6185 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6186                                SDPatternOperator OpNode> {
6187   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6188                                       V64, V64,
6189                                       V128_lo, VectorIndexH,
6190                                       asm, ".4h", ".4h", ".4h", ".h",
6191     [(set (v4i16 V64:$Rd),
6192         (OpNode (v4i16 V64:$Rn),
6193          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6194     bits<3> idx;
6195     let Inst{11} = idx{2};
6196     let Inst{21} = idx{1};
6197     let Inst{20} = idx{0};
6198   }
6199
6200   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6201                                       V128, V128,
6202                                       V128_lo, VectorIndexH,
6203                                       asm, ".8h", ".8h", ".8h", ".h",
6204     [(set (v8i16 V128:$Rd),
6205        (OpNode (v8i16 V128:$Rn),
6206          (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6207     bits<3> idx;
6208     let Inst{11} = idx{2};
6209     let Inst{21} = idx{1};
6210     let Inst{20} = idx{0};
6211   }
6212
6213   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6214                                       V64, V64,
6215                                       V128, VectorIndexS,
6216                                       asm, ".2s", ".2s", ".2s", ".s",
6217     [(set (v2i32 V64:$Rd),
6218        (OpNode (v2i32 V64:$Rn),
6219           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6220     bits<2> idx;
6221     let Inst{11} = idx{1};
6222     let Inst{21} = idx{0};
6223   }
6224
6225   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6226                                       V128, V128,
6227                                       V128, VectorIndexS,
6228                                       asm, ".4s", ".4s", ".4s", ".s",
6229     [(set (v4i32 V128:$Rd),
6230        (OpNode (v4i32 V128:$Rn),
6231           (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6232     bits<2> idx;
6233     let Inst{11} = idx{1};
6234     let Inst{21} = idx{0};
6235   }
6236 }
6237
6238 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6239                                    SDPatternOperator OpNode> {
6240   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6241                                           V128_lo, VectorIndexH,
6242                                           asm, ".4h", ".4h", ".4h", ".h",
6243     [(set (v4i16 V64:$dst),
6244         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6245          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6246     bits<3> idx;
6247     let Inst{11} = idx{2};
6248     let Inst{21} = idx{1};
6249     let Inst{20} = idx{0};
6250   }
6251
6252   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6253                                       V128, V128,
6254                                       V128_lo, VectorIndexH,
6255                                       asm, ".8h", ".8h", ".8h", ".h",
6256     [(set (v8i16 V128:$dst),
6257        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6258          (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6259     bits<3> idx;
6260     let Inst{11} = idx{2};
6261     let Inst{21} = idx{1};
6262     let Inst{20} = idx{0};
6263   }
6264
6265   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6266                                       V64, V64,
6267                                       V128, VectorIndexS,
6268                                       asm, ".2s", ".2s", ".2s", ".s",
6269     [(set (v2i32 V64:$dst),
6270        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6271           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6272     bits<2> idx;
6273     let Inst{11} = idx{1};
6274     let Inst{21} = idx{0};
6275   }
6276
6277   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6278                                       V128, V128,
6279                                       V128, VectorIndexS,
6280                                       asm, ".4s", ".4s", ".4s", ".s",
6281     [(set (v4i32 V128:$dst),
6282        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6283           (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6284     bits<2> idx;
6285     let Inst{11} = idx{1};
6286     let Inst{21} = idx{0};
6287   }
6288 }
6289
6290 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6291                              SDPatternOperator OpNode> {
6292   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6293                                       V128, V64,
6294                                       V128_lo, VectorIndexH,
6295                                       asm, ".4s", ".4s", ".4h", ".h",
6296     [(set (v4i32 V128:$Rd),
6297         (OpNode (v4i16 V64:$Rn),
6298          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6299     bits<3> idx;
6300     let Inst{11} = idx{2};
6301     let Inst{21} = idx{1};
6302     let Inst{20} = idx{0};
6303   }
6304
6305   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6306                                       V128, V128,
6307                                       V128_lo, VectorIndexH,
6308                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6309     [(set (v4i32 V128:$Rd),
6310           (OpNode (extract_high_v8i16 V128:$Rn),
6311                   (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6312                                                       VectorIndexH:$idx))))]> {
6313
6314     bits<3> idx;
6315     let Inst{11} = idx{2};
6316     let Inst{21} = idx{1};
6317     let Inst{20} = idx{0};
6318   }
6319
6320   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6321                                       V128, V64,
6322                                       V128, VectorIndexS,
6323                                       asm, ".2d", ".2d", ".2s", ".s",
6324     [(set (v2i64 V128:$Rd),
6325         (OpNode (v2i32 V64:$Rn),
6326          (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6327     bits<2> idx;
6328     let Inst{11} = idx{1};
6329     let Inst{21} = idx{0};
6330   }
6331
6332   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6333                                       V128, V128,
6334                                       V128, VectorIndexS,
6335                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6336     [(set (v2i64 V128:$Rd),
6337           (OpNode (extract_high_v4i32 V128:$Rn),
6338                   (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6339                                                       VectorIndexS:$idx))))]> {
6340     bits<2> idx;
6341     let Inst{11} = idx{1};
6342     let Inst{21} = idx{0};
6343   }
6344
6345   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6346                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6347                                       asm, ".h", "", "", ".h", []> {
6348     bits<3> idx;
6349     let Inst{11} = idx{2};
6350     let Inst{21} = idx{1};
6351     let Inst{20} = idx{0};
6352   }
6353
6354   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6355                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6356                                       asm, ".s", "", "", ".s", []> {
6357     bits<2> idx;
6358     let Inst{11} = idx{1};
6359     let Inst{21} = idx{0};
6360   }
6361 }
6362
6363 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6364                                        SDPatternOperator Accum> {
6365   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6366                                       V128, V64,
6367                                       V128_lo, VectorIndexH,
6368                                       asm, ".4s", ".4s", ".4h", ".h",
6369     [(set (v4i32 V128:$dst),
6370           (Accum (v4i32 V128:$Rd),
6371                  (v4i32 (int_arm64_neon_sqdmull
6372                              (v4i16 V64:$Rn),
6373                              (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6374                                                     VectorIndexH:$idx))))))]> {
6375     bits<3> idx;
6376     let Inst{11} = idx{2};
6377     let Inst{21} = idx{1};
6378     let Inst{20} = idx{0};
6379   }
6380
6381   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6382   // intermediate EXTRACT_SUBREG would be untyped.
6383   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6384                 (i32 (vector_extract (v4i32
6385                          (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6386                              (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6387                                                     VectorIndexH:$idx)))),
6388                          (i64 0))))),
6389             (EXTRACT_SUBREG
6390                 (!cast<Instruction>(NAME # v4i16_indexed)
6391                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6392                     V128_lo:$Rm, VectorIndexH:$idx),
6393                 ssub)>;
6394
6395   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6396                                       V128, V128,
6397                                       V128_lo, VectorIndexH,
6398                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6399     [(set (v4i32 V128:$dst),
6400           (Accum (v4i32 V128:$Rd),
6401                  (v4i32 (int_arm64_neon_sqdmull
6402                             (extract_high_v8i16 V128:$Rn),
6403                             (extract_high_v8i16
6404                                 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6405                                                 VectorIndexH:$idx))))))]> {
6406     bits<3> idx;
6407     let Inst{11} = idx{2};
6408     let Inst{21} = idx{1};
6409     let Inst{20} = idx{0};
6410   }
6411
6412   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6413                                       V128, V64,
6414                                       V128, VectorIndexS,
6415                                       asm, ".2d", ".2d", ".2s", ".s",
6416     [(set (v2i64 V128:$dst),
6417         (Accum (v2i64 V128:$Rd),
6418                (v2i64 (int_arm64_neon_sqdmull
6419                           (v2i32 V64:$Rn),
6420                           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6421                                                  VectorIndexS:$idx))))))]> {
6422     bits<2> idx;
6423     let Inst{11} = idx{1};
6424     let Inst{21} = idx{0};
6425   }
6426
6427   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6428                                       V128, V128,
6429                                       V128, VectorIndexS,
6430                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6431     [(set (v2i64 V128:$dst),
6432           (Accum (v2i64 V128:$Rd),
6433                  (v2i64 (int_arm64_neon_sqdmull
6434                             (extract_high_v4i32 V128:$Rn),
6435                             (extract_high_v4i32
6436                                 (ARM64duplane32 (v4i32 V128:$Rm),
6437                                                 VectorIndexS:$idx))))))]> {
6438     bits<2> idx;
6439     let Inst{11} = idx{1};
6440     let Inst{21} = idx{0};
6441   }
6442
6443   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6444                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6445                                       asm, ".h", "", "", ".h", []> {
6446     bits<3> idx;
6447     let Inst{11} = idx{2};
6448     let Inst{21} = idx{1};
6449     let Inst{20} = idx{0};
6450   }
6451
6452
6453   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6454                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6455                                       asm, ".s", "", "", ".s",
6456     [(set (i64 FPR64Op:$dst),
6457           (Accum (i64 FPR64Op:$Rd),
6458                  (i64 (int_arm64_neon_sqdmulls_scalar
6459                             (i32 FPR32Op:$Rn),
6460                             (i32 (vector_extract (v4i32 V128:$Rm),
6461                                                  VectorIndexS:$idx))))))]> {
6462
6463     bits<2> idx;
6464     let Inst{11} = idx{1};
6465     let Inst{21} = idx{0};
6466   }
6467 }
6468
6469 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6470                                    SDPatternOperator OpNode> {
6471   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6472   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6473                                       V128, V64,
6474                                       V128_lo, VectorIndexH,
6475                                       asm, ".4s", ".4s", ".4h", ".h",
6476     [(set (v4i32 V128:$Rd),
6477         (OpNode (v4i16 V64:$Rn),
6478          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6479     bits<3> idx;
6480     let Inst{11} = idx{2};
6481     let Inst{21} = idx{1};
6482     let Inst{20} = idx{0};
6483   }
6484
6485   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6486                                       V128, V128,
6487                                       V128_lo, VectorIndexH,
6488                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6489     [(set (v4i32 V128:$Rd),
6490           (OpNode (extract_high_v8i16 V128:$Rn),
6491                   (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6492                                                       VectorIndexH:$idx))))]> {
6493
6494     bits<3> idx;
6495     let Inst{11} = idx{2};
6496     let Inst{21} = idx{1};
6497     let Inst{20} = idx{0};
6498   }
6499
6500   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6501                                       V128, V64,
6502                                       V128, VectorIndexS,
6503                                       asm, ".2d", ".2d", ".2s", ".s",
6504     [(set (v2i64 V128:$Rd),
6505         (OpNode (v2i32 V64:$Rn),
6506          (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6507     bits<2> idx;
6508     let Inst{11} = idx{1};
6509     let Inst{21} = idx{0};
6510   }
6511
6512   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6513                                       V128, V128,
6514                                       V128, VectorIndexS,
6515                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6516     [(set (v2i64 V128:$Rd),
6517           (OpNode (extract_high_v4i32 V128:$Rn),
6518                   (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6519                                                       VectorIndexS:$idx))))]> {
6520     bits<2> idx;
6521     let Inst{11} = idx{1};
6522     let Inst{21} = idx{0};
6523   }
6524   }
6525 }
6526
6527 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6528                                        SDPatternOperator OpNode> {
6529   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6530   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6531                                       V128, V64,
6532                                       V128_lo, VectorIndexH,
6533                                       asm, ".4s", ".4s", ".4h", ".h",
6534     [(set (v4i32 V128:$dst),
6535         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6536          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6537     bits<3> idx;
6538     let Inst{11} = idx{2};
6539     let Inst{21} = idx{1};
6540     let Inst{20} = idx{0};
6541   }
6542
6543   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6544                                       V128, V128,
6545                                       V128_lo, VectorIndexH,
6546                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6547     [(set (v4i32 V128:$dst),
6548           (OpNode (v4i32 V128:$Rd),
6549                   (extract_high_v8i16 V128:$Rn),
6550                   (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6551                                                       VectorIndexH:$idx))))]> {
6552     bits<3> idx;
6553     let Inst{11} = idx{2};
6554     let Inst{21} = idx{1};
6555     let Inst{20} = idx{0};
6556   }
6557
6558   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6559                                       V128, V64,
6560                                       V128, VectorIndexS,
6561                                       asm, ".2d", ".2d", ".2s", ".s",
6562     [(set (v2i64 V128:$dst),
6563         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6564          (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6565     bits<2> idx;
6566     let Inst{11} = idx{1};
6567     let Inst{21} = idx{0};
6568   }
6569
6570   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6571                                       V128, V128,
6572                                       V128, VectorIndexS,
6573                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6574     [(set (v2i64 V128:$dst),
6575           (OpNode (v2i64 V128:$Rd),
6576                   (extract_high_v4i32 V128:$Rn),
6577                   (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6578                                                       VectorIndexS:$idx))))]> {
6579     bits<2> idx;
6580     let Inst{11} = idx{1};
6581     let Inst{21} = idx{0};
6582   }
6583   }
6584 }
6585
6586 //----------------------------------------------------------------------------
6587 // AdvSIMD scalar shift by immediate
6588 //----------------------------------------------------------------------------
6589
6590 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6591 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6592                      RegisterClass regtype1, RegisterClass regtype2,
6593                      Operand immtype, string asm, list<dag> pattern>
6594   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6595       asm, "\t$Rd, $Rn, $imm", "", pattern>,
6596     Sched<[WriteV]> {
6597   bits<5> Rd;
6598   bits<5> Rn;
6599   bits<7> imm;
6600   let Inst{31-30} = 0b01;
6601   let Inst{29}    = U;
6602   let Inst{28-23} = 0b111110;
6603   let Inst{22-16} = fixed_imm;
6604   let Inst{15-11} = opc;
6605   let Inst{10}    = 1;
6606   let Inst{9-5} = Rn;
6607   let Inst{4-0} = Rd;
6608 }
6609
6610 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6611 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6612                      RegisterClass regtype1, RegisterClass regtype2,
6613                      Operand immtype, string asm, list<dag> pattern>
6614   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6615       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6616     Sched<[WriteV]> {
6617   bits<5> Rd;
6618   bits<5> Rn;
6619   bits<7> imm;
6620   let Inst{31-30} = 0b01;
6621   let Inst{29}    = U;
6622   let Inst{28-23} = 0b111110;
6623   let Inst{22-16} = fixed_imm;
6624   let Inst{15-11} = opc;
6625   let Inst{10}    = 1;
6626   let Inst{9-5} = Rn;
6627   let Inst{4-0} = Rd;
6628 }
6629
6630
6631 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6632   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6633                               FPR32, FPR32, vecshiftR32, asm, []> {
6634     let Inst{20-16} = imm{4-0};
6635   }
6636
6637   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6638                               FPR64, FPR64, vecshiftR64, asm, []> {
6639     let Inst{21-16} = imm{5-0};
6640   }
6641 }
6642
6643 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6644                              SDPatternOperator OpNode> {
6645   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6646                               FPR64, FPR64, vecshiftR64, asm,
6647   [(set (v1i64 FPR64:$Rd),
6648      (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
6649     let Inst{21-16} = imm{5-0};
6650   }
6651 }
6652
6653 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6654 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6655                                  SDPatternOperator OpNode = null_frag> {
6656   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6657                               FPR64, FPR64, vecshiftR64, asm,
6658   [(set (v1i64 FPR64:$dst),
6659      (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6660              (i32 vecshiftR64:$imm)))]> {
6661     let Inst{21-16} = imm{5-0};
6662   }
6663 }
6664
6665 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6666                              SDPatternOperator OpNode> {
6667   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6668                               FPR64, FPR64, vecshiftL64, asm,
6669     [(set (v1i64 FPR64:$Rd),
6670        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6671     let Inst{21-16} = imm{5-0};
6672   }
6673 }
6674
6675 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6676 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6677   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6678                               FPR64, FPR64, vecshiftL64, asm, []> {
6679     let Inst{21-16} = imm{5-0};
6680   }
6681 }
6682
6683 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6684 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6685                                SDPatternOperator OpNode = null_frag> {
6686   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6687                               FPR8, FPR16, vecshiftR8, asm, []> {
6688     let Inst{18-16} = imm{2-0};
6689   }
6690
6691   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6692                               FPR16, FPR32, vecshiftR16, asm, []> {
6693     let Inst{19-16} = imm{3-0};
6694   }
6695
6696   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6697                               FPR32, FPR64, vecshiftR32, asm,
6698     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6699     let Inst{20-16} = imm{4-0};
6700   }
6701 }
6702
6703 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6704                                 SDPatternOperator OpNode> {
6705   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6706                               FPR8, FPR8, vecshiftL8, asm, []> {
6707     let Inst{18-16} = imm{2-0};
6708   }
6709
6710   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6711                               FPR16, FPR16, vecshiftL16, asm, []> {
6712     let Inst{19-16} = imm{3-0};
6713   }
6714
6715   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6716                               FPR32, FPR32, vecshiftL32, asm,
6717     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6718     let Inst{20-16} = imm{4-0};
6719   }
6720
6721   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6722                               FPR64, FPR64, vecshiftL64, asm,
6723     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn),
6724                                      (i32 vecshiftL64:$imm)))]> {
6725     let Inst{21-16} = imm{5-0};
6726   }
6727 }
6728
6729 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6730   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6731                               FPR8, FPR8, vecshiftR8, asm, []> {
6732     let Inst{18-16} = imm{2-0};
6733   }
6734
6735   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6736                               FPR16, FPR16, vecshiftR16, asm, []> {
6737     let Inst{19-16} = imm{3-0};
6738   }
6739
6740   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6741                               FPR32, FPR32, vecshiftR32, asm, []> {
6742     let Inst{20-16} = imm{4-0};
6743   }
6744
6745   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6746                               FPR64, FPR64, vecshiftR64, asm, []> {
6747     let Inst{21-16} = imm{5-0};
6748   }
6749 }
6750
6751 //----------------------------------------------------------------------------
6752 // AdvSIMD vector x indexed element
6753 //----------------------------------------------------------------------------
6754
6755 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6756 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6757                      RegisterOperand dst_reg, RegisterOperand src_reg,
6758                      Operand immtype,
6759                      string asm, string dst_kind, string src_kind,
6760                      list<dag> pattern>
6761   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6762       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6763            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6764     Sched<[WriteV]> {
6765   bits<5> Rd;
6766   bits<5> Rn;
6767   let Inst{31}    = 0;
6768   let Inst{30}    = Q;
6769   let Inst{29}    = U;
6770   let Inst{28-23} = 0b011110;
6771   let Inst{22-16} = fixed_imm;
6772   let Inst{15-11} = opc;
6773   let Inst{10}    = 1;
6774   let Inst{9-5}   = Rn;
6775   let Inst{4-0}   = Rd;
6776 }
6777
6778 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6779 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6780                      RegisterOperand vectype1, RegisterOperand vectype2,
6781                      Operand immtype,
6782                      string asm, string dst_kind, string src_kind,
6783                      list<dag> pattern>
6784   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6785       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6786            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6787     Sched<[WriteV]> {
6788   bits<5> Rd;
6789   bits<5> Rn;
6790   let Inst{31}    = 0;
6791   let Inst{30}    = Q;
6792   let Inst{29}    = U;
6793   let Inst{28-23} = 0b011110;
6794   let Inst{22-16} = fixed_imm;
6795   let Inst{15-11} = opc;
6796   let Inst{10}    = 1;
6797   let Inst{9-5}   = Rn;
6798   let Inst{4-0}   = Rd;
6799 }
6800
6801 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6802                               Intrinsic OpNode> {
6803   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6804                                   V64, V64, vecshiftR32,
6805                                   asm, ".2s", ".2s",
6806       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6807     bits<5> imm;
6808     let Inst{20-16} = imm;
6809   }
6810
6811   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6812                                   V128, V128, vecshiftR32,
6813                                   asm, ".4s", ".4s",
6814       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6815     bits<5> imm;
6816     let Inst{20-16} = imm;
6817   }
6818
6819   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6820                                   V128, V128, vecshiftR64,
6821                                   asm, ".2d", ".2d",
6822       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
6823     bits<6> imm;
6824     let Inst{21-16} = imm;
6825   }
6826 }
6827
6828 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
6829                                   Intrinsic OpNode> {
6830   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6831                                   V64, V64, vecshiftR32,
6832                                   asm, ".2s", ".2s",
6833       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
6834     bits<5> imm;
6835     let Inst{20-16} = imm;
6836   }
6837
6838   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6839                                   V128, V128, vecshiftR32,
6840                                   asm, ".4s", ".4s",
6841       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
6842     bits<5> imm;
6843     let Inst{20-16} = imm;
6844   }
6845
6846   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6847                                   V128, V128, vecshiftR64,
6848                                   asm, ".2d", ".2d",
6849       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
6850     bits<6> imm;
6851     let Inst{21-16} = imm;
6852   }
6853 }
6854
6855 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
6856                                      SDPatternOperator OpNode> {
6857   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6858                                   V64, V128, vecshiftR16Narrow,
6859                                   asm, ".8b", ".8h",
6860       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
6861     bits<3> imm;
6862     let Inst{18-16} = imm;
6863   }
6864
6865   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
6866                                   V128, V128, vecshiftR16Narrow,
6867                                   asm#"2", ".16b", ".8h", []> {
6868     bits<3> imm;
6869     let Inst{18-16} = imm;
6870     let hasSideEffects = 0;
6871   }
6872
6873   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6874                                   V64, V128, vecshiftR32Narrow,
6875                                   asm, ".4h", ".4s",
6876       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
6877     bits<4> imm;
6878     let Inst{19-16} = imm;
6879   }
6880
6881   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
6882                                   V128, V128, vecshiftR32Narrow,
6883                                   asm#"2", ".8h", ".4s", []> {
6884     bits<4> imm;
6885     let Inst{19-16} = imm;
6886     let hasSideEffects = 0;
6887   }
6888
6889   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6890                                   V64, V128, vecshiftR64Narrow,
6891                                   asm, ".2s", ".2d",
6892       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
6893     bits<5> imm;
6894     let Inst{20-16} = imm;
6895   }
6896
6897   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
6898                                   V128, V128, vecshiftR64Narrow,
6899                                   asm#"2", ".4s", ".2d", []> {
6900     bits<5> imm;
6901     let Inst{20-16} = imm;
6902     let hasSideEffects = 0;
6903   }
6904
6905   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
6906   // themselves, so put them here instead.
6907
6908   // Patterns involving what's effectively an insert high and a normal
6909   // intrinsic, represented by CONCAT_VECTORS.
6910   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
6911                                                    vecshiftR16Narrow:$imm)),
6912             (!cast<Instruction>(NAME # "v16i8_shift")
6913                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6914                 V128:$Rn, vecshiftR16Narrow:$imm)>;
6915   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
6916                                                      vecshiftR32Narrow:$imm)),
6917             (!cast<Instruction>(NAME # "v8i16_shift")
6918                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6919                 V128:$Rn, vecshiftR32Narrow:$imm)>;
6920   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
6921                                                      vecshiftR64Narrow:$imm)),
6922             (!cast<Instruction>(NAME # "v4i32_shift")
6923                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6924                 V128:$Rn, vecshiftR64Narrow:$imm)>;
6925 }
6926
6927 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
6928                                 SDPatternOperator OpNode> {
6929   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6930                                   V64, V64, vecshiftL8,
6931                                   asm, ".8b", ".8b",
6932                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
6933                        (i32 vecshiftL8:$imm)))]> {
6934     bits<3> imm;
6935     let Inst{18-16} = imm;
6936   }
6937
6938   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
6939                                   V128, V128, vecshiftL8,
6940                                   asm, ".16b", ".16b",
6941              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
6942                    (i32 vecshiftL8:$imm)))]> {
6943     bits<3> imm;
6944     let Inst{18-16} = imm;
6945   }
6946
6947   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6948                                   V64, V64, vecshiftL16,
6949                                   asm, ".4h", ".4h",
6950               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
6951                     (i32 vecshiftL16:$imm)))]> {
6952     bits<4> imm;
6953     let Inst{19-16} = imm;
6954   }
6955
6956   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
6957                                   V128, V128, vecshiftL16,
6958                                   asm, ".8h", ".8h",
6959             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6960                   (i32 vecshiftL16:$imm)))]> {
6961     bits<4> imm;
6962     let Inst{19-16} = imm;
6963   }
6964
6965   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6966                                   V64, V64, vecshiftL32,
6967                                   asm, ".2s", ".2s",
6968               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
6969                     (i32 vecshiftL32:$imm)))]> {
6970     bits<5> imm;
6971     let Inst{20-16} = imm;
6972   }
6973
6974   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6975                                   V128, V128, vecshiftL32,
6976                                   asm, ".4s", ".4s",
6977             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6978                   (i32 vecshiftL32:$imm)))]> {
6979     bits<5> imm;
6980     let Inst{20-16} = imm;
6981   }
6982
6983   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6984                                   V128, V128, vecshiftL64,
6985                                   asm, ".2d", ".2d",
6986             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6987                   (i32 vecshiftL64:$imm)))]> {
6988     bits<6> imm;
6989     let Inst{21-16} = imm;
6990   }
6991 }
6992
6993 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
6994                                 SDPatternOperator OpNode> {
6995   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6996                                   V64, V64, vecshiftR8,
6997                                   asm, ".8b", ".8b",
6998                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
6999                        (i32 vecshiftR8:$imm)))]> {
7000     bits<3> imm;
7001     let Inst{18-16} = imm;
7002   }
7003
7004   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7005                                   V128, V128, vecshiftR8,
7006                                   asm, ".16b", ".16b",
7007              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7008                    (i32 vecshiftR8:$imm)))]> {
7009     bits<3> imm;
7010     let Inst{18-16} = imm;
7011   }
7012
7013   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7014                                   V64, V64, vecshiftR16,
7015                                   asm, ".4h", ".4h",
7016               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7017                     (i32 vecshiftR16:$imm)))]> {
7018     bits<4> imm;
7019     let Inst{19-16} = imm;
7020   }
7021
7022   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7023                                   V128, V128, vecshiftR16,
7024                                   asm, ".8h", ".8h",
7025             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7026                   (i32 vecshiftR16:$imm)))]> {
7027     bits<4> imm;
7028     let Inst{19-16} = imm;
7029   }
7030
7031   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7032                                   V64, V64, vecshiftR32,
7033                                   asm, ".2s", ".2s",
7034               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7035                     (i32 vecshiftR32:$imm)))]> {
7036     bits<5> imm;
7037     let Inst{20-16} = imm;
7038   }
7039
7040   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7041                                   V128, V128, vecshiftR32,
7042                                   asm, ".4s", ".4s",
7043             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7044                   (i32 vecshiftR32:$imm)))]> {
7045     bits<5> imm;
7046     let Inst{20-16} = imm;
7047   }
7048
7049   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7050                                   V128, V128, vecshiftR64,
7051                                   asm, ".2d", ".2d",
7052             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7053                   (i32 vecshiftR64:$imm)))]> {
7054     bits<6> imm;
7055     let Inst{21-16} = imm;
7056   }
7057 }
7058
7059 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7060 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7061                                     SDPatternOperator OpNode = null_frag> {
7062   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7063                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
7064                  [(set (v8i8 V64:$dst),
7065                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7066                            (i32 vecshiftR8:$imm)))]> {
7067     bits<3> imm;
7068     let Inst{18-16} = imm;
7069   }
7070
7071   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7072                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
7073              [(set (v16i8 V128:$dst),
7074                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7075                        (i32 vecshiftR8:$imm)))]> {
7076     bits<3> imm;
7077     let Inst{18-16} = imm;
7078   }
7079
7080   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7081                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
7082               [(set (v4i16 V64:$dst),
7083                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7084                         (i32 vecshiftR16:$imm)))]> {
7085     bits<4> imm;
7086     let Inst{19-16} = imm;
7087   }
7088
7089   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7090                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
7091             [(set (v8i16 V128:$dst),
7092               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7093                       (i32 vecshiftR16:$imm)))]> {
7094     bits<4> imm;
7095     let Inst{19-16} = imm;
7096   }
7097
7098   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7099                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
7100               [(set (v2i32 V64:$dst),
7101                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7102                         (i32 vecshiftR32:$imm)))]> {
7103     bits<5> imm;
7104     let Inst{20-16} = imm;
7105   }
7106
7107   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7108                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
7109             [(set (v4i32 V128:$dst),
7110               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7111                       (i32 vecshiftR32:$imm)))]> {
7112     bits<5> imm;
7113     let Inst{20-16} = imm;
7114   }
7115
7116   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7117                                   V128, V128, vecshiftR64,
7118                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7119               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7120                       (i32 vecshiftR64:$imm)))]> {
7121     bits<6> imm;
7122     let Inst{21-16} = imm;
7123   }
7124 }
7125
7126 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7127                                     SDPatternOperator OpNode = null_frag> {
7128   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7129                                   V64, V64, vecshiftL8,
7130                                   asm, ".8b", ".8b",
7131                     [(set (v8i8 V64:$dst),
7132                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7133                                   (i32 vecshiftL8:$imm)))]> {
7134     bits<3> imm;
7135     let Inst{18-16} = imm;
7136   }
7137
7138   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7139                                   V128, V128, vecshiftL8,
7140                                   asm, ".16b", ".16b",
7141                     [(set (v16i8 V128:$dst),
7142                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7143                                   (i32 vecshiftL8:$imm)))]> {
7144     bits<3> imm;
7145     let Inst{18-16} = imm;
7146   }
7147
7148   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7149                                   V64, V64, vecshiftL16,
7150                                   asm, ".4h", ".4h",
7151                     [(set (v4i16 V64:$dst),
7152                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7153                                    (i32 vecshiftL16:$imm)))]> {
7154     bits<4> imm;
7155     let Inst{19-16} = imm;
7156   }
7157
7158   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7159                                   V128, V128, vecshiftL16,
7160                                   asm, ".8h", ".8h",
7161                     [(set (v8i16 V128:$dst),
7162                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7163                                   (i32 vecshiftL16:$imm)))]> {
7164     bits<4> imm;
7165     let Inst{19-16} = imm;
7166   }
7167
7168   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7169                                   V64, V64, vecshiftL32,
7170                                   asm, ".2s", ".2s",
7171                     [(set (v2i32 V64:$dst),
7172                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7173                                   (i32 vecshiftL32:$imm)))]> {
7174     bits<5> imm;
7175     let Inst{20-16} = imm;
7176   }
7177
7178   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7179                                   V128, V128, vecshiftL32,
7180                                   asm, ".4s", ".4s",
7181                     [(set (v4i32 V128:$dst),
7182                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7183                                   (i32 vecshiftL32:$imm)))]> {
7184     bits<5> imm;
7185     let Inst{20-16} = imm;
7186   }
7187
7188   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7189                                   V128, V128, vecshiftL64,
7190                                   asm, ".2d", ".2d",
7191                     [(set (v2i64 V128:$dst),
7192                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7193                                   (i32 vecshiftL64:$imm)))]> {
7194     bits<6> imm;
7195     let Inst{21-16} = imm;
7196   }
7197 }
7198
7199 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7200                                    SDPatternOperator OpNode> {
7201   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7202                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
7203       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7204     bits<3> imm;
7205     let Inst{18-16} = imm;
7206   }
7207
7208   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7209                                   V128, V128, vecshiftL8,
7210                                   asm#"2", ".8h", ".16b",
7211       [(set (v8i16 V128:$Rd),
7212             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7213     bits<3> imm;
7214     let Inst{18-16} = imm;
7215   }
7216
7217   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7218                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
7219       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7220     bits<4> imm;
7221     let Inst{19-16} = imm;
7222   }
7223
7224   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7225                                   V128, V128, vecshiftL16,
7226                                   asm#"2", ".4s", ".8h",
7227       [(set (v4i32 V128:$Rd),
7228             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7229
7230     bits<4> imm;
7231     let Inst{19-16} = imm;
7232   }
7233
7234   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7235                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
7236       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7237     bits<5> imm;
7238     let Inst{20-16} = imm;
7239   }
7240
7241   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7242                                   V128, V128, vecshiftL32,
7243                                   asm#"2", ".2d", ".4s",
7244       [(set (v2i64 V128:$Rd),
7245             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7246     bits<5> imm;
7247     let Inst{20-16} = imm;
7248   }
7249 }
7250
7251
7252 //---
7253 // Vector load/store
7254 //---
7255 // SIMD ldX/stX no-index memory references don't allow the optional
7256 // ", #0" constant and handle post-indexing explicitly, so we use
7257 // a more specialized parse method for them. Otherwise, it's the same as
7258 // the general am_noindex handling.
7259 def MemorySIMDNoIndexOperand : AsmOperandClass {
7260   let Name = "MemorySIMDNoIndex";
7261   let ParserMethod = "tryParseNoIndexMemory";
7262 }
7263 def am_simdnoindex : Operand<i64>,
7264                      ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
7265   let PrintMethod = "printAMNoIndex";
7266   let ParserMatchClass = MemorySIMDNoIndexOperand;
7267   let MIOperandInfo = (ops GPR64sp:$base);
7268   let DecoderMethod = "DecodeGPR64spRegisterClass";
7269 }
7270
7271 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7272                    string asm, dag oops, dag iops, list<dag> pattern>
7273   : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7274   bits<5> Vt;
7275   bits<5> vaddr;
7276   let Inst{31} = 0;
7277   let Inst{30} = Q;
7278   let Inst{29-23} = 0b0011000;
7279   let Inst{22} = L;
7280   let Inst{21-16} = 0b000000;
7281   let Inst{15-12} = opcode;
7282   let Inst{11-10} = size;
7283   let Inst{9-5} = vaddr;
7284   let Inst{4-0} = Vt;
7285 }
7286
7287 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7288                        string asm, dag oops, dag iops>
7289   : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "", []> {
7290   bits<5> Vt;
7291   bits<5> vaddr;
7292   bits<5> Xm;
7293   let Inst{31} = 0;
7294   let Inst{30} = Q;
7295   let Inst{29-23} = 0b0011001;
7296   let Inst{22} = L;
7297   let Inst{21} = 0;
7298   let Inst{20-16} = Xm;
7299   let Inst{15-12} = opcode;
7300   let Inst{11-10} = size;
7301   let Inst{9-5} = vaddr;
7302   let Inst{4-0} = Vt;
7303   let DecoderMethod = "DecodeSIMDLdStPost";
7304 }
7305
7306 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7307 // register post-index addressing from the zero register.
7308 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7309                            int Offset, int Size> {
7310   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7311   //      "ld1\t$Vt, $vaddr, #16"
7312   // may get mapped to
7313   //      (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7314   def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7315                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7316                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7317                       am_simdnoindex:$vaddr, XZR), 1>;
7318
7319   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7320   //      "ld1.8b\t$Vt, $vaddr, #16"
7321   // may get mapped to
7322   //      (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7323   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7324                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7325                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7326                       am_simdnoindex:$vaddr, XZR), 0>;
7327
7328   // E.g. "ld1.8b { v0, v1 }, [x1]"
7329   //      "ld1\t$Vt, $vaddr"
7330   // may get mapped to
7331   //      (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7332   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7333                   (!cast<Instruction>(NAME # Count # "v" # layout)
7334                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7335                       am_simdnoindex:$vaddr), 0>;
7336
7337   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7338   //      "ld1\t$Vt, $vaddr, $Xm"
7339   // may get mapped to
7340   //      (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7341   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7342                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7343                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7344                       am_simdnoindex:$vaddr,
7345                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7346 }
7347
7348 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7349                        int Offset64, bits<4> opcode> {
7350   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7351     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7352                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7353                            (ins am_simdnoindex:$vaddr), []>;
7354     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7355                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7356                            (ins am_simdnoindex:$vaddr), []>;
7357     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7358                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7359                            (ins am_simdnoindex:$vaddr), []>;
7360     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7361                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7362                            (ins am_simdnoindex:$vaddr), []>;
7363     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7364                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7365                            (ins am_simdnoindex:$vaddr), []>;
7366     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7367                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7368                            (ins am_simdnoindex:$vaddr), []>;
7369     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7370                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7371                            (ins am_simdnoindex:$vaddr), []>;
7372
7373
7374     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7375                        (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7376                        (ins am_simdnoindex:$vaddr,
7377                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7378     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7379                        (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7380                        (ins am_simdnoindex:$vaddr,
7381                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7382     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7383                        (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7384                        (ins am_simdnoindex:$vaddr,
7385                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7386     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7387                        (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7388                        (ins am_simdnoindex:$vaddr,
7389                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7390     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7391                        (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7392                        (ins am_simdnoindex:$vaddr,
7393                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7394     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7395                        (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7396                        (ins am_simdnoindex:$vaddr,
7397                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7398     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7399                        (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7400                        (ins am_simdnoindex:$vaddr,
7401                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7402   }
7403
7404   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7405   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7406   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7407   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7408   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7409   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7410   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7411 }
7412
7413 // Only ld1/st1 has a v1d version.
7414 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7415                        int Offset64, bits<4> opcode> {
7416   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7417     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7418                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7419                                  am_simdnoindex:$vaddr), []>;
7420     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7421                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7422                                 am_simdnoindex:$vaddr), []>;
7423     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7424                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7425                                 am_simdnoindex:$vaddr), []>;
7426     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7427                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7428                                 am_simdnoindex:$vaddr), []>;
7429     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7430                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7431                                 am_simdnoindex:$vaddr), []>;
7432     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7433                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7434                                 am_simdnoindex:$vaddr), []>;
7435     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7436                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7437                                 am_simdnoindex:$vaddr), []>;
7438
7439     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, (outs),
7440                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7441                             am_simdnoindex:$vaddr,
7442                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7443     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, (outs),
7444                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7445                             am_simdnoindex:$vaddr,
7446                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7447     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, (outs),
7448                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7449                             am_simdnoindex:$vaddr,
7450                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7451     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, (outs),
7452                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7453                             am_simdnoindex:$vaddr,
7454                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7455     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, (outs),
7456                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7457                             am_simdnoindex:$vaddr,
7458                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7459     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, (outs),
7460                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7461                             am_simdnoindex:$vaddr,
7462                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7463     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, (outs),
7464                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7465                             am_simdnoindex:$vaddr,
7466                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7467   }
7468
7469   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7470   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7471   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7472   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7473   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7474   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7475   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7476 }
7477
7478 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7479                        int Offset128, int Offset64, bits<4> opcode>
7480   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7481
7482   // LD1 instructions have extra "1d" variants.
7483   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7484     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7485                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7486                            (ins am_simdnoindex:$vaddr), []>;
7487
7488     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7489                        (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7490                        (ins am_simdnoindex:$vaddr,
7491                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7492   }
7493
7494   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7495 }
7496
7497 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7498                        int Offset128, int Offset64, bits<4> opcode>
7499   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7500
7501   // ST1 instructions have extra "1d" variants.
7502   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7503     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7504                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7505                                 am_simdnoindex:$vaddr), []>;
7506
7507     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, (outs),
7508                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7509                             am_simdnoindex:$vaddr,
7510                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7511   }
7512
7513   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7514 }
7515
7516 multiclass SIMDLd1Multiple<string asm> {
7517   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
7518   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7519   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7520   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7521 }
7522
7523 multiclass SIMDSt1Multiple<string asm> {
7524   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
7525   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7526   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7527   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7528 }
7529
7530 multiclass SIMDLd2Multiple<string asm> {
7531   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7532 }
7533
7534 multiclass SIMDSt2Multiple<string asm> {
7535   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7536 }
7537
7538 multiclass SIMDLd3Multiple<string asm> {
7539   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7540 }
7541
7542 multiclass SIMDSt3Multiple<string asm> {
7543   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7544 }
7545
7546 multiclass SIMDLd4Multiple<string asm> {
7547   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7548 }
7549
7550 multiclass SIMDSt4Multiple<string asm> {
7551   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7552 }
7553
7554 //---
7555 // AdvSIMD Load/store single-element
7556 //---
7557
7558 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7559                          string asm, string operands, dag oops, dag iops,
7560                          list<dag> pattern>
7561   : I<oops, iops, asm, operands, "", pattern> {
7562   bits<5> Vt;
7563   bits<5> vaddr;
7564   let Inst{31} = 0;
7565   let Inst{29-24} = 0b001101;
7566   let Inst{22} = L;
7567   let Inst{21} = R;
7568   let Inst{15-13} = opcode;
7569   let Inst{9-5} = vaddr;
7570   let Inst{4-0} = Vt;
7571   let DecoderMethod = "DecodeSIMDLdStSingle";
7572 }
7573
7574 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7575                          string asm, string operands, dag oops, dag iops,
7576                          list<dag> pattern>
7577   : I<oops, iops, asm, operands, "$Vt = $dst", pattern> {
7578   bits<5> Vt;
7579   bits<5> vaddr;
7580   let Inst{31} = 0;
7581   let Inst{29-24} = 0b001101;
7582   let Inst{22} = L;
7583   let Inst{21} = R;
7584   let Inst{15-13} = opcode;
7585   let Inst{9-5} = vaddr;
7586   let Inst{4-0} = Vt;
7587   let DecoderMethod = "DecodeSIMDLdStSingleTied";
7588 }
7589
7590
7591 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7592 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7593                   Operand listtype>
7594   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr",
7595                        (outs listtype:$Vt), (ins am_simdnoindex:$vaddr), []> {
7596   let Inst{30} = Q;
7597   let Inst{23} = 0;
7598   let Inst{20-16} = 0b00000;
7599   let Inst{12} = S;
7600   let Inst{11-10} = size;
7601 }
7602 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7603 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7604                       string asm, Operand listtype, Operand GPR64pi>
7605   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7606                        (outs listtype:$Vt),
7607                        (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7608   bits<5> Xm;
7609   let Inst{30} = Q;
7610   let Inst{23} = 1;
7611   let Inst{20-16} = Xm;
7612   let Inst{12} = S;
7613   let Inst{11-10} = size;
7614 }
7615
7616 multiclass SIMDLdrAliases<string asm, string layout, string Count,
7617                           int Offset, int Size> {
7618   // E.g. "ld1r { v0.8b }, [x1], #1"
7619   //      "ld1r.8b\t$Vt, $vaddr, #1"
7620   // may get mapped to
7621   //      (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7622   def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7623                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
7624                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7625                       am_simdnoindex:$vaddr, XZR), 1>;
7626
7627   // E.g. "ld1r.8b { v0 }, [x1], #1"
7628   //      "ld1r.8b\t$Vt, $vaddr, #1"
7629   // may get mapped to
7630   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7631   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7632                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
7633                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7634                       am_simdnoindex:$vaddr, XZR), 0>;
7635
7636   // E.g. "ld1r.8b { v0 }, [x1]"
7637   //      "ld1r.8b\t$Vt, $vaddr"
7638   // may get mapped to
7639   //      (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7640   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7641                   (!cast<Instruction>(NAME # "v" # layout)
7642                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7643                       am_simdnoindex:$vaddr), 0>;
7644
7645   // E.g. "ld1r.8b { v0 }, [x1], x2"
7646   //      "ld1r.8b\t$Vt, $vaddr, $Xm"
7647   // may get mapped to
7648   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7649   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7650                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
7651                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7652                       am_simdnoindex:$vaddr,
7653                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7654 }
7655
7656 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7657   int Offset1, int Offset2, int Offset4, int Offset8> {
7658   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7659                         !cast<Operand>("VecList" # Count # "8b")>;
7660   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7661                         !cast<Operand>("VecList" # Count #"16b")>;
7662   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7663                         !cast<Operand>("VecList" # Count #"4h")>;
7664   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7665                         !cast<Operand>("VecList" # Count #"8h")>;
7666   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7667                         !cast<Operand>("VecList" # Count #"2s")>;
7668   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7669                         !cast<Operand>("VecList" # Count #"4s")>;
7670   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7671                         !cast<Operand>("VecList" # Count #"1d")>;
7672   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7673                         !cast<Operand>("VecList" # Count #"2d")>;
7674
7675   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7676                                  !cast<Operand>("VecList" # Count # "8b"),
7677                                  !cast<Operand>("GPR64pi" # Offset1)>;
7678   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7679                                  !cast<Operand>("VecList" # Count # "16b"),
7680                                  !cast<Operand>("GPR64pi" # Offset1)>;
7681   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7682                                  !cast<Operand>("VecList" # Count # "4h"),
7683                                  !cast<Operand>("GPR64pi" # Offset2)>;
7684   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7685                                  !cast<Operand>("VecList" # Count # "8h"),
7686                                  !cast<Operand>("GPR64pi" # Offset2)>;
7687   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7688                                  !cast<Operand>("VecList" # Count # "2s"),
7689                                  !cast<Operand>("GPR64pi" # Offset4)>;
7690   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7691                                  !cast<Operand>("VecList" # Count # "4s"),
7692                                  !cast<Operand>("GPR64pi" # Offset4)>;
7693   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7694                                  !cast<Operand>("VecList" # Count # "1d"),
7695                                  !cast<Operand>("GPR64pi" # Offset8)>;
7696   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7697                                  !cast<Operand>("VecList" # Count # "2d"),
7698                                  !cast<Operand>("GPR64pi" # Offset8)>;
7699
7700   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
7701   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7702   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
7703   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
7704   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
7705   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
7706   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
7707   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
7708 }
7709
7710 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7711                       dag oops, dag iops, list<dag> pattern>
7712   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7713                        pattern> {
7714   // idx encoded in Q:S:size fields.
7715   bits<4> idx;
7716   let Inst{30} = idx{3};
7717   let Inst{23} = 0;
7718   let Inst{20-16} = 0b00000;
7719   let Inst{12} = idx{2};
7720   let Inst{11-10} = idx{1-0};
7721 }
7722 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7723                       dag oops, dag iops, list<dag> pattern>
7724   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7725                        pattern> {
7726   // idx encoded in Q:S:size fields.
7727   bits<4> idx;
7728   let Inst{30} = idx{3};
7729   let Inst{23} = 0;
7730   let Inst{20-16} = 0b00000;
7731   let Inst{12} = idx{2};
7732   let Inst{11-10} = idx{1-0};
7733 }
7734 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7735                           dag oops, dag iops>
7736   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7737                        oops, iops, []> {
7738   // idx encoded in Q:S:size fields.
7739   bits<4> idx;
7740   bits<5> Xm;
7741   let Inst{30} = idx{3};
7742   let Inst{23} = 1;
7743   let Inst{20-16} = Xm;
7744   let Inst{12} = idx{2};
7745   let Inst{11-10} = idx{1-0};
7746 }
7747 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7748                           dag oops, dag iops>
7749   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7750                        oops, iops, []> {
7751   // idx encoded in Q:S:size fields.
7752   bits<4> idx;
7753   bits<5> Xm;
7754   let Inst{30} = idx{3};
7755   let Inst{23} = 1;
7756   let Inst{20-16} = Xm;
7757   let Inst{12} = idx{2};
7758   let Inst{11-10} = idx{1-0};
7759 }
7760
7761 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7762                       dag oops, dag iops, list<dag> pattern>
7763   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7764                        pattern> {
7765   // idx encoded in Q:S:size<1> fields.
7766   bits<3> idx;
7767   let Inst{30} = idx{2};
7768   let Inst{23} = 0;
7769   let Inst{20-16} = 0b00000;
7770   let Inst{12} = idx{1};
7771   let Inst{11} = idx{0};
7772   let Inst{10} = size;
7773 }
7774 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7775                       dag oops, dag iops, list<dag> pattern>
7776   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7777                        pattern> {
7778   // idx encoded in Q:S:size<1> fields.
7779   bits<3> idx;
7780   let Inst{30} = idx{2};
7781   let Inst{23} = 0;
7782   let Inst{20-16} = 0b00000;
7783   let Inst{12} = idx{1};
7784   let Inst{11} = idx{0};
7785   let Inst{10} = size;
7786 }
7787
7788 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7789                           dag oops, dag iops>
7790   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7791                        oops, iops, []> {
7792   // idx encoded in Q:S:size<1> fields.
7793   bits<3> idx;
7794   bits<5> Xm;
7795   let Inst{30} = idx{2};
7796   let Inst{23} = 1;
7797   let Inst{20-16} = Xm;
7798   let Inst{12} = idx{1};
7799   let Inst{11} = idx{0};
7800   let Inst{10} = size;
7801 }
7802 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7803                           dag oops, dag iops>
7804   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7805                        oops, iops, []> {
7806   // idx encoded in Q:S:size<1> fields.
7807   bits<3> idx;
7808   bits<5> Xm;
7809   let Inst{30} = idx{2};
7810   let Inst{23} = 1;
7811   let Inst{20-16} = Xm;
7812   let Inst{12} = idx{1};
7813   let Inst{11} = idx{0};
7814   let Inst{10} = size;
7815 }
7816 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7817                       dag oops, dag iops, list<dag> pattern>
7818   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7819                        pattern> {
7820   // idx encoded in Q:S fields.
7821   bits<2> idx;
7822   let Inst{30} = idx{1};
7823   let Inst{23} = 0;
7824   let Inst{20-16} = 0b00000;
7825   let Inst{12} = idx{0};
7826   let Inst{11-10} = size;
7827 }
7828 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7829                       dag oops, dag iops, list<dag> pattern>
7830   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7831                        pattern> {
7832   // idx encoded in Q:S fields.
7833   bits<2> idx;
7834   let Inst{30} = idx{1};
7835   let Inst{23} = 0;
7836   let Inst{20-16} = 0b00000;
7837   let Inst{12} = idx{0};
7838   let Inst{11-10} = size;
7839 }
7840 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
7841                           string asm, dag oops, dag iops>
7842   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7843                        oops, iops, []> {
7844   // idx encoded in Q:S fields.
7845   bits<2> idx;
7846   bits<5> Xm;
7847   let Inst{30} = idx{1};
7848   let Inst{23} = 1;
7849   let Inst{20-16} = Xm;
7850   let Inst{12} = idx{0};
7851   let Inst{11-10} = size;
7852 }
7853 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7854                           string asm, dag oops, dag iops>
7855   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7856                        oops, iops, []> {
7857   // idx encoded in Q:S fields.
7858   bits<2> idx;
7859   bits<5> Xm;
7860   let Inst{30} = idx{1};
7861   let Inst{23} = 1;
7862   let Inst{20-16} = Xm;
7863   let Inst{12} = idx{0};
7864   let Inst{11-10} = size;
7865 }
7866 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7867                       dag oops, dag iops, list<dag> pattern>
7868   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7869                        pattern> {
7870   // idx encoded in Q field.
7871   bits<1> idx;
7872   let Inst{30} = idx;
7873   let Inst{23} = 0;
7874   let Inst{20-16} = 0b00000;
7875   let Inst{12} = 0;
7876   let Inst{11-10} = size;
7877 }
7878 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7879                       dag oops, dag iops, list<dag> pattern>
7880   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7881                        pattern> {
7882   // idx encoded in Q field.
7883   bits<1> idx;
7884   let Inst{30} = idx;
7885   let Inst{23} = 0;
7886   let Inst{20-16} = 0b00000;
7887   let Inst{12} = 0;
7888   let Inst{11-10} = size;
7889 }
7890 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
7891                           string asm, dag oops, dag iops>
7892   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7893                        oops, iops, []> {
7894   // idx encoded in Q field.
7895   bits<1> idx;
7896   bits<5> Xm;
7897   let Inst{30} = idx;
7898   let Inst{23} = 1;
7899   let Inst{20-16} = Xm;
7900   let Inst{12} = 0;
7901   let Inst{11-10} = size;
7902 }
7903 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7904                           string asm, dag oops, dag iops>
7905   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7906                        oops, iops, []> {
7907   // idx encoded in Q field.
7908   bits<1> idx;
7909   bits<5> Xm;
7910   let Inst{30} = idx;
7911   let Inst{23} = 1;
7912   let Inst{20-16} = Xm;
7913   let Inst{12} = 0;
7914   let Inst{11-10} = size;
7915 }
7916
7917 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7918 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
7919                          RegisterOperand listtype,
7920                          RegisterOperand GPR64pi> {
7921   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
7922                            (outs listtype:$dst),
7923                            (ins listtype:$Vt, VectorIndexB:$idx,
7924                                 am_simdnoindex:$vaddr), []>;
7925
7926   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
7927                             (outs listtype:$dst),
7928                             (ins listtype:$Vt, VectorIndexB:$idx,
7929                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7930 }
7931 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7932 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
7933                          RegisterOperand listtype,
7934                          RegisterOperand GPR64pi> {
7935   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
7936                             (outs listtype:$dst),
7937                             (ins listtype:$Vt, VectorIndexH:$idx,
7938                                  am_simdnoindex:$vaddr), []>;
7939
7940   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
7941                             (outs listtype:$dst),
7942                             (ins listtype:$Vt, VectorIndexH:$idx,
7943                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7944 }
7945 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7946 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
7947                          RegisterOperand listtype,
7948                          RegisterOperand GPR64pi> {
7949   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
7950                             (outs listtype:$dst),
7951                             (ins listtype:$Vt, VectorIndexS:$idx,
7952                                  am_simdnoindex:$vaddr), []>;
7953
7954   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
7955                             (outs listtype:$dst),
7956                             (ins listtype:$Vt, VectorIndexS:$idx,
7957                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7958 }
7959 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7960 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
7961                          RegisterOperand listtype,
7962                          RegisterOperand GPR64pi> {
7963   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
7964                             (outs listtype:$dst),
7965                             (ins listtype:$Vt, VectorIndexD:$idx,
7966                                  am_simdnoindex:$vaddr), []>;
7967
7968   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
7969                             (outs listtype:$dst),
7970                             (ins listtype:$Vt, VectorIndexD:$idx,
7971                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7972 }
7973 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
7974 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
7975                          RegisterOperand listtype, list<dag> pattern,
7976                          RegisterOperand GPR64pi> {
7977   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
7978                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
7979                                         am_simdnoindex:$vaddr),
7980                            pattern>;
7981
7982   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
7983                             (outs), (ins listtype:$Vt, VectorIndexB:$idx,
7984                                          am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7985 }
7986 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
7987 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
7988                          RegisterOperand listtype, list<dag> pattern,
7989                          RegisterOperand GPR64pi> {
7990   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
7991                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
7992                                          am_simdnoindex:$vaddr),
7993                         pattern>;
7994
7995   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
7996                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
7997                                          am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7998 }
7999 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8000 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8001                          RegisterOperand listtype, list<dag> pattern,
8002                          RegisterOperand GPR64pi> {
8003   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8004                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8005                                          am_simdnoindex:$vaddr),
8006                             pattern>;
8007
8008   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8009                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8010                                          am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8011 }
8012 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8013 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8014                          RegisterOperand listtype, list<dag> pattern,
8015                          RegisterOperand GPR64pi> {
8016   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8017                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8018                                          am_simdnoindex:$vaddr), pattern>;
8019
8020   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8021                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8022                                          am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8023 }
8024
8025 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8026                                  string Count, int Offset, Operand idxtype> {
8027   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8028   //      "ld1\t$Vt, $vaddr, #1"
8029   // may get mapped to
8030   //      (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8031   def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8032                   (!cast<Instruction>(NAME # Type  # "_POST")
8033                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8034                       idxtype:$idx, am_simdnoindex:$vaddr, XZR), 1>;
8035
8036   // E.g. "ld1.8b { v0 }[0], [x1], #1"
8037   //      "ld1.8b\t$Vt, $vaddr, #1"
8038   // may get mapped to
8039   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8040   def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8041                   (!cast<Instruction>(NAME # Type # "_POST")
8042                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8043                       idxtype:$idx, am_simdnoindex:$vaddr, XZR), 0>;
8044
8045   // E.g. "ld1.8b { v0 }[0], [x1]"
8046   //      "ld1.8b\t$Vt, $vaddr"
8047   // may get mapped to
8048   //      (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8049   def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8050                       (!cast<Instruction>(NAME # Type)
8051                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8052                          idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8053
8054   // E.g. "ld1.8b { v0 }[0], [x1], x2"
8055   //      "ld1.8b\t$Vt, $vaddr, $Xm"
8056   // may get mapped to
8057   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8058   def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8059                       (!cast<Instruction>(NAME # Type # "_POST")
8060                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8061                          idxtype:$idx, am_simdnoindex:$vaddr,
8062                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8063 }
8064
8065 multiclass SIMDLdSt1SingleAliases<string asm> {
8066   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
8067   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8068   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8069   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8070 }
8071
8072 multiclass SIMDLdSt2SingleAliases<string asm> {
8073   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
8074   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
8075   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
8076   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8077 }
8078
8079 multiclass SIMDLdSt3SingleAliases<string asm> {
8080   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
8081   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
8082   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8083   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8084 }
8085
8086 multiclass SIMDLdSt4SingleAliases<string asm> {
8087   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
8088   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
8089   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8090   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8091 }
8092
8093 //----------------------------------------------------------------------------
8094 // Crypto extensions
8095 //----------------------------------------------------------------------------
8096
8097 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8098 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8099               list<dag> pat>
8100   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8101     Sched<[WriteV]>{
8102   bits<5> Rd;
8103   bits<5> Rn;
8104   let Inst{31-16} = 0b0100111000101000;
8105   let Inst{15-12} = opc;
8106   let Inst{11-10} = 0b10;
8107   let Inst{9-5}   = Rn;
8108   let Inst{4-0}   = Rd;
8109 }
8110
8111 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8112   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8113             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8114
8115 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8116   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8117             "$Rd = $dst",
8118             [(set (v16i8 V128:$dst),
8119                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8120
8121 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8122 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8123                      dag oops, dag iops, list<dag> pat>
8124   : I<oops, iops, asm,
8125       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8126       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8127     Sched<[WriteV]>{
8128   bits<5> Rd;
8129   bits<5> Rn;
8130   bits<5> Rm;
8131   let Inst{31-21} = 0b01011110000;
8132   let Inst{20-16} = Rm;
8133   let Inst{15}    = 0;
8134   let Inst{14-12} = opc;
8135   let Inst{11-10} = 0b00;
8136   let Inst{9-5}   = Rn;
8137   let Inst{4-0}   = Rd;
8138 }
8139
8140 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8141   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8142                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8143                    [(set (v4i32 FPR128:$dst),
8144                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8145                                  (v4i32 V128:$Rm)))]>;
8146
8147 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8148   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8149                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
8150                    [(set (v4i32 V128:$dst),
8151                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8152                                  (v4i32 V128:$Rm)))]>;
8153
8154 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8155   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8156                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8157                    [(set (v4i32 FPR128:$dst),
8158                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8159                                  (v4i32 V128:$Rm)))]>;
8160
8161 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8162 class SHA2OpInst<bits<4> opc, string asm, string kind,
8163                  string cstr, dag oops, dag iops,
8164                  list<dag> pat>
8165   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8166                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8167     Sched<[WriteV]>{
8168   bits<5> Rd;
8169   bits<5> Rn;
8170   let Inst{31-16} = 0b0101111000101000;
8171   let Inst{15-12} = opc;
8172   let Inst{11-10} = 0b10;
8173   let Inst{9-5}   = Rn;
8174   let Inst{4-0}   = Rd;
8175 }
8176
8177 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8178   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8179                (ins V128:$Rd, V128:$Rn),
8180                [(set (v4i32 V128:$dst),
8181                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8182
8183 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8184   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8185                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8186
8187 // Allow the size specifier tokens to be upper case, not just lower.
8188 def : TokenAlias<".8B", ".8b">;
8189 def : TokenAlias<".4H", ".4h">;
8190 def : TokenAlias<".2S", ".2s">;
8191 def : TokenAlias<".1D", ".1d">;
8192 def : TokenAlias<".16B", ".16b">;
8193 def : TokenAlias<".8H", ".8h">;
8194 def : TokenAlias<".4S", ".4s">;
8195 def : TokenAlias<".2D", ".2d">;
8196 def : TokenAlias<".B", ".b">;
8197 def : TokenAlias<".H", ".h">;
8198 def : TokenAlias<".S", ".s">;
8199 def : TokenAlias<".D", ".d">;