[AArch64] Add v8.1a atomic instructions
[oota-llvm.git] / lib / Target / AArch64 / AArch64InstrFormats.td
1 //===- AArch64InstrFormats.td - AArch64 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 AArch64 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 // AArch64 Instruction Format
25 class AArch64Inst<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   = "AArch64";
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     : AArch64Inst<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> : AArch64Inst<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   let RenderMethod = "addShifterOperands";
94   let DiagnosticType = "InvalidMovImm32Shift";
95 }
96 def MovImm64ShifterOperand : AsmOperandClass {
97   let SuperClasses = [ShifterOperand];
98   let Name = "MovImm64Shifter";
99   let RenderMethod = "addShifterOperands";
100   let DiagnosticType = "InvalidMovImm64Shift";
101 }
102
103 // Shifter operand for arithmetic register shifted encodings.
104 class ArithmeticShifterOperand<int width> : AsmOperandClass {
105   let SuperClasses = [ShifterOperand];
106   let Name = "ArithmeticShifter" # width;
107   let PredicateMethod = "isArithmeticShifter<" # width # ">";
108   let RenderMethod = "addShifterOperands";
109   let DiagnosticType = "AddSubRegShift" # width;
110 }
111
112 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
113 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
114
115 // Shifter operand for logical register shifted encodings.
116 class LogicalShifterOperand<int width> : AsmOperandClass {
117   let SuperClasses = [ShifterOperand];
118   let Name = "LogicalShifter" # width;
119   let PredicateMethod = "isLogicalShifter<" # width # ">";
120   let RenderMethod = "addShifterOperands";
121   let DiagnosticType = "AddSubRegShift" # width;
122 }
123
124 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
125 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
126
127 // Shifter operand for logical vector 128/64-bit shifted encodings.
128 def LogicalVecShifterOperand : AsmOperandClass {
129   let SuperClasses = [ShifterOperand];
130   let Name = "LogicalVecShifter";
131   let RenderMethod = "addShifterOperands";
132 }
133 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
134   let SuperClasses = [LogicalVecShifterOperand];
135   let Name = "LogicalVecHalfWordShifter";
136   let RenderMethod = "addShifterOperands";
137 }
138
139 // The "MSL" shifter on the vector MOVI instruction.
140 def MoveVecShifterOperand : AsmOperandClass {
141   let SuperClasses = [ShifterOperand];
142   let Name = "MoveVecShifter";
143   let RenderMethod = "addShifterOperands";
144 }
145
146 // Extend operand for arithmetic encodings.
147 def ExtendOperand : AsmOperandClass {
148   let Name = "Extend";
149   let DiagnosticType = "AddSubRegExtendLarge";
150 }
151 def ExtendOperand64 : AsmOperandClass {
152   let SuperClasses = [ExtendOperand];
153   let Name = "Extend64";
154   let DiagnosticType = "AddSubRegExtendSmall";
155 }
156 // 'extend' that's a lsl of a 64-bit register.
157 def ExtendOperandLSL64 : AsmOperandClass {
158   let SuperClasses = [ExtendOperand];
159   let Name = "ExtendLSL64";
160   let RenderMethod = "addExtend64Operands";
161   let DiagnosticType = "AddSubRegExtendLarge";
162 }
163
164 // 8-bit floating-point immediate encodings.
165 def FPImmOperand : AsmOperandClass {
166   let Name = "FPImm";
167   let ParserMethod = "tryParseFPImm";
168   let DiagnosticType = "InvalidFPImm";
169 }
170
171 def CondCode : AsmOperandClass {
172   let Name = "CondCode";
173   let DiagnosticType = "InvalidCondCode";
174 }
175
176 // A 32-bit register pasrsed as 64-bit
177 def GPR32as64Operand : AsmOperandClass {
178   let Name = "GPR32as64";
179 }
180 def GPR32as64 : RegisterOperand<GPR32> {
181   let ParserMatchClass = GPR32as64Operand;
182 }
183
184 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
185 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
186 // are encoded as the eight bit value 'abcdefgh'.
187 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
188
189
190 //===----------------------------------------------------------------------===//
191 // Operand Definitions.
192 //
193
194 // ADR[P] instruction labels.
195 def AdrpOperand : AsmOperandClass {
196   let Name = "AdrpLabel";
197   let ParserMethod = "tryParseAdrpLabel";
198   let DiagnosticType = "InvalidLabel";
199 }
200 def adrplabel : Operand<i64> {
201   let EncoderMethod = "getAdrLabelOpValue";
202   let PrintMethod = "printAdrpLabel";
203   let ParserMatchClass = AdrpOperand;
204 }
205
206 def AdrOperand : AsmOperandClass {
207   let Name = "AdrLabel";
208   let ParserMethod = "tryParseAdrLabel";
209   let DiagnosticType = "InvalidLabel";
210 }
211 def adrlabel : Operand<i64> {
212   let EncoderMethod = "getAdrLabelOpValue";
213   let ParserMatchClass = AdrOperand;
214 }
215
216 // simm9 predicate - True if the immediate is in the range [-256, 255].
217 def SImm9Operand : AsmOperandClass {
218   let Name = "SImm9";
219   let DiagnosticType = "InvalidMemoryIndexedSImm9";
220 }
221 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
222   let ParserMatchClass = SImm9Operand;
223 }
224
225 // simm7sN predicate - True if the immediate is a multiple of N in the range
226 // [-64 * N, 63 * N].
227 class SImm7Scaled<int Scale> : AsmOperandClass {
228   let Name = "SImm7s" # Scale;
229   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm7";
230 }
231
232 def SImm7s4Operand : SImm7Scaled<4>;
233 def SImm7s8Operand : SImm7Scaled<8>;
234 def SImm7s16Operand : SImm7Scaled<16>;
235
236 def simm7s4 : Operand<i32> {
237   let ParserMatchClass = SImm7s4Operand;
238   let PrintMethod = "printImmScale<4>";
239 }
240
241 def simm7s8 : Operand<i32> {
242   let ParserMatchClass = SImm7s8Operand;
243   let PrintMethod = "printImmScale<8>";
244 }
245
246 def simm7s16 : Operand<i32> {
247   let ParserMatchClass = SImm7s16Operand;
248   let PrintMethod = "printImmScale<16>";
249 }
250
251 class AsmImmRange<int Low, int High> : AsmOperandClass {
252   let Name = "Imm" # Low # "_" # High;
253   let DiagnosticType = "InvalidImm" # Low # "_" # High;
254 }
255
256 def Imm1_8Operand : AsmImmRange<1, 8>;
257 def Imm1_16Operand : AsmImmRange<1, 16>;
258 def Imm1_32Operand : AsmImmRange<1, 32>;
259 def Imm1_64Operand : AsmImmRange<1, 64>;
260
261 def MovZSymbolG3AsmOperand : AsmOperandClass {
262   let Name = "MovZSymbolG3";
263   let RenderMethod = "addImmOperands";
264 }
265
266 def movz_symbol_g3 : Operand<i32> {
267   let ParserMatchClass = MovZSymbolG3AsmOperand;
268 }
269
270 def MovZSymbolG2AsmOperand : AsmOperandClass {
271   let Name = "MovZSymbolG2";
272   let RenderMethod = "addImmOperands";
273 }
274
275 def movz_symbol_g2 : Operand<i32> {
276   let ParserMatchClass = MovZSymbolG2AsmOperand;
277 }
278
279 def MovZSymbolG1AsmOperand : AsmOperandClass {
280   let Name = "MovZSymbolG1";
281   let RenderMethod = "addImmOperands";
282 }
283
284 def movz_symbol_g1 : Operand<i32> {
285   let ParserMatchClass = MovZSymbolG1AsmOperand;
286 }
287
288 def MovZSymbolG0AsmOperand : AsmOperandClass {
289   let Name = "MovZSymbolG0";
290   let RenderMethod = "addImmOperands";
291 }
292
293 def movz_symbol_g0 : Operand<i32> {
294   let ParserMatchClass = MovZSymbolG0AsmOperand;
295 }
296
297 def MovKSymbolG3AsmOperand : AsmOperandClass {
298   let Name = "MovKSymbolG3";
299   let RenderMethod = "addImmOperands";
300 }
301
302 def movk_symbol_g3 : Operand<i32> {
303   let ParserMatchClass = MovKSymbolG3AsmOperand;
304 }
305
306 def MovKSymbolG2AsmOperand : AsmOperandClass {
307   let Name = "MovKSymbolG2";
308   let RenderMethod = "addImmOperands";
309 }
310
311 def movk_symbol_g2 : Operand<i32> {
312   let ParserMatchClass = MovKSymbolG2AsmOperand;
313 }
314
315 def MovKSymbolG1AsmOperand : AsmOperandClass {
316   let Name = "MovKSymbolG1";
317   let RenderMethod = "addImmOperands";
318 }
319
320 def movk_symbol_g1 : Operand<i32> {
321   let ParserMatchClass = MovKSymbolG1AsmOperand;
322 }
323
324 def MovKSymbolG0AsmOperand : AsmOperandClass {
325   let Name = "MovKSymbolG0";
326   let RenderMethod = "addImmOperands";
327 }
328
329 def movk_symbol_g0 : Operand<i32> {
330   let ParserMatchClass = MovKSymbolG0AsmOperand;
331 }
332
333 class fixedpoint_i32<ValueType FloatVT>
334   : Operand<FloatVT>,
335     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
336   let EncoderMethod = "getFixedPointScaleOpValue";
337   let DecoderMethod = "DecodeFixedPointScaleImm32";
338   let ParserMatchClass = Imm1_32Operand;
339 }
340
341 class fixedpoint_i64<ValueType FloatVT>
342   : Operand<FloatVT>,
343     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
344   let EncoderMethod = "getFixedPointScaleOpValue";
345   let DecoderMethod = "DecodeFixedPointScaleImm64";
346   let ParserMatchClass = Imm1_64Operand;
347 }
348
349 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
350 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
351
352 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
353 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
354
355 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
356   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
357 }]> {
358   let EncoderMethod = "getVecShiftR8OpValue";
359   let DecoderMethod = "DecodeVecShiftR8Imm";
360   let ParserMatchClass = Imm1_8Operand;
361 }
362 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
363   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
364 }]> {
365   let EncoderMethod = "getVecShiftR16OpValue";
366   let DecoderMethod = "DecodeVecShiftR16Imm";
367   let ParserMatchClass = Imm1_16Operand;
368 }
369 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
370   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
371 }]> {
372   let EncoderMethod = "getVecShiftR16OpValue";
373   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
374   let ParserMatchClass = Imm1_8Operand;
375 }
376 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
377   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
378 }]> {
379   let EncoderMethod = "getVecShiftR32OpValue";
380   let DecoderMethod = "DecodeVecShiftR32Imm";
381   let ParserMatchClass = Imm1_32Operand;
382 }
383 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
384   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
385 }]> {
386   let EncoderMethod = "getVecShiftR32OpValue";
387   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
388   let ParserMatchClass = Imm1_16Operand;
389 }
390 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
391   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
392 }]> {
393   let EncoderMethod = "getVecShiftR64OpValue";
394   let DecoderMethod = "DecodeVecShiftR64Imm";
395   let ParserMatchClass = Imm1_64Operand;
396 }
397 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
398   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
399 }]> {
400   let EncoderMethod = "getVecShiftR64OpValue";
401   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
402   let ParserMatchClass = Imm1_32Operand;
403 }
404
405 def Imm0_7Operand : AsmImmRange<0, 7>;
406 def Imm0_15Operand : AsmImmRange<0, 15>;
407 def Imm0_31Operand : AsmImmRange<0, 31>;
408 def Imm0_63Operand : AsmImmRange<0, 63>;
409
410 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
411   return (((uint32_t)Imm) < 8);
412 }]> {
413   let EncoderMethod = "getVecShiftL8OpValue";
414   let DecoderMethod = "DecodeVecShiftL8Imm";
415   let ParserMatchClass = Imm0_7Operand;
416 }
417 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
418   return (((uint32_t)Imm) < 16);
419 }]> {
420   let EncoderMethod = "getVecShiftL16OpValue";
421   let DecoderMethod = "DecodeVecShiftL16Imm";
422   let ParserMatchClass = Imm0_15Operand;
423 }
424 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
425   return (((uint32_t)Imm) < 32);
426 }]> {
427   let EncoderMethod = "getVecShiftL32OpValue";
428   let DecoderMethod = "DecodeVecShiftL32Imm";
429   let ParserMatchClass = Imm0_31Operand;
430 }
431 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
432   return (((uint32_t)Imm) < 64);
433 }]> {
434   let EncoderMethod = "getVecShiftL64OpValue";
435   let DecoderMethod = "DecodeVecShiftL64Imm";
436   let ParserMatchClass = Imm0_63Operand;
437 }
438
439
440 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
441 // instructions for splatting repeating bit patterns across the immediate.
442 def logical_imm32_XFORM : SDNodeXForm<imm, [{
443   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
444   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
445 }]>;
446 def logical_imm64_XFORM : SDNodeXForm<imm, [{
447   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
448   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
449 }]>;
450
451 let DiagnosticType = "LogicalSecondSource" in {
452   def LogicalImm32Operand : AsmOperandClass {
453     let Name = "LogicalImm32";
454   }
455   def LogicalImm64Operand : AsmOperandClass {
456     let Name = "LogicalImm64";
457   }
458   def LogicalImm32NotOperand : AsmOperandClass {
459     let Name = "LogicalImm32Not";
460   }
461   def LogicalImm64NotOperand : AsmOperandClass {
462     let Name = "LogicalImm64Not";
463   }
464 }
465 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
466   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
467 }], logical_imm32_XFORM> {
468   let PrintMethod = "printLogicalImm32";
469   let ParserMatchClass = LogicalImm32Operand;
470 }
471 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
472   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
473 }], logical_imm64_XFORM> {
474   let PrintMethod = "printLogicalImm64";
475   let ParserMatchClass = LogicalImm64Operand;
476 }
477 def logical_imm32_not : Operand<i32> {
478   let ParserMatchClass = LogicalImm32NotOperand;
479 }
480 def logical_imm64_not : Operand<i64> {
481   let ParserMatchClass = LogicalImm64NotOperand;
482 }
483
484 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
485 def Imm0_65535Operand : AsmImmRange<0, 65535>;
486 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
487   return ((uint32_t)Imm) < 65536;
488 }]> {
489   let ParserMatchClass = Imm0_65535Operand;
490   let PrintMethod = "printHexImm";
491 }
492
493 // imm0_255 predicate - True if the immediate is in the range [0,255].
494 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
495 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
496   return ((uint32_t)Imm) < 256;
497 }]> {
498   let ParserMatchClass = Imm0_255Operand;
499   let PrintMethod = "printHexImm";
500 }
501
502 // imm0_127 predicate - True if the immediate is in the range [0,127]
503 def Imm0_127Operand : AsmImmRange<0, 127>;
504 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
505   return ((uint32_t)Imm) < 128;
506 }]> {
507   let ParserMatchClass = Imm0_127Operand;
508   let PrintMethod = "printHexImm";
509 }
510
511 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
512 // for all shift-amounts.
513
514 // imm0_63 predicate - True if the immediate is in the range [0,63]
515 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
516   return ((uint64_t)Imm) < 64;
517 }]> {
518   let ParserMatchClass = Imm0_63Operand;
519 }
520
521 // imm0_31 predicate - True if the immediate is in the range [0,31]
522 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
523   return ((uint64_t)Imm) < 32;
524 }]> {
525   let ParserMatchClass = Imm0_31Operand;
526 }
527
528 // True if the 32-bit immediate is in the range [0,31]
529 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
530   return ((uint64_t)Imm) < 32;
531 }]> {
532   let ParserMatchClass = Imm0_31Operand;
533 }
534
535 // imm0_15 predicate - True if the immediate is in the range [0,15]
536 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
537   return ((uint64_t)Imm) < 16;
538 }]> {
539   let ParserMatchClass = Imm0_15Operand;
540 }
541
542 // imm0_7 predicate - True if the immediate is in the range [0,7]
543 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
544   return ((uint64_t)Imm) < 8;
545 }]> {
546   let ParserMatchClass = Imm0_7Operand;
547 }
548
549 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
550 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
551   return ((uint32_t)Imm) < 16;
552 }]> {
553   let ParserMatchClass = Imm0_15Operand;
554 }
555
556 // An arithmetic shifter operand:
557 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
558 //  {5-0} - imm6
559 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
560   let PrintMethod = "printShifter";
561   let ParserMatchClass = !cast<AsmOperandClass>(
562                          "ArithmeticShifterOperand" # width);
563 }
564
565 def arith_shift32 : arith_shift<i32, 32>;
566 def arith_shift64 : arith_shift<i64, 64>;
567
568 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
569     : Operand<Ty>,
570       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
571   let PrintMethod = "printShiftedRegister";
572   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
573 }
574
575 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
576 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
577
578 // An arithmetic shifter operand:
579 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
580 //  {5-0} - imm6
581 class logical_shift<int width> : Operand<i32> {
582   let PrintMethod = "printShifter";
583   let ParserMatchClass = !cast<AsmOperandClass>(
584                          "LogicalShifterOperand" # width);
585 }
586
587 def logical_shift32 : logical_shift<32>;
588 def logical_shift64 : logical_shift<64>;
589
590 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
591     : Operand<Ty>,
592       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
593   let PrintMethod = "printShiftedRegister";
594   let MIOperandInfo = (ops regclass, shiftop);
595 }
596
597 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
598 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
599
600 // A logical vector shifter operand:
601 //  {7-6} - shift type: 00 = lsl
602 //  {5-0} - imm6: #0, #8, #16, or #24
603 def logical_vec_shift : Operand<i32> {
604   let PrintMethod = "printShifter";
605   let EncoderMethod = "getVecShifterOpValue";
606   let ParserMatchClass = LogicalVecShifterOperand;
607 }
608
609 // A logical vector half-word shifter operand:
610 //  {7-6} - shift type: 00 = lsl
611 //  {5-0} - imm6: #0 or #8
612 def logical_vec_hw_shift : Operand<i32> {
613   let PrintMethod = "printShifter";
614   let EncoderMethod = "getVecShifterOpValue";
615   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
616 }
617
618 // A vector move shifter operand:
619 //  {0} - imm1: #8 or #16
620 def move_vec_shift : Operand<i32> {
621   let PrintMethod = "printShifter";
622   let EncoderMethod = "getMoveVecShifterOpValue";
623   let ParserMatchClass = MoveVecShifterOperand;
624 }
625
626 def AddSubImmOperand : AsmOperandClass {
627   let Name = "AddSubImm";
628   let ParserMethod = "tryParseAddSubImm";
629   let DiagnosticType = "AddSubSecondSource";
630 }
631 // An ADD/SUB immediate shifter operand:
632 //  second operand:
633 //  {7-6} - shift type: 00 = lsl
634 //  {5-0} - imm6: #0 or #12
635 class addsub_shifted_imm<ValueType Ty>
636     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
637   let PrintMethod = "printAddSubImm";
638   let EncoderMethod = "getAddSubImmOpValue";
639   let ParserMatchClass = AddSubImmOperand;
640   let MIOperandInfo = (ops i32imm, i32imm);
641 }
642
643 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
644 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
645
646 class neg_addsub_shifted_imm<ValueType Ty>
647     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
648   let PrintMethod = "printAddSubImm";
649   let EncoderMethod = "getAddSubImmOpValue";
650   let ParserMatchClass = AddSubImmOperand;
651   let MIOperandInfo = (ops i32imm, i32imm);
652 }
653
654 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
655 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
656
657 // An extend operand:
658 //  {5-3} - extend type
659 //  {2-0} - imm3
660 def arith_extend : Operand<i32> {
661   let PrintMethod = "printArithExtend";
662   let ParserMatchClass = ExtendOperand;
663 }
664 def arith_extend64 : Operand<i32> {
665   let PrintMethod = "printArithExtend";
666   let ParserMatchClass = ExtendOperand64;
667 }
668
669 // 'extend' that's a lsl of a 64-bit register.
670 def arith_extendlsl64 : Operand<i32> {
671   let PrintMethod = "printArithExtend";
672   let ParserMatchClass = ExtendOperandLSL64;
673 }
674
675 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
676                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
677   let PrintMethod = "printExtendedRegister";
678   let MIOperandInfo = (ops GPR32, arith_extend);
679 }
680
681 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
682                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
683   let PrintMethod = "printExtendedRegister";
684   let MIOperandInfo = (ops GPR32, arith_extend64);
685 }
686
687 // Floating-point immediate.
688 def fpimm32 : Operand<f32>,
689               PatLeaf<(f32 fpimm), [{
690       return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
691     }], SDNodeXForm<fpimm, [{
692       APFloat InVal = N->getValueAPF();
693       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
694       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
695     }]>> {
696   let ParserMatchClass = FPImmOperand;
697   let PrintMethod = "printFPImmOperand";
698 }
699 def fpimm64 : Operand<f64>,
700               PatLeaf<(f64 fpimm), [{
701       return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
702     }], SDNodeXForm<fpimm, [{
703       APFloat InVal = N->getValueAPF();
704       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
705       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
706     }]>> {
707   let ParserMatchClass = FPImmOperand;
708   let PrintMethod = "printFPImmOperand";
709 }
710
711 def fpimm8 : Operand<i32> {
712   let ParserMatchClass = FPImmOperand;
713   let PrintMethod = "printFPImmOperand";
714 }
715
716 def fpimm0 : PatLeaf<(fpimm), [{
717   return N->isExactlyValue(+0.0);
718 }]>;
719
720 // Vector lane operands
721 class AsmVectorIndex<string Suffix> : AsmOperandClass {
722   let Name = "VectorIndex" # Suffix;
723   let DiagnosticType = "InvalidIndex" # Suffix;
724 }
725 def VectorIndex1Operand : AsmVectorIndex<"1">;
726 def VectorIndexBOperand : AsmVectorIndex<"B">;
727 def VectorIndexHOperand : AsmVectorIndex<"H">;
728 def VectorIndexSOperand : AsmVectorIndex<"S">;
729 def VectorIndexDOperand : AsmVectorIndex<"D">;
730
731 def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
732   return ((uint64_t)Imm) == 1;
733 }]> {
734   let ParserMatchClass = VectorIndex1Operand;
735   let PrintMethod = "printVectorIndex";
736   let MIOperandInfo = (ops i64imm);
737 }
738 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
739   return ((uint64_t)Imm) < 16;
740 }]> {
741   let ParserMatchClass = VectorIndexBOperand;
742   let PrintMethod = "printVectorIndex";
743   let MIOperandInfo = (ops i64imm);
744 }
745 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
746   return ((uint64_t)Imm) < 8;
747 }]> {
748   let ParserMatchClass = VectorIndexHOperand;
749   let PrintMethod = "printVectorIndex";
750   let MIOperandInfo = (ops i64imm);
751 }
752 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
753   return ((uint64_t)Imm) < 4;
754 }]> {
755   let ParserMatchClass = VectorIndexSOperand;
756   let PrintMethod = "printVectorIndex";
757   let MIOperandInfo = (ops i64imm);
758 }
759 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
760   return ((uint64_t)Imm) < 2;
761 }]> {
762   let ParserMatchClass = VectorIndexDOperand;
763   let PrintMethod = "printVectorIndex";
764   let MIOperandInfo = (ops i64imm);
765 }
766
767 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
768 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
769 // are encoded as the eight bit value 'abcdefgh'.
770 def simdimmtype10 : Operand<i32>,
771                     PatLeaf<(f64 fpimm), [{
772       return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
773                                                .bitcastToAPInt()
774                                                .getZExtValue());
775     }], SDNodeXForm<fpimm, [{
776       APFloat InVal = N->getValueAPF();
777       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
778                                                            .bitcastToAPInt()
779                                                            .getZExtValue());
780       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
781     }]>> {
782   let ParserMatchClass = SIMDImmType10Operand;
783   let PrintMethod = "printSIMDType10Operand";
784 }
785
786
787 //---
788 // System management
789 //---
790
791 // Base encoding for system instruction operands.
792 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
793 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
794                   list<dag> pattern = []>
795     : I<oops, iops, asm, operands, "", pattern> {
796   let Inst{31-22} = 0b1101010100;
797   let Inst{21}    = L;
798 }
799
800 // System instructions which do not have an Rt register.
801 class SimpleSystemI<bit L, dag iops, string asm, string operands,
802                     list<dag> pattern = []>
803     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
804   let Inst{4-0} = 0b11111;
805 }
806
807 // System instructions which have an Rt register.
808 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
809     : BaseSystemI<L, oops, iops, asm, operands>,
810       Sched<[WriteSys]> {
811   bits<5> Rt;
812   let Inst{4-0} = Rt;
813 }
814
815 // Hint instructions that take both a CRm and a 3-bit immediate.
816 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
817 // model patterns with sufficiently fine granularity
818 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
819   class HintI<string mnemonic>
820       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "",
821                       [(int_aarch64_hint imm0_127:$imm)]>,
822         Sched<[WriteHint]> {
823     bits <7> imm;
824     let Inst{20-12} = 0b000110010;
825     let Inst{11-5} = imm;
826   }
827
828 // System instructions taking a single literal operand which encodes into
829 // CRm. op2 differentiates the opcodes.
830 def BarrierAsmOperand : AsmOperandClass {
831   let Name = "Barrier";
832   let ParserMethod = "tryParseBarrierOperand";
833 }
834 def barrier_op : Operand<i32> {
835   let PrintMethod = "printBarrierOption";
836   let ParserMatchClass = BarrierAsmOperand;
837 }
838 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
839                  list<dag> pattern = []>
840     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
841       Sched<[WriteBarrier]> {
842   bits<4> CRm;
843   let Inst{20-12} = 0b000110011;
844   let Inst{11-8} = CRm;
845   let Inst{7-5} = opc;
846 }
847
848 // MRS/MSR system instructions. These have different operand classes because
849 // a different subset of registers can be accessed through each instruction.
850 def MRSSystemRegisterOperand : AsmOperandClass {
851   let Name = "MRSSystemRegister";
852   let ParserMethod = "tryParseSysReg";
853   let DiagnosticType = "MRS";
854 }
855 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
856 def mrs_sysreg_op : Operand<i32> {
857   let ParserMatchClass = MRSSystemRegisterOperand;
858   let DecoderMethod = "DecodeMRSSystemRegister";
859   let PrintMethod = "printMRSSystemRegister";
860 }
861
862 def MSRSystemRegisterOperand : AsmOperandClass {
863   let Name = "MSRSystemRegister";
864   let ParserMethod = "tryParseSysReg";
865   let DiagnosticType = "MSR";
866 }
867 def msr_sysreg_op : Operand<i32> {
868   let ParserMatchClass = MSRSystemRegisterOperand;
869   let DecoderMethod = "DecodeMSRSystemRegister";
870   let PrintMethod = "printMSRSystemRegister";
871 }
872
873 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
874                        "mrs", "\t$Rt, $systemreg"> {
875   bits<16> systemreg;
876   let Inst{20-5} = systemreg;
877 }
878
879 // FIXME: Some of these def NZCV, others don't. Best way to model that?
880 // Explicitly modeling each of the system register as a register class
881 // would do it, but feels like overkill at this point.
882 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
883                        "msr", "\t$systemreg, $Rt"> {
884   bits<16> systemreg;
885   let Inst{20-5} = systemreg;
886 }
887
888 def SystemPStateFieldOperand : AsmOperandClass {
889   let Name = "SystemPStateField";
890   let ParserMethod = "tryParseSysReg";
891 }
892 def pstatefield_op : Operand<i32> {
893   let ParserMatchClass = SystemPStateFieldOperand;
894   let PrintMethod = "printSystemPStateField";
895 }
896
897 let Defs = [NZCV] in
898 class MSRpstateI
899   : SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm),
900                   "msr", "\t$pstate_field, $imm">,
901     Sched<[WriteSys]> {
902   bits<6> pstatefield;
903   bits<4> imm;
904   let Inst{20-19} = 0b00;
905   let Inst{18-16} = pstatefield{5-3};
906   let Inst{15-12} = 0b0100;
907   let Inst{11-8} = imm;
908   let Inst{7-5} = pstatefield{2-0};
909
910   let DecoderMethod = "DecodeSystemPStateInstruction";
911 }
912
913 // SYS and SYSL generic system instructions.
914 def SysCRAsmOperand : AsmOperandClass {
915   let Name = "SysCR";
916   let ParserMethod = "tryParseSysCROperand";
917 }
918
919 def sys_cr_op : Operand<i32> {
920   let PrintMethod = "printSysCROperand";
921   let ParserMatchClass = SysCRAsmOperand;
922 }
923
924 class SystemXtI<bit L, string asm>
925   : RtSystemI<L, (outs),
926        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
927        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
928   bits<3> op1;
929   bits<4> Cn;
930   bits<4> Cm;
931   bits<3> op2;
932   let Inst{20-19} = 0b01;
933   let Inst{18-16} = op1;
934   let Inst{15-12} = Cn;
935   let Inst{11-8}  = Cm;
936   let Inst{7-5}   = op2;
937 }
938
939 class SystemLXtI<bit L, string asm>
940   : RtSystemI<L, (outs),
941        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
942        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
943   bits<3> op1;
944   bits<4> Cn;
945   bits<4> Cm;
946   bits<3> op2;
947   let Inst{20-19} = 0b01;
948   let Inst{18-16} = op1;
949   let Inst{15-12} = Cn;
950   let Inst{11-8}  = Cm;
951   let Inst{7-5}   = op2;
952 }
953
954
955 // Branch (register) instructions:
956 //
957 //  case opc of
958 //    0001 blr
959 //    0000 br
960 //    0101 dret
961 //    0100 eret
962 //    0010 ret
963 //    otherwise UNDEFINED
964 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
965                     string operands, list<dag> pattern>
966     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
967   let Inst{31-25} = 0b1101011;
968   let Inst{24-21} = opc;
969   let Inst{20-16} = 0b11111;
970   let Inst{15-10} = 0b000000;
971   let Inst{4-0}   = 0b00000;
972 }
973
974 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
975     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
976   bits<5> Rn;
977   let Inst{9-5} = Rn;
978 }
979
980 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
981 class SpecialReturn<bits<4> opc, string asm>
982     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
983   let Inst{9-5} = 0b11111;
984 }
985
986 //---
987 // Conditional branch instruction.
988 //---
989
990 // Condition code.
991 // 4-bit immediate. Pretty-printed as <cc>
992 def ccode : Operand<i32> {
993   let PrintMethod = "printCondCode";
994   let ParserMatchClass = CondCode;
995 }
996 def inv_ccode : Operand<i32> {
997   // AL and NV are invalid in the aliases which use inv_ccode
998   let PrintMethod = "printInverseCondCode";
999   let ParserMatchClass = CondCode;
1000   let MCOperandPredicate = [{
1001     return MCOp.isImm() &&
1002            MCOp.getImm() != AArch64CC::AL &&
1003            MCOp.getImm() != AArch64CC::NV;
1004   }];
1005 }
1006
1007 // Conditional branch target. 19-bit immediate. The low two bits of the target
1008 // offset are implied zero and so are not part of the immediate.
1009 def PCRelLabel19Operand : AsmOperandClass {
1010   let Name = "PCRelLabel19";
1011   let DiagnosticType = "InvalidLabel";
1012 }
1013 def am_brcond : Operand<OtherVT> {
1014   let EncoderMethod = "getCondBranchTargetOpValue";
1015   let DecoderMethod = "DecodePCRelLabel19";
1016   let PrintMethod = "printAlignedLabel";
1017   let ParserMatchClass = PCRelLabel19Operand;
1018 }
1019
1020 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1021                      "b", ".$cond\t$target", "",
1022                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1023                    Sched<[WriteBr]> {
1024   let isBranch = 1;
1025   let isTerminator = 1;
1026   let Uses = [NZCV];
1027
1028   bits<4> cond;
1029   bits<19> target;
1030   let Inst{31-24} = 0b01010100;
1031   let Inst{23-5} = target;
1032   let Inst{4} = 0;
1033   let Inst{3-0} = cond;
1034 }
1035
1036 //---
1037 // Compare-and-branch instructions.
1038 //---
1039 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1040     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1041          asm, "\t$Rt, $target", "",
1042          [(node regtype:$Rt, bb:$target)]>,
1043       Sched<[WriteBr]> {
1044   let isBranch = 1;
1045   let isTerminator = 1;
1046
1047   bits<5> Rt;
1048   bits<19> target;
1049   let Inst{30-25} = 0b011010;
1050   let Inst{24}    = op;
1051   let Inst{23-5}  = target;
1052   let Inst{4-0}   = Rt;
1053 }
1054
1055 multiclass CmpBranch<bit op, string asm, SDNode node> {
1056   def W : BaseCmpBranch<GPR32, op, asm, node> {
1057     let Inst{31} = 0;
1058   }
1059   def X : BaseCmpBranch<GPR64, op, asm, node> {
1060     let Inst{31} = 1;
1061   }
1062 }
1063
1064 //---
1065 // Test-bit-and-branch instructions.
1066 //---
1067 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1068 // the target offset are implied zero and so are not part of the immediate.
1069 def BranchTarget14Operand : AsmOperandClass {
1070   let Name = "BranchTarget14";
1071 }
1072 def am_tbrcond : Operand<OtherVT> {
1073   let EncoderMethod = "getTestBranchTargetOpValue";
1074   let PrintMethod = "printAlignedLabel";
1075   let ParserMatchClass = BranchTarget14Operand;
1076 }
1077
1078 // AsmOperand classes to emit (or not) special diagnostics
1079 def TBZImm0_31Operand : AsmOperandClass {
1080   let Name = "TBZImm0_31";
1081   let PredicateMethod = "isImm0_31";
1082   let RenderMethod = "addImm0_31Operands";
1083 }
1084 def TBZImm32_63Operand : AsmOperandClass {
1085   let Name = "Imm32_63";
1086   let DiagnosticType = "InvalidImm0_63";
1087 }
1088
1089 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1090   return (((uint32_t)Imm) < 32);
1091 }]> {
1092   let ParserMatchClass = matcher;
1093 }
1094
1095 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1096 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1097
1098 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1099   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1100 }]> {
1101   let ParserMatchClass = TBZImm32_63Operand;
1102 }
1103
1104 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1105                      bit op, string asm, SDNode node>
1106     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1107        asm, "\t$Rt, $bit_off, $target", "",
1108        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1109       Sched<[WriteBr]> {
1110   let isBranch = 1;
1111   let isTerminator = 1;
1112
1113   bits<5> Rt;
1114   bits<6> bit_off;
1115   bits<14> target;
1116
1117   let Inst{30-25} = 0b011011;
1118   let Inst{24}    = op;
1119   let Inst{23-19} = bit_off{4-0};
1120   let Inst{18-5}  = target;
1121   let Inst{4-0}   = Rt;
1122
1123   let DecoderMethod = "DecodeTestAndBranch";
1124 }
1125
1126 multiclass TestBranch<bit op, string asm, SDNode node> {
1127   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1128     let Inst{31} = 0;
1129   }
1130
1131   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1132     let Inst{31} = 1;
1133   }
1134
1135   // Alias X-reg with 0-31 imm to W-Reg.
1136   def : InstAlias<asm # "\t$Rd, $imm, $target",
1137                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1138                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1139   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1140             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1141             tbz_imm0_31_diag:$imm, bb:$target)>;
1142 }
1143
1144 //---
1145 // Unconditional branch (immediate) instructions.
1146 //---
1147 def BranchTarget26Operand : AsmOperandClass {
1148   let Name = "BranchTarget26";
1149   let DiagnosticType = "InvalidLabel";
1150 }
1151 def am_b_target : Operand<OtherVT> {
1152   let EncoderMethod = "getBranchTargetOpValue";
1153   let PrintMethod = "printAlignedLabel";
1154   let ParserMatchClass = BranchTarget26Operand;
1155 }
1156 def am_bl_target : Operand<i64> {
1157   let EncoderMethod = "getBranchTargetOpValue";
1158   let PrintMethod = "printAlignedLabel";
1159   let ParserMatchClass = BranchTarget26Operand;
1160 }
1161
1162 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1163     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1164   bits<26> addr;
1165   let Inst{31}    = op;
1166   let Inst{30-26} = 0b00101;
1167   let Inst{25-0}  = addr;
1168
1169   let DecoderMethod = "DecodeUnconditionalBranch";
1170 }
1171
1172 class BranchImm<bit op, string asm, list<dag> pattern>
1173     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1174 class CallImm<bit op, string asm, list<dag> pattern>
1175     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1176
1177 //---
1178 // Basic one-operand data processing instructions.
1179 //---
1180
1181 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1182 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1183                          SDPatternOperator node>
1184   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1185       [(set regtype:$Rd, (node regtype:$Rn))]>,
1186     Sched<[WriteI, ReadI]> {
1187   bits<5> Rd;
1188   bits<5> Rn;
1189
1190   let Inst{30-13} = 0b101101011000000000;
1191   let Inst{12-10} = opc;
1192   let Inst{9-5}   = Rn;
1193   let Inst{4-0}   = Rd;
1194 }
1195
1196 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1197 multiclass OneOperandData<bits<3> opc, string asm,
1198                           SDPatternOperator node = null_frag> {
1199   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1200     let Inst{31} = 0;
1201   }
1202
1203   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1204     let Inst{31} = 1;
1205   }
1206 }
1207
1208 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1209     : BaseOneOperandData<opc, GPR32, asm, node> {
1210   let Inst{31} = 0;
1211 }
1212
1213 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1214     : BaseOneOperandData<opc, GPR64, asm, node> {
1215   let Inst{31} = 1;
1216 }
1217
1218 //---
1219 // Basic two-operand data processing instructions.
1220 //---
1221 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1222                           list<dag> pattern>
1223     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1224         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1225       Sched<[WriteI, ReadI, ReadI]> {
1226   let Uses = [NZCV];
1227   bits<5> Rd;
1228   bits<5> Rn;
1229   bits<5> Rm;
1230   let Inst{30}    = isSub;
1231   let Inst{28-21} = 0b11010000;
1232   let Inst{20-16} = Rm;
1233   let Inst{15-10} = 0;
1234   let Inst{9-5}   = Rn;
1235   let Inst{4-0}   = Rd;
1236 }
1237
1238 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1239                       SDNode OpNode>
1240     : BaseBaseAddSubCarry<isSub, regtype, asm,
1241         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1242
1243 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1244                               SDNode OpNode>
1245     : BaseBaseAddSubCarry<isSub, regtype, asm,
1246         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1247          (implicit NZCV)]> {
1248   let Defs = [NZCV];
1249 }
1250
1251 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1252                        SDNode OpNode, SDNode OpNode_setflags> {
1253   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1254     let Inst{31} = 0;
1255     let Inst{29} = 0;
1256   }
1257   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1258     let Inst{31} = 1;
1259     let Inst{29} = 0;
1260   }
1261
1262   // Sets flags.
1263   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1264                                     OpNode_setflags> {
1265     let Inst{31} = 0;
1266     let Inst{29} = 1;
1267   }
1268   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1269                                     OpNode_setflags> {
1270     let Inst{31} = 1;
1271     let Inst{29} = 1;
1272   }
1273 }
1274
1275 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1276                      SDPatternOperator OpNode>
1277   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1278       asm, "\t$Rd, $Rn, $Rm", "",
1279       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1280   bits<5> Rd;
1281   bits<5> Rn;
1282   bits<5> Rm;
1283   let Inst{30-21} = 0b0011010110;
1284   let Inst{20-16} = Rm;
1285   let Inst{15-14} = 0b00;
1286   let Inst{13-10} = opc;
1287   let Inst{9-5}   = Rn;
1288   let Inst{4-0}   = Rd;
1289 }
1290
1291 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1292               SDPatternOperator OpNode>
1293     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1294   let Inst{10}    = isSigned;
1295 }
1296
1297 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1298   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1299            Sched<[WriteID32, ReadID, ReadID]> {
1300     let Inst{31} = 0;
1301   }
1302   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1303            Sched<[WriteID64, ReadID, ReadID]> {
1304     let Inst{31} = 1;
1305   }
1306 }
1307
1308 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1309                 SDPatternOperator OpNode = null_frag>
1310   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1311     Sched<[WriteIS, ReadI]> {
1312   let Inst{11-10} = shift_type;
1313 }
1314
1315 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1316   def Wr : BaseShift<shift_type, GPR32, asm> {
1317     let Inst{31} = 0;
1318   }
1319
1320   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1321     let Inst{31} = 1;
1322   }
1323
1324   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1325             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1326                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1327
1328   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1329             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1330
1331   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1332             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1333
1334   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1335             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1336 }
1337
1338 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1339     : InstAlias<asm#" $dst, $src1, $src2",
1340                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1341
1342 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1343                        RegisterClass addtype, string asm,
1344                        list<dag> pattern>
1345   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1346       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1347   bits<5> Rd;
1348   bits<5> Rn;
1349   bits<5> Rm;
1350   bits<5> Ra;
1351   let Inst{30-24} = 0b0011011;
1352   let Inst{23-21} = opc;
1353   let Inst{20-16} = Rm;
1354   let Inst{15}    = isSub;
1355   let Inst{14-10} = Ra;
1356   let Inst{9-5}   = Rn;
1357   let Inst{4-0}   = Rd;
1358 }
1359
1360 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1361   // MADD/MSUB generation is decided by MachineCombiner.cpp
1362   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1363       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1364       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1365     let Inst{31} = 0;
1366   }
1367
1368   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1369       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1370       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1371     let Inst{31} = 1;
1372   }
1373 }
1374
1375 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1376                    SDNode AccNode, SDNode ExtNode>
1377   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1378     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1379                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1380     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1381   let Inst{31} = 1;
1382 }
1383
1384 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1385   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1386       asm, "\t$Rd, $Rn, $Rm", "",
1387       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1388     Sched<[WriteIM64, ReadIM, ReadIM]> {
1389   bits<5> Rd;
1390   bits<5> Rn;
1391   bits<5> Rm;
1392   let Inst{31-24} = 0b10011011;
1393   let Inst{23-21} = opc;
1394   let Inst{20-16} = Rm;
1395   let Inst{15}    = 0;
1396   let Inst{9-5}   = Rn;
1397   let Inst{4-0}   = Rd;
1398
1399   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1400   // (i.e. all bits 1) but is ignored by the processor.
1401   let PostEncoderMethod = "fixMulHigh";
1402 }
1403
1404 class MulAccumWAlias<string asm, Instruction inst>
1405     : InstAlias<asm#" $dst, $src1, $src2",
1406                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1407 class MulAccumXAlias<string asm, Instruction inst>
1408     : InstAlias<asm#" $dst, $src1, $src2",
1409                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1410 class WideMulAccumAlias<string asm, Instruction inst>
1411     : InstAlias<asm#" $dst, $src1, $src2",
1412                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1413
1414 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1415               SDPatternOperator OpNode, string asm>
1416   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1417       asm, "\t$Rd, $Rn, $Rm", "",
1418       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1419     Sched<[WriteISReg, ReadI, ReadISReg]> {
1420   bits<5> Rd;
1421   bits<5> Rn;
1422   bits<5> Rm;
1423
1424   let Inst{31} = sf;
1425   let Inst{30-21} = 0b0011010110;
1426   let Inst{20-16} = Rm;
1427   let Inst{15-13} = 0b010;
1428   let Inst{12} = C;
1429   let Inst{11-10} = sz;
1430   let Inst{9-5} = Rn;
1431   let Inst{4-0} = Rd;
1432   let Predicates = [HasCRC];
1433 }
1434
1435 //---
1436 // Address generation.
1437 //---
1438
1439 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1440     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1441         pattern>,
1442       Sched<[WriteI]> {
1443   bits<5>  Xd;
1444   bits<21> label;
1445   let Inst{31}    = page;
1446   let Inst{30-29} = label{1-0};
1447   let Inst{28-24} = 0b10000;
1448   let Inst{23-5}  = label{20-2};
1449   let Inst{4-0}   = Xd;
1450
1451   let DecoderMethod = "DecodeAdrInstruction";
1452 }
1453
1454 //---
1455 // Move immediate.
1456 //---
1457
1458 def movimm32_imm : Operand<i32> {
1459   let ParserMatchClass = Imm0_65535Operand;
1460   let EncoderMethod = "getMoveWideImmOpValue";
1461   let PrintMethod = "printHexImm";
1462 }
1463 def movimm32_shift : Operand<i32> {
1464   let PrintMethod = "printShifter";
1465   let ParserMatchClass = MovImm32ShifterOperand;
1466 }
1467 def movimm64_shift : Operand<i32> {
1468   let PrintMethod = "printShifter";
1469   let ParserMatchClass = MovImm64ShifterOperand;
1470 }
1471
1472 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1473 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1474                         string asm>
1475   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1476        asm, "\t$Rd, $imm$shift", "", []>,
1477     Sched<[WriteImm]> {
1478   bits<5> Rd;
1479   bits<16> imm;
1480   bits<6> shift;
1481   let Inst{30-29} = opc;
1482   let Inst{28-23} = 0b100101;
1483   let Inst{22-21} = shift{5-4};
1484   let Inst{20-5}  = imm;
1485   let Inst{4-0}   = Rd;
1486
1487   let DecoderMethod = "DecodeMoveImmInstruction";
1488 }
1489
1490 multiclass MoveImmediate<bits<2> opc, string asm> {
1491   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1492     let Inst{31} = 0;
1493   }
1494
1495   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1496     let Inst{31} = 1;
1497   }
1498 }
1499
1500 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1501 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1502                           string asm>
1503   : I<(outs regtype:$Rd),
1504       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1505        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1506     Sched<[WriteI, ReadI]> {
1507   bits<5> Rd;
1508   bits<16> imm;
1509   bits<6> shift;
1510   let Inst{30-29} = opc;
1511   let Inst{28-23} = 0b100101;
1512   let Inst{22-21} = shift{5-4};
1513   let Inst{20-5}  = imm;
1514   let Inst{4-0}   = Rd;
1515
1516   let DecoderMethod = "DecodeMoveImmInstruction";
1517 }
1518
1519 multiclass InsertImmediate<bits<2> opc, string asm> {
1520   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1521     let Inst{31} = 0;
1522   }
1523
1524   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1525     let Inst{31} = 1;
1526   }
1527 }
1528
1529 //---
1530 // Add/Subtract
1531 //---
1532
1533 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1534                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1535                     string asm, SDPatternOperator OpNode>
1536     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1537         asm, "\t$Rd, $Rn, $imm", "",
1538         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1539       Sched<[WriteI, ReadI]>  {
1540   bits<5>  Rd;
1541   bits<5>  Rn;
1542   bits<14> imm;
1543   let Inst{30}    = isSub;
1544   let Inst{29}    = setFlags;
1545   let Inst{28-24} = 0b10001;
1546   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1547   let Inst{21-10} = imm{11-0};
1548   let Inst{9-5}   = Rn;
1549   let Inst{4-0}   = Rd;
1550   let DecoderMethod = "DecodeBaseAddSubImm";
1551 }
1552
1553 class BaseAddSubRegPseudo<RegisterClass regtype,
1554                           SDPatternOperator OpNode>
1555     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1556              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1557       Sched<[WriteI, ReadI, ReadI]>;
1558
1559 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1560                      arith_shifted_reg shifted_regtype, string asm,
1561                      SDPatternOperator OpNode>
1562     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1563         asm, "\t$Rd, $Rn, $Rm", "",
1564         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1565       Sched<[WriteISReg, ReadI, ReadISReg]> {
1566   // The operands are in order to match the 'addr' MI operands, so we
1567   // don't need an encoder method and by-name matching. Just use the default
1568   // in-order handling. Since we're using by-order, make sure the names
1569   // do not match.
1570   bits<5> dst;
1571   bits<5> src1;
1572   bits<5> src2;
1573   bits<8> shift;
1574   let Inst{30}    = isSub;
1575   let Inst{29}    = setFlags;
1576   let Inst{28-24} = 0b01011;
1577   let Inst{23-22} = shift{7-6};
1578   let Inst{21}    = 0;
1579   let Inst{20-16} = src2;
1580   let Inst{15-10} = shift{5-0};
1581   let Inst{9-5}   = src1;
1582   let Inst{4-0}   = dst;
1583
1584   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1585 }
1586
1587 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1588                      RegisterClass src1Regtype, Operand src2Regtype,
1589                      string asm, SDPatternOperator OpNode>
1590     : I<(outs dstRegtype:$R1),
1591         (ins src1Regtype:$R2, src2Regtype:$R3),
1592         asm, "\t$R1, $R2, $R3", "",
1593         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1594       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1595   bits<5> Rd;
1596   bits<5> Rn;
1597   bits<5> Rm;
1598   bits<6> ext;
1599   let Inst{30}    = isSub;
1600   let Inst{29}    = setFlags;
1601   let Inst{28-24} = 0b01011;
1602   let Inst{23-21} = 0b001;
1603   let Inst{20-16} = Rm;
1604   let Inst{15-13} = ext{5-3};
1605   let Inst{12-10} = ext{2-0};
1606   let Inst{9-5}   = Rn;
1607   let Inst{4-0}   = Rd;
1608
1609   let DecoderMethod = "DecodeAddSubERegInstruction";
1610 }
1611
1612 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1613 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1614                        RegisterClass src1Regtype, RegisterClass src2Regtype,
1615                        Operand ext_op, string asm>
1616     : I<(outs dstRegtype:$Rd),
1617         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1618         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1619       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1620   bits<5> Rd;
1621   bits<5> Rn;
1622   bits<5> Rm;
1623   bits<6> ext;
1624   let Inst{30}    = isSub;
1625   let Inst{29}    = setFlags;
1626   let Inst{28-24} = 0b01011;
1627   let Inst{23-21} = 0b001;
1628   let Inst{20-16} = Rm;
1629   let Inst{15}    = ext{5};
1630   let Inst{12-10} = ext{2-0};
1631   let Inst{9-5}   = Rn;
1632   let Inst{4-0}   = Rd;
1633
1634   let DecoderMethod = "DecodeAddSubERegInstruction";
1635 }
1636
1637 // Aliases for register+register add/subtract.
1638 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1639                      RegisterClass src1Regtype, RegisterClass src2Regtype,
1640                      int shiftExt>
1641     : InstAlias<asm#" $dst, $src1, $src2",
1642                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1643                       shiftExt)>;
1644
1645 multiclass AddSub<bit isSub, string mnemonic,
1646                   SDPatternOperator OpNode = null_frag> {
1647   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1648   // Add/Subtract immediate
1649   // Increase the weight of the immediate variant to try to match it before
1650   // the extended register variant.
1651   // We used to match the register variant before the immediate when the
1652   // register argument could be implicitly zero-extended.
1653   let AddedComplexity = 6 in
1654   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1655                            mnemonic, OpNode> {
1656     let Inst{31} = 0;
1657   }
1658   let AddedComplexity = 6 in
1659   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1660                            mnemonic, OpNode> {
1661     let Inst{31} = 1;
1662   }
1663
1664   // Add/Subtract register - Only used for CodeGen
1665   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1666   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1667
1668   // Add/Subtract shifted register
1669   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1670                            OpNode> {
1671     let Inst{31} = 0;
1672   }
1673   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1674                            OpNode> {
1675     let Inst{31} = 1;
1676   }
1677   }
1678
1679   // Add/Subtract extended register
1680   let AddedComplexity = 1, hasSideEffects = 0 in {
1681   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1682                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1683     let Inst{31} = 0;
1684   }
1685   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1686                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1687     let Inst{31} = 1;
1688   }
1689   }
1690
1691   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1692                                arith_extendlsl64, mnemonic> {
1693     // UXTX and SXTX only.
1694     let Inst{14-13} = 0b11;
1695     let Inst{31} = 1;
1696   }
1697
1698   // Register/register aliases with no shift when SP is not used.
1699   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1700                        GPR32, GPR32, GPR32, 0>;
1701   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1702                        GPR64, GPR64, GPR64, 0>;
1703
1704   // Register/register aliases with no shift when either the destination or
1705   // first source register is SP.
1706   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1707                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1708   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1709                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1710   def : AddSubRegAlias<mnemonic,
1711                        !cast<Instruction>(NAME#"Xrx64"),
1712                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1713   def : AddSubRegAlias<mnemonic,
1714                        !cast<Instruction>(NAME#"Xrx64"),
1715                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1716 }
1717
1718 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp> {
1719   let isCompare = 1, Defs = [NZCV] in {
1720   // Add/Subtract immediate
1721   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1722                            mnemonic, OpNode> {
1723     let Inst{31} = 0;
1724   }
1725   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1726                            mnemonic, OpNode> {
1727     let Inst{31} = 1;
1728   }
1729
1730   // Add/Subtract register
1731   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1732   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1733
1734   // Add/Subtract shifted register
1735   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1736                            OpNode> {
1737     let Inst{31} = 0;
1738   }
1739   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1740                            OpNode> {
1741     let Inst{31} = 1;
1742   }
1743
1744   // Add/Subtract extended register
1745   let AddedComplexity = 1 in {
1746   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1747                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1748     let Inst{31} = 0;
1749   }
1750   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1751                            arith_extended_reg32<i64>, mnemonic, OpNode> {
1752     let Inst{31} = 1;
1753   }
1754   }
1755
1756   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1757                                arith_extendlsl64, mnemonic> {
1758     // UXTX and SXTX only.
1759     let Inst{14-13} = 0b11;
1760     let Inst{31} = 1;
1761   }
1762   } // Defs = [NZCV]
1763
1764   // Compare aliases
1765   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Wri")
1766                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1767   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Xri")
1768                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1769   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1770                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1771   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1772                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1773   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1774                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1775   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1776                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1777   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1778                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1779
1780   // Compare shorthands
1781   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1782                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1783   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1784                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1785   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1786                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1787   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1788                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1789
1790   // Register/register aliases with no shift when SP is not used.
1791   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1792                        GPR32, GPR32, GPR32, 0>;
1793   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1794                        GPR64, GPR64, GPR64, 0>;
1795
1796   // Register/register aliases with no shift when the first source register
1797   // is SP.
1798   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1799                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1800   def : AddSubRegAlias<mnemonic,
1801                        !cast<Instruction>(NAME#"Xrx64"),
1802                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1803 }
1804
1805 //---
1806 // Extract
1807 //---
1808 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1809                                       SDTCisPtrTy<3>]>;
1810 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1811
1812 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1813                      list<dag> patterns>
1814     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1815          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1816       Sched<[WriteExtr, ReadExtrHi]> {
1817   bits<5> Rd;
1818   bits<5> Rn;
1819   bits<5> Rm;
1820   bits<6> imm;
1821
1822   let Inst{30-23} = 0b00100111;
1823   let Inst{21}    = 0;
1824   let Inst{20-16} = Rm;
1825   let Inst{15-10} = imm;
1826   let Inst{9-5}   = Rn;
1827   let Inst{4-0}   = Rd;
1828 }
1829
1830 multiclass ExtractImm<string asm> {
1831   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1832                       [(set GPR32:$Rd,
1833                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1834     let Inst{31} = 0;
1835     let Inst{22} = 0;
1836     // imm<5> must be zero.
1837     let imm{5}   = 0;
1838   }
1839   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1840                       [(set GPR64:$Rd,
1841                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1842
1843     let Inst{31} = 1;
1844     let Inst{22} = 1;
1845   }
1846 }
1847
1848 //---
1849 // Bitfield
1850 //---
1851
1852 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1853 class BaseBitfieldImm<bits<2> opc,
1854                       RegisterClass regtype, Operand imm_type, string asm>
1855     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1856          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1857       Sched<[WriteIS, ReadI]> {
1858   bits<5> Rd;
1859   bits<5> Rn;
1860   bits<6> immr;
1861   bits<6> imms;
1862
1863   let Inst{30-29} = opc;
1864   let Inst{28-23} = 0b100110;
1865   let Inst{21-16} = immr;
1866   let Inst{15-10} = imms;
1867   let Inst{9-5}   = Rn;
1868   let Inst{4-0}   = Rd;
1869 }
1870
1871 multiclass BitfieldImm<bits<2> opc, string asm> {
1872   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1873     let Inst{31} = 0;
1874     let Inst{22} = 0;
1875     // imms<5> and immr<5> must be zero, else ReservedValue().
1876     let Inst{21} = 0;
1877     let Inst{15} = 0;
1878   }
1879   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1880     let Inst{31} = 1;
1881     let Inst{22} = 1;
1882   }
1883 }
1884
1885 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1886 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1887                       RegisterClass regtype, Operand imm_type, string asm>
1888     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1889                              imm_type:$imms),
1890          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1891       Sched<[WriteIS, ReadI]> {
1892   bits<5> Rd;
1893   bits<5> Rn;
1894   bits<6> immr;
1895   bits<6> imms;
1896
1897   let Inst{30-29} = opc;
1898   let Inst{28-23} = 0b100110;
1899   let Inst{21-16} = immr;
1900   let Inst{15-10} = imms;
1901   let Inst{9-5}   = Rn;
1902   let Inst{4-0}   = Rd;
1903 }
1904
1905 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1906   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1907     let Inst{31} = 0;
1908     let Inst{22} = 0;
1909     // imms<5> and immr<5> must be zero, else ReservedValue().
1910     let Inst{21} = 0;
1911     let Inst{15} = 0;
1912   }
1913   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1914     let Inst{31} = 1;
1915     let Inst{22} = 1;
1916   }
1917 }
1918
1919 //---
1920 // Logical
1921 //---
1922
1923 // Logical (immediate)
1924 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1925                      RegisterClass sregtype, Operand imm_type, string asm,
1926                      list<dag> pattern>
1927     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1928          asm, "\t$Rd, $Rn, $imm", "", pattern>,
1929       Sched<[WriteI, ReadI]> {
1930   bits<5>  Rd;
1931   bits<5>  Rn;
1932   bits<13> imm;
1933   let Inst{30-29} = opc;
1934   let Inst{28-23} = 0b100100;
1935   let Inst{22}    = imm{12};
1936   let Inst{21-16} = imm{11-6};
1937   let Inst{15-10} = imm{5-0};
1938   let Inst{9-5}   = Rn;
1939   let Inst{4-0}   = Rd;
1940
1941   let DecoderMethod = "DecodeLogicalImmInstruction";
1942 }
1943
1944 // Logical (shifted register)
1945 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1946                       logical_shifted_reg shifted_regtype, string asm,
1947                       list<dag> pattern>
1948     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1949         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1950       Sched<[WriteISReg, ReadI, ReadISReg]> {
1951   // The operands are in order to match the 'addr' MI operands, so we
1952   // don't need an encoder method and by-name matching. Just use the default
1953   // in-order handling. Since we're using by-order, make sure the names
1954   // do not match.
1955   bits<5> dst;
1956   bits<5> src1;
1957   bits<5> src2;
1958   bits<8> shift;
1959   let Inst{30-29} = opc;
1960   let Inst{28-24} = 0b01010;
1961   let Inst{23-22} = shift{7-6};
1962   let Inst{21}    = N;
1963   let Inst{20-16} = src2;
1964   let Inst{15-10} = shift{5-0};
1965   let Inst{9-5}   = src1;
1966   let Inst{4-0}   = dst;
1967
1968   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1969 }
1970
1971 // Aliases for register+register logical instructions.
1972 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1973     : InstAlias<asm#" $dst, $src1, $src2",
1974                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1975
1976 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
1977                       string Alias> {
1978   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
1979   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1980                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1981                                                logical_imm32:$imm))]> {
1982     let Inst{31} = 0;
1983     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1984   }
1985   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
1986   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1987                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1988                                                logical_imm64:$imm))]> {
1989     let Inst{31} = 1;
1990   }
1991
1992   def : InstAlias<Alias # " $Rd, $Rn, $imm",
1993                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
1994                       logical_imm32_not:$imm), 0>;
1995   def : InstAlias<Alias # " $Rd, $Rn, $imm",
1996                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
1997                        logical_imm64_not:$imm), 0>;
1998 }
1999
2000 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2001                        string Alias> {
2002   let isCompare = 1, Defs = [NZCV] in {
2003   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2004       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2005     let Inst{31} = 0;
2006     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2007   }
2008   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2009       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2010     let Inst{31} = 1;
2011   }
2012   } // end Defs = [NZCV]
2013
2014   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2015                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2016                       logical_imm32_not:$imm), 0>;
2017   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2018                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2019                        logical_imm64_not:$imm), 0>;
2020 }
2021
2022 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2023     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2024              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2025       Sched<[WriteI, ReadI, ReadI]>;
2026
2027 // Split from LogicalImm as not all instructions have both.
2028 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2029                       SDPatternOperator OpNode> {
2030   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2031   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2032   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2033   }
2034
2035   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2036                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2037                                                  logical_shifted_reg32:$Rm))]> {
2038     let Inst{31} = 0;
2039   }
2040   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2041                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2042                                                  logical_shifted_reg64:$Rm))]> {
2043     let Inst{31} = 1;
2044   }
2045
2046   def : LogicalRegAlias<mnemonic,
2047                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2048   def : LogicalRegAlias<mnemonic,
2049                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2050 }
2051
2052 // Split from LogicalReg to allow setting NZCV Defs
2053 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2054                        SDPatternOperator OpNode = null_frag> {
2055   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2056   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2057   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2058
2059   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2060             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2061     let Inst{31} = 0;
2062   }
2063   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2064             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2065     let Inst{31} = 1;
2066   }
2067   } // Defs = [NZCV]
2068
2069   def : LogicalRegAlias<mnemonic,
2070                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2071   def : LogicalRegAlias<mnemonic,
2072                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2073 }
2074
2075 //---
2076 // Conditionally set flags
2077 //---
2078
2079 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2080 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2081                             string mnemonic, SDNode OpNode>
2082     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2083          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2084          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2085                              (i32 imm:$cond), NZCV))]>,
2086       Sched<[WriteI, ReadI]> {
2087   let Uses = [NZCV];
2088   let Defs = [NZCV];
2089
2090   bits<5> Rn;
2091   bits<5> imm;
2092   bits<4> nzcv;
2093   bits<4> cond;
2094
2095   let Inst{30}    = op;
2096   let Inst{29-21} = 0b111010010;
2097   let Inst{20-16} = imm;
2098   let Inst{15-12} = cond;
2099   let Inst{11-10} = 0b10;
2100   let Inst{9-5}   = Rn;
2101   let Inst{4}     = 0b0;
2102   let Inst{3-0}   = nzcv;
2103 }
2104
2105 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2106 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2107                             SDNode OpNode>
2108     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2109          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2110          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2111                              (i32 imm:$cond), NZCV))]>,
2112       Sched<[WriteI, ReadI, ReadI]> {
2113   let Uses = [NZCV];
2114   let Defs = [NZCV];
2115
2116   bits<5> Rn;
2117   bits<5> Rm;
2118   bits<4> nzcv;
2119   bits<4> cond;
2120
2121   let Inst{30}    = op;
2122   let Inst{29-21} = 0b111010010;
2123   let Inst{20-16} = Rm;
2124   let Inst{15-12} = cond;
2125   let Inst{11-10} = 0b00;
2126   let Inst{9-5}   = Rn;
2127   let Inst{4}     = 0b0;
2128   let Inst{3-0}   = nzcv;
2129 }
2130
2131 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2132   // immediate operand variants
2133   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2134     let Inst{31} = 0;
2135   }
2136   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2137     let Inst{31} = 1;
2138   }
2139   // register operand variants
2140   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2141     let Inst{31} = 0;
2142   }
2143   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2144     let Inst{31} = 1;
2145   }
2146 }
2147
2148 //---
2149 // Conditional select
2150 //---
2151
2152 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2153     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2154          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2155          [(set regtype:$Rd,
2156                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2157       Sched<[WriteI, ReadI, ReadI]> {
2158   let Uses = [NZCV];
2159
2160   bits<5> Rd;
2161   bits<5> Rn;
2162   bits<5> Rm;
2163   bits<4> cond;
2164
2165   let Inst{30}    = op;
2166   let Inst{29-21} = 0b011010100;
2167   let Inst{20-16} = Rm;
2168   let Inst{15-12} = cond;
2169   let Inst{11-10} = op2;
2170   let Inst{9-5}   = Rn;
2171   let Inst{4-0}   = Rd;
2172 }
2173
2174 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2175   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2176     let Inst{31} = 0;
2177   }
2178   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2179     let Inst{31} = 1;
2180   }
2181 }
2182
2183 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2184                        PatFrag frag>
2185     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2186          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2187          [(set regtype:$Rd,
2188                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2189                (i32 imm:$cond), NZCV))]>,
2190       Sched<[WriteI, ReadI, ReadI]> {
2191   let Uses = [NZCV];
2192
2193   bits<5> Rd;
2194   bits<5> Rn;
2195   bits<5> Rm;
2196   bits<4> cond;
2197
2198   let Inst{30}    = op;
2199   let Inst{29-21} = 0b011010100;
2200   let Inst{20-16} = Rm;
2201   let Inst{15-12} = cond;
2202   let Inst{11-10} = op2;
2203   let Inst{9-5}   = Rn;
2204   let Inst{4-0}   = Rd;
2205 }
2206
2207 def inv_cond_XFORM : SDNodeXForm<imm, [{
2208   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2209   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2210                                    MVT::i32);
2211 }]>;
2212
2213 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2214   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2215     let Inst{31} = 0;
2216   }
2217   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2218     let Inst{31} = 1;
2219   }
2220
2221   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2222             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2223                                            (inv_cond_XFORM imm:$cond))>;
2224
2225   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2226             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2227                                            (inv_cond_XFORM imm:$cond))>;
2228 }
2229
2230 //---
2231 // Special Mask Value
2232 //---
2233 def maski8_or_more : Operand<i32>,
2234   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2235 }
2236 def maski16_or_more : Operand<i32>,
2237   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2238 }
2239
2240
2241 //---
2242 // Load/store
2243 //---
2244
2245 // (unsigned immediate)
2246 // Indexed for 8-bit registers. offset is in range [0,4095].
2247 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2248 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2249 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2250 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2251 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2252
2253 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2254   let Name = "UImm12Offset" # Scale;
2255   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2256   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2257   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2258 }
2259
2260 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2261 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2262 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2263 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2264 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2265
2266 class uimm12_scaled<int Scale> : Operand<i64> {
2267   let ParserMatchClass
2268    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2269   let EncoderMethod
2270    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2271   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2272 }
2273
2274 def uimm12s1 : uimm12_scaled<1>;
2275 def uimm12s2 : uimm12_scaled<2>;
2276 def uimm12s4 : uimm12_scaled<4>;
2277 def uimm12s8 : uimm12_scaled<8>;
2278 def uimm12s16 : uimm12_scaled<16>;
2279
2280 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2281                       string asm, list<dag> pattern>
2282     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2283   bits<5> Rt;
2284
2285   bits<5> Rn;
2286   bits<12> offset;
2287
2288   let Inst{31-30} = sz;
2289   let Inst{29-27} = 0b111;
2290   let Inst{26}    = V;
2291   let Inst{25-24} = 0b01;
2292   let Inst{23-22} = opc;
2293   let Inst{21-10} = offset;
2294   let Inst{9-5}   = Rn;
2295   let Inst{4-0}   = Rt;
2296
2297   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2298 }
2299
2300 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2301                   Operand indextype, string asm, list<dag> pattern> {
2302   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2303   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2304                            (ins GPR64sp:$Rn, indextype:$offset),
2305                            asm, pattern>,
2306            Sched<[WriteLD]>;
2307
2308   def : InstAlias<asm # " $Rt, [$Rn]",
2309                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2310 }
2311
2312 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2313              Operand indextype, string asm, list<dag> pattern> {
2314   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2315   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2316                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2317                            asm, pattern>,
2318            Sched<[WriteST]>;
2319
2320   def : InstAlias<asm # " $Rt, [$Rn]",
2321                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2322 }
2323
2324 def PrefetchOperand : AsmOperandClass {
2325   let Name = "Prefetch";
2326   let ParserMethod = "tryParsePrefetch";
2327 }
2328 def prfop : Operand<i32> {
2329   let PrintMethod = "printPrefetchOp";
2330   let ParserMatchClass = PrefetchOperand;
2331 }
2332
2333 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2334 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2335     : BaseLoadStoreUI<sz, V, opc,
2336                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2337                       asm, pat>,
2338       Sched<[WriteLD]>;
2339
2340 //---
2341 // Load literal
2342 //---
2343
2344 // Load literal address: 19-bit immediate. The low two bits of the target
2345 // offset are implied zero and so are not part of the immediate.
2346 def am_ldrlit : Operand<OtherVT> {
2347   let EncoderMethod = "getLoadLiteralOpValue";
2348   let DecoderMethod = "DecodePCRelLabel19";
2349   let PrintMethod = "printAlignedLabel";
2350   let ParserMatchClass = PCRelLabel19Operand;
2351 }
2352
2353 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2354 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2355     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2356         asm, "\t$Rt, $label", "", []>,
2357       Sched<[WriteLD]> {
2358   bits<5> Rt;
2359   bits<19> label;
2360   let Inst{31-30} = opc;
2361   let Inst{29-27} = 0b011;
2362   let Inst{26}    = V;
2363   let Inst{25-24} = 0b00;
2364   let Inst{23-5}  = label;
2365   let Inst{4-0}   = Rt;
2366 }
2367
2368 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2369 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2370     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2371         asm, "\t$Rt, $label", "", pat>,
2372       Sched<[WriteLD]> {
2373   bits<5> Rt;
2374   bits<19> label;
2375   let Inst{31-30} = opc;
2376   let Inst{29-27} = 0b011;
2377   let Inst{26}    = V;
2378   let Inst{25-24} = 0b00;
2379   let Inst{23-5}  = label;
2380   let Inst{4-0}   = Rt;
2381 }
2382
2383 //---
2384 // Load/store register offset
2385 //---
2386
2387 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2388 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2389 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2390 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2391 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2392
2393 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2394 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2395 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2396 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2397 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2398
2399 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2400   let Name = "Mem" # Reg # "Extend" # Width;
2401   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2402   let RenderMethod = "addMemExtendOperands";
2403   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2404 }
2405
2406 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2407   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2408   // the trivial shift.
2409   let RenderMethod = "addMemExtend8Operands";
2410 }
2411 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2412 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2413 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2414 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2415
2416 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2417   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2418   // the trivial shift.
2419   let RenderMethod = "addMemExtend8Operands";
2420 }
2421 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2422 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2423 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2424 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2425
2426 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2427         : Operand<i32> {
2428   let ParserMatchClass = ParserClass;
2429   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2430   let DecoderMethod = "DecodeMemExtend";
2431   let EncoderMethod = "getMemExtendOpValue";
2432   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2433 }
2434
2435 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2436 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2437 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2438 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2439 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2440
2441 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2442 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2443 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2444 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2445 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2446
2447 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2448                   Operand wextend, Operand xextend>  {
2449   // CodeGen-level pattern covering the entire addressing mode.
2450   ComplexPattern Wpat = windex;
2451   ComplexPattern Xpat = xindex;
2452
2453   // Asm-level Operand covering the valid "uxtw #3" style syntax.
2454   Operand Wext = wextend;
2455   Operand Xext = xextend;
2456 }
2457
2458 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2459 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2460 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2461 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2462 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2463                        ro_Xextend128>;
2464
2465 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2466                       string asm, dag ins, dag outs, list<dag> pat>
2467     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2468   bits<5> Rt;
2469   bits<5> Rn;
2470   bits<5> Rm;
2471   bits<2> extend;
2472   let Inst{31-30} = sz;
2473   let Inst{29-27} = 0b111;
2474   let Inst{26}    = V;
2475   let Inst{25-24} = 0b00;
2476   let Inst{23-22} = opc;
2477   let Inst{21}    = 1;
2478   let Inst{20-16} = Rm;
2479   let Inst{15}    = extend{1}; // sign extend Rm?
2480   let Inst{14}    = 1;
2481   let Inst{12}    = extend{0}; // do shift?
2482   let Inst{11-10} = 0b10;
2483   let Inst{9-5}   = Rn;
2484   let Inst{4-0}   = Rt;
2485 }
2486
2487 class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2488   : InstAlias<asm # " $Rt, [$Rn, $Rm]",
2489               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2490
2491 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2492                    string asm, ValueType Ty, SDPatternOperator loadop> {
2493   let AddedComplexity = 10 in
2494   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2495                  (outs regtype:$Rt),
2496                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2497                  [(set (Ty regtype:$Rt),
2498                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2499                                              ro_Wextend8:$extend)))]>,
2500            Sched<[WriteLDIdx, ReadAdrBase]> {
2501     let Inst{13} = 0b0;
2502   }
2503
2504   let AddedComplexity = 10 in
2505   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2506                  (outs regtype:$Rt),
2507                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2508                  [(set (Ty regtype:$Rt),
2509                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2510                                              ro_Xextend8:$extend)))]>,
2511            Sched<[WriteLDIdx, ReadAdrBase]> {
2512     let Inst{13} = 0b1;
2513   }
2514
2515   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2516 }
2517
2518 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2519                     string asm, ValueType Ty, SDPatternOperator storeop> {
2520   let AddedComplexity = 10 in
2521   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2522                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2523                  [(storeop (Ty regtype:$Rt),
2524                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2525                                          ro_Wextend8:$extend))]>,
2526             Sched<[WriteSTIdx, ReadAdrBase]> {
2527     let Inst{13} = 0b0;
2528   }
2529
2530   let AddedComplexity = 10 in
2531   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2532                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2533                  [(storeop (Ty regtype:$Rt),
2534                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2535                                          ro_Xextend8:$extend))]>,
2536             Sched<[WriteSTIdx, ReadAdrBase]> {
2537     let Inst{13} = 0b1;
2538   }
2539
2540   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2541 }
2542
2543 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2544                       string asm, dag ins, dag outs, list<dag> pat>
2545     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2546   bits<5> Rt;
2547   bits<5> Rn;
2548   bits<5> Rm;
2549   bits<2> extend;
2550   let Inst{31-30} = sz;
2551   let Inst{29-27} = 0b111;
2552   let Inst{26}    = V;
2553   let Inst{25-24} = 0b00;
2554   let Inst{23-22} = opc;
2555   let Inst{21}    = 1;
2556   let Inst{20-16} = Rm;
2557   let Inst{15}    = extend{1}; // sign extend Rm?
2558   let Inst{14}    = 1;
2559   let Inst{12}    = extend{0}; // do shift?
2560   let Inst{11-10} = 0b10;
2561   let Inst{9-5}   = Rn;
2562   let Inst{4-0}   = Rt;
2563 }
2564
2565 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2566                     string asm, ValueType Ty, SDPatternOperator loadop> {
2567   let AddedComplexity = 10 in
2568   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2569                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2570                  [(set (Ty regtype:$Rt),
2571                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2572                                               ro_Wextend16:$extend)))]>,
2573             Sched<[WriteLDIdx, ReadAdrBase]> {
2574     let Inst{13} = 0b0;
2575   }
2576
2577   let AddedComplexity = 10 in
2578   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2579                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2580                  [(set (Ty regtype:$Rt),
2581                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2582                                              ro_Xextend16:$extend)))]>,
2583             Sched<[WriteLDIdx, ReadAdrBase]> {
2584     let Inst{13} = 0b1;
2585   }
2586
2587   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2588 }
2589
2590 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2591                      string asm, ValueType Ty, SDPatternOperator storeop> {
2592   let AddedComplexity = 10 in
2593   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2594                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2595                 [(storeop (Ty regtype:$Rt),
2596                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2597                                          ro_Wextend16:$extend))]>,
2598            Sched<[WriteSTIdx, ReadAdrBase]> {
2599     let Inst{13} = 0b0;
2600   }
2601
2602   let AddedComplexity = 10 in
2603   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2604                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2605                 [(storeop (Ty regtype:$Rt),
2606                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2607                                          ro_Xextend16:$extend))]>,
2608            Sched<[WriteSTIdx, ReadAdrBase]> {
2609     let Inst{13} = 0b1;
2610   }
2611
2612   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2613 }
2614
2615 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2616                       string asm, dag ins, dag outs, list<dag> pat>
2617     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2618   bits<5> Rt;
2619   bits<5> Rn;
2620   bits<5> Rm;
2621   bits<2> extend;
2622   let Inst{31-30} = sz;
2623   let Inst{29-27} = 0b111;
2624   let Inst{26}    = V;
2625   let Inst{25-24} = 0b00;
2626   let Inst{23-22} = opc;
2627   let Inst{21}    = 1;
2628   let Inst{20-16} = Rm;
2629   let Inst{15}    = extend{1}; // sign extend Rm?
2630   let Inst{14}    = 1;
2631   let Inst{12}    = extend{0}; // do shift?
2632   let Inst{11-10} = 0b10;
2633   let Inst{9-5}   = Rn;
2634   let Inst{4-0}   = Rt;
2635 }
2636
2637 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2638                     string asm, ValueType Ty, SDPatternOperator loadop> {
2639   let AddedComplexity = 10 in
2640   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2641                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2642                  [(set (Ty regtype:$Rt),
2643                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2644                                               ro_Wextend32:$extend)))]>,
2645            Sched<[WriteLDIdx, ReadAdrBase]> {
2646     let Inst{13} = 0b0;
2647   }
2648
2649   let AddedComplexity = 10 in
2650   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2651                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2652                  [(set (Ty regtype:$Rt),
2653                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2654                                               ro_Xextend32:$extend)))]>,
2655            Sched<[WriteLDIdx, ReadAdrBase]> {
2656     let Inst{13} = 0b1;
2657   }
2658
2659   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2660 }
2661
2662 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2663                      string asm, ValueType Ty, SDPatternOperator storeop> {
2664   let AddedComplexity = 10 in
2665   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2666                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2667                 [(storeop (Ty regtype:$Rt),
2668                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2669                                          ro_Wextend32:$extend))]>,
2670             Sched<[WriteSTIdx, ReadAdrBase]> {
2671     let Inst{13} = 0b0;
2672   }
2673
2674   let AddedComplexity = 10 in
2675   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2676                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2677                 [(storeop (Ty regtype:$Rt),
2678                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2679                                         ro_Xextend32:$extend))]>,
2680             Sched<[WriteSTIdx, ReadAdrBase]> {
2681     let Inst{13} = 0b1;
2682   }
2683
2684   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2685 }
2686
2687 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2688                       string asm, dag ins, dag outs, list<dag> pat>
2689     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2690   bits<5> Rt;
2691   bits<5> Rn;
2692   bits<5> Rm;
2693   bits<2> extend;
2694   let Inst{31-30} = sz;
2695   let Inst{29-27} = 0b111;
2696   let Inst{26}    = V;
2697   let Inst{25-24} = 0b00;
2698   let Inst{23-22} = opc;
2699   let Inst{21}    = 1;
2700   let Inst{20-16} = Rm;
2701   let Inst{15}    = extend{1}; // sign extend Rm?
2702   let Inst{14}    = 1;
2703   let Inst{12}    = extend{0}; // do shift?
2704   let Inst{11-10} = 0b10;
2705   let Inst{9-5}   = Rn;
2706   let Inst{4-0}   = Rt;
2707 }
2708
2709 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2710                     string asm, ValueType Ty, SDPatternOperator loadop> {
2711   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2712   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2713                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2714                 [(set (Ty regtype:$Rt),
2715                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2716                                              ro_Wextend64:$extend)))]>,
2717            Sched<[WriteLDIdx, ReadAdrBase]> {
2718     let Inst{13} = 0b0;
2719   }
2720
2721   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2722   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2723                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2724                  [(set (Ty regtype:$Rt),
2725                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2726                                               ro_Xextend64:$extend)))]>,
2727            Sched<[WriteLDIdx, ReadAdrBase]> {
2728     let Inst{13} = 0b1;
2729   }
2730
2731   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2732 }
2733
2734 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2735                      string asm, ValueType Ty, SDPatternOperator storeop> {
2736   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2737   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2738                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2739                 [(storeop (Ty regtype:$Rt),
2740                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2741                                          ro_Wextend64:$extend))]>,
2742             Sched<[WriteSTIdx, ReadAdrBase]> {
2743     let Inst{13} = 0b0;
2744   }
2745
2746   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2747   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2748                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2749                 [(storeop (Ty regtype:$Rt),
2750                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2751                                          ro_Xextend64:$extend))]>,
2752             Sched<[WriteSTIdx, ReadAdrBase]> {
2753     let Inst{13} = 0b1;
2754   }
2755
2756   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2757 }
2758
2759 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2760                       string asm, dag ins, dag outs, list<dag> pat>
2761     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2762   bits<5> Rt;
2763   bits<5> Rn;
2764   bits<5> Rm;
2765   bits<2> extend;
2766   let Inst{31-30} = sz;
2767   let Inst{29-27} = 0b111;
2768   let Inst{26}    = V;
2769   let Inst{25-24} = 0b00;
2770   let Inst{23-22} = opc;
2771   let Inst{21}    = 1;
2772   let Inst{20-16} = Rm;
2773   let Inst{15}    = extend{1}; // sign extend Rm?
2774   let Inst{14}    = 1;
2775   let Inst{12}    = extend{0}; // do shift?
2776   let Inst{11-10} = 0b10;
2777   let Inst{9-5}   = Rn;
2778   let Inst{4-0}   = Rt;
2779 }
2780
2781 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2782                      string asm, ValueType Ty, SDPatternOperator loadop> {
2783   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2784   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2785                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2786                  [(set (Ty regtype:$Rt),
2787                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2788                                                ro_Wextend128:$extend)))]>,
2789             Sched<[WriteLDIdx, ReadAdrBase]> {
2790     let Inst{13} = 0b0;
2791   }
2792
2793   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2794   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2795                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2796                  [(set (Ty regtype:$Rt),
2797                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2798                                                ro_Xextend128:$extend)))]>,
2799             Sched<[WriteLDIdx, ReadAdrBase]> {
2800     let Inst{13} = 0b1;
2801   }
2802
2803   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2804 }
2805
2806 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2807                       string asm, ValueType Ty, SDPatternOperator storeop> {
2808   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2809   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2810                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2811                 [(storeop (Ty regtype:$Rt),
2812                           (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2813                                           ro_Wextend128:$extend))]>,
2814             Sched<[WriteSTIdx, ReadAdrBase]> {
2815     let Inst{13} = 0b0;
2816   }
2817
2818   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2819   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2820                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2821                 [(storeop (Ty regtype:$Rt),
2822                           (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2823                                           ro_Xextend128:$extend))]>,
2824             Sched<[WriteSTIdx, ReadAdrBase]> {
2825     let Inst{13} = 0b1;
2826   }
2827
2828   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2829 }
2830
2831 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2832 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2833                      string asm, list<dag> pat>
2834     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2835       Sched<[WriteLD]> {
2836   bits<5> Rt;
2837   bits<5> Rn;
2838   bits<5> Rm;
2839   bits<2> extend;
2840   let Inst{31-30} = sz;
2841   let Inst{29-27} = 0b111;
2842   let Inst{26}    = V;
2843   let Inst{25-24} = 0b00;
2844   let Inst{23-22} = opc;
2845   let Inst{21}    = 1;
2846   let Inst{20-16} = Rm;
2847   let Inst{15}    = extend{1}; // sign extend Rm?
2848   let Inst{14}    = 1;
2849   let Inst{12}    = extend{0}; // do shift?
2850   let Inst{11-10} = 0b10;
2851   let Inst{9-5}   = Rn;
2852   let Inst{4-0}   = Rt;
2853 }
2854
2855 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2856   def roW : BasePrefetchRO<sz, V, opc, (outs),
2857                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2858                 asm, [(AArch64Prefetch imm:$Rt,
2859                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2860                                                     ro_Wextend64:$extend))]> {
2861     let Inst{13} = 0b0;
2862   }
2863
2864   def roX : BasePrefetchRO<sz, V, opc, (outs),
2865                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2866                 asm,  [(AArch64Prefetch imm:$Rt,
2867                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2868                                                      ro_Xextend64:$extend))]> {
2869     let Inst{13} = 0b1;
2870   }
2871
2872   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2873                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2874                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2875 }
2876
2877 //---
2878 // Load/store unscaled immediate
2879 //---
2880
2881 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2882 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2883 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2884 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2885 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2886
2887 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2888                            string asm, list<dag> pattern>
2889     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2890   bits<5> Rt;
2891   bits<5> Rn;
2892   bits<9> offset;
2893   let Inst{31-30} = sz;
2894   let Inst{29-27} = 0b111;
2895   let Inst{26}    = V;
2896   let Inst{25-24} = 0b00;
2897   let Inst{23-22} = opc;
2898   let Inst{21}    = 0;
2899   let Inst{20-12} = offset;
2900   let Inst{11-10} = 0b00;
2901   let Inst{9-5}   = Rn;
2902   let Inst{4-0}   = Rt;
2903
2904   let DecoderMethod = "DecodeSignedLdStInstruction";
2905 }
2906
2907 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2908                    string asm, list<dag> pattern> {
2909   let AddedComplexity = 1 in // try this before LoadUI
2910   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2911                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
2912           Sched<[WriteLD]>;
2913
2914   def : InstAlias<asm # " $Rt, [$Rn]",
2915                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2916 }
2917
2918 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2919                          string asm, list<dag> pattern> {
2920   let AddedComplexity = 1 in // try this before StoreUI
2921   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
2922                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
2923                                asm, pattern>,
2924           Sched<[WriteST]>;
2925
2926   def : InstAlias<asm # " $Rt, [$Rn]",
2927                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2928 }
2929
2930 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
2931                             list<dag> pat> {
2932   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2933   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
2934                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
2935                                asm, pat>,
2936           Sched<[WriteLD]>;
2937
2938   def : InstAlias<asm # " $Rt, [$Rn]",
2939                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
2940 }
2941
2942 //---
2943 // Load/store unscaled immediate, unprivileged
2944 //---
2945
2946 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2947                                 dag oops, dag iops, string asm>
2948     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
2949   bits<5> Rt;
2950   bits<5> Rn;
2951   bits<9> offset;
2952   let Inst{31-30} = sz;
2953   let Inst{29-27} = 0b111;
2954   let Inst{26}    = V;
2955   let Inst{25-24} = 0b00;
2956   let Inst{23-22} = opc;
2957   let Inst{21}    = 0;
2958   let Inst{20-12} = offset;
2959   let Inst{11-10} = 0b10;
2960   let Inst{9-5}   = Rn;
2961   let Inst{4-0}   = Rt;
2962
2963   let DecoderMethod = "DecodeSignedLdStInstruction";
2964 }
2965
2966 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
2967                             RegisterClass regtype, string asm> {
2968   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
2969   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
2970                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
2971           Sched<[WriteLD]>;
2972
2973   def : InstAlias<asm # " $Rt, [$Rn]",
2974                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2975 }
2976
2977 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2978                              RegisterClass regtype, string asm> {
2979   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2980   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
2981                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
2982                                  asm>,
2983           Sched<[WriteST]>;
2984
2985   def : InstAlias<asm # " $Rt, [$Rn]",
2986                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2987 }
2988
2989 //---
2990 // Load/store pre-indexed
2991 //---
2992
2993 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2994                           string asm, string cstr, list<dag> pat>
2995     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
2996   bits<5> Rt;
2997   bits<5> Rn;
2998   bits<9> offset;
2999   let Inst{31-30} = sz;
3000   let Inst{29-27} = 0b111;
3001   let Inst{26}    = V;
3002   let Inst{25-24} = 0;
3003   let Inst{23-22} = opc;
3004   let Inst{21}    = 0;
3005   let Inst{20-12} = offset;
3006   let Inst{11-10} = 0b11;
3007   let Inst{9-5}   = Rn;
3008   let Inst{4-0}   = Rt;
3009
3010   let DecoderMethod = "DecodeSignedLdStInstruction";
3011 }
3012
3013 let hasSideEffects = 0 in {
3014 let mayStore = 0, mayLoad = 1 in
3015 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3016              string asm>
3017     : BaseLoadStorePreIdx<sz, V, opc,
3018                      (outs GPR64sp:$wback, regtype:$Rt),
3019                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3020                      "$Rn = $wback,@earlyclobber $wback", []>,
3021       Sched<[WriteLD, WriteAdr]>;
3022
3023 let mayStore = 1, mayLoad = 0 in
3024 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3025                   string asm, SDPatternOperator storeop, ValueType Ty>
3026     : BaseLoadStorePreIdx<sz, V, opc,
3027                       (outs GPR64sp:$wback),
3028                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3029                       asm, "$Rn = $wback,@earlyclobber $wback",
3030       [(set GPR64sp:$wback,
3031             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3032       Sched<[WriteAdr, WriteST]>;
3033 } // hasSideEffects = 0
3034
3035 //---
3036 // Load/store post-indexed
3037 //---
3038
3039 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3040                           string asm, string cstr, list<dag> pat>
3041     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3042   bits<5> Rt;
3043   bits<5> Rn;
3044   bits<9> offset;
3045   let Inst{31-30} = sz;
3046   let Inst{29-27} = 0b111;
3047   let Inst{26}    = V;
3048   let Inst{25-24} = 0b00;
3049   let Inst{23-22} = opc;
3050   let Inst{21}    = 0b0;
3051   let Inst{20-12} = offset;
3052   let Inst{11-10} = 0b01;
3053   let Inst{9-5}   = Rn;
3054   let Inst{4-0}   = Rt;
3055
3056   let DecoderMethod = "DecodeSignedLdStInstruction";
3057 }
3058
3059 let hasSideEffects = 0 in {
3060 let mayStore = 0, mayLoad = 1 in
3061 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3062              string asm>
3063     : BaseLoadStorePostIdx<sz, V, opc,
3064                       (outs GPR64sp:$wback, regtype:$Rt),
3065                       (ins GPR64sp:$Rn, simm9:$offset),
3066                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3067       Sched<[WriteLD, WriteI]>;
3068
3069 let mayStore = 1, mayLoad = 0 in
3070 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3071                    string asm, SDPatternOperator storeop, ValueType Ty>
3072     : BaseLoadStorePostIdx<sz, V, opc,
3073                       (outs GPR64sp:$wback),
3074                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3075                        asm, "$Rn = $wback,@earlyclobber $wback",
3076       [(set GPR64sp:$wback,
3077             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3078     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3079 } // hasSideEffects = 0
3080
3081
3082 //---
3083 // Load/store pair
3084 //---
3085
3086 // (indexed, offset)
3087
3088 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3089                               string asm>
3090     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3091   bits<5> Rt;
3092   bits<5> Rt2;
3093   bits<5> Rn;
3094   bits<7> offset;
3095   let Inst{31-30} = opc;
3096   let Inst{29-27} = 0b101;
3097   let Inst{26}    = V;
3098   let Inst{25-23} = 0b010;
3099   let Inst{22}    = L;
3100   let Inst{21-15} = offset;
3101   let Inst{14-10} = Rt2;
3102   let Inst{9-5}   = Rn;
3103   let Inst{4-0}   = Rt;
3104
3105   let DecoderMethod = "DecodePairLdStInstruction";
3106 }
3107
3108 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3109                           Operand indextype, string asm> {
3110   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3111   def i : BaseLoadStorePairOffset<opc, V, 1,
3112                                   (outs regtype:$Rt, regtype:$Rt2),
3113                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3114           Sched<[WriteLD, WriteLDHi]>;
3115
3116   def : InstAlias<asm # " $Rt, $Rt2, [$Rn]",
3117                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3118                                                   GPR64sp:$Rn, 0)>;
3119 }
3120
3121
3122 multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3123                            Operand indextype, string asm> {
3124   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3125   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3126                                   (ins regtype:$Rt, regtype:$Rt2,
3127                                        GPR64sp:$Rn, indextype:$offset),
3128                                   asm>,
3129           Sched<[WriteSTP]>;
3130
3131   def : InstAlias<asm # " $Rt, $Rt2, [$Rn]",
3132                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3133                                                   GPR64sp:$Rn, 0)>;
3134 }
3135
3136 // (pre-indexed)
3137 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3138                               string asm>
3139     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3140   bits<5> Rt;
3141   bits<5> Rt2;
3142   bits<5> Rn;
3143   bits<7> offset;
3144   let Inst{31-30} = opc;
3145   let Inst{29-27} = 0b101;
3146   let Inst{26}    = V;
3147   let Inst{25-23} = 0b011;
3148   let Inst{22}    = L;
3149   let Inst{21-15} = offset;
3150   let Inst{14-10} = Rt2;
3151   let Inst{9-5}   = Rn;
3152   let Inst{4-0}   = Rt;
3153
3154   let DecoderMethod = "DecodePairLdStInstruction";
3155 }
3156
3157 let hasSideEffects = 0 in {
3158 let mayStore = 0, mayLoad = 1 in
3159 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3160                      Operand indextype, string asm>
3161     : BaseLoadStorePairPreIdx<opc, V, 1,
3162                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3163                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3164       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3165
3166 let mayStore = 1, mayLoad = 0 in
3167 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3168                       Operand indextype, string asm>
3169     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3170                              (ins regtype:$Rt, regtype:$Rt2,
3171                                   GPR64sp:$Rn, indextype:$offset),
3172                              asm>,
3173       Sched<[WriteAdr, WriteSTP]>;
3174 } // hasSideEffects = 0
3175
3176 // (post-indexed)
3177
3178 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3179                               string asm>
3180     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3181   bits<5> Rt;
3182   bits<5> Rt2;
3183   bits<5> Rn;
3184   bits<7> offset;
3185   let Inst{31-30} = opc;
3186   let Inst{29-27} = 0b101;
3187   let Inst{26}    = V;
3188   let Inst{25-23} = 0b001;
3189   let Inst{22}    = L;
3190   let Inst{21-15} = offset;
3191   let Inst{14-10} = Rt2;
3192   let Inst{9-5}   = Rn;
3193   let Inst{4-0}   = Rt;
3194
3195   let DecoderMethod = "DecodePairLdStInstruction";
3196 }
3197
3198 let hasSideEffects = 0 in {
3199 let mayStore = 0, mayLoad = 1 in
3200 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3201                       Operand idxtype, string asm>
3202     : BaseLoadStorePairPostIdx<opc, V, 1,
3203                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3204                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3205       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3206
3207 let mayStore = 1, mayLoad = 0 in
3208 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3209                        Operand idxtype, string asm>
3210     : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
3211                              (ins GPR64sp:$wback, regtype:$Rt, regtype:$Rt2,
3212                                   GPR64sp:$Rn, idxtype:$offset),
3213                              asm>,
3214       Sched<[WriteAdr, WriteSTP]>;
3215 } // hasSideEffects = 0
3216
3217 //  (no-allocate)
3218
3219 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3220                               string asm>
3221     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3222   bits<5> Rt;
3223   bits<5> Rt2;
3224   bits<5> Rn;
3225   bits<7> offset;
3226   let Inst{31-30} = opc;
3227   let Inst{29-27} = 0b101;
3228   let Inst{26}    = V;
3229   let Inst{25-23} = 0b000;
3230   let Inst{22}    = L;
3231   let Inst{21-15} = offset;
3232   let Inst{14-10} = Rt2;
3233   let Inst{9-5}   = Rn;
3234   let Inst{4-0}   = Rt;
3235
3236   let DecoderMethod = "DecodePairLdStInstruction";
3237 }
3238
3239 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3240                            Operand indextype, string asm> {
3241   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3242   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3243                                    (outs regtype:$Rt, regtype:$Rt2),
3244                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3245           Sched<[WriteLD, WriteLDHi]>;
3246
3247
3248   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3249                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3250                                                   GPR64sp:$Rn, 0)>;
3251 }
3252
3253 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3254                       Operand indextype, string asm> {
3255   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3256   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3257                                    (ins regtype:$Rt, regtype:$Rt2,
3258                                         GPR64sp:$Rn, indextype:$offset),
3259                                    asm>,
3260           Sched<[WriteSTP]>;
3261
3262   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3263                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3264                                                   GPR64sp:$Rn, 0)>;
3265 }
3266
3267 //---
3268 // Load/store exclusive
3269 //---
3270
3271 // True exclusive operations write to and/or read from the system's exclusive
3272 // monitors, which as far as a compiler is concerned can be modelled as a
3273 // random shared memory address. Hence LoadExclusive mayStore.
3274 //
3275 // Since these instructions have the undefined register bits set to 1 in
3276 // their canonical form, we need a post encoder method to set those bits
3277 // to 1 when encoding these instructions. We do this using the
3278 // fixLoadStoreExclusive function. This function has template parameters:
3279 //
3280 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3281 //
3282 // hasRs indicates that the instruction uses the Rs field, so we won't set
3283 // it to 1 (and the same for Rt2). We don't need template parameters for
3284 // the other register fields since Rt and Rn are always used.
3285 //
3286 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3287 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3288                              dag oops, dag iops, string asm, string operands>
3289     : I<oops, iops, asm, operands, "", []> {
3290   let Inst{31-30} = sz;
3291   let Inst{29-24} = 0b001000;
3292   let Inst{23}    = o2;
3293   let Inst{22}    = L;
3294   let Inst{21}    = o1;
3295   let Inst{15}    = o0;
3296
3297   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3298 }
3299
3300 // Neither Rs nor Rt2 operands.
3301 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3302                                dag oops, dag iops, string asm, string operands>
3303     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3304   bits<5> Rt;
3305   bits<5> Rn;
3306   let Inst{20-16} = 0b11111;
3307   let Unpredictable{20-16} = 0b11111;
3308   let Inst{14-10} = 0b11111;
3309   let Unpredictable{14-10} = 0b11111;
3310   let Inst{9-5} = Rn;
3311   let Inst{4-0} = Rt;
3312
3313   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3314 }
3315
3316 // Simple load acquires don't set the exclusive monitor
3317 let mayLoad = 1, mayStore = 0 in
3318 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3319                   RegisterClass regtype, string asm>
3320     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3321                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3322       Sched<[WriteLD]>;
3323
3324 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3325                     RegisterClass regtype, string asm>
3326     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3327                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3328       Sched<[WriteLD]>;
3329
3330 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3331                        RegisterClass regtype, string asm>
3332     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3333                              (outs regtype:$Rt, regtype:$Rt2),
3334                              (ins GPR64sp0:$Rn), asm,
3335                              "\t$Rt, $Rt2, [$Rn]">,
3336       Sched<[WriteLD, WriteLDHi]> {
3337   bits<5> Rt;
3338   bits<5> Rt2;
3339   bits<5> Rn;
3340   let Inst{14-10} = Rt2;
3341   let Inst{9-5} = Rn;
3342   let Inst{4-0} = Rt;
3343
3344   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3345 }
3346
3347 // Simple store release operations do not check the exclusive monitor.
3348 let mayLoad = 0, mayStore = 1 in
3349 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3350                    RegisterClass regtype, string asm>
3351     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3352                                (ins regtype:$Rt, GPR64sp0:$Rn),
3353                                asm, "\t$Rt, [$Rn]">,
3354       Sched<[WriteST]>;
3355
3356 let mayLoad = 1, mayStore = 1 in
3357 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3358                      RegisterClass regtype, string asm>
3359     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3360                              (ins regtype:$Rt, GPR64sp0:$Rn),
3361                              asm, "\t$Ws, $Rt, [$Rn]">,
3362       Sched<[WriteSTX]> {
3363   bits<5> Ws;
3364   bits<5> Rt;
3365   bits<5> Rn;
3366   let Inst{20-16} = Ws;
3367   let Inst{9-5} = Rn;
3368   let Inst{4-0} = Rt;
3369
3370   let Constraints = "@earlyclobber $Ws";
3371   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3372 }
3373
3374 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3375                          RegisterClass regtype, string asm>
3376     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3377                              (outs GPR32:$Ws),
3378                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3379                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3380       Sched<[WriteSTX]> {
3381   bits<5> Ws;
3382   bits<5> Rt;
3383   bits<5> Rt2;
3384   bits<5> Rn;
3385   let Inst{20-16} = Ws;
3386   let Inst{14-10} = Rt2;
3387   let Inst{9-5} = Rn;
3388   let Inst{4-0} = Rt;
3389
3390   let Constraints = "@earlyclobber $Ws";
3391 }
3392
3393 //---
3394 // Exception generation
3395 //---
3396
3397 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3398 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3399     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3400       Sched<[WriteSys]> {
3401   bits<16> imm;
3402   let Inst{31-24} = 0b11010100;
3403   let Inst{23-21} = op1;
3404   let Inst{20-5}  = imm;
3405   let Inst{4-2}   = 0b000;
3406   let Inst{1-0}   = ll;
3407 }
3408
3409 let Predicates = [HasFPARMv8] in {
3410
3411 //---
3412 // Floating point to integer conversion
3413 //---
3414
3415 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3416                       RegisterClass srcType, RegisterClass dstType,
3417                       string asm, list<dag> pattern>
3418     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3419          asm, "\t$Rd, $Rn", "", pattern>,
3420       Sched<[WriteFCvt]> {
3421   bits<5> Rd;
3422   bits<5> Rn;
3423   let Inst{30-29} = 0b00;
3424   let Inst{28-24} = 0b11110;
3425   let Inst{23-22} = type;
3426   let Inst{21}    = 1;
3427   let Inst{20-19} = rmode;
3428   let Inst{18-16} = opcode;
3429   let Inst{15-10} = 0;
3430   let Inst{9-5}   = Rn;
3431   let Inst{4-0}   = Rd;
3432 }
3433
3434 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3435 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3436                       RegisterClass srcType, RegisterClass dstType,
3437                       Operand immType, string asm, list<dag> pattern>
3438     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3439          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3440       Sched<[WriteFCvt]> {
3441   bits<5> Rd;
3442   bits<5> Rn;
3443   bits<6> scale;
3444   let Inst{30-29} = 0b00;
3445   let Inst{28-24} = 0b11110;
3446   let Inst{23-22} = type;
3447   let Inst{21}    = 0;
3448   let Inst{20-19} = rmode;
3449   let Inst{18-16} = opcode;
3450   let Inst{15-10} = scale;
3451   let Inst{9-5}   = Rn;
3452   let Inst{4-0}   = Rd;
3453 }
3454
3455 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3456            SDPatternOperator OpN> {
3457   // Unscaled single-precision to 32-bit
3458   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3459                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3460     let Inst{31} = 0; // 32-bit GPR flag
3461   }
3462
3463   // Unscaled single-precision to 64-bit
3464   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3465                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3466     let Inst{31} = 1; // 64-bit GPR flag
3467   }
3468
3469   // Unscaled double-precision to 32-bit
3470   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3471                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3472     let Inst{31} = 0; // 32-bit GPR flag
3473   }
3474
3475   // Unscaled double-precision to 64-bit
3476   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3477                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3478     let Inst{31} = 1; // 64-bit GPR flag
3479   }
3480 }
3481
3482 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3483                              SDPatternOperator OpN> {
3484   // Scaled single-precision to 32-bit
3485   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3486                               fixedpoint_f32_i32, asm,
3487               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3488                                           fixedpoint_f32_i32:$scale)))]> {
3489     let Inst{31} = 0; // 32-bit GPR flag
3490     let scale{5} = 1;
3491   }
3492
3493   // Scaled single-precision to 64-bit
3494   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3495                               fixedpoint_f32_i64, asm,
3496               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3497                                           fixedpoint_f32_i64:$scale)))]> {
3498     let Inst{31} = 1; // 64-bit GPR flag
3499   }
3500
3501   // Scaled double-precision to 32-bit
3502   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3503                               fixedpoint_f64_i32, asm,
3504               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3505                                           fixedpoint_f64_i32:$scale)))]> {
3506     let Inst{31} = 0; // 32-bit GPR flag
3507     let scale{5} = 1;
3508   }
3509
3510   // Scaled double-precision to 64-bit
3511   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3512                               fixedpoint_f64_i64, asm,
3513               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3514                                           fixedpoint_f64_i64:$scale)))]> {
3515     let Inst{31} = 1; // 64-bit GPR flag
3516   }
3517 }
3518
3519 //---
3520 // Integer to floating point conversion
3521 //---
3522
3523 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3524 class BaseIntegerToFP<bit isUnsigned,
3525                       RegisterClass srcType, RegisterClass dstType,
3526                       Operand immType, string asm, list<dag> pattern>
3527     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3528          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3529       Sched<[WriteFCvt]> {
3530   bits<5> Rd;
3531   bits<5> Rn;
3532   bits<6> scale;
3533   let Inst{30-23} = 0b00111100;
3534   let Inst{21-17} = 0b00001;
3535   let Inst{16}    = isUnsigned;
3536   let Inst{15-10} = scale;
3537   let Inst{9-5}   = Rn;
3538   let Inst{4-0}   = Rd;
3539 }
3540
3541 class BaseIntegerToFPUnscaled<bit isUnsigned,
3542                       RegisterClass srcType, RegisterClass dstType,
3543                       ValueType dvt, string asm, SDNode node>
3544     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3545          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3546       Sched<[WriteFCvt]> {
3547   bits<5> Rd;
3548   bits<5> Rn;
3549   bits<6> scale;
3550   let Inst{30-23} = 0b00111100;
3551   let Inst{21-17} = 0b10001;
3552   let Inst{16}    = isUnsigned;
3553   let Inst{15-10} = 0b000000;
3554   let Inst{9-5}   = Rn;
3555   let Inst{4-0}   = Rd;
3556 }
3557
3558 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3559   // Unscaled
3560   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3561     let Inst{31} = 0; // 32-bit GPR flag
3562     let Inst{22} = 0; // 32-bit FPR flag
3563   }
3564
3565   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3566     let Inst{31} = 0; // 32-bit GPR flag
3567     let Inst{22} = 1; // 64-bit FPR flag
3568   }
3569
3570   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3571     let Inst{31} = 1; // 64-bit GPR flag
3572     let Inst{22} = 0; // 32-bit FPR flag
3573   }
3574
3575   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3576     let Inst{31} = 1; // 64-bit GPR flag
3577     let Inst{22} = 1; // 64-bit FPR flag
3578   }
3579
3580   // Scaled
3581   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3582                              [(set FPR32:$Rd,
3583                                    (fdiv (node GPR32:$Rn),
3584                                          fixedpoint_f32_i32:$scale))]> {
3585     let Inst{31} = 0; // 32-bit GPR flag
3586     let Inst{22} = 0; // 32-bit FPR flag
3587     let scale{5} = 1;
3588   }
3589
3590   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3591                              [(set FPR64:$Rd,
3592                                    (fdiv (node GPR32:$Rn),
3593                                          fixedpoint_f64_i32:$scale))]> {
3594     let Inst{31} = 0; // 32-bit GPR flag
3595     let Inst{22} = 1; // 64-bit FPR flag
3596     let scale{5} = 1;
3597   }
3598
3599   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3600                              [(set FPR32:$Rd,
3601                                    (fdiv (node GPR64:$Rn),
3602                                          fixedpoint_f32_i64:$scale))]> {
3603     let Inst{31} = 1; // 64-bit GPR flag
3604     let Inst{22} = 0; // 32-bit FPR flag
3605   }
3606
3607   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3608                              [(set FPR64:$Rd,
3609                                    (fdiv (node GPR64:$Rn),
3610                                          fixedpoint_f64_i64:$scale))]> {
3611     let Inst{31} = 1; // 64-bit GPR flag
3612     let Inst{22} = 1; // 64-bit FPR flag
3613   }
3614 }
3615
3616 //---
3617 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3618 //---
3619
3620 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3621 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3622                       RegisterClass srcType, RegisterClass dstType,
3623                       string asm>
3624     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3625         // We use COPY_TO_REGCLASS for these bitconvert operations.
3626         // copyPhysReg() expands the resultant COPY instructions after
3627         // regalloc is done. This gives greater freedom for the allocator
3628         // and related passes (coalescing, copy propagation, et. al.) to
3629         // be more effective.
3630         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3631       Sched<[WriteFCopy]> {
3632   bits<5> Rd;
3633   bits<5> Rn;
3634   let Inst{30-23} = 0b00111100;
3635   let Inst{21}    = 1;
3636   let Inst{20-19} = rmode;
3637   let Inst{18-16} = opcode;
3638   let Inst{15-10} = 0b000000;
3639   let Inst{9-5}   = Rn;
3640   let Inst{4-0}   = Rd;
3641 }
3642
3643 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3644 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3645                      RegisterClass srcType, RegisterOperand dstType, string asm,
3646                      string kind>
3647     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3648         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3649       Sched<[WriteFCopy]> {
3650   bits<5> Rd;
3651   bits<5> Rn;
3652   let Inst{30-23} = 0b00111101;
3653   let Inst{21}    = 1;
3654   let Inst{20-19} = rmode;
3655   let Inst{18-16} = opcode;
3656   let Inst{15-10} = 0b000000;
3657   let Inst{9-5}   = Rn;
3658   let Inst{4-0}   = Rd;
3659
3660   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3661 }
3662
3663 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3664 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3665                      RegisterOperand srcType, RegisterClass dstType, string asm,
3666                      string kind>
3667     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3668         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3669       Sched<[WriteFCopy]> {
3670   bits<5> Rd;
3671   bits<5> Rn;
3672   let Inst{30-23} = 0b00111101;
3673   let Inst{21}    = 1;
3674   let Inst{20-19} = rmode;
3675   let Inst{18-16} = opcode;
3676   let Inst{15-10} = 0b000000;
3677   let Inst{9-5}   = Rn;
3678   let Inst{4-0}   = Rd;
3679
3680   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3681 }
3682
3683
3684
3685 multiclass UnscaledConversion<string asm> {
3686   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3687     let Inst{31} = 0; // 32-bit GPR flag
3688     let Inst{22} = 0; // 32-bit FPR flag
3689   }
3690
3691   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3692     let Inst{31} = 1; // 64-bit GPR flag
3693     let Inst{22} = 1; // 64-bit FPR flag
3694   }
3695
3696   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3697     let Inst{31} = 0; // 32-bit GPR flag
3698     let Inst{22} = 0; // 32-bit FPR flag
3699   }
3700
3701   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3702     let Inst{31} = 1; // 64-bit GPR flag
3703     let Inst{22} = 1; // 64-bit FPR flag
3704   }
3705
3706   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3707                                              asm, ".d"> {
3708     let Inst{31} = 1;
3709     let Inst{22} = 0;
3710   }
3711
3712   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3713                                                asm, ".d"> {
3714     let Inst{31} = 1;
3715     let Inst{22} = 0;
3716   }
3717 }
3718
3719 //---
3720 // Floating point conversion
3721 //---
3722
3723 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3724                        RegisterClass srcType, string asm, list<dag> pattern>
3725     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3726       Sched<[WriteFCvt]> {
3727   bits<5> Rd;
3728   bits<5> Rn;
3729   let Inst{31-24} = 0b00011110;
3730   let Inst{23-22} = type;
3731   let Inst{21-17} = 0b10001;
3732   let Inst{16-15} = opcode;
3733   let Inst{14-10} = 0b10000;
3734   let Inst{9-5}   = Rn;
3735   let Inst{4-0}   = Rd;
3736 }
3737
3738 multiclass FPConversion<string asm> {
3739   // Double-precision to Half-precision
3740   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3741                              [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3742
3743   // Double-precision to Single-precision
3744   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3745                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3746
3747   // Half-precision to Double-precision
3748   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3749                              [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3750
3751   // Half-precision to Single-precision
3752   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3753                              [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3754
3755   // Single-precision to Double-precision
3756   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3757                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3758
3759   // Single-precision to Half-precision
3760   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3761                              [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3762 }
3763
3764 //---
3765 // Single operand floating point data processing
3766 //---
3767
3768 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3769 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3770                               ValueType vt, string asm, SDPatternOperator node>
3771     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3772          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3773       Sched<[WriteF]> {
3774   bits<5> Rd;
3775   bits<5> Rn;
3776   let Inst{31-23} = 0b000111100;
3777   let Inst{21-19} = 0b100;
3778   let Inst{18-15} = opcode;
3779   let Inst{14-10} = 0b10000;
3780   let Inst{9-5}   = Rn;
3781   let Inst{4-0}   = Rd;
3782 }
3783
3784 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3785                                SDPatternOperator node = null_frag> {
3786   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3787     let Inst{22} = 0; // 32-bit size flag
3788   }
3789
3790   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3791     let Inst{22} = 1; // 64-bit size flag
3792   }
3793 }
3794
3795 //---
3796 // Two operand floating point data processing
3797 //---
3798
3799 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3800 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3801                            string asm, list<dag> pat>
3802     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3803          asm, "\t$Rd, $Rn, $Rm", "", pat>,
3804       Sched<[WriteF]> {
3805   bits<5> Rd;
3806   bits<5> Rn;
3807   bits<5> Rm;
3808   let Inst{31-23} = 0b000111100;
3809   let Inst{21}    = 1;
3810   let Inst{20-16} = Rm;
3811   let Inst{15-12} = opcode;
3812   let Inst{11-10} = 0b10;
3813   let Inst{9-5}   = Rn;
3814   let Inst{4-0}   = Rd;
3815 }
3816
3817 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3818                             SDPatternOperator node = null_frag> {
3819   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3820                          [(set (f32 FPR32:$Rd),
3821                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3822     let Inst{22} = 0; // 32-bit size flag
3823   }
3824
3825   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3826                          [(set (f64 FPR64:$Rd),
3827                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3828     let Inst{22} = 1; // 64-bit size flag
3829   }
3830 }
3831
3832 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3833   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3834                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3835     let Inst{22} = 0; // 32-bit size flag
3836   }
3837
3838   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3839                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3840     let Inst{22} = 1; // 64-bit size flag
3841   }
3842 }
3843
3844
3845 //---
3846 // Three operand floating point data processing
3847 //---
3848
3849 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3850                              RegisterClass regtype, string asm, list<dag> pat>
3851     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3852          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3853       Sched<[WriteFMul]> {
3854   bits<5> Rd;
3855   bits<5> Rn;
3856   bits<5> Rm;
3857   bits<5> Ra;
3858   let Inst{31-23} = 0b000111110;
3859   let Inst{21}    = isNegated;
3860   let Inst{20-16} = Rm;
3861   let Inst{15}    = isSub;
3862   let Inst{14-10} = Ra;
3863   let Inst{9-5}   = Rn;
3864   let Inst{4-0}   = Rd;
3865 }
3866
3867 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3868                               SDPatternOperator node> {
3869   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3870             [(set FPR32:$Rd,
3871                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3872     let Inst{22} = 0; // 32-bit size flag
3873   }
3874
3875   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3876             [(set FPR64:$Rd,
3877                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3878     let Inst{22} = 1; // 64-bit size flag
3879   }
3880 }
3881
3882 //---
3883 // Floating point data comparisons
3884 //---
3885
3886 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3887 class BaseOneOperandFPComparison<bit signalAllNans,
3888                                  RegisterClass regtype, string asm,
3889                                  list<dag> pat>
3890     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3891       Sched<[WriteFCmp]> {
3892   bits<5> Rn;
3893   let Inst{31-23} = 0b000111100;
3894   let Inst{21}    = 1;
3895
3896   let Inst{15-10} = 0b001000;
3897   let Inst{9-5}   = Rn;
3898   let Inst{4}     = signalAllNans;
3899   let Inst{3-0}   = 0b1000;
3900
3901   // Rm should be 0b00000 canonically, but we need to accept any value.
3902   let PostEncoderMethod = "fixOneOperandFPComparison";
3903 }
3904
3905 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3906 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3907                                 string asm, list<dag> pat>
3908     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3909       Sched<[WriteFCmp]> {
3910   bits<5> Rm;
3911   bits<5> Rn;
3912   let Inst{31-23} = 0b000111100;
3913   let Inst{21}    = 1;
3914   let Inst{20-16} = Rm;
3915   let Inst{15-10} = 0b001000;
3916   let Inst{9-5}   = Rn;
3917   let Inst{4}     = signalAllNans;
3918   let Inst{3-0}   = 0b0000;
3919 }
3920
3921 multiclass FPComparison<bit signalAllNans, string asm,
3922                         SDPatternOperator OpNode = null_frag> {
3923   let Defs = [NZCV] in {
3924   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3925       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
3926     let Inst{22} = 0;
3927   }
3928
3929   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3930       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
3931     let Inst{22} = 0;
3932   }
3933
3934   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3935       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
3936     let Inst{22} = 1;
3937   }
3938
3939   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3940       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
3941     let Inst{22} = 1;
3942   }
3943   } // Defs = [NZCV]
3944 }
3945
3946 //---
3947 // Floating point conditional comparisons
3948 //---
3949
3950 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3951 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
3952                            string mnemonic, list<dag> pat>
3953     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3954          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
3955       Sched<[WriteFCmp]> {
3956   let Uses = [NZCV];
3957   let Defs = [NZCV];
3958
3959   bits<5> Rn;
3960   bits<5> Rm;
3961   bits<4> nzcv;
3962   bits<4> cond;
3963
3964   let Inst{31-23} = 0b000111100;
3965   let Inst{21}    = 1;
3966   let Inst{20-16} = Rm;
3967   let Inst{15-12} = cond;
3968   let Inst{11-10} = 0b01;
3969   let Inst{9-5}   = Rn;
3970   let Inst{4}     = signalAllNans;
3971   let Inst{3-0}   = nzcv;
3972 }
3973
3974 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
3975                             SDPatternOperator OpNode = null_frag> {
3976   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
3977       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
3978                           (i32 imm:$cond), NZCV))]> {
3979     let Inst{22} = 0;
3980   }
3981   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
3982       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
3983                           (i32 imm:$cond), NZCV))]> {
3984     let Inst{22} = 1;
3985   }
3986 }
3987
3988 //---
3989 // Floating point conditional select
3990 //---
3991
3992 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3993     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3994          asm, "\t$Rd, $Rn, $Rm, $cond", "",
3995          [(set regtype:$Rd,
3996                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
3997                           (i32 imm:$cond), NZCV))]>,
3998       Sched<[WriteF]> {
3999   bits<5> Rd;
4000   bits<5> Rn;
4001   bits<5> Rm;
4002   bits<4> cond;
4003
4004   let Inst{31-23} = 0b000111100;
4005   let Inst{21}    = 1;
4006   let Inst{20-16} = Rm;
4007   let Inst{15-12} = cond;
4008   let Inst{11-10} = 0b11;
4009   let Inst{9-5}   = Rn;
4010   let Inst{4-0}   = Rd;
4011 }
4012
4013 multiclass FPCondSelect<string asm> {
4014   let Uses = [NZCV] in {
4015   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4016     let Inst{22} = 0;
4017   }
4018
4019   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4020     let Inst{22} = 1;
4021   }
4022   } // Uses = [NZCV]
4023 }
4024
4025 //---
4026 // Floating move immediate
4027 //---
4028
4029 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4030   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4031       [(set regtype:$Rd, fpimmtype:$imm)]>,
4032     Sched<[WriteFImm]> {
4033   bits<5> Rd;
4034   bits<8> imm;
4035   let Inst{31-23} = 0b000111100;
4036   let Inst{21}    = 1;
4037   let Inst{20-13} = imm;
4038   let Inst{12-5}  = 0b10000000;
4039   let Inst{4-0}   = Rd;
4040 }
4041
4042 multiclass FPMoveImmediate<string asm> {
4043   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4044     let Inst{22} = 0;
4045   }
4046
4047   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4048     let Inst{22} = 1;
4049   }
4050 }
4051 } // end of 'let Predicates = [HasFPARMv8]'
4052
4053 //----------------------------------------------------------------------------
4054 // AdvSIMD
4055 //----------------------------------------------------------------------------
4056
4057 let Predicates = [HasNEON] in {
4058
4059 //----------------------------------------------------------------------------
4060 // AdvSIMD three register vector instructions
4061 //----------------------------------------------------------------------------
4062
4063 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4064 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4065                         RegisterOperand regtype, string asm, string kind,
4066                         list<dag> pattern>
4067   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4068       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4069       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4070     Sched<[WriteV]> {
4071   bits<5> Rd;
4072   bits<5> Rn;
4073   bits<5> Rm;
4074   let Inst{31}    = 0;
4075   let Inst{30}    = Q;
4076   let Inst{29}    = U;
4077   let Inst{28-24} = 0b01110;
4078   let Inst{23-22} = size;
4079   let Inst{21}    = 1;
4080   let Inst{20-16} = Rm;
4081   let Inst{15-11} = opcode;
4082   let Inst{10}    = 1;
4083   let Inst{9-5}   = Rn;
4084   let Inst{4-0}   = Rd;
4085 }
4086
4087 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4088 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4089                         RegisterOperand regtype, string asm, string kind,
4090                         list<dag> pattern>
4091   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4092       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4093       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4094     Sched<[WriteV]> {
4095   bits<5> Rd;
4096   bits<5> Rn;
4097   bits<5> Rm;
4098   let Inst{31}    = 0;
4099   let Inst{30}    = Q;
4100   let Inst{29}    = U;
4101   let Inst{28-24} = 0b01110;
4102   let Inst{23-22} = size;
4103   let Inst{21}    = 1;
4104   let Inst{20-16} = Rm;
4105   let Inst{15-11} = opcode;
4106   let Inst{10}    = 1;
4107   let Inst{9-5}   = Rn;
4108   let Inst{4-0}   = Rd;
4109 }
4110
4111 // All operand sizes distinguished in the encoding.
4112 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4113                                SDPatternOperator OpNode> {
4114   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4115                                       asm, ".8b",
4116          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4117   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4118                                       asm, ".16b",
4119          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4120   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4121                                       asm, ".4h",
4122          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4123   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4124                                       asm, ".8h",
4125          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4126   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4127                                       asm, ".2s",
4128          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4129   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4130                                       asm, ".4s",
4131          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4132   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
4133                                       asm, ".2d",
4134          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4135 }
4136
4137 // As above, but D sized elements unsupported.
4138 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4139                                   SDPatternOperator OpNode> {
4140   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4141                                       asm, ".8b",
4142         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4143   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4144                                       asm, ".16b",
4145         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4146   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4147                                       asm, ".4h",
4148         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4149   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4150                                       asm, ".8h",
4151         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4152   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4153                                       asm, ".2s",
4154         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4155   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4156                                       asm, ".4s",
4157         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4158 }
4159
4160 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4161                                   SDPatternOperator OpNode> {
4162   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
4163                                       asm, ".8b",
4164       [(set (v8i8 V64:$dst),
4165             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4166   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
4167                                       asm, ".16b",
4168       [(set (v16i8 V128:$dst),
4169             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4170   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
4171                                       asm, ".4h",
4172       [(set (v4i16 V64:$dst),
4173             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4174   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
4175                                       asm, ".8h",
4176       [(set (v8i16 V128:$dst),
4177             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4178   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
4179                                       asm, ".2s",
4180       [(set (v2i32 V64:$dst),
4181             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4182   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
4183                                       asm, ".4s",
4184       [(set (v4i32 V128:$dst),
4185             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4186 }
4187
4188 // As above, but only B sized elements supported.
4189 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4190                                 SDPatternOperator OpNode> {
4191   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4192                                       asm, ".8b",
4193     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4194   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4195                                       asm, ".16b",
4196     [(set (v16i8 V128:$Rd),
4197           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4198 }
4199
4200 // As above, but only S and D sized floating point elements supported.
4201 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
4202                                  string asm, SDPatternOperator OpNode> {
4203   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4204                                       asm, ".2s",
4205         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4206   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4207                                       asm, ".4s",
4208         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4209   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4210                                       asm, ".2d",
4211         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4212 }
4213
4214 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
4215                                     string asm,
4216                                     SDPatternOperator OpNode> {
4217   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4218                                       asm, ".2s",
4219         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4220   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4221                                       asm, ".4s",
4222         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4223   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4224                                       asm, ".2d",
4225         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4226 }
4227
4228 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
4229                                  string asm, SDPatternOperator OpNode> {
4230   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
4231                                       asm, ".2s",
4232      [(set (v2f32 V64:$dst),
4233            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4234   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
4235                                       asm, ".4s",
4236      [(set (v4f32 V128:$dst),
4237            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4238   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
4239                                       asm, ".2d",
4240      [(set (v2f64 V128:$dst),
4241            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4242 }
4243
4244 // As above, but D and B sized elements unsupported.
4245 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4246                                 SDPatternOperator OpNode> {
4247   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4248                                       asm, ".4h",
4249         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4250   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4251                                       asm, ".8h",
4252         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4253   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4254                                       asm, ".2s",
4255         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4256   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4257                                       asm, ".4s",
4258         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4259 }
4260
4261 // Logical three vector ops share opcode bits, and only use B sized elements.
4262 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4263                                   SDPatternOperator OpNode = null_frag> {
4264   def v8i8  : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4265                                      asm, ".8b",
4266                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4267   def v16i8  : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4268                                      asm, ".16b",
4269                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4270
4271   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4272           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4273   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4274           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4275   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4276           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4277
4278   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4279       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4280   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4281       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4282   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4283       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4284 }
4285
4286 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4287                                   string asm, SDPatternOperator OpNode> {
4288   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4289                                      asm, ".8b",
4290              [(set (v8i8 V64:$dst),
4291                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4292   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4293                                      asm, ".16b",
4294              [(set (v16i8 V128:$dst),
4295                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4296                            (v16i8 V128:$Rm)))]>;
4297
4298   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4299                            (v4i16 V64:$RHS))),
4300           (!cast<Instruction>(NAME#"v8i8")
4301             V64:$LHS, V64:$MHS, V64:$RHS)>;
4302   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4303                            (v2i32 V64:$RHS))),
4304           (!cast<Instruction>(NAME#"v8i8")
4305             V64:$LHS, V64:$MHS, V64:$RHS)>;
4306   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4307                            (v1i64 V64:$RHS))),
4308           (!cast<Instruction>(NAME#"v8i8")
4309             V64:$LHS, V64:$MHS, V64:$RHS)>;
4310
4311   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4312                            (v8i16 V128:$RHS))),
4313       (!cast<Instruction>(NAME#"v16i8")
4314         V128:$LHS, V128:$MHS, V128:$RHS)>;
4315   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4316                            (v4i32 V128:$RHS))),
4317       (!cast<Instruction>(NAME#"v16i8")
4318         V128:$LHS, V128:$MHS, V128:$RHS)>;
4319   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4320                            (v2i64 V128:$RHS))),
4321       (!cast<Instruction>(NAME#"v16i8")
4322         V128:$LHS, V128:$MHS, V128:$RHS)>;
4323 }
4324
4325
4326 //----------------------------------------------------------------------------
4327 // AdvSIMD two register vector instructions.
4328 //----------------------------------------------------------------------------
4329
4330 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4331 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4332                         RegisterOperand regtype, string asm, string dstkind,
4333                         string srckind, list<dag> pattern>
4334   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4335       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4336       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4337     Sched<[WriteV]> {
4338   bits<5> Rd;
4339   bits<5> Rn;
4340   let Inst{31}    = 0;
4341   let Inst{30}    = Q;
4342   let Inst{29}    = U;
4343   let Inst{28-24} = 0b01110;
4344   let Inst{23-22} = size;
4345   let Inst{21-17} = 0b10000;
4346   let Inst{16-12} = opcode;
4347   let Inst{11-10} = 0b10;
4348   let Inst{9-5}   = Rn;
4349   let Inst{4-0}   = Rd;
4350 }
4351
4352 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4353 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4354                             RegisterOperand regtype, string asm, string dstkind,
4355                             string srckind, list<dag> pattern>
4356   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4357       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4358       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", 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 // Supports B, H, and S element sizes.
4375 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4376                             SDPatternOperator OpNode> {
4377   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4378                                       asm, ".8b", ".8b",
4379                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4380   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4381                                       asm, ".16b", ".16b",
4382                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4383   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4384                                       asm, ".4h", ".4h",
4385                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4386   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4387                                       asm, ".8h", ".8h",
4388                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4389   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4390                                       asm, ".2s", ".2s",
4391                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4392   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4393                                       asm, ".4s", ".4s",
4394                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4395 }
4396
4397 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4398                             RegisterOperand regtype, string asm, string dstkind,
4399                             string srckind, string amount>
4400   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4401       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4402       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4403     Sched<[WriteV]> {
4404   bits<5> Rd;
4405   bits<5> Rn;
4406   let Inst{31}    = 0;
4407   let Inst{30}    = Q;
4408   let Inst{29-24} = 0b101110;
4409   let Inst{23-22} = size;
4410   let Inst{21-10} = 0b100001001110;
4411   let Inst{9-5}   = Rn;
4412   let Inst{4-0}   = Rd;
4413 }
4414
4415 multiclass SIMDVectorLShiftLongBySizeBHS {
4416   let hasSideEffects = 0 in {
4417   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4418                                              "shll", ".8h",  ".8b", "8">;
4419   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4420                                              "shll2", ".8h", ".16b", "8">;
4421   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4422                                              "shll", ".4s",  ".4h", "16">;
4423   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4424                                              "shll2", ".4s", ".8h", "16">;
4425   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4426                                              "shll", ".2d",  ".2s", "32">;
4427   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4428                                              "shll2", ".2d", ".4s", "32">;
4429   }
4430 }
4431
4432 // Supports all element sizes.
4433 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4434                              SDPatternOperator OpNode> {
4435   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4436                                       asm, ".4h", ".8b",
4437                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4438   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4439                                       asm, ".8h", ".16b",
4440                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4441   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4442                                       asm, ".2s", ".4h",
4443                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4444   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4445                                       asm, ".4s", ".8h",
4446                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4447   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4448                                       asm, ".1d", ".2s",
4449                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4450   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4451                                       asm, ".2d", ".4s",
4452                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4453 }
4454
4455 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4456                                  SDPatternOperator OpNode> {
4457   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4458                                           asm, ".4h", ".8b",
4459       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4460                                       (v8i8 V64:$Rn)))]>;
4461   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4462                                           asm, ".8h", ".16b",
4463       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4464                                       (v16i8 V128:$Rn)))]>;
4465   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4466                                           asm, ".2s", ".4h",
4467       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4468                                       (v4i16 V64:$Rn)))]>;
4469   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4470                                           asm, ".4s", ".8h",
4471       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4472                                       (v8i16 V128:$Rn)))]>;
4473   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4474                                           asm, ".1d", ".2s",
4475       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4476                                       (v2i32 V64:$Rn)))]>;
4477   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4478                                           asm, ".2d", ".4s",
4479       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4480                                       (v4i32 V128:$Rn)))]>;
4481 }
4482
4483 // Supports all element sizes, except 1xD.
4484 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4485                                   SDPatternOperator OpNode> {
4486   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4487                                     asm, ".8b", ".8b",
4488     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4489   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4490                                     asm, ".16b", ".16b",
4491     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4492   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4493                                     asm, ".4h", ".4h",
4494     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4495   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4496                                     asm, ".8h", ".8h",
4497     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4498   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4499                                     asm, ".2s", ".2s",
4500     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4501   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4502                                     asm, ".4s", ".4s",
4503     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4504   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4505                                     asm, ".2d", ".2d",
4506     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4507 }
4508
4509 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4510                              SDPatternOperator OpNode = null_frag> {
4511   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4512                                 asm, ".8b", ".8b",
4513     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4514   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4515                                 asm, ".16b", ".16b",
4516     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4517   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4518                                 asm, ".4h", ".4h",
4519     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4520   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4521                                 asm, ".8h", ".8h",
4522     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4523   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4524                                 asm, ".2s", ".2s",
4525     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4526   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4527                                 asm, ".4s", ".4s",
4528     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4529   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4530                                 asm, ".2d", ".2d",
4531     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4532 }
4533
4534
4535 // Supports only B element sizes.
4536 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4537                           SDPatternOperator OpNode> {
4538   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4539                                 asm, ".8b", ".8b",
4540                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4541   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4542                                 asm, ".16b", ".16b",
4543                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4544
4545 }
4546
4547 // Supports only B and H element sizes.
4548 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4549                                 SDPatternOperator OpNode> {
4550   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4551                                 asm, ".8b", ".8b",
4552                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4553   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4554                                 asm, ".16b", ".16b",
4555                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4556   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4557                                 asm, ".4h", ".4h",
4558                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4559   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4560                                 asm, ".8h", ".8h",
4561                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4562 }
4563
4564 // Supports only S and D element sizes, uses high bit of the size field
4565 // as an extra opcode bit.
4566 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4567                            SDPatternOperator OpNode> {
4568   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4569                                 asm, ".2s", ".2s",
4570                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4571   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4572                                 asm, ".4s", ".4s",
4573                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4574   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4575                                 asm, ".2d", ".2d",
4576                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4577 }
4578
4579 // Supports only S element size.
4580 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4581                            SDPatternOperator OpNode> {
4582   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4583                                 asm, ".2s", ".2s",
4584                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4585   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4586                                 asm, ".4s", ".4s",
4587                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4588 }
4589
4590
4591 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4592                            SDPatternOperator OpNode> {
4593   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4594                                 asm, ".2s", ".2s",
4595                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4596   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4597                                 asm, ".4s", ".4s",
4598                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4599   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4600                                 asm, ".2d", ".2d",
4601                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4602 }
4603
4604 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4605                            SDPatternOperator OpNode> {
4606   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4607                                 asm, ".2s", ".2s",
4608                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4609   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4610                                 asm, ".4s", ".4s",
4611                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4612   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4613                                 asm, ".2d", ".2d",
4614                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4615 }
4616
4617
4618 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4619                            RegisterOperand inreg, RegisterOperand outreg,
4620                            string asm, string outkind, string inkind,
4621                            list<dag> pattern>
4622   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4623       "{\t$Rd" # outkind # ", $Rn" # inkind #
4624       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4625     Sched<[WriteV]> {
4626   bits<5> Rd;
4627   bits<5> Rn;
4628   let Inst{31}    = 0;
4629   let Inst{30}    = Q;
4630   let Inst{29}    = U;
4631   let Inst{28-24} = 0b01110;
4632   let Inst{23-22} = size;
4633   let Inst{21-17} = 0b10000;
4634   let Inst{16-12} = opcode;
4635   let Inst{11-10} = 0b10;
4636   let Inst{9-5}   = Rn;
4637   let Inst{4-0}   = Rd;
4638 }
4639
4640 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4641                            RegisterOperand inreg, RegisterOperand outreg,
4642                            string asm, string outkind, string inkind,
4643                            list<dag> pattern>
4644   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4645       "{\t$Rd" # outkind # ", $Rn" # inkind #
4646       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4647     Sched<[WriteV]> {
4648   bits<5> Rd;
4649   bits<5> Rn;
4650   let Inst{31}    = 0;
4651   let Inst{30}    = Q;
4652   let Inst{29}    = U;
4653   let Inst{28-24} = 0b01110;
4654   let Inst{23-22} = size;
4655   let Inst{21-17} = 0b10000;
4656   let Inst{16-12} = opcode;
4657   let Inst{11-10} = 0b10;
4658   let Inst{9-5}   = Rn;
4659   let Inst{4-0}   = Rd;
4660 }
4661
4662 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4663                               SDPatternOperator OpNode> {
4664   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4665                                       asm, ".8b", ".8h",
4666         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4667   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4668                                       asm#"2", ".16b", ".8h", []>;
4669   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4670                                       asm, ".4h", ".4s",
4671         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4672   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4673                                       asm#"2", ".8h", ".4s", []>;
4674   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4675                                       asm, ".2s", ".2d",
4676         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4677   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4678                                       asm#"2", ".4s", ".2d", []>;
4679
4680   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4681             (!cast<Instruction>(NAME # "v16i8")
4682                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4683   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4684             (!cast<Instruction>(NAME # "v8i16")
4685                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4686   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4687             (!cast<Instruction>(NAME # "v4i32")
4688                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4689 }
4690
4691 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4692                            RegisterOperand regtype,
4693                            string asm, string kind, string zero,
4694                            ValueType dty, ValueType sty, SDNode OpNode>
4695   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4696       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4697       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4698       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4699     Sched<[WriteV]> {
4700   bits<5> Rd;
4701   bits<5> Rn;
4702   let Inst{31}    = 0;
4703   let Inst{30}    = Q;
4704   let Inst{29}    = U;
4705   let Inst{28-24} = 0b01110;
4706   let Inst{23-22} = size;
4707   let Inst{21-17} = 0b10000;
4708   let Inst{16-12} = opcode;
4709   let Inst{11-10} = 0b10;
4710   let Inst{9-5}   = Rn;
4711   let Inst{4-0}   = Rd;
4712 }
4713
4714 // Comparisons support all element sizes, except 1xD.
4715 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4716                             SDNode OpNode> {
4717   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4718                                      asm, ".8b", "0",
4719                                      v8i8, v8i8, OpNode>;
4720   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4721                                      asm, ".16b", "0",
4722                                      v16i8, v16i8, OpNode>;
4723   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4724                                      asm, ".4h", "0",
4725                                      v4i16, v4i16, OpNode>;
4726   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4727                                      asm, ".8h", "0",
4728                                      v8i16, v8i16, OpNode>;
4729   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4730                                      asm, ".2s", "0",
4731                                      v2i32, v2i32, OpNode>;
4732   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4733                                      asm, ".4s", "0",
4734                                      v4i32, v4i32, OpNode>;
4735   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4736                                      asm, ".2d", "0",
4737                                      v2i64, v2i64, OpNode>;
4738 }
4739
4740 // FP Comparisons support only S and D element sizes.
4741 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4742                               string asm, SDNode OpNode> {
4743
4744   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4745                                      asm, ".2s", "0.0",
4746                                      v2i32, v2f32, OpNode>;
4747   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4748                                      asm, ".4s", "0.0",
4749                                      v4i32, v4f32, OpNode>;
4750   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4751                                      asm, ".2d", "0.0",
4752                                      v2i64, v2f64, OpNode>;
4753
4754   def : InstAlias<asm # " $Vd.2s, $Vn.2s, #0",
4755                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4756   def : InstAlias<asm # " $Vd.4s, $Vn.4s, #0",
4757                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4758   def : InstAlias<asm # " $Vd.2d, $Vn.2d, #0",
4759                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4760   def : InstAlias<asm # ".2s $Vd, $Vn, #0",
4761                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4762   def : InstAlias<asm # ".4s $Vd, $Vn, #0",
4763                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4764   def : InstAlias<asm # ".2d $Vd, $Vn, #0",
4765                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4766 }
4767
4768 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4769 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4770                              RegisterOperand outtype, RegisterOperand intype,
4771                              string asm, string VdTy, string VnTy,
4772                              list<dag> pattern>
4773   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4774       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4775     Sched<[WriteV]> {
4776   bits<5> Rd;
4777   bits<5> Rn;
4778   let Inst{31}    = 0;
4779   let Inst{30}    = Q;
4780   let Inst{29}    = U;
4781   let Inst{28-24} = 0b01110;
4782   let Inst{23-22} = size;
4783   let Inst{21-17} = 0b10000;
4784   let Inst{16-12} = opcode;
4785   let Inst{11-10} = 0b10;
4786   let Inst{9-5}   = Rn;
4787   let Inst{4-0}   = Rd;
4788 }
4789
4790 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4791                              RegisterOperand outtype, RegisterOperand intype,
4792                              string asm, string VdTy, string VnTy,
4793                              list<dag> pattern>
4794   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4795       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4796     Sched<[WriteV]> {
4797   bits<5> Rd;
4798   bits<5> Rn;
4799   let Inst{31}    = 0;
4800   let Inst{30}    = Q;
4801   let Inst{29}    = U;
4802   let Inst{28-24} = 0b01110;
4803   let Inst{23-22} = size;
4804   let Inst{21-17} = 0b10000;
4805   let Inst{16-12} = opcode;
4806   let Inst{11-10} = 0b10;
4807   let Inst{9-5}   = Rn;
4808   let Inst{4-0}   = Rd;
4809 }
4810
4811 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4812   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4813                                     asm, ".4s", ".4h", []>;
4814   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4815                                     asm#"2", ".4s", ".8h", []>;
4816   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4817                                     asm, ".2d", ".2s", []>;
4818   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4819                                     asm#"2", ".2d", ".4s", []>;
4820 }
4821
4822 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4823   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4824                                     asm, ".4h", ".4s", []>;
4825   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4826                                     asm#"2", ".8h", ".4s", []>;
4827   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4828                                     asm, ".2s", ".2d", []>;
4829   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4830                                     asm#"2", ".4s", ".2d", []>;
4831 }
4832
4833 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4834                                      Intrinsic OpNode> {
4835   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4836                                      asm, ".2s", ".2d",
4837                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4838   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4839                                     asm#"2", ".4s", ".2d", []>;
4840
4841   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4842             (!cast<Instruction>(NAME # "v4f32")
4843                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4844 }
4845
4846 //----------------------------------------------------------------------------
4847 // AdvSIMD three register different-size vector instructions.
4848 //----------------------------------------------------------------------------
4849
4850 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4851 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4852                       RegisterOperand outtype, RegisterOperand intype1,
4853                       RegisterOperand intype2, string asm,
4854                       string outkind, string inkind1, string inkind2,
4855                       list<dag> pattern>
4856   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4857       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4858       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4859     Sched<[WriteV]> {
4860   bits<5> Rd;
4861   bits<5> Rn;
4862   bits<5> Rm;
4863   let Inst{31}    = 0;
4864   let Inst{30}    = size{0};
4865   let Inst{29}    = U;
4866   let Inst{28-24} = 0b01110;
4867   let Inst{23-22} = size{2-1};
4868   let Inst{21}    = 1;
4869   let Inst{20-16} = Rm;
4870   let Inst{15-12} = opcode;
4871   let Inst{11-10} = 0b00;
4872   let Inst{9-5}   = Rn;
4873   let Inst{4-0}   = Rd;
4874 }
4875
4876 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4877 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4878                       RegisterOperand outtype, RegisterOperand intype1,
4879                       RegisterOperand intype2, string asm,
4880                       string outkind, string inkind1, string inkind2,
4881                       list<dag> pattern>
4882   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4883       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4884       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4885     Sched<[WriteV]> {
4886   bits<5> Rd;
4887   bits<5> Rn;
4888   bits<5> Rm;
4889   let Inst{31}    = 0;
4890   let Inst{30}    = size{0};
4891   let Inst{29}    = U;
4892   let Inst{28-24} = 0b01110;
4893   let Inst{23-22} = size{2-1};
4894   let Inst{21}    = 1;
4895   let Inst{20-16} = Rm;
4896   let Inst{15-12} = opcode;
4897   let Inst{11-10} = 0b00;
4898   let Inst{9-5}   = Rn;
4899   let Inst{4-0}   = Rd;
4900 }
4901
4902 // FIXME: TableGen doesn't know how to deal with expanded types that also
4903 //        change the element count (in this case, placing the results in
4904 //        the high elements of the result register rather than the low
4905 //        elements). Until that's fixed, we can't code-gen those.
4906 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4907                                     Intrinsic IntOp> {
4908   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4909                                                   V64, V128, V128,
4910                                                   asm, ".8b", ".8h", ".8h",
4911      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4912   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4913                                                   V128, V128, V128,
4914                                                   asm#"2", ".16b", ".8h", ".8h",
4915      []>;
4916   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4917                                                   V64, V128, V128,
4918                                                   asm, ".4h", ".4s", ".4s",
4919      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4920   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4921                                                   V128, V128, V128,
4922                                                   asm#"2", ".8h", ".4s", ".4s",
4923      []>;
4924   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4925                                                   V64, V128, V128,
4926                                                   asm, ".2s", ".2d", ".2d",
4927      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4928   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4929                                                   V128, V128, V128,
4930                                                   asm#"2", ".4s", ".2d", ".2d",
4931      []>;
4932
4933
4934   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4935   // a version attached to an instruction.
4936   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4937                                                    (v8i16 V128:$Rm))),
4938             (!cast<Instruction>(NAME # "v8i16_v16i8")
4939                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4940                 V128:$Rn, V128:$Rm)>;
4941   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4942                                                     (v4i32 V128:$Rm))),
4943             (!cast<Instruction>(NAME # "v4i32_v8i16")
4944                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4945                 V128:$Rn, V128:$Rm)>;
4946   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4947                                                     (v2i64 V128:$Rm))),
4948             (!cast<Instruction>(NAME # "v2i64_v4i32")
4949                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4950                 V128:$Rn, V128:$Rm)>;
4951 }
4952
4953 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4954                                       Intrinsic IntOp> {
4955   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4956                                             V128, V64, V64,
4957                                             asm, ".8h", ".8b", ".8b",
4958       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4959   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4960                                             V128, V128, V128,
4961                                             asm#"2", ".8h", ".16b", ".16b", []>;
4962   let Predicates = [HasCrypto] in {
4963     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4964                                               V128, V64, V64,
4965                                               asm, ".1q", ".1d", ".1d", []>;
4966     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4967                                               V128, V128, V128,
4968                                               asm#"2", ".1q", ".2d", ".2d", []>;
4969   }
4970
4971   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4972                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
4973       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4974 }
4975
4976 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4977                                  SDPatternOperator OpNode> {
4978   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4979                                                   V128, V64, V64,
4980                                                   asm, ".4s", ".4h", ".4h",
4981       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4982   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4983                                                   V128, V128, V128,
4984                                                   asm#"2", ".4s", ".8h", ".8h",
4985       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4986                                       (extract_high_v8i16 V128:$Rm)))]>;
4987   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4988                                                   V128, V64, V64,
4989                                                   asm, ".2d", ".2s", ".2s",
4990       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4991   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4992                                                   V128, V128, V128,
4993                                                   asm#"2", ".2d", ".4s", ".4s",
4994       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4995                                       (extract_high_v4i32 V128:$Rm)))]>;
4996 }
4997
4998 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4999                                   SDPatternOperator OpNode = null_frag> {
5000   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5001                                                   V128, V64, V64,
5002                                                   asm, ".8h", ".8b", ".8b",
5003       [(set (v8i16 V128:$Rd),
5004             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5005   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5006                                                  V128, V128, V128,
5007                                                  asm#"2", ".8h", ".16b", ".16b",
5008       [(set (v8i16 V128:$Rd),
5009             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5010                                 (extract_high_v16i8 V128:$Rm)))))]>;
5011   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5012                                                   V128, V64, V64,
5013                                                   asm, ".4s", ".4h", ".4h",
5014       [(set (v4i32 V128:$Rd),
5015             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5016   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5017                                                   V128, V128, V128,
5018                                                   asm#"2", ".4s", ".8h", ".8h",
5019       [(set (v4i32 V128:$Rd),
5020             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5021                                   (extract_high_v8i16 V128:$Rm)))))]>;
5022   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5023                                                   V128, V64, V64,
5024                                                   asm, ".2d", ".2s", ".2s",
5025       [(set (v2i64 V128:$Rd),
5026             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5027   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5028                                                   V128, V128, V128,
5029                                                   asm#"2", ".2d", ".4s", ".4s",
5030       [(set (v2i64 V128:$Rd),
5031             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5032                                  (extract_high_v4i32 V128:$Rm)))))]>;
5033 }
5034
5035 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5036                                           string asm,
5037                                           SDPatternOperator OpNode> {
5038   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5039                                                   V128, V64, V64,
5040                                                   asm, ".8h", ".8b", ".8b",
5041     [(set (v8i16 V128:$dst),
5042           (add (v8i16 V128:$Rd),
5043                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5044   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5045                                                  V128, V128, V128,
5046                                                  asm#"2", ".8h", ".16b", ".16b",
5047     [(set (v8i16 V128:$dst),
5048           (add (v8i16 V128:$Rd),
5049                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5050                                    (extract_high_v16i8 V128:$Rm))))))]>;
5051   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5052                                                   V128, V64, V64,
5053                                                   asm, ".4s", ".4h", ".4h",
5054     [(set (v4i32 V128:$dst),
5055           (add (v4i32 V128:$Rd),
5056                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5057   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5058                                                   V128, V128, V128,
5059                                                   asm#"2", ".4s", ".8h", ".8h",
5060     [(set (v4i32 V128:$dst),
5061           (add (v4i32 V128:$Rd),
5062                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5063                                     (extract_high_v8i16 V128:$Rm))))))]>;
5064   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5065                                                   V128, V64, V64,
5066                                                   asm, ".2d", ".2s", ".2s",
5067     [(set (v2i64 V128:$dst),
5068           (add (v2i64 V128:$Rd),
5069                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5070   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5071                                                   V128, V128, V128,
5072                                                   asm#"2", ".2d", ".4s", ".4s",
5073     [(set (v2i64 V128:$dst),
5074           (add (v2i64 V128:$Rd),
5075                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5076                                     (extract_high_v4i32 V128:$Rm))))))]>;
5077 }
5078
5079 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5080                                   SDPatternOperator OpNode = null_frag> {
5081   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5082                                                   V128, V64, V64,
5083                                                   asm, ".8h", ".8b", ".8b",
5084       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5085   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5086                                                  V128, V128, V128,
5087                                                  asm#"2", ".8h", ".16b", ".16b",
5088       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5089                                       (extract_high_v16i8 V128:$Rm)))]>;
5090   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5091                                                   V128, V64, V64,
5092                                                   asm, ".4s", ".4h", ".4h",
5093       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5094   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5095                                                   V128, V128, V128,
5096                                                   asm#"2", ".4s", ".8h", ".8h",
5097       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5098                                       (extract_high_v8i16 V128:$Rm)))]>;
5099   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5100                                                   V128, V64, V64,
5101                                                   asm, ".2d", ".2s", ".2s",
5102       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5103   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5104                                                   V128, V128, V128,
5105                                                   asm#"2", ".2d", ".4s", ".4s",
5106       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5107                                       (extract_high_v4i32 V128:$Rm)))]>;
5108 }
5109
5110 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5111                                       string asm,
5112                                       SDPatternOperator OpNode> {
5113   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5114                                                   V128, V64, V64,
5115                                                   asm, ".8h", ".8b", ".8b",
5116     [(set (v8i16 V128:$dst),
5117           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5118   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5119                                                  V128, V128, V128,
5120                                                  asm#"2", ".8h", ".16b", ".16b",
5121     [(set (v8i16 V128:$dst),
5122           (OpNode (v8i16 V128:$Rd),
5123                   (extract_high_v16i8 V128:$Rn),
5124                   (extract_high_v16i8 V128:$Rm)))]>;
5125   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5126                                                   V128, V64, V64,
5127                                                   asm, ".4s", ".4h", ".4h",
5128     [(set (v4i32 V128:$dst),
5129           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5130   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5131                                                   V128, V128, V128,
5132                                                   asm#"2", ".4s", ".8h", ".8h",
5133     [(set (v4i32 V128:$dst),
5134           (OpNode (v4i32 V128:$Rd),
5135                   (extract_high_v8i16 V128:$Rn),
5136                   (extract_high_v8i16 V128:$Rm)))]>;
5137   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5138                                                   V128, V64, V64,
5139                                                   asm, ".2d", ".2s", ".2s",
5140     [(set (v2i64 V128:$dst),
5141           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5142   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5143                                                   V128, V128, V128,
5144                                                   asm#"2", ".2d", ".4s", ".4s",
5145     [(set (v2i64 V128:$dst),
5146           (OpNode (v2i64 V128:$Rd),
5147                   (extract_high_v4i32 V128:$Rn),
5148                   (extract_high_v4i32 V128:$Rm)))]>;
5149 }
5150
5151 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5152                                            SDPatternOperator Accum> {
5153   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5154                                                   V128, V64, V64,
5155                                                   asm, ".4s", ".4h", ".4h",
5156     [(set (v4i32 V128:$dst),
5157           (Accum (v4i32 V128:$Rd),
5158                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5159                                                 (v4i16 V64:$Rm)))))]>;
5160   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5161                                                   V128, V128, V128,
5162                                                   asm#"2", ".4s", ".8h", ".8h",
5163     [(set (v4i32 V128:$dst),
5164           (Accum (v4i32 V128:$Rd),
5165                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5166                                             (extract_high_v8i16 V128:$Rm)))))]>;
5167   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5168                                                   V128, V64, V64,
5169                                                   asm, ".2d", ".2s", ".2s",
5170     [(set (v2i64 V128:$dst),
5171           (Accum (v2i64 V128:$Rd),
5172                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5173                                                 (v2i32 V64:$Rm)))))]>;
5174   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5175                                                   V128, V128, V128,
5176                                                   asm#"2", ".2d", ".4s", ".4s",
5177     [(set (v2i64 V128:$dst),
5178           (Accum (v2i64 V128:$Rd),
5179                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5180                                             (extract_high_v4i32 V128:$Rm)))))]>;
5181 }
5182
5183 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5184                                   SDPatternOperator OpNode> {
5185   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5186                                                   V128, V128, V64,
5187                                                   asm, ".8h", ".8h", ".8b",
5188        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5189   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5190                                                   V128, V128, V128,
5191                                                   asm#"2", ".8h", ".8h", ".16b",
5192        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5193                                        (extract_high_v16i8 V128:$Rm)))]>;
5194   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5195                                                   V128, V128, V64,
5196                                                   asm, ".4s", ".4s", ".4h",
5197        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5198   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5199                                                   V128, V128, V128,
5200                                                   asm#"2", ".4s", ".4s", ".8h",
5201        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5202                                        (extract_high_v8i16 V128:$Rm)))]>;
5203   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5204                                                   V128, V128, V64,
5205                                                   asm, ".2d", ".2d", ".2s",
5206        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5207   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5208                                                   V128, V128, V128,
5209                                                   asm#"2", ".2d", ".2d", ".4s",
5210        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5211                                        (extract_high_v4i32 V128:$Rm)))]>;
5212 }
5213
5214 //----------------------------------------------------------------------------
5215 // AdvSIMD bitwise extract from vector
5216 //----------------------------------------------------------------------------
5217
5218 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5219                              string asm, string kind>
5220   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5221       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5222       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5223       [(set (vty regtype:$Rd),
5224             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5225     Sched<[WriteV]> {
5226   bits<5> Rd;
5227   bits<5> Rn;
5228   bits<5> Rm;
5229   bits<4> imm;
5230   let Inst{31}    = 0;
5231   let Inst{30}    = size;
5232   let Inst{29-21} = 0b101110000;
5233   let Inst{20-16} = Rm;
5234   let Inst{15}    = 0;
5235   let Inst{14-11} = imm;
5236   let Inst{10}    = 0;
5237   let Inst{9-5}   = Rn;
5238   let Inst{4-0}   = Rd;
5239 }
5240
5241
5242 multiclass SIMDBitwiseExtract<string asm> {
5243   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5244     let imm{3} = 0;
5245   }
5246   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5247 }
5248
5249 //----------------------------------------------------------------------------
5250 // AdvSIMD zip vector
5251 //----------------------------------------------------------------------------
5252
5253 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5254                         string asm, string kind, SDNode OpNode, ValueType valty>
5255   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5256       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5257       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5258       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5259     Sched<[WriteV]> {
5260   bits<5> Rd;
5261   bits<5> Rn;
5262   bits<5> Rm;
5263   let Inst{31}    = 0;
5264   let Inst{30}    = size{0};
5265   let Inst{29-24} = 0b001110;
5266   let Inst{23-22} = size{2-1};
5267   let Inst{21}    = 0;
5268   let Inst{20-16} = Rm;
5269   let Inst{15}    = 0;
5270   let Inst{14-12} = opc;
5271   let Inst{11-10} = 0b10;
5272   let Inst{9-5}   = Rn;
5273   let Inst{4-0}   = Rd;
5274 }
5275
5276 multiclass SIMDZipVector<bits<3>opc, string asm,
5277                          SDNode OpNode> {
5278   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5279       asm, ".8b", OpNode, v8i8>;
5280   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5281       asm, ".16b", OpNode, v16i8>;
5282   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5283       asm, ".4h", OpNode, v4i16>;
5284   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5285       asm, ".8h", OpNode, v8i16>;
5286   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5287       asm, ".2s", OpNode, v2i32>;
5288   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5289       asm, ".4s", OpNode, v4i32>;
5290   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5291       asm, ".2d", OpNode, v2i64>;
5292
5293   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5294         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5295   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5296         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5297   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5298         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5299   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5300         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5301   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5302         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5303 }
5304
5305 //----------------------------------------------------------------------------
5306 // AdvSIMD three register scalar instructions
5307 //----------------------------------------------------------------------------
5308
5309 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5310 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5311                         RegisterClass regtype, string asm,
5312                         list<dag> pattern>
5313   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5314       "\t$Rd, $Rn, $Rm", "", pattern>,
5315     Sched<[WriteV]> {
5316   bits<5> Rd;
5317   bits<5> Rn;
5318   bits<5> Rm;
5319   let Inst{31-30} = 0b01;
5320   let Inst{29}    = U;
5321   let Inst{28-24} = 0b11110;
5322   let Inst{23-22} = size;
5323   let Inst{21}    = 1;
5324   let Inst{20-16} = Rm;
5325   let Inst{15-11} = opcode;
5326   let Inst{10}    = 1;
5327   let Inst{9-5}   = Rn;
5328   let Inst{4-0}   = Rd;
5329 }
5330
5331 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5332 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5333                         dag oops, dag iops, string asm,
5334             list<dag> pattern>
5335   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5336     Sched<[WriteV]> {
5337   bits<5> Rd;
5338   bits<5> Rn;
5339   bits<5> Rm;
5340   let Inst{31-30} = 0b01;
5341   let Inst{29}    = U;
5342   let Inst{28-24} = 0b11110;
5343   let Inst{23-22} = size;
5344   let Inst{21}    = R;
5345   let Inst{20-16} = Rm;
5346   let Inst{15-11} = opcode;
5347   let Inst{10}    = 1;
5348   let Inst{9-5}   = Rn;
5349   let Inst{4-0}   = Rd;
5350 }
5351
5352 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5353                             SDPatternOperator OpNode> {
5354   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5355     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5356 }
5357
5358 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5359                                SDPatternOperator OpNode> {
5360   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5361     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5362   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5363   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5364   def v1i8   : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5365
5366   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5367             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5368   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5369             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5370 }
5371
5372 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5373                              SDPatternOperator OpNode> {
5374   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5375                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5376   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5377 }
5378
5379 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5380                                  SDPatternOperator OpNode = null_frag> {
5381   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5382                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm), 
5383                                      asm, []>;
5384   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5385                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm), 
5386                                      asm, []>;
5387 }
5388
5389 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5390                              SDPatternOperator OpNode = null_frag> {
5391   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5392     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5393       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5394     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5395       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5396   }
5397
5398   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5399             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5400 }
5401
5402 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5403                                 SDPatternOperator OpNode = null_frag> {
5404   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5405     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5406       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5407     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5408       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5409   }
5410
5411   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5412             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5413 }
5414
5415 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5416               dag oops, dag iops, string asm, string cstr, list<dag> pat>
5417   : I<oops, iops, asm,
5418       "\t$Rd, $Rn, $Rm", cstr, pat>,
5419     Sched<[WriteV]> {
5420   bits<5> Rd;
5421   bits<5> Rn;
5422   bits<5> Rm;
5423   let Inst{31-30} = 0b01;
5424   let Inst{29}    = U;
5425   let Inst{28-24} = 0b11110;
5426   let Inst{23-22} = size;
5427   let Inst{21}    = 1;
5428   let Inst{20-16} = Rm;
5429   let Inst{15-11} = opcode;
5430   let Inst{10}    = 0;
5431   let Inst{9-5}   = Rn;
5432   let Inst{4-0}   = Rd;
5433 }
5434
5435 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5436 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5437                                   SDPatternOperator OpNode = null_frag> {
5438   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5439                                       (outs FPR32:$Rd),
5440                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5441   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5442                                       (outs FPR64:$Rd),
5443                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5444             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5445 }
5446
5447 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5448 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5449                                   SDPatternOperator OpNode = null_frag> {
5450   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5451                                       (outs FPR32:$dst),
5452                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5453                                       asm, "$Rd = $dst", []>;
5454   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5455                                       (outs FPR64:$dst),
5456                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5457                                       asm, "$Rd = $dst",
5458             [(set (i64 FPR64:$dst),
5459                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5460 }
5461
5462 //----------------------------------------------------------------------------
5463 // AdvSIMD two register scalar instructions
5464 //----------------------------------------------------------------------------
5465
5466 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5467 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5468                         RegisterClass regtype, RegisterClass regtype2,
5469                         string asm, list<dag> pat>
5470   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5471       "\t$Rd, $Rn", "", pat>,
5472     Sched<[WriteV]> {
5473   bits<5> Rd;
5474   bits<5> Rn;
5475   let Inst{31-30} = 0b01;
5476   let Inst{29}    = U;
5477   let Inst{28-24} = 0b11110;
5478   let Inst{23-22} = size;
5479   let Inst{21-17} = 0b10000;
5480   let Inst{16-12} = opcode;
5481   let Inst{11-10} = 0b10;
5482   let Inst{9-5}   = Rn;
5483   let Inst{4-0}   = Rd;
5484 }
5485
5486 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5487 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5488                         RegisterClass regtype, RegisterClass regtype2,
5489                         string asm, list<dag> pat>
5490   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5491       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5492     Sched<[WriteV]> {
5493   bits<5> Rd;
5494   bits<5> Rn;
5495   let Inst{31-30} = 0b01;
5496   let Inst{29}    = U;
5497   let Inst{28-24} = 0b11110;
5498   let Inst{23-22} = size;
5499   let Inst{21-17} = 0b10000;
5500   let Inst{16-12} = opcode;
5501   let Inst{11-10} = 0b10;
5502   let Inst{9-5}   = Rn;
5503   let Inst{4-0}   = Rd;
5504 }
5505
5506
5507 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5508 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5509                         RegisterClass regtype, string asm, string zero>
5510   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5511       "\t$Rd, $Rn, #" # zero, "", []>,
5512     Sched<[WriteV]> {
5513   bits<5> Rd;
5514   bits<5> Rn;
5515   let Inst{31-30} = 0b01;
5516   let Inst{29}    = U;
5517   let Inst{28-24} = 0b11110;
5518   let Inst{23-22} = size;
5519   let Inst{21-17} = 0b10000;
5520   let Inst{16-12} = opcode;
5521   let Inst{11-10} = 0b10;
5522   let Inst{9-5}   = Rn;
5523   let Inst{4-0}   = Rd;
5524 }
5525
5526 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5527   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5528      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5529     Sched<[WriteV]> {
5530   bits<5> Rd;
5531   bits<5> Rn;
5532   let Inst{31-17} = 0b011111100110000;
5533   let Inst{16-12} = opcode;
5534   let Inst{11-10} = 0b10;
5535   let Inst{9-5}   = Rn;
5536   let Inst{4-0}   = Rd;
5537 }
5538
5539 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5540                              SDPatternOperator OpNode> {
5541   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5542
5543   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5544             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5545 }
5546
5547 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5548                               SDPatternOperator OpNode> {
5549   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5550   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5551
5552   def : InstAlias<asm # " $Rd, $Rn, #0",
5553                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5554   def : InstAlias<asm # " $Rd, $Rn, #0",
5555                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5556
5557   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5558             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5559 }
5560
5561 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5562                           SDPatternOperator OpNode = null_frag> {
5563   def v1i64       : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5564     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5565
5566   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5567             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5568 }
5569
5570 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5571   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5572   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5573 }
5574
5575 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5576                               SDPatternOperator OpNode> {
5577   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5578                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5579   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5580                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5581 }
5582
5583 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5584                              SDPatternOperator OpNode = null_frag> {
5585   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5586     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5587            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5588     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5589            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5590     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5591     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5592   }
5593
5594   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5595             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5596 }
5597
5598 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5599                                  Intrinsic OpNode> {
5600   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5601     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5602         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5603     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5604         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5605     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5606     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5607   }
5608
5609   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5610             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5611 }
5612
5613
5614
5615 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5616 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5617                                  SDPatternOperator OpNode = null_frag> {
5618   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5619         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5620   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5621   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5622 }
5623
5624 //----------------------------------------------------------------------------
5625 // AdvSIMD scalar pairwise instructions
5626 //----------------------------------------------------------------------------
5627
5628 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5629 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5630                         RegisterOperand regtype, RegisterOperand vectype,
5631                         string asm, string kind>
5632   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5633       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5634     Sched<[WriteV]> {
5635   bits<5> Rd;
5636   bits<5> Rn;
5637   let Inst{31-30} = 0b01;
5638   let Inst{29}    = U;
5639   let Inst{28-24} = 0b11110;
5640   let Inst{23-22} = size;
5641   let Inst{21-17} = 0b11000;
5642   let Inst{16-12} = opcode;
5643   let Inst{11-10} = 0b10;
5644   let Inst{9-5}   = Rn;
5645   let Inst{4-0}   = Rd;
5646 }
5647
5648 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5649   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5650                                       asm, ".2d">;
5651 }
5652
5653 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5654   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5655                                       asm, ".2s">;
5656   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5657                                       asm, ".2d">;
5658 }
5659
5660 //----------------------------------------------------------------------------
5661 // AdvSIMD across lanes instructions
5662 //----------------------------------------------------------------------------
5663
5664 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5665 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5666                           RegisterClass regtype, RegisterOperand vectype,
5667                           string asm, string kind, list<dag> pattern>
5668   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5669       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5670     Sched<[WriteV]> {
5671   bits<5> Rd;
5672   bits<5> Rn;
5673   let Inst{31}    = 0;
5674   let Inst{30}    = Q;
5675   let Inst{29}    = U;
5676   let Inst{28-24} = 0b01110;
5677   let Inst{23-22} = size;
5678   let Inst{21-17} = 0b11000;
5679   let Inst{16-12} = opcode;
5680   let Inst{11-10} = 0b10;
5681   let Inst{9-5}   = Rn;
5682   let Inst{4-0}   = Rd;
5683 }
5684
5685 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5686                               string asm> {
5687   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5688                                    asm, ".8b", []>;
5689   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5690                                    asm, ".16b", []>;
5691   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5692                                    asm, ".4h", []>;
5693   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5694                                    asm, ".8h", []>;
5695   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5696                                    asm, ".4s", []>;
5697 }
5698
5699 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5700   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5701                                    asm, ".8b", []>;
5702   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5703                                    asm, ".16b", []>;
5704   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5705                                    asm, ".4h", []>;
5706   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5707                                    asm, ".8h", []>;
5708   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5709                                    asm, ".4s", []>;
5710 }
5711
5712 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5713                             Intrinsic intOp> {
5714   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5715                                    asm, ".4s",
5716         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5717 }
5718
5719 //----------------------------------------------------------------------------
5720 // AdvSIMD INS/DUP instructions
5721 //----------------------------------------------------------------------------
5722
5723 // FIXME: There has got to be a better way to factor these. ugh.
5724
5725 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5726                      string operands, string constraints, list<dag> pattern>
5727   : I<outs, ins, asm, operands, constraints, pattern>,
5728     Sched<[WriteV]> {
5729   bits<5> Rd;
5730   bits<5> Rn;
5731   let Inst{31} = 0;
5732   let Inst{30} = Q;
5733   let Inst{29} = op;
5734   let Inst{28-21} = 0b01110000;
5735   let Inst{15} = 0;
5736   let Inst{10} = 1;
5737   let Inst{9-5} = Rn;
5738   let Inst{4-0} = Rd;
5739 }
5740
5741 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5742                       RegisterOperand vecreg, RegisterClass regtype>
5743   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5744                    "{\t$Rd" # size # ", $Rn" #
5745                    "|" # size # "\t$Rd, $Rn}", "",
5746                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
5747   let Inst{20-16} = imm5;
5748   let Inst{14-11} = 0b0001;
5749 }
5750
5751 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5752                          ValueType vectype, ValueType insreg,
5753                          RegisterOperand vecreg, Operand idxtype,
5754                          ValueType elttype, SDNode OpNode>
5755   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5756                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5757                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5758                  [(set (vectype vecreg:$Rd),
5759                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5760   let Inst{14-11} = 0b0000;
5761 }
5762
5763 class SIMDDup64FromElement
5764   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5765                        VectorIndexD, i64, AArch64duplane64> {
5766   bits<1> idx;
5767   let Inst{20} = idx;
5768   let Inst{19-16} = 0b1000;
5769 }
5770
5771 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5772                            RegisterOperand vecreg>
5773   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5774                        VectorIndexS, i64, AArch64duplane32> {
5775   bits<2> idx;
5776   let Inst{20-19} = idx;
5777   let Inst{18-16} = 0b100;
5778 }
5779
5780 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5781                            RegisterOperand vecreg>
5782   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5783                        VectorIndexH, i64, AArch64duplane16> {
5784   bits<3> idx;
5785   let Inst{20-18} = idx;
5786   let Inst{17-16} = 0b10;
5787 }
5788
5789 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5790                           RegisterOperand vecreg>
5791   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5792                        VectorIndexB, i64, AArch64duplane8> {
5793   bits<4> idx;
5794   let Inst{20-17} = idx;
5795   let Inst{16} = 1;
5796 }
5797
5798 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5799                   Operand idxtype, string asm, list<dag> pattern>
5800   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5801                    "{\t$Rd, $Rn" # size # "$idx" #
5802                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5803   let Inst{14-11} = imm4;
5804 }
5805
5806 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5807                Operand idxtype>
5808   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5809 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5810                Operand idxtype>
5811   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5812       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5813
5814 class SIMDMovAlias<string asm, string size, Instruction inst,
5815                    RegisterClass regtype, Operand idxtype>
5816     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5817                     "|" # size # "\t$dst, $src$idx}",
5818                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5819
5820 multiclass SMov {
5821   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5822     bits<4> idx;
5823     let Inst{20-17} = idx;
5824     let Inst{16} = 1;
5825   }
5826   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5827     bits<4> idx;
5828     let Inst{20-17} = idx;
5829     let Inst{16} = 1;
5830   }
5831   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5832     bits<3> idx;
5833     let Inst{20-18} = idx;
5834     let Inst{17-16} = 0b10;
5835   }
5836   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5837     bits<3> idx;
5838     let Inst{20-18} = idx;
5839     let Inst{17-16} = 0b10;
5840   }
5841   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5842     bits<2> idx;
5843     let Inst{20-19} = idx;
5844     let Inst{18-16} = 0b100;
5845   }
5846 }
5847
5848 multiclass UMov {
5849   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5850     bits<4> idx;
5851     let Inst{20-17} = idx;
5852     let Inst{16} = 1;
5853   }
5854   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5855     bits<3> idx;
5856     let Inst{20-18} = idx;
5857     let Inst{17-16} = 0b10;
5858   }
5859   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5860     bits<2> idx;
5861     let Inst{20-19} = idx;
5862     let Inst{18-16} = 0b100;
5863   }
5864   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5865     bits<1> idx;
5866     let Inst{20} = idx;
5867     let Inst{19-16} = 0b1000;
5868   }
5869   def : SIMDMovAlias<"mov", ".s",
5870                      !cast<Instruction>(NAME#"vi32"),
5871                      GPR32, VectorIndexS>;
5872   def : SIMDMovAlias<"mov", ".d",
5873                      !cast<Instruction>(NAME#"vi64"),
5874                      GPR64, VectorIndexD>;
5875 }
5876
5877 class SIMDInsFromMain<string size, ValueType vectype,
5878                       RegisterClass regtype, Operand idxtype>
5879   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5880                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5881                    "{\t$Rd" # size # "$idx, $Rn" #
5882                    "|" # size # "\t$Rd$idx, $Rn}",
5883                    "$Rd = $dst",
5884             [(set V128:$dst,
5885               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5886   let Inst{14-11} = 0b0011;
5887 }
5888
5889 class SIMDInsFromElement<string size, ValueType vectype,
5890                          ValueType elttype, Operand idxtype>
5891   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5892                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5893                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5894                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
5895                    "$Rd = $dst",
5896          [(set V128:$dst,
5897                (vector_insert
5898                  (vectype V128:$Rd),
5899                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5900                  idxtype:$idx))]>;
5901
5902 class SIMDInsMainMovAlias<string size, Instruction inst,
5903                           RegisterClass regtype, Operand idxtype>
5904     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5905                         "|" # size #"\t$dst$idx, $src}",
5906                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5907 class SIMDInsElementMovAlias<string size, Instruction inst,
5908                              Operand idxtype>
5909     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5910                       # "|" # size #" $dst$idx, $src$idx2}",
5911                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5912
5913
5914 multiclass SIMDIns {
5915   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5916     bits<4> idx;
5917     let Inst{20-17} = idx;
5918     let Inst{16} = 1;
5919   }
5920   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5921     bits<3> idx;
5922     let Inst{20-18} = idx;
5923     let Inst{17-16} = 0b10;
5924   }
5925   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5926     bits<2> idx;
5927     let Inst{20-19} = idx;
5928     let Inst{18-16} = 0b100;
5929   }
5930   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5931     bits<1> idx;
5932     let Inst{20} = idx;
5933     let Inst{19-16} = 0b1000;
5934   }
5935
5936   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5937     bits<4> idx;
5938     bits<4> idx2;
5939     let Inst{20-17} = idx;
5940     let Inst{16} = 1;
5941     let Inst{14-11} = idx2;
5942   }
5943   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5944     bits<3> idx;
5945     bits<3> idx2;
5946     let Inst{20-18} = idx;
5947     let Inst{17-16} = 0b10;
5948     let Inst{14-12} = idx2;
5949     let Inst{11} = {?};
5950   }
5951   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5952     bits<2> idx;
5953     bits<2> idx2;
5954     let Inst{20-19} = idx;
5955     let Inst{18-16} = 0b100;
5956     let Inst{14-13} = idx2;
5957     let Inst{12-11} = {?,?};
5958   }
5959   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5960     bits<1> idx;
5961     bits<1> idx2;
5962     let Inst{20} = idx;
5963     let Inst{19-16} = 0b1000;
5964     let Inst{14} = idx2;
5965     let Inst{13-11} = {?,?,?};
5966   }
5967
5968   // For all forms of the INS instruction, the "mov" mnemonic is the
5969   // preferred alias. Why they didn't just call the instruction "mov" in
5970   // the first place is a very good question indeed...
5971   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5972                          GPR32, VectorIndexB>;
5973   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5974                          GPR32, VectorIndexH>;
5975   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5976                          GPR32, VectorIndexS>;
5977   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5978                          GPR64, VectorIndexD>;
5979
5980   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5981                          VectorIndexB>;
5982   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5983                          VectorIndexH>;
5984   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5985                          VectorIndexS>;
5986   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5987                          VectorIndexD>;
5988 }
5989
5990 //----------------------------------------------------------------------------
5991 // AdvSIMD TBL/TBX
5992 //----------------------------------------------------------------------------
5993
5994 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5995 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5996                           RegisterOperand listtype, string asm, string kind>
5997   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5998        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5999     Sched<[WriteV]> {
6000   bits<5> Vd;
6001   bits<5> Vn;
6002   bits<5> Vm;
6003   let Inst{31}    = 0;
6004   let Inst{30}    = Q;
6005   let Inst{29-21} = 0b001110000;
6006   let Inst{20-16} = Vm;
6007   let Inst{15}    = 0;
6008   let Inst{14-13} = len;
6009   let Inst{12}    = op;
6010   let Inst{11-10} = 0b00;
6011   let Inst{9-5}   = Vn;
6012   let Inst{4-0}   = Vd;
6013 }
6014
6015 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6016 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6017                           RegisterOperand listtype, string asm, string kind>
6018   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6019        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6020     Sched<[WriteV]> {
6021   bits<5> Vd;
6022   bits<5> Vn;
6023   bits<5> Vm;
6024   let Inst{31}    = 0;
6025   let Inst{30}    = Q;
6026   let Inst{29-21} = 0b001110000;
6027   let Inst{20-16} = Vm;
6028   let Inst{15}    = 0;
6029   let Inst{14-13} = len;
6030   let Inst{12}    = op;
6031   let Inst{11-10} = 0b00;
6032   let Inst{9-5}   = Vn;
6033   let Inst{4-0}   = Vd;
6034 }
6035
6036 class SIMDTableLookupAlias<string asm, Instruction inst,
6037                           RegisterOperand vectype, RegisterOperand listtype>
6038     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6039                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6040
6041 multiclass SIMDTableLookup<bit op, string asm> {
6042   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6043                                       asm, ".8b">;
6044   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6045                                       asm, ".8b">;
6046   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6047                                       asm, ".8b">;
6048   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6049                                       asm, ".8b">;
6050   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6051                                       asm, ".16b">;
6052   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6053                                       asm, ".16b">;
6054   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6055                                       asm, ".16b">;
6056   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6057                                       asm, ".16b">;
6058
6059   def : SIMDTableLookupAlias<asm # ".8b",
6060                          !cast<Instruction>(NAME#"v8i8One"),
6061                          V64, VecListOne128>;
6062   def : SIMDTableLookupAlias<asm # ".8b",
6063                          !cast<Instruction>(NAME#"v8i8Two"),
6064                          V64, VecListTwo128>;
6065   def : SIMDTableLookupAlias<asm # ".8b",
6066                          !cast<Instruction>(NAME#"v8i8Three"),
6067                          V64, VecListThree128>;
6068   def : SIMDTableLookupAlias<asm # ".8b",
6069                          !cast<Instruction>(NAME#"v8i8Four"),
6070                          V64, VecListFour128>;
6071   def : SIMDTableLookupAlias<asm # ".16b",
6072                          !cast<Instruction>(NAME#"v16i8One"),
6073                          V128, VecListOne128>;
6074   def : SIMDTableLookupAlias<asm # ".16b",
6075                          !cast<Instruction>(NAME#"v16i8Two"),
6076                          V128, VecListTwo128>;
6077   def : SIMDTableLookupAlias<asm # ".16b",
6078                          !cast<Instruction>(NAME#"v16i8Three"),
6079                          V128, VecListThree128>;
6080   def : SIMDTableLookupAlias<asm # ".16b",
6081                          !cast<Instruction>(NAME#"v16i8Four"),
6082                          V128, VecListFour128>;
6083 }
6084
6085 multiclass SIMDTableLookupTied<bit op, string asm> {
6086   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6087                                       asm, ".8b">;
6088   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6089                                       asm, ".8b">;
6090   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6091                                       asm, ".8b">;
6092   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6093                                       asm, ".8b">;
6094   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6095                                       asm, ".16b">;
6096   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6097                                       asm, ".16b">;
6098   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6099                                       asm, ".16b">;
6100   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6101                                       asm, ".16b">;
6102
6103   def : SIMDTableLookupAlias<asm # ".8b",
6104                          !cast<Instruction>(NAME#"v8i8One"),
6105                          V64, VecListOne128>;
6106   def : SIMDTableLookupAlias<asm # ".8b",
6107                          !cast<Instruction>(NAME#"v8i8Two"),
6108                          V64, VecListTwo128>;
6109   def : SIMDTableLookupAlias<asm # ".8b",
6110                          !cast<Instruction>(NAME#"v8i8Three"),
6111                          V64, VecListThree128>;
6112   def : SIMDTableLookupAlias<asm # ".8b",
6113                          !cast<Instruction>(NAME#"v8i8Four"),
6114                          V64, VecListFour128>;
6115   def : SIMDTableLookupAlias<asm # ".16b",
6116                          !cast<Instruction>(NAME#"v16i8One"),
6117                          V128, VecListOne128>;
6118   def : SIMDTableLookupAlias<asm # ".16b",
6119                          !cast<Instruction>(NAME#"v16i8Two"),
6120                          V128, VecListTwo128>;
6121   def : SIMDTableLookupAlias<asm # ".16b",
6122                          !cast<Instruction>(NAME#"v16i8Three"),
6123                          V128, VecListThree128>;
6124   def : SIMDTableLookupAlias<asm # ".16b",
6125                          !cast<Instruction>(NAME#"v16i8Four"),
6126                          V128, VecListFour128>;
6127 }
6128
6129
6130 //----------------------------------------------------------------------------
6131 // AdvSIMD scalar CPY
6132 //----------------------------------------------------------------------------
6133 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6134 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6135                         string kind, Operand idxtype>
6136   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6137        "{\t$dst, $src" # kind # "$idx" #
6138        "|\t$dst, $src$idx}", "", []>,
6139     Sched<[WriteV]> {
6140   bits<5> dst;
6141   bits<5> src;
6142   let Inst{31-21} = 0b01011110000;
6143   let Inst{15-10} = 0b000001;
6144   let Inst{9-5}   = src;
6145   let Inst{4-0}   = dst;
6146 }
6147
6148 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6149       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6150     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6151                     # "|\t$dst, $src$index}",
6152                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6153
6154
6155 multiclass SIMDScalarCPY<string asm> {
6156   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6157     bits<4> idx;
6158     let Inst{20-17} = idx;
6159     let Inst{16} = 1;
6160   }
6161   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6162     bits<3> idx;
6163     let Inst{20-18} = idx;
6164     let Inst{17-16} = 0b10;
6165   }
6166   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6167     bits<2> idx;
6168     let Inst{20-19} = idx;
6169     let Inst{18-16} = 0b100;
6170   }
6171   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6172     bits<1> idx;
6173     let Inst{20} = idx;
6174     let Inst{19-16} = 0b1000;
6175   }
6176
6177   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6178                                                           VectorIndexD:$idx)))),
6179             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6180
6181   // 'DUP' mnemonic aliases.
6182   def : SIMDScalarCPYAlias<"dup", ".b",
6183                            !cast<Instruction>(NAME#"i8"),
6184                            FPR8, V128, VectorIndexB>;
6185   def : SIMDScalarCPYAlias<"dup", ".h",
6186                            !cast<Instruction>(NAME#"i16"),
6187                            FPR16, V128, VectorIndexH>;
6188   def : SIMDScalarCPYAlias<"dup", ".s",
6189                            !cast<Instruction>(NAME#"i32"),
6190                            FPR32, V128, VectorIndexS>;
6191   def : SIMDScalarCPYAlias<"dup", ".d",
6192                            !cast<Instruction>(NAME#"i64"),
6193                            FPR64, V128, VectorIndexD>;
6194 }
6195
6196 //----------------------------------------------------------------------------
6197 // AdvSIMD modified immediate instructions
6198 //----------------------------------------------------------------------------
6199
6200 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
6201                           string asm, string op_string,
6202                           string cstr, list<dag> pattern>
6203   : I<oops, iops, asm, op_string, cstr, pattern>,
6204     Sched<[WriteV]> {
6205   bits<5> Rd;
6206   bits<8> imm8;
6207   let Inst{31}    = 0;
6208   let Inst{30}    = Q;
6209   let Inst{29}    = op;
6210   let Inst{28-19} = 0b0111100000;
6211   let Inst{18-16} = imm8{7-5};
6212   let Inst{11-10} = 0b01;
6213   let Inst{9-5}   = imm8{4-0};
6214   let Inst{4-0}   = Rd;
6215 }
6216
6217 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
6218                                 Operand immtype, dag opt_shift_iop,
6219                                 string opt_shift, string asm, string kind,
6220                                 list<dag> pattern>
6221   : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
6222                         !con((ins immtype:$imm8), opt_shift_iop), asm,
6223                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
6224                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6225                         "", pattern> {
6226   let DecoderMethod = "DecodeModImmInstruction";
6227 }
6228
6229 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6230                                 Operand immtype, dag opt_shift_iop,
6231                                 string opt_shift, string asm, string kind,
6232                                 list<dag> pattern>
6233   : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
6234                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6235                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6236                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6237                         "$Rd = $dst", pattern> {
6238   let DecoderMethod = "DecodeModImmTiedInstruction";
6239 }
6240
6241 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6242                                      RegisterOperand vectype, string asm,
6243                                      string kind, list<dag> pattern>
6244   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6245                               (ins logical_vec_shift:$shift),
6246                               "$shift", asm, kind, pattern> {
6247   bits<2> shift;
6248   let Inst{15}    = b15_b12{1};
6249   let Inst{14-13} = shift;
6250   let Inst{12}    = b15_b12{0};
6251 }
6252
6253 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6254                                      RegisterOperand vectype, string asm,
6255                                      string kind, list<dag> pattern>
6256   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6257                               (ins logical_vec_shift:$shift),
6258                               "$shift", asm, kind, pattern> {
6259   bits<2> shift;
6260   let Inst{15}    = b15_b12{1};
6261   let Inst{14-13} = shift;
6262   let Inst{12}    = b15_b12{0};
6263 }
6264
6265
6266 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6267                                          RegisterOperand vectype, string asm,
6268                                          string kind, list<dag> pattern>
6269   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6270                               (ins logical_vec_hw_shift:$shift),
6271                               "$shift", asm, kind, pattern> {
6272   bits<2> shift;
6273   let Inst{15} = b15_b12{1};
6274   let Inst{14} = 0;
6275   let Inst{13} = shift{0};
6276   let Inst{12} = b15_b12{0};
6277 }
6278
6279 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6280                                          RegisterOperand vectype, string asm,
6281                                          string kind, list<dag> pattern>
6282   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6283                               (ins logical_vec_hw_shift:$shift),
6284                               "$shift", asm, kind, pattern> {
6285   bits<2> shift;
6286   let Inst{15} = b15_b12{1};
6287   let Inst{14} = 0;
6288   let Inst{13} = shift{0};
6289   let Inst{12} = b15_b12{0};
6290 }
6291
6292 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6293                                       string asm> {
6294   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6295                                                  asm, ".4h", []>;
6296   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6297                                                  asm, ".8h", []>;
6298
6299   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6300                                              asm, ".2s", []>;
6301   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6302                                              asm, ".4s", []>;
6303 }
6304
6305 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6306                                       bits<2> w_cmode, string asm,
6307                                       SDNode OpNode> {
6308   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6309                                                  asm, ".4h",
6310              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6311                                              imm0_255:$imm8,
6312                                              (i32 imm:$shift)))]>;
6313   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6314                                                  asm, ".8h",
6315              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6316                                               imm0_255:$imm8,
6317                                               (i32 imm:$shift)))]>;
6318
6319   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6320                                              asm, ".2s",
6321              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6322                                              imm0_255:$imm8,
6323                                              (i32 imm:$shift)))]>;
6324   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6325                                              asm, ".4s",
6326              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6327                                               imm0_255:$imm8,
6328                                               (i32 imm:$shift)))]>;
6329 }
6330
6331 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6332                              RegisterOperand vectype, string asm,
6333                              string kind, list<dag> pattern>
6334   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6335                               (ins move_vec_shift:$shift),
6336                               "$shift", asm, kind, pattern> {
6337   bits<1> shift;
6338   let Inst{15-13} = cmode{3-1};
6339   let Inst{12}    = shift;
6340 }
6341
6342 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
6343                                    RegisterOperand vectype,
6344                                    Operand imm_type, string asm,
6345                                    string kind, list<dag> pattern>
6346   : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
6347                               asm, kind, pattern> {
6348   let Inst{15-12} = cmode;
6349 }
6350
6351 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6352                                    list<dag> pattern>
6353   : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6354                         "\t$Rd, $imm8", "", pattern> {
6355   let Inst{15-12} = cmode;
6356   let DecoderMethod = "DecodeModImmInstruction";
6357 }
6358
6359 //----------------------------------------------------------------------------
6360 // AdvSIMD indexed element
6361 //----------------------------------------------------------------------------
6362
6363 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6364 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6365                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6366                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6367                       string apple_kind, string dst_kind, string lhs_kind,
6368                       string rhs_kind, list<dag> pattern>
6369   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6370       asm,
6371       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6372       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6373     Sched<[WriteV]> {
6374   bits<5> Rd;
6375   bits<5> Rn;
6376   bits<5> Rm;
6377
6378   let Inst{31}    = 0;
6379   let Inst{30}    = Q;
6380   let Inst{29}    = U;
6381   let Inst{28}    = Scalar;
6382   let Inst{27-24} = 0b1111;
6383   let Inst{23-22} = size;
6384   // Bit 21 must be set by the derived class.
6385   let Inst{20-16} = Rm;
6386   let Inst{15-12} = opc;
6387   // Bit 11 must be set by the derived class.
6388   let Inst{10}    = 0;
6389   let Inst{9-5}   = Rn;
6390   let Inst{4-0}   = Rd;
6391 }
6392
6393 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6394 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6395                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6396                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6397                       string apple_kind, string dst_kind, string lhs_kind,
6398                       string rhs_kind, list<dag> pattern>
6399   : I<(outs dst_reg:$dst),
6400       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6401       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6402       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6403     Sched<[WriteV]> {
6404   bits<5> Rd;
6405   bits<5> Rn;
6406   bits<5> Rm;
6407
6408   let Inst{31}    = 0;
6409   let Inst{30}    = Q;
6410   let Inst{29}    = U;
6411   let Inst{28}    = Scalar;
6412   let Inst{27-24} = 0b1111;
6413   let Inst{23-22} = size;
6414   // Bit 21 must be set by the derived class.
6415   let Inst{20-16} = Rm;
6416   let Inst{15-12} = opc;
6417   // Bit 11 must be set by the derived class.
6418   let Inst{10}    = 0;
6419   let Inst{9-5}   = Rn;
6420   let Inst{4-0}   = Rd;
6421 }
6422
6423 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
6424                            SDPatternOperator OpNode> {
6425   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6426                                       V64, V64,
6427                                       V128, VectorIndexS,
6428                                       asm, ".2s", ".2s", ".2s", ".s",
6429     [(set (v2f32 V64:$Rd),
6430         (OpNode (v2f32 V64:$Rn),
6431          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6432     bits<2> idx;
6433     let Inst{11} = idx{1};
6434     let Inst{21} = idx{0};
6435   }
6436
6437   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6438                                       V128, V128,
6439                                       V128, VectorIndexS,
6440                                       asm, ".4s", ".4s", ".4s", ".s",
6441     [(set (v4f32 V128:$Rd),
6442         (OpNode (v4f32 V128:$Rn),
6443          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6444     bits<2> idx;
6445     let Inst{11} = idx{1};
6446     let Inst{21} = idx{0};
6447   }
6448
6449   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6450                                       V128, V128,
6451                                       V128, VectorIndexD,
6452                                       asm, ".2d", ".2d", ".2d", ".d",
6453     [(set (v2f64 V128:$Rd),
6454         (OpNode (v2f64 V128:$Rn),
6455          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6456     bits<1> idx;
6457     let Inst{11} = idx{0};
6458     let Inst{21} = 0;
6459   }
6460
6461   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6462                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6463                                       asm, ".s", "", "", ".s",
6464     [(set (f32 FPR32Op:$Rd),
6465           (OpNode (f32 FPR32Op:$Rn),
6466                   (f32 (vector_extract (v4f32 V128:$Rm),
6467                                        VectorIndexS:$idx))))]> {
6468     bits<2> idx;
6469     let Inst{11} = idx{1};
6470     let Inst{21} = idx{0};
6471   }
6472
6473   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6474                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6475                                       asm, ".d", "", "", ".d",
6476     [(set (f64 FPR64Op:$Rd),
6477           (OpNode (f64 FPR64Op:$Rn),
6478                   (f64 (vector_extract (v2f64 V128:$Rm),
6479                                        VectorIndexD:$idx))))]> {
6480     bits<1> idx;
6481     let Inst{11} = idx{0};
6482     let Inst{21} = 0;
6483   }
6484 }
6485
6486 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6487   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6488   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6489                            (AArch64duplane32 (v4f32 V128:$Rm),
6490                                            VectorIndexS:$idx))),
6491             (!cast<Instruction>(INST # v2i32_indexed)
6492                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6493   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6494                            (AArch64dup (f32 FPR32Op:$Rm)))),
6495             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6496                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6497
6498
6499   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6500   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6501                            (AArch64duplane32 (v4f32 V128:$Rm),
6502                                            VectorIndexS:$idx))),
6503             (!cast<Instruction>(INST # "v4i32_indexed")
6504                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6505   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6506                            (AArch64dup (f32 FPR32Op:$Rm)))),
6507             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6508                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6509
6510   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6511   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6512                            (AArch64duplane64 (v2f64 V128:$Rm),
6513                                            VectorIndexD:$idx))),
6514             (!cast<Instruction>(INST # "v2i64_indexed")
6515                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6516   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6517                            (AArch64dup (f64 FPR64Op:$Rm)))),
6518             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6519                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6520
6521   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6522   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6523                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6524             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6525                 V128:$Rm, VectorIndexS:$idx)>;
6526   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6527                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6528             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6529                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6530
6531   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6532   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6533                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6534             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6535                 V128:$Rm, VectorIndexD:$idx)>;
6536 }
6537
6538 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6539   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6540                                           V128, VectorIndexS,
6541                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6542     bits<2> idx;
6543     let Inst{11} = idx{1};
6544     let Inst{21} = idx{0};
6545   }
6546
6547   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6548                                       V128, V128,
6549                                       V128, VectorIndexS,
6550                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6551     bits<2> idx;
6552     let Inst{11} = idx{1};
6553     let Inst{21} = idx{0};
6554   }
6555
6556   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6557                                       V128, V128,
6558                                       V128, VectorIndexD,
6559                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6560     bits<1> idx;
6561     let Inst{11} = idx{0};
6562     let Inst{21} = 0;
6563   }
6564
6565
6566   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6567                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6568                                       asm, ".s", "", "", ".s", []> {
6569     bits<2> idx;
6570     let Inst{11} = idx{1};
6571     let Inst{21} = idx{0};
6572   }
6573
6574   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6575                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6576                                       asm, ".d", "", "", ".d", []> {
6577     bits<1> idx;
6578     let Inst{11} = idx{0};
6579     let Inst{21} = 0;
6580   }
6581 }
6582
6583 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6584                          SDPatternOperator OpNode> {
6585   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6586                                       V128_lo, VectorIndexH,
6587                                       asm, ".4h", ".4h", ".4h", ".h",
6588     [(set (v4i16 V64:$Rd),
6589         (OpNode (v4i16 V64:$Rn),
6590          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6591     bits<3> idx;
6592     let Inst{11} = idx{2};
6593     let Inst{21} = idx{1};
6594     let Inst{20} = idx{0};
6595   }
6596
6597   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6598                                       V128, V128,
6599                                       V128_lo, VectorIndexH,
6600                                       asm, ".8h", ".8h", ".8h", ".h",
6601     [(set (v8i16 V128:$Rd),
6602        (OpNode (v8i16 V128:$Rn),
6603          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6604     bits<3> idx;
6605     let Inst{11} = idx{2};
6606     let Inst{21} = idx{1};
6607     let Inst{20} = idx{0};
6608   }
6609
6610   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6611                                       V64, V64,
6612                                       V128, VectorIndexS,
6613                                       asm, ".2s", ".2s", ".2s",  ".s",
6614     [(set (v2i32 V64:$Rd),
6615        (OpNode (v2i32 V64:$Rn),
6616           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6617     bits<2> idx;
6618     let Inst{11} = idx{1};
6619     let Inst{21} = idx{0};
6620   }
6621
6622   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6623                                       V128, V128,
6624                                       V128, VectorIndexS,
6625                                       asm, ".4s", ".4s", ".4s", ".s",
6626     [(set (v4i32 V128:$Rd),
6627        (OpNode (v4i32 V128:$Rn),
6628           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6629     bits<2> idx;
6630     let Inst{11} = idx{1};
6631     let Inst{21} = idx{0};
6632   }
6633
6634   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6635                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6636                                       asm, ".h", "", "", ".h", []> {
6637     bits<3> idx;
6638     let Inst{11} = idx{2};
6639     let Inst{21} = idx{1};
6640     let Inst{20} = idx{0};
6641   }
6642
6643   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6644                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6645                                       asm, ".s", "", "", ".s",
6646       [(set (i32 FPR32Op:$Rd),
6647             (OpNode FPR32Op:$Rn,
6648                     (i32 (vector_extract (v4i32 V128:$Rm),
6649                                          VectorIndexS:$idx))))]> {
6650     bits<2> idx;
6651     let Inst{11} = idx{1};
6652     let Inst{21} = idx{0};
6653   }
6654 }
6655
6656 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6657                                SDPatternOperator OpNode> {
6658   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6659                                       V64, V64,
6660                                       V128_lo, VectorIndexH,
6661                                       asm, ".4h", ".4h", ".4h", ".h",
6662     [(set (v4i16 V64:$Rd),
6663         (OpNode (v4i16 V64:$Rn),
6664          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6665     bits<3> idx;
6666     let Inst{11} = idx{2};
6667     let Inst{21} = idx{1};
6668     let Inst{20} = idx{0};
6669   }
6670
6671   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6672                                       V128, V128,
6673                                       V128_lo, VectorIndexH,
6674                                       asm, ".8h", ".8h", ".8h", ".h",
6675     [(set (v8i16 V128:$Rd),
6676        (OpNode (v8i16 V128:$Rn),
6677          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6678     bits<3> idx;
6679     let Inst{11} = idx{2};
6680     let Inst{21} = idx{1};
6681     let Inst{20} = idx{0};
6682   }
6683
6684   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6685                                       V64, V64,
6686                                       V128, VectorIndexS,
6687                                       asm, ".2s", ".2s", ".2s", ".s",
6688     [(set (v2i32 V64:$Rd),
6689        (OpNode (v2i32 V64:$Rn),
6690           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6691     bits<2> idx;
6692     let Inst{11} = idx{1};
6693     let Inst{21} = idx{0};
6694   }
6695
6696   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6697                                       V128, V128,
6698                                       V128, VectorIndexS,
6699                                       asm, ".4s", ".4s", ".4s", ".s",
6700     [(set (v4i32 V128:$Rd),
6701        (OpNode (v4i32 V128:$Rn),
6702           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6703     bits<2> idx;
6704     let Inst{11} = idx{1};
6705     let Inst{21} = idx{0};
6706   }
6707 }
6708
6709 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6710                                    SDPatternOperator OpNode> {
6711   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6712                                           V128_lo, VectorIndexH,
6713                                           asm, ".4h", ".4h", ".4h", ".h",
6714     [(set (v4i16 V64:$dst),
6715         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6716          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6717     bits<3> idx;
6718     let Inst{11} = idx{2};
6719     let Inst{21} = idx{1};
6720     let Inst{20} = idx{0};
6721   }
6722
6723   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6724                                       V128, V128,
6725                                       V128_lo, VectorIndexH,
6726                                       asm, ".8h", ".8h", ".8h", ".h",
6727     [(set (v8i16 V128:$dst),
6728        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6729          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6730     bits<3> idx;
6731     let Inst{11} = idx{2};
6732     let Inst{21} = idx{1};
6733     let Inst{20} = idx{0};
6734   }
6735
6736   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6737                                       V64, V64,
6738                                       V128, VectorIndexS,
6739                                       asm, ".2s", ".2s", ".2s", ".s",
6740     [(set (v2i32 V64:$dst),
6741        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6742           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6743     bits<2> idx;
6744     let Inst{11} = idx{1};
6745     let Inst{21} = idx{0};
6746   }
6747
6748   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6749                                       V128, V128,
6750                                       V128, VectorIndexS,
6751                                       asm, ".4s", ".4s", ".4s", ".s",
6752     [(set (v4i32 V128:$dst),
6753        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6754           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6755     bits<2> idx;
6756     let Inst{11} = idx{1};
6757     let Inst{21} = idx{0};
6758   }
6759 }
6760
6761 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6762                              SDPatternOperator OpNode> {
6763   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6764                                       V128, V64,
6765                                       V128_lo, VectorIndexH,
6766                                       asm, ".4s", ".4s", ".4h", ".h",
6767     [(set (v4i32 V128:$Rd),
6768         (OpNode (v4i16 V64:$Rn),
6769          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6770     bits<3> idx;
6771     let Inst{11} = idx{2};
6772     let Inst{21} = idx{1};
6773     let Inst{20} = idx{0};
6774   }
6775
6776   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6777                                       V128, V128,
6778                                       V128_lo, VectorIndexH,
6779                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6780     [(set (v4i32 V128:$Rd),
6781           (OpNode (extract_high_v8i16 V128:$Rn),
6782                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6783                                                       VectorIndexH:$idx))))]> {
6784
6785     bits<3> idx;
6786     let Inst{11} = idx{2};
6787     let Inst{21} = idx{1};
6788     let Inst{20} = idx{0};
6789   }
6790
6791   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6792                                       V128, V64,
6793                                       V128, VectorIndexS,
6794                                       asm, ".2d", ".2d", ".2s", ".s",
6795     [(set (v2i64 V128:$Rd),
6796         (OpNode (v2i32 V64:$Rn),
6797          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6798     bits<2> idx;
6799     let Inst{11} = idx{1};
6800     let Inst{21} = idx{0};
6801   }
6802
6803   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6804                                       V128, V128,
6805                                       V128, VectorIndexS,
6806                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6807     [(set (v2i64 V128:$Rd),
6808           (OpNode (extract_high_v4i32 V128:$Rn),
6809                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
6810                                                       VectorIndexS:$idx))))]> {
6811     bits<2> idx;
6812     let Inst{11} = idx{1};
6813     let Inst{21} = idx{0};
6814   }
6815
6816   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6817                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6818                                       asm, ".h", "", "", ".h", []> {
6819     bits<3> idx;
6820     let Inst{11} = idx{2};
6821     let Inst{21} = idx{1};
6822     let Inst{20} = idx{0};
6823   }
6824
6825   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6826                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6827                                       asm, ".s", "", "", ".s", []> {
6828     bits<2> idx;
6829     let Inst{11} = idx{1};
6830     let Inst{21} = idx{0};
6831   }
6832 }
6833
6834 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6835                                        SDPatternOperator Accum> {
6836   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6837                                       V128, V64,
6838                                       V128_lo, VectorIndexH,
6839                                       asm, ".4s", ".4s", ".4h", ".h",
6840     [(set (v4i32 V128:$dst),
6841           (Accum (v4i32 V128:$Rd),
6842                  (v4i32 (int_aarch64_neon_sqdmull
6843                              (v4i16 V64:$Rn),
6844                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6845                                                     VectorIndexH:$idx))))))]> {
6846     bits<3> idx;
6847     let Inst{11} = idx{2};
6848     let Inst{21} = idx{1};
6849     let Inst{20} = idx{0};
6850   }
6851
6852   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6853   // intermediate EXTRACT_SUBREG would be untyped.
6854   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6855                 (i32 (vector_extract (v4i32
6856                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6857                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6858                                                     VectorIndexH:$idx)))),
6859                          (i64 0))))),
6860             (EXTRACT_SUBREG
6861                 (!cast<Instruction>(NAME # v4i16_indexed)
6862                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6863                     V128_lo:$Rm, VectorIndexH:$idx),
6864                 ssub)>;
6865
6866   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6867                                       V128, V128,
6868                                       V128_lo, VectorIndexH,
6869                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6870     [(set (v4i32 V128:$dst),
6871           (Accum (v4i32 V128:$Rd),
6872                  (v4i32 (int_aarch64_neon_sqdmull
6873                             (extract_high_v8i16 V128:$Rn),
6874                             (extract_high_v8i16
6875                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6876                                                 VectorIndexH:$idx))))))]> {
6877     bits<3> idx;
6878     let Inst{11} = idx{2};
6879     let Inst{21} = idx{1};
6880     let Inst{20} = idx{0};
6881   }
6882
6883   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6884                                       V128, V64,
6885                                       V128, VectorIndexS,
6886                                       asm, ".2d", ".2d", ".2s", ".s",
6887     [(set (v2i64 V128:$dst),
6888         (Accum (v2i64 V128:$Rd),
6889                (v2i64 (int_aarch64_neon_sqdmull
6890                           (v2i32 V64:$Rn),
6891                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
6892                                                  VectorIndexS:$idx))))))]> {
6893     bits<2> idx;
6894     let Inst{11} = idx{1};
6895     let Inst{21} = idx{0};
6896   }
6897
6898   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6899                                       V128, V128,
6900                                       V128, VectorIndexS,
6901                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6902     [(set (v2i64 V128:$dst),
6903           (Accum (v2i64 V128:$Rd),
6904                  (v2i64 (int_aarch64_neon_sqdmull
6905                             (extract_high_v4i32 V128:$Rn),
6906                             (extract_high_v4i32
6907                                 (AArch64duplane32 (v4i32 V128:$Rm),
6908                                                 VectorIndexS:$idx))))))]> {
6909     bits<2> idx;
6910     let Inst{11} = idx{1};
6911     let Inst{21} = idx{0};
6912   }
6913
6914   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6915                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6916                                       asm, ".h", "", "", ".h", []> {
6917     bits<3> idx;
6918     let Inst{11} = idx{2};
6919     let Inst{21} = idx{1};
6920     let Inst{20} = idx{0};
6921   }
6922
6923
6924   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6925                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6926                                       asm, ".s", "", "", ".s",
6927     [(set (i64 FPR64Op:$dst),
6928           (Accum (i64 FPR64Op:$Rd),
6929                  (i64 (int_aarch64_neon_sqdmulls_scalar
6930                             (i32 FPR32Op:$Rn),
6931                             (i32 (vector_extract (v4i32 V128:$Rm),
6932                                                  VectorIndexS:$idx))))))]> {
6933
6934     bits<2> idx;
6935     let Inst{11} = idx{1};
6936     let Inst{21} = idx{0};
6937   }
6938 }
6939
6940 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6941                                    SDPatternOperator OpNode> {
6942   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6943   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6944                                       V128, V64,
6945                                       V128_lo, VectorIndexH,
6946                                       asm, ".4s", ".4s", ".4h", ".h",
6947     [(set (v4i32 V128:$Rd),
6948         (OpNode (v4i16 V64:$Rn),
6949          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6950     bits<3> idx;
6951     let Inst{11} = idx{2};
6952     let Inst{21} = idx{1};
6953     let Inst{20} = idx{0};
6954   }
6955
6956   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6957                                       V128, V128,
6958                                       V128_lo, VectorIndexH,
6959                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6960     [(set (v4i32 V128:$Rd),
6961           (OpNode (extract_high_v8i16 V128:$Rn),
6962                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6963                                                       VectorIndexH:$idx))))]> {
6964
6965     bits<3> idx;
6966     let Inst{11} = idx{2};
6967     let Inst{21} = idx{1};
6968     let Inst{20} = idx{0};
6969   }
6970
6971   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6972                                       V128, V64,
6973                                       V128, VectorIndexS,
6974                                       asm, ".2d", ".2d", ".2s", ".s",
6975     [(set (v2i64 V128:$Rd),
6976         (OpNode (v2i32 V64:$Rn),
6977          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6978     bits<2> idx;
6979     let Inst{11} = idx{1};
6980     let Inst{21} = idx{0};
6981   }
6982
6983   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6984                                       V128, V128,
6985                                       V128, VectorIndexS,
6986                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6987     [(set (v2i64 V128:$Rd),
6988           (OpNode (extract_high_v4i32 V128:$Rn),
6989                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
6990                                                       VectorIndexS:$idx))))]> {
6991     bits<2> idx;
6992     let Inst{11} = idx{1};
6993     let Inst{21} = idx{0};
6994   }
6995   }
6996 }
6997
6998 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6999                                        SDPatternOperator OpNode> {
7000   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7001   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7002                                       V128, V64,
7003                                       V128_lo, VectorIndexH,
7004                                       asm, ".4s", ".4s", ".4h", ".h",
7005     [(set (v4i32 V128:$dst),
7006         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7007          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7008     bits<3> idx;
7009     let Inst{11} = idx{2};
7010     let Inst{21} = idx{1};
7011     let Inst{20} = idx{0};
7012   }
7013
7014   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7015                                       V128, V128,
7016                                       V128_lo, VectorIndexH,
7017                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7018     [(set (v4i32 V128:$dst),
7019           (OpNode (v4i32 V128:$Rd),
7020                   (extract_high_v8i16 V128:$Rn),
7021                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7022                                                       VectorIndexH:$idx))))]> {
7023     bits<3> idx;
7024     let Inst{11} = idx{2};
7025     let Inst{21} = idx{1};
7026     let Inst{20} = idx{0};
7027   }
7028
7029   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7030                                       V128, V64,
7031                                       V128, VectorIndexS,
7032                                       asm, ".2d", ".2d", ".2s", ".s",
7033     [(set (v2i64 V128:$dst),
7034         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7035          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7036     bits<2> idx;
7037     let Inst{11} = idx{1};
7038     let Inst{21} = idx{0};
7039   }
7040
7041   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7042                                       V128, V128,
7043                                       V128, VectorIndexS,
7044                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7045     [(set (v2i64 V128:$dst),
7046           (OpNode (v2i64 V128:$Rd),
7047                   (extract_high_v4i32 V128:$Rn),
7048                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7049                                                       VectorIndexS:$idx))))]> {
7050     bits<2> idx;
7051     let Inst{11} = idx{1};
7052     let Inst{21} = idx{0};
7053   }
7054   }
7055 }
7056
7057 //----------------------------------------------------------------------------
7058 // AdvSIMD scalar shift by immediate
7059 //----------------------------------------------------------------------------
7060
7061 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7062 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7063                      RegisterClass regtype1, RegisterClass regtype2,
7064                      Operand immtype, string asm, list<dag> pattern>
7065   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7066       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7067     Sched<[WriteV]> {
7068   bits<5> Rd;
7069   bits<5> Rn;
7070   bits<7> imm;
7071   let Inst{31-30} = 0b01;
7072   let Inst{29}    = U;
7073   let Inst{28-23} = 0b111110;
7074   let Inst{22-16} = fixed_imm;
7075   let Inst{15-11} = opc;
7076   let Inst{10}    = 1;
7077   let Inst{9-5} = Rn;
7078   let Inst{4-0} = Rd;
7079 }
7080
7081 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7082 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7083                      RegisterClass regtype1, RegisterClass regtype2,
7084                      Operand immtype, string asm, list<dag> pattern>
7085   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7086       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7087     Sched<[WriteV]> {
7088   bits<5> Rd;
7089   bits<5> Rn;
7090   bits<7> imm;
7091   let Inst{31-30} = 0b01;
7092   let Inst{29}    = U;
7093   let Inst{28-23} = 0b111110;
7094   let Inst{22-16} = fixed_imm;
7095   let Inst{15-11} = opc;
7096   let Inst{10}    = 1;
7097   let Inst{9-5} = Rn;
7098   let Inst{4-0} = Rd;
7099 }
7100
7101
7102 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
7103   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7104                               FPR32, FPR32, vecshiftR32, asm, []> {
7105     let Inst{20-16} = imm{4-0};
7106   }
7107
7108   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7109                               FPR64, FPR64, vecshiftR64, asm, []> {
7110     let Inst{21-16} = imm{5-0};
7111   }
7112 }
7113
7114 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7115                              SDPatternOperator OpNode> {
7116   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7117                               FPR64, FPR64, vecshiftR64, asm,
7118   [(set (i64 FPR64:$Rd),
7119      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7120     let Inst{21-16} = imm{5-0};
7121   }
7122
7123   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7124             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7125 }
7126
7127 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7128                                  SDPatternOperator OpNode = null_frag> {
7129   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7130                               FPR64, FPR64, vecshiftR64, asm,
7131   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7132                                                    (i32 vecshiftR64:$imm)))]> {
7133     let Inst{21-16} = imm{5-0};
7134   }
7135
7136   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7137                            (i32 vecshiftR64:$imm))),
7138             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7139                                             vecshiftR64:$imm)>;
7140 }
7141
7142 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7143                              SDPatternOperator OpNode> {
7144   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7145                               FPR64, FPR64, vecshiftL64, asm,
7146     [(set (v1i64 FPR64:$Rd),
7147        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7148     let Inst{21-16} = imm{5-0};
7149   }
7150 }
7151
7152 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7153 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7154   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7155                               FPR64, FPR64, vecshiftL64, asm, []> {
7156     let Inst{21-16} = imm{5-0};
7157   }
7158 }
7159
7160 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7161 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7162                                SDPatternOperator OpNode = null_frag> {
7163   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7164                               FPR8, FPR16, vecshiftR8, asm, []> {
7165     let Inst{18-16} = imm{2-0};
7166   }
7167
7168   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7169                               FPR16, FPR32, vecshiftR16, asm, []> {
7170     let Inst{19-16} = imm{3-0};
7171   }
7172
7173   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7174                               FPR32, FPR64, vecshiftR32, asm,
7175     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7176     let Inst{20-16} = imm{4-0};
7177   }
7178 }
7179
7180 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7181                                 SDPatternOperator OpNode> {
7182   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7183                               FPR8, FPR8, vecshiftL8, asm, []> {
7184     let Inst{18-16} = imm{2-0};
7185   }
7186
7187   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7188                               FPR16, FPR16, vecshiftL16, asm, []> {
7189     let Inst{19-16} = imm{3-0};
7190   }
7191
7192   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7193                               FPR32, FPR32, vecshiftL32, asm,
7194     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7195     let Inst{20-16} = imm{4-0};
7196   }
7197
7198   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7199                               FPR64, FPR64, vecshiftL64, asm,
7200     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7201     let Inst{21-16} = imm{5-0};
7202   }
7203
7204   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7205             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7206 }
7207
7208 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7209   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7210                               FPR8, FPR8, vecshiftR8, asm, []> {
7211     let Inst{18-16} = imm{2-0};
7212   }
7213
7214   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7215                               FPR16, FPR16, vecshiftR16, asm, []> {
7216     let Inst{19-16} = imm{3-0};
7217   }
7218
7219   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7220                               FPR32, FPR32, vecshiftR32, asm, []> {
7221     let Inst{20-16} = imm{4-0};
7222   }
7223
7224   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7225                               FPR64, FPR64, vecshiftR64, asm, []> {
7226     let Inst{21-16} = imm{5-0};
7227   }
7228 }
7229
7230 //----------------------------------------------------------------------------
7231 // AdvSIMD vector x indexed element
7232 //----------------------------------------------------------------------------
7233
7234 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7235 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7236                      RegisterOperand dst_reg, RegisterOperand src_reg,
7237                      Operand immtype,
7238                      string asm, string dst_kind, string src_kind,
7239                      list<dag> pattern>
7240   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7241       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7242            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7243     Sched<[WriteV]> {
7244   bits<5> Rd;
7245   bits<5> Rn;
7246   let Inst{31}    = 0;
7247   let Inst{30}    = Q;
7248   let Inst{29}    = U;
7249   let Inst{28-23} = 0b011110;
7250   let Inst{22-16} = fixed_imm;
7251   let Inst{15-11} = opc;
7252   let Inst{10}    = 1;
7253   let Inst{9-5}   = Rn;
7254   let Inst{4-0}   = Rd;
7255 }
7256
7257 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7258 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7259                      RegisterOperand vectype1, RegisterOperand vectype2,
7260                      Operand immtype,
7261                      string asm, string dst_kind, string src_kind,
7262                      list<dag> pattern>
7263   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7264       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7265            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7266     Sched<[WriteV]> {
7267   bits<5> Rd;
7268   bits<5> Rn;
7269   let Inst{31}    = 0;
7270   let Inst{30}    = Q;
7271   let Inst{29}    = U;
7272   let Inst{28-23} = 0b011110;
7273   let Inst{22-16} = fixed_imm;
7274   let Inst{15-11} = opc;
7275   let Inst{10}    = 1;
7276   let Inst{9-5}   = Rn;
7277   let Inst{4-0}   = Rd;
7278 }
7279
7280 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7281                               Intrinsic OpNode> {
7282   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7283                                   V64, V64, vecshiftR32,
7284                                   asm, ".2s", ".2s",
7285       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
7286     bits<5> imm;
7287     let Inst{20-16} = imm;
7288   }
7289
7290   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7291                                   V128, V128, vecshiftR32,
7292                                   asm, ".4s", ".4s",
7293       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7294     bits<5> imm;
7295     let Inst{20-16} = imm;
7296   }
7297
7298   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7299                                   V128, V128, vecshiftR64,
7300                                   asm, ".2d", ".2d",
7301       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7302     bits<6> imm;
7303     let Inst{21-16} = imm;
7304   }
7305 }
7306
7307 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
7308                                   Intrinsic OpNode> {
7309   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7310                                   V64, V64, vecshiftR32,
7311                                   asm, ".2s", ".2s",
7312       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7313     bits<5> imm;
7314     let Inst{20-16} = imm;
7315   }
7316
7317   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7318                                   V128, V128, vecshiftR32,
7319                                   asm, ".4s", ".4s",
7320       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7321     bits<5> imm;
7322     let Inst{20-16} = imm;
7323   }
7324
7325   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7326                                   V128, V128, vecshiftR64,
7327                                   asm, ".2d", ".2d",
7328       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7329     bits<6> imm;
7330     let Inst{21-16} = imm;
7331   }
7332 }
7333
7334 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7335                                      SDPatternOperator OpNode> {
7336   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7337                                   V64, V128, vecshiftR16Narrow,
7338                                   asm, ".8b", ".8h",
7339       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7340     bits<3> imm;
7341     let Inst{18-16} = imm;
7342   }
7343
7344   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7345                                   V128, V128, vecshiftR16Narrow,
7346                                   asm#"2", ".16b", ".8h", []> {
7347     bits<3> imm;
7348     let Inst{18-16} = imm;
7349     let hasSideEffects = 0;
7350   }
7351
7352   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7353                                   V64, V128, vecshiftR32Narrow,
7354                                   asm, ".4h", ".4s",
7355       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7356     bits<4> imm;
7357     let Inst{19-16} = imm;
7358   }
7359
7360   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7361                                   V128, V128, vecshiftR32Narrow,
7362                                   asm#"2", ".8h", ".4s", []> {
7363     bits<4> imm;
7364     let Inst{19-16} = imm;
7365     let hasSideEffects = 0;
7366   }
7367
7368   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7369                                   V64, V128, vecshiftR64Narrow,
7370                                   asm, ".2s", ".2d",
7371       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7372     bits<5> imm;
7373     let Inst{20-16} = imm;
7374   }
7375
7376   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7377                                   V128, V128, vecshiftR64Narrow,
7378                                   asm#"2", ".4s", ".2d", []> {
7379     bits<5> imm;
7380     let Inst{20-16} = imm;
7381     let hasSideEffects = 0;
7382   }
7383
7384   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7385   // themselves, so put them here instead.
7386
7387   // Patterns involving what's effectively an insert high and a normal
7388   // intrinsic, represented by CONCAT_VECTORS.
7389   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7390                                                    vecshiftR16Narrow:$imm)),
7391             (!cast<Instruction>(NAME # "v16i8_shift")
7392                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7393                 V128:$Rn, vecshiftR16Narrow:$imm)>;
7394   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7395                                                      vecshiftR32Narrow:$imm)),
7396             (!cast<Instruction>(NAME # "v8i16_shift")
7397                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7398                 V128:$Rn, vecshiftR32Narrow:$imm)>;
7399   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7400                                                      vecshiftR64Narrow:$imm)),
7401             (!cast<Instruction>(NAME # "v4i32_shift")
7402                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7403                 V128:$Rn, vecshiftR64Narrow:$imm)>;
7404 }
7405
7406 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7407                                 SDPatternOperator OpNode> {
7408   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7409                                   V64, V64, vecshiftL8,
7410                                   asm, ".8b", ".8b",
7411                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7412                        (i32 vecshiftL8:$imm)))]> {
7413     bits<3> imm;
7414     let Inst{18-16} = imm;
7415   }
7416
7417   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7418                                   V128, V128, vecshiftL8,
7419                                   asm, ".16b", ".16b",
7420              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7421                    (i32 vecshiftL8:$imm)))]> {
7422     bits<3> imm;
7423     let Inst{18-16} = imm;
7424   }
7425
7426   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7427                                   V64, V64, vecshiftL16,
7428                                   asm, ".4h", ".4h",
7429               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7430                     (i32 vecshiftL16:$imm)))]> {
7431     bits<4> imm;
7432     let Inst{19-16} = imm;
7433   }
7434
7435   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7436                                   V128, V128, vecshiftL16,
7437                                   asm, ".8h", ".8h",
7438             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7439                   (i32 vecshiftL16:$imm)))]> {
7440     bits<4> imm;
7441     let Inst{19-16} = imm;
7442   }
7443
7444   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7445                                   V64, V64, vecshiftL32,
7446                                   asm, ".2s", ".2s",
7447               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7448                     (i32 vecshiftL32:$imm)))]> {
7449     bits<5> imm;
7450     let Inst{20-16} = imm;
7451   }
7452
7453   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7454                                   V128, V128, vecshiftL32,
7455                                   asm, ".4s", ".4s",
7456             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7457                   (i32 vecshiftL32:$imm)))]> {
7458     bits<5> imm;
7459     let Inst{20-16} = imm;
7460   }
7461
7462   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7463                                   V128, V128, vecshiftL64,
7464                                   asm, ".2d", ".2d",
7465             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7466                   (i32 vecshiftL64:$imm)))]> {
7467     bits<6> imm;
7468     let Inst{21-16} = imm;
7469   }
7470 }
7471
7472 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7473                                 SDPatternOperator OpNode> {
7474   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7475                                   V64, V64, vecshiftR8,
7476                                   asm, ".8b", ".8b",
7477                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7478                        (i32 vecshiftR8:$imm)))]> {
7479     bits<3> imm;
7480     let Inst{18-16} = imm;
7481   }
7482
7483   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7484                                   V128, V128, vecshiftR8,
7485                                   asm, ".16b", ".16b",
7486              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7487                    (i32 vecshiftR8:$imm)))]> {
7488     bits<3> imm;
7489     let Inst{18-16} = imm;
7490   }
7491
7492   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7493                                   V64, V64, vecshiftR16,
7494                                   asm, ".4h", ".4h",
7495               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7496                     (i32 vecshiftR16:$imm)))]> {
7497     bits<4> imm;
7498     let Inst{19-16} = imm;
7499   }
7500
7501   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7502                                   V128, V128, vecshiftR16,
7503                                   asm, ".8h", ".8h",
7504             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7505                   (i32 vecshiftR16:$imm)))]> {
7506     bits<4> imm;
7507     let Inst{19-16} = imm;
7508   }
7509
7510   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7511                                   V64, V64, vecshiftR32,
7512                                   asm, ".2s", ".2s",
7513               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7514                     (i32 vecshiftR32:$imm)))]> {
7515     bits<5> imm;
7516     let Inst{20-16} = imm;
7517   }
7518
7519   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7520                                   V128, V128, vecshiftR32,
7521                                   asm, ".4s", ".4s",
7522             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7523                   (i32 vecshiftR32:$imm)))]> {
7524     bits<5> imm;
7525     let Inst{20-16} = imm;
7526   }
7527
7528   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7529                                   V128, V128, vecshiftR64,
7530                                   asm, ".2d", ".2d",
7531             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7532                   (i32 vecshiftR64:$imm)))]> {
7533     bits<6> imm;
7534     let Inst{21-16} = imm;
7535   }
7536 }
7537
7538 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7539 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7540                                     SDPatternOperator OpNode = null_frag> {
7541   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7542                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
7543                  [(set (v8i8 V64:$dst),
7544                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7545                            (i32 vecshiftR8:$imm)))]> {
7546     bits<3> imm;
7547     let Inst{18-16} = imm;
7548   }
7549
7550   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7551                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
7552              [(set (v16i8 V128:$dst),
7553                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7554                        (i32 vecshiftR8:$imm)))]> {
7555     bits<3> imm;
7556     let Inst{18-16} = imm;
7557   }
7558
7559   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7560                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
7561               [(set (v4i16 V64:$dst),
7562                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7563                         (i32 vecshiftR16:$imm)))]> {
7564     bits<4> imm;
7565     let Inst{19-16} = imm;
7566   }
7567
7568   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7569                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
7570             [(set (v8i16 V128:$dst),
7571               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7572                       (i32 vecshiftR16:$imm)))]> {
7573     bits<4> imm;
7574     let Inst{19-16} = imm;
7575   }
7576
7577   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7578                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
7579               [(set (v2i32 V64:$dst),
7580                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7581                         (i32 vecshiftR32:$imm)))]> {
7582     bits<5> imm;
7583     let Inst{20-16} = imm;
7584   }
7585
7586   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7587                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
7588             [(set (v4i32 V128:$dst),
7589               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7590                       (i32 vecshiftR32:$imm)))]> {
7591     bits<5> imm;
7592     let Inst{20-16} = imm;
7593   }
7594
7595   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7596                                   V128, V128, vecshiftR64,
7597                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7598               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7599                       (i32 vecshiftR64:$imm)))]> {
7600     bits<6> imm;
7601     let Inst{21-16} = imm;
7602   }
7603 }
7604
7605 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7606                                     SDPatternOperator OpNode = null_frag> {
7607   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7608                                   V64, V64, vecshiftL8,
7609                                   asm, ".8b", ".8b",
7610                     [(set (v8i8 V64:$dst),
7611                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7612                                   (i32 vecshiftL8:$imm)))]> {
7613     bits<3> imm;
7614     let Inst{18-16} = imm;
7615   }
7616
7617   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7618                                   V128, V128, vecshiftL8,
7619                                   asm, ".16b", ".16b",
7620                     [(set (v16i8 V128:$dst),
7621                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7622                                   (i32 vecshiftL8:$imm)))]> {
7623     bits<3> imm;
7624     let Inst{18-16} = imm;
7625   }
7626
7627   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7628                                   V64, V64, vecshiftL16,
7629                                   asm, ".4h", ".4h",
7630                     [(set (v4i16 V64:$dst),
7631                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7632                                    (i32 vecshiftL16:$imm)))]> {
7633     bits<4> imm;
7634     let Inst{19-16} = imm;
7635   }
7636
7637   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7638                                   V128, V128, vecshiftL16,
7639                                   asm, ".8h", ".8h",
7640                     [(set (v8i16 V128:$dst),
7641                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7642                                   (i32 vecshiftL16:$imm)))]> {
7643     bits<4> imm;
7644     let Inst{19-16} = imm;
7645   }
7646
7647   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7648                                   V64, V64, vecshiftL32,
7649                                   asm, ".2s", ".2s",
7650                     [(set (v2i32 V64:$dst),
7651                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7652                                   (i32 vecshiftL32:$imm)))]> {
7653     bits<5> imm;
7654     let Inst{20-16} = imm;
7655   }
7656
7657   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7658                                   V128, V128, vecshiftL32,
7659                                   asm, ".4s", ".4s",
7660                     [(set (v4i32 V128:$dst),
7661                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7662                                   (i32 vecshiftL32:$imm)))]> {
7663     bits<5> imm;
7664     let Inst{20-16} = imm;
7665   }
7666
7667   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7668                                   V128, V128, vecshiftL64,
7669                                   asm, ".2d", ".2d",
7670                     [(set (v2i64 V128:$dst),
7671                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7672                                   (i32 vecshiftL64:$imm)))]> {
7673     bits<6> imm;
7674     let Inst{21-16} = imm;
7675   }
7676 }
7677
7678 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7679                                    SDPatternOperator OpNode> {
7680   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7681                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
7682       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7683     bits<3> imm;
7684     let Inst{18-16} = imm;
7685   }
7686
7687   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7688                                   V128, V128, vecshiftL8,
7689                                   asm#"2", ".8h", ".16b",
7690       [(set (v8i16 V128:$Rd),
7691             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7692     bits<3> imm;
7693     let Inst{18-16} = imm;
7694   }
7695
7696   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7697                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
7698       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7699     bits<4> imm;
7700     let Inst{19-16} = imm;
7701   }
7702
7703   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7704                                   V128, V128, vecshiftL16,
7705                                   asm#"2", ".4s", ".8h",
7706       [(set (v4i32 V128:$Rd),
7707             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7708
7709     bits<4> imm;
7710     let Inst{19-16} = imm;
7711   }
7712
7713   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7714                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
7715       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7716     bits<5> imm;
7717     let Inst{20-16} = imm;
7718   }
7719
7720   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7721                                   V128, V128, vecshiftL32,
7722                                   asm#"2", ".2d", ".4s",
7723       [(set (v2i64 V128:$Rd),
7724             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7725     bits<5> imm;
7726     let Inst{20-16} = imm;
7727   }
7728 }
7729
7730
7731 //---
7732 // Vector load/store
7733 //---
7734 // SIMD ldX/stX no-index memory references don't allow the optional
7735 // ", #0" constant and handle post-indexing explicitly, so we use
7736 // a more specialized parse method for them. Otherwise, it's the same as
7737 // the general GPR64sp handling.
7738
7739 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7740                    string asm, dag oops, dag iops, list<dag> pattern>
7741   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
7742   bits<5> Vt;
7743   bits<5> Rn;
7744   let Inst{31} = 0;
7745   let Inst{30} = Q;
7746   let Inst{29-23} = 0b0011000;
7747   let Inst{22} = L;
7748   let Inst{21-16} = 0b000000;
7749   let Inst{15-12} = opcode;
7750   let Inst{11-10} = size;
7751   let Inst{9-5} = Rn;
7752   let Inst{4-0} = Vt;
7753 }
7754
7755 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7756                        string asm, dag oops, dag iops>
7757   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
7758   bits<5> Vt;
7759   bits<5> Rn;
7760   bits<5> Xm;
7761   let Inst{31} = 0;
7762   let Inst{30} = Q;
7763   let Inst{29-23} = 0b0011001;
7764   let Inst{22} = L;
7765   let Inst{21} = 0;
7766   let Inst{20-16} = Xm;
7767   let Inst{15-12} = opcode;
7768   let Inst{11-10} = size;
7769   let Inst{9-5} = Rn;
7770   let Inst{4-0} = Vt;
7771 }
7772
7773 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7774 // register post-index addressing from the zero register.
7775 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7776                            int Offset, int Size> {
7777   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7778   //      "ld1\t$Vt, [$Rn], #16"
7779   // may get mapped to
7780   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
7781   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
7782                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7783                       GPR64sp:$Rn,
7784                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7785                       XZR), 1>;
7786
7787   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7788   //      "ld1.8b\t$Vt, [$Rn], #16"
7789   // may get mapped to
7790   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
7791   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
7792                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7793                       GPR64sp:$Rn,
7794                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7795                       XZR), 0>;
7796
7797   // E.g. "ld1.8b { v0, v1 }, [x1]"
7798   //      "ld1\t$Vt, [$Rn]"
7799   // may get mapped to
7800   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
7801   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
7802                   (!cast<Instruction>(NAME # Count # "v" # layout)
7803                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7804                       GPR64sp:$Rn), 0>;
7805
7806   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7807   //      "ld1\t$Vt, [$Rn], $Xm"
7808   // may get mapped to
7809   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
7810   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
7811                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7812                       GPR64sp:$Rn,
7813                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7814                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7815 }
7816
7817 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7818                        int Offset64, bits<4> opcode> {
7819   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7820     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7821                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7822                            (ins GPR64sp:$Rn), []>;
7823     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7824                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7825                            (ins GPR64sp:$Rn), []>;
7826     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7827                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7828                            (ins GPR64sp:$Rn), []>;
7829     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7830                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7831                            (ins GPR64sp:$Rn), []>;
7832     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7833                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7834                            (ins GPR64sp:$Rn), []>;
7835     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7836                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7837                            (ins GPR64sp:$Rn), []>;
7838     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7839                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7840                            (ins GPR64sp:$Rn), []>;
7841
7842
7843     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7844                        (outs GPR64sp:$wback,
7845                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
7846                        (ins GPR64sp:$Rn,
7847                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7848     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7849                        (outs GPR64sp:$wback,
7850                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
7851                        (ins GPR64sp:$Rn,
7852                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7853     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7854                        (outs GPR64sp:$wback,
7855                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
7856                        (ins GPR64sp:$Rn,
7857                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7858     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7859                        (outs GPR64sp:$wback,
7860                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
7861                        (ins GPR64sp:$Rn,
7862                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7863     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7864                        (outs GPR64sp:$wback,
7865                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
7866                        (ins GPR64sp:$Rn,
7867                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7868     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7869                        (outs GPR64sp:$wback,
7870                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
7871                        (ins GPR64sp:$Rn,
7872                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7873     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7874                        (outs GPR64sp:$wback,
7875                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
7876                        (ins GPR64sp:$Rn,
7877                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7878   }
7879
7880   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7881   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7882   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7883   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7884   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7885   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7886   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7887 }
7888
7889 // Only ld1/st1 has a v1d version.
7890 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7891                        int Offset64, bits<4> opcode> {
7892   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7893     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7894                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7895                                  GPR64sp:$Rn), []>;
7896     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7897                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7898                                 GPR64sp:$Rn), []>;
7899     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7900                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7901                                 GPR64sp:$Rn), []>;
7902     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7903                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7904                                 GPR64sp:$Rn), []>;
7905     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7906                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7907                                 GPR64sp:$Rn), []>;
7908     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7909                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7910                                 GPR64sp:$Rn), []>;
7911     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7912                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7913                                 GPR64sp:$Rn), []>;
7914
7915     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
7916                        (outs GPR64sp:$wback),
7917                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7918                             GPR64sp:$Rn,
7919                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7920     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
7921                        (outs GPR64sp:$wback),
7922                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7923                             GPR64sp:$Rn,
7924                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7925     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
7926                        (outs GPR64sp:$wback),
7927                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7928                             GPR64sp:$Rn,
7929                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7930     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
7931                        (outs GPR64sp:$wback),
7932                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7933                             GPR64sp:$Rn,
7934                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7935     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
7936                        (outs GPR64sp:$wback),
7937                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7938                             GPR64sp:$Rn,
7939                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7940     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
7941                        (outs GPR64sp:$wback),
7942                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7943                             GPR64sp:$Rn,
7944                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7945     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
7946                        (outs GPR64sp:$wback),
7947                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7948                             GPR64sp:$Rn,
7949                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7950   }
7951
7952   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7953   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7954   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7955   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7956   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7957   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7958   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7959 }
7960
7961 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7962                        int Offset128, int Offset64, bits<4> opcode>
7963   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7964
7965   // LD1 instructions have extra "1d" variants.
7966   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7967     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7968                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7969                            (ins GPR64sp:$Rn), []>;
7970
7971     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7972                        (outs GPR64sp:$wback,
7973                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
7974                        (ins GPR64sp:$Rn,
7975                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7976   }
7977
7978   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7979 }
7980
7981 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7982                        int Offset128, int Offset64, bits<4> opcode>
7983   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7984
7985   // ST1 instructions have extra "1d" variants.
7986   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7987     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7988                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7989                                 GPR64sp:$Rn), []>;
7990
7991     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
7992                        (outs GPR64sp:$wback),
7993                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7994                             GPR64sp:$Rn,
7995                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7996   }
7997
7998   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7999 }
8000
8001 multiclass SIMDLd1Multiple<string asm> {
8002   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8003   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8004   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8005   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8006 }
8007
8008 multiclass SIMDSt1Multiple<string asm> {
8009   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8010   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8011   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8012   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8013 }
8014
8015 multiclass SIMDLd2Multiple<string asm> {
8016   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8017 }
8018
8019 multiclass SIMDSt2Multiple<string asm> {
8020   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8021 }
8022
8023 multiclass SIMDLd3Multiple<string asm> {
8024   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8025 }
8026
8027 multiclass SIMDSt3Multiple<string asm> {
8028   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8029 }
8030
8031 multiclass SIMDLd4Multiple<string asm> {
8032   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8033 }
8034
8035 multiclass SIMDSt4Multiple<string asm> {
8036   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8037 }
8038
8039 //---
8040 // AdvSIMD Load/store single-element
8041 //---
8042
8043 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8044                          string asm, string operands, string cst,
8045                          dag oops, dag iops, list<dag> pattern>
8046   : I<oops, iops, asm, operands, cst, pattern> {
8047   bits<5> Vt;
8048   bits<5> Rn;
8049   let Inst{31} = 0;
8050   let Inst{29-24} = 0b001101;
8051   let Inst{22} = L;
8052   let Inst{21} = R;
8053   let Inst{15-13} = opcode;
8054   let Inst{9-5} = Rn;
8055   let Inst{4-0} = Vt;
8056 }
8057
8058 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8059                          string asm, string operands, string cst,
8060                          dag oops, dag iops, list<dag> pattern>
8061   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8062   bits<5> Vt;
8063   bits<5> Rn;
8064   let Inst{31} = 0;
8065   let Inst{29-24} = 0b001101;
8066   let Inst{22} = L;
8067   let Inst{21} = R;
8068   let Inst{15-13} = opcode;
8069   let Inst{9-5} = Rn;
8070   let Inst{4-0} = Vt;
8071 }
8072
8073
8074 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8075 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8076                   Operand listtype>
8077   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8078                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
8079                        []> {
8080   let Inst{30} = Q;
8081   let Inst{23} = 0;
8082   let Inst{20-16} = 0b00000;
8083   let Inst{12} = S;
8084   let Inst{11-10} = size;
8085 }
8086 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8087 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8088                       string asm, Operand listtype, Operand GPR64pi>
8089   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8090                        "$Rn = $wback",
8091                        (outs GPR64sp:$wback, listtype:$Vt),
8092                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8093   bits<5> Xm;
8094   let Inst{30} = Q;
8095   let Inst{23} = 1;
8096   let Inst{20-16} = Xm;
8097   let Inst{12} = S;
8098   let Inst{11-10} = size;
8099 }
8100
8101 multiclass SIMDLdrAliases<string asm, string layout, string Count,
8102                           int Offset, int Size> {
8103   // E.g. "ld1r { v0.8b }, [x1], #1"
8104   //      "ld1r.8b\t$Vt, [$Rn], #1"
8105   // may get mapped to
8106   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8107   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8108                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8109                       GPR64sp:$Rn,
8110                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8111                       XZR), 1>;
8112
8113   // E.g. "ld1r.8b { v0 }, [x1], #1"
8114   //      "ld1r.8b\t$Vt, [$Rn], #1"
8115   // may get mapped to
8116   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8117   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8118                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8119                       GPR64sp:$Rn,
8120                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8121                       XZR), 0>;
8122
8123   // E.g. "ld1r.8b { v0 }, [x1]"
8124   //      "ld1r.8b\t$Vt, [$Rn]"
8125   // may get mapped to
8126   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8127   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8128                   (!cast<Instruction>(NAME # "v" # layout)
8129                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8130                       GPR64sp:$Rn), 0>;
8131
8132   // E.g. "ld1r.8b { v0 }, [x1], x2"
8133   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
8134   // may get mapped to
8135   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8136   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8137                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8138                       GPR64sp:$Rn,
8139                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8140                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8141 }
8142
8143 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8144   int Offset1, int Offset2, int Offset4, int Offset8> {
8145   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8146                         !cast<Operand>("VecList" # Count # "8b")>;
8147   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8148                         !cast<Operand>("VecList" # Count #"16b")>;
8149   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8150                         !cast<Operand>("VecList" # Count #"4h")>;
8151   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8152                         !cast<Operand>("VecList" # Count #"8h")>;
8153   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8154                         !cast<Operand>("VecList" # Count #"2s")>;
8155   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8156                         !cast<Operand>("VecList" # Count #"4s")>;
8157   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8158                         !cast<Operand>("VecList" # Count #"1d")>;
8159   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8160                         !cast<Operand>("VecList" # Count #"2d")>;
8161
8162   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8163                                  !cast<Operand>("VecList" # Count # "8b"),
8164                                  !cast<Operand>("GPR64pi" # Offset1)>;
8165   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8166                                  !cast<Operand>("VecList" # Count # "16b"),
8167                                  !cast<Operand>("GPR64pi" # Offset1)>;
8168   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8169                                  !cast<Operand>("VecList" # Count # "4h"),
8170                                  !cast<Operand>("GPR64pi" # Offset2)>;
8171   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8172                                  !cast<Operand>("VecList" # Count # "8h"),
8173                                  !cast<Operand>("GPR64pi" # Offset2)>;
8174   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8175                                  !cast<Operand>("VecList" # Count # "2s"),
8176                                  !cast<Operand>("GPR64pi" # Offset4)>;
8177   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8178                                  !cast<Operand>("VecList" # Count # "4s"),
8179                                  !cast<Operand>("GPR64pi" # Offset4)>;
8180   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8181                                  !cast<Operand>("VecList" # Count # "1d"),
8182                                  !cast<Operand>("GPR64pi" # Offset8)>;
8183   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8184                                  !cast<Operand>("VecList" # Count # "2d"),
8185                                  !cast<Operand>("GPR64pi" # Offset8)>;
8186
8187   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
8188   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8189   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
8190   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
8191   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
8192   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
8193   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
8194   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
8195 }
8196
8197 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8198                       dag oops, dag iops, list<dag> pattern>
8199   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8200                        pattern> {
8201   // idx encoded in Q:S:size fields.
8202   bits<4> idx;
8203   let Inst{30} = idx{3};
8204   let Inst{23} = 0;
8205   let Inst{20-16} = 0b00000;
8206   let Inst{12} = idx{2};
8207   let Inst{11-10} = idx{1-0};
8208 }
8209 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8210                       dag oops, dag iops, list<dag> pattern>
8211   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8212                            oops, iops, pattern> {
8213   // idx encoded in Q:S:size fields.
8214   bits<4> idx;
8215   let Inst{30} = idx{3};
8216   let Inst{23} = 0;
8217   let Inst{20-16} = 0b00000;
8218   let Inst{12} = idx{2};
8219   let Inst{11-10} = idx{1-0};
8220 }
8221 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8222                           dag oops, dag iops>
8223   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8224                        "$Rn = $wback", oops, iops, []> {
8225   // idx encoded in Q:S:size fields.
8226   bits<4> idx;
8227   bits<5> Xm;
8228   let Inst{30} = idx{3};
8229   let Inst{23} = 1;
8230   let Inst{20-16} = Xm;
8231   let Inst{12} = idx{2};
8232   let Inst{11-10} = idx{1-0};
8233 }
8234 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8235                           dag oops, dag iops>
8236   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8237                            "$Rn = $wback", oops, iops, []> {
8238   // idx encoded in Q:S:size fields.
8239   bits<4> idx;
8240   bits<5> Xm;
8241   let Inst{30} = idx{3};
8242   let Inst{23} = 1;
8243   let Inst{20-16} = Xm;
8244   let Inst{12} = idx{2};
8245   let Inst{11-10} = idx{1-0};
8246 }
8247
8248 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8249                       dag oops, dag iops, list<dag> pattern>
8250   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8251                        pattern> {
8252   // idx encoded in Q:S:size<1> fields.
8253   bits<3> idx;
8254   let Inst{30} = idx{2};
8255   let Inst{23} = 0;
8256   let Inst{20-16} = 0b00000;
8257   let Inst{12} = idx{1};
8258   let Inst{11} = idx{0};
8259   let Inst{10} = size;
8260 }
8261 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8262                       dag oops, dag iops, list<dag> pattern>
8263   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8264                            oops, iops, pattern> {
8265   // idx encoded in Q:S:size<1> fields.
8266   bits<3> idx;
8267   let Inst{30} = idx{2};
8268   let Inst{23} = 0;
8269   let Inst{20-16} = 0b00000;
8270   let Inst{12} = idx{1};
8271   let Inst{11} = idx{0};
8272   let Inst{10} = size;
8273 }
8274
8275 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8276                           dag oops, dag iops>
8277   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8278                        "$Rn = $wback", oops, iops, []> {
8279   // idx encoded in Q:S:size<1> fields.
8280   bits<3> idx;
8281   bits<5> Xm;
8282   let Inst{30} = idx{2};
8283   let Inst{23} = 1;
8284   let Inst{20-16} = Xm;
8285   let Inst{12} = idx{1};
8286   let Inst{11} = idx{0};
8287   let Inst{10} = size;
8288 }
8289 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8290                           dag oops, dag iops>
8291   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8292                            "$Rn = $wback", oops, iops, []> {
8293   // idx encoded in Q:S:size<1> fields.
8294   bits<3> idx;
8295   bits<5> Xm;
8296   let Inst{30} = idx{2};
8297   let Inst{23} = 1;
8298   let Inst{20-16} = Xm;
8299   let Inst{12} = idx{1};
8300   let Inst{11} = idx{0};
8301   let Inst{10} = size;
8302 }
8303 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8304                       dag oops, dag iops, list<dag> pattern>
8305   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8306                        pattern> {
8307   // idx encoded in Q:S fields.
8308   bits<2> idx;
8309   let Inst{30} = idx{1};
8310   let Inst{23} = 0;
8311   let Inst{20-16} = 0b00000;
8312   let Inst{12} = idx{0};
8313   let Inst{11-10} = size;
8314 }
8315 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8316                       dag oops, dag iops, list<dag> pattern>
8317   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8318                            oops, iops, pattern> {
8319   // idx encoded in Q:S fields.
8320   bits<2> idx;
8321   let Inst{30} = idx{1};
8322   let Inst{23} = 0;
8323   let Inst{20-16} = 0b00000;
8324   let Inst{12} = idx{0};
8325   let Inst{11-10} = size;
8326 }
8327 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8328                           string asm, dag oops, dag iops>
8329   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8330                        "$Rn = $wback", oops, iops, []> {
8331   // idx encoded in Q:S fields.
8332   bits<2> idx;
8333   bits<5> Xm;
8334   let Inst{30} = idx{1};
8335   let Inst{23} = 1;
8336   let Inst{20-16} = Xm;
8337   let Inst{12} = idx{0};
8338   let Inst{11-10} = size;
8339 }
8340 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8341                           string asm, dag oops, dag iops>
8342   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8343                            "$Rn = $wback", oops, iops, []> {
8344   // idx encoded in Q:S fields.
8345   bits<2> idx;
8346   bits<5> Xm;
8347   let Inst{30} = idx{1};
8348   let Inst{23} = 1;
8349   let Inst{20-16} = Xm;
8350   let Inst{12} = idx{0};
8351   let Inst{11-10} = size;
8352 }
8353 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8354                       dag oops, dag iops, list<dag> pattern>
8355   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8356                        pattern> {
8357   // idx encoded in Q field.
8358   bits<1> idx;
8359   let Inst{30} = idx;
8360   let Inst{23} = 0;
8361   let Inst{20-16} = 0b00000;
8362   let Inst{12} = 0;
8363   let Inst{11-10} = size;
8364 }
8365 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8366                       dag oops, dag iops, list<dag> pattern>
8367   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8368                            oops, iops, pattern> {
8369   // idx encoded in Q field.
8370   bits<1> idx;
8371   let Inst{30} = idx;
8372   let Inst{23} = 0;
8373   let Inst{20-16} = 0b00000;
8374   let Inst{12} = 0;
8375   let Inst{11-10} = size;
8376 }
8377 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8378                           string asm, dag oops, dag iops>
8379   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8380                        "$Rn = $wback", oops, iops, []> {
8381   // idx encoded in Q field.
8382   bits<1> idx;
8383   bits<5> Xm;
8384   let Inst{30} = idx;
8385   let Inst{23} = 1;
8386   let Inst{20-16} = Xm;
8387   let Inst{12} = 0;
8388   let Inst{11-10} = size;
8389 }
8390 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8391                           string asm, dag oops, dag iops>
8392   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8393                            "$Rn = $wback", oops, iops, []> {
8394   // idx encoded in Q field.
8395   bits<1> idx;
8396   bits<5> Xm;
8397   let Inst{30} = idx;
8398   let Inst{23} = 1;
8399   let Inst{20-16} = Xm;
8400   let Inst{12} = 0;
8401   let Inst{11-10} = size;
8402 }
8403
8404 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8405 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8406                          RegisterOperand listtype,
8407                          RegisterOperand GPR64pi> {
8408   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8409                            (outs listtype:$dst),
8410                            (ins listtype:$Vt, VectorIndexB:$idx,
8411                                 GPR64sp:$Rn), []>;
8412
8413   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8414                             (outs GPR64sp:$wback, listtype:$dst),
8415                             (ins listtype:$Vt, VectorIndexB:$idx,
8416                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8417 }
8418 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8419 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8420                          RegisterOperand listtype,
8421                          RegisterOperand GPR64pi> {
8422   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8423                             (outs listtype:$dst),
8424                             (ins listtype:$Vt, VectorIndexH:$idx,
8425                                  GPR64sp:$Rn), []>;
8426
8427   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8428                             (outs GPR64sp:$wback, listtype:$dst),
8429                             (ins listtype:$Vt, VectorIndexH:$idx,
8430                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8431 }
8432 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8433 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8434                          RegisterOperand listtype,
8435                          RegisterOperand GPR64pi> {
8436   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8437                             (outs listtype:$dst),
8438                             (ins listtype:$Vt, VectorIndexS:$idx,
8439                                  GPR64sp:$Rn), []>;
8440
8441   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8442                             (outs GPR64sp:$wback, listtype:$dst),
8443                             (ins listtype:$Vt, VectorIndexS:$idx,
8444                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8445 }
8446 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8447 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8448                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8449   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8450                             (outs listtype:$dst),
8451                             (ins listtype:$Vt, VectorIndexD:$idx,
8452                                  GPR64sp:$Rn), []>;
8453
8454   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8455                             (outs GPR64sp:$wback, listtype:$dst),
8456                             (ins listtype:$Vt, VectorIndexD:$idx,
8457                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8458 }
8459 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8460 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8461                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8462   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8463                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8464                                         GPR64sp:$Rn), []>;
8465
8466   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8467                                     (outs GPR64sp:$wback),
8468                                     (ins listtype:$Vt, VectorIndexB:$idx,
8469                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
8470 }
8471 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8472 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8473                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8474   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8475                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8476                                          GPR64sp:$Rn), []>;
8477
8478   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8479                             (outs GPR64sp:$wback),
8480                             (ins listtype:$Vt, VectorIndexH:$idx,
8481                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8482 }
8483 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8484 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8485                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8486   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8487                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8488                                          GPR64sp:$Rn), []>;
8489
8490   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8491                             (outs GPR64sp:$wback),
8492                             (ins listtype:$Vt, VectorIndexS:$idx,
8493                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8494 }
8495 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8496 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8497                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8498   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8499                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8500                                          GPR64sp:$Rn), []>;
8501
8502   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8503                             (outs GPR64sp:$wback),
8504                             (ins listtype:$Vt, VectorIndexD:$idx,
8505                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8506 }
8507
8508 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8509                                  string Count, int Offset, Operand idxtype> {
8510   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8511   //      "ld1\t$Vt, [$Rn], #1"
8512   // may get mapped to
8513   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8514   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8515                   (!cast<Instruction>(NAME # Type  # "_POST")
8516                       GPR64sp:$Rn,
8517                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8518                       idxtype:$idx, XZR), 1>;
8519
8520   // E.g. "ld1.8b { v0 }[0], [x1], #1"
8521   //      "ld1.8b\t$Vt, [$Rn], #1"
8522   // may get mapped to
8523   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8524   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
8525                   (!cast<Instruction>(NAME # Type # "_POST")
8526                       GPR64sp:$Rn,
8527                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8528                       idxtype:$idx, XZR), 0>;
8529
8530   // E.g. "ld1.8b { v0 }[0], [x1]"
8531   //      "ld1.8b\t$Vt, [$Rn]"
8532   // may get mapped to
8533   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8534   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
8535                       (!cast<Instruction>(NAME # Type)
8536                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8537                          idxtype:$idx, GPR64sp:$Rn), 0>;
8538
8539   // E.g. "ld1.8b { v0 }[0], [x1], x2"
8540   //      "ld1.8b\t$Vt, [$Rn], $Xm"
8541   // may get mapped to
8542   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8543   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
8544                       (!cast<Instruction>(NAME # Type # "_POST")
8545                          GPR64sp:$Rn,
8546                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8547                          idxtype:$idx,
8548                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8549 }
8550
8551 multiclass SIMDLdSt1SingleAliases<string asm> {
8552   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
8553   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8554   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8555   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8556 }
8557
8558 multiclass SIMDLdSt2SingleAliases<string asm> {
8559   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
8560   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
8561   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
8562   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8563 }
8564
8565 multiclass SIMDLdSt3SingleAliases<string asm> {
8566   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
8567   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
8568   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8569   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8570 }
8571
8572 multiclass SIMDLdSt4SingleAliases<string asm> {
8573   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
8574   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
8575   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8576   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8577 }
8578 } // end of 'let Predicates = [HasNEON]'
8579
8580 //----------------------------------------------------------------------------
8581 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
8582 //----------------------------------------------------------------------------
8583
8584 let Predicates = [HasNEON, HasV8_1a] in {
8585
8586 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
8587                                     RegisterOperand regtype, string asm, 
8588                                     string kind, list<dag> pattern>
8589   : BaseSIMDThreeSameVectorTied<Q, U, size, opcode, regtype, asm, kind, 
8590                                 pattern> {
8591   let Inst{21}=0;
8592 }
8593 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
8594                                              SDPatternOperator Accum> {
8595   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
8596     [(set (v4i16 V64:$dst),
8597           (Accum (v4i16 V64:$Rd),
8598                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
8599                                                    (v4i16 V64:$Rm)))))]>;         
8600   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
8601     [(set (v8i16 V128:$dst),
8602           (Accum (v8i16 V128:$Rd),
8603                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
8604                                                    (v8i16 V128:$Rm)))))]>;
8605   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
8606     [(set (v2i32 V64:$dst),
8607           (Accum (v2i32 V64:$Rd),
8608                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
8609                                                    (v2i32 V64:$Rm)))))]>;
8610   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
8611     [(set (v4i32 V128:$dst),
8612           (Accum (v4i32 V128:$Rd),
8613                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
8614                                                    (v4i32 V128:$Rm)))))]>;
8615 }
8616
8617 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
8618                                      SDPatternOperator Accum> {
8619   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8620                                           V64, V64, V128_lo, VectorIndexH,
8621                                           asm, ".4h", ".4h", ".4h", ".h",
8622     [(set (v4i16 V64:$dst),
8623           (Accum (v4i16 V64:$Rd),
8624                  (v4i16 (int_aarch64_neon_sqrdmulh
8625                           (v4i16 V64:$Rn),
8626                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8627                                                     VectorIndexH:$idx))))))]> {
8628     bits<3> idx;
8629     let Inst{11} = idx{2};
8630     let Inst{21} = idx{1};
8631     let Inst{20} = idx{0};
8632   }
8633
8634   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8635                                           V128, V128, V128_lo, VectorIndexH,
8636                                           asm, ".8h", ".8h", ".8h", ".h",
8637     [(set (v8i16 V128:$dst),
8638           (Accum (v8i16 V128:$Rd),
8639                  (v8i16 (int_aarch64_neon_sqrdmulh
8640                           (v8i16 V128:$Rn),
8641                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8642                                                    VectorIndexH:$idx))))))]> {
8643     bits<3> idx;
8644     let Inst{11} = idx{2};
8645     let Inst{21} = idx{1};
8646     let Inst{20} = idx{0};
8647   }
8648
8649   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8650                                           V64, V64, V128, VectorIndexS,
8651                                           asm, ".2s", ".2s", ".2s", ".s",
8652     [(set (v2i32 V64:$dst),
8653         (Accum (v2i32 V64:$Rd),
8654                (v2i32 (int_aarch64_neon_sqrdmulh
8655                         (v2i32 V64:$Rn),
8656                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8657                                                  VectorIndexS:$idx))))))]> {
8658     bits<2> idx;
8659     let Inst{11} = idx{1};
8660     let Inst{21} = idx{0};
8661   }
8662
8663   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but 
8664   // an intermediate EXTRACT_SUBREG would be untyped.
8665   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we 
8666   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
8667   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8668                        (i32 (vector_extract 
8669                                (v4i32 (insert_subvector
8670                                        (undef), 
8671                                         (v2i32 (int_aarch64_neon_sqrdmulh 
8672                                                  (v2i32 V64:$Rn),
8673                                                  (v2i32 (AArch64duplane32 
8674                                                           (v4i32 V128:$Rm),
8675                                                           VectorIndexS:$idx)))),
8676                                       (i32 0))),
8677                                (i64 0))))),
8678             (EXTRACT_SUBREG
8679                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
8680                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), 
8681                                                 FPR32Op:$Rd, 
8682                                                 ssub)), 
8683                           V64:$Rn,
8684                           V128:$Rm, 
8685                           VectorIndexS:$idx)),
8686                 ssub)>;
8687
8688   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8689                                           V128, V128, V128, VectorIndexS,
8690                                           asm, ".4s", ".4s", ".4s", ".s",
8691     [(set (v4i32 V128:$dst),
8692           (Accum (v4i32 V128:$Rd),
8693                  (v4i32 (int_aarch64_neon_sqrdmulh
8694                           (v4i32 V128:$Rn),
8695                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8696                                                    VectorIndexS:$idx))))))]> {
8697     bits<2> idx;
8698     let Inst{11} = idx{1};
8699     let Inst{21} = idx{0};
8700   }
8701
8702   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
8703   // an intermediate EXTRACT_SUBREG would be untyped.
8704   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8705                         (i32 (vector_extract 
8706                                (v4i32 (int_aarch64_neon_sqrdmulh 
8707                                         (v4i32 V128:$Rn),
8708                                         (v4i32 (AArch64duplane32 
8709                                                  (v4i32 V128:$Rm),
8710                                                  VectorIndexS:$idx)))),
8711                                (i64 0))))),
8712             (EXTRACT_SUBREG
8713                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
8714                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), 
8715                                                FPR32Op:$Rd, 
8716                                                ssub)), 
8717                          V128:$Rn,
8718                          V128:$Rm, 
8719                          VectorIndexS:$idx)),
8720                 ssub)>;
8721
8722   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8723                                         FPR16Op, FPR16Op, V128_lo,
8724                                         VectorIndexH, asm, ".h", "", "", ".h", 
8725                                         []> {
8726     bits<3> idx;
8727     let Inst{11} = idx{2};
8728     let Inst{21} = idx{1};
8729     let Inst{20} = idx{0};
8730   }
8731
8732   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8733                                         FPR32Op, FPR32Op, V128, VectorIndexS,
8734                                         asm, ".s", "", "", ".s",
8735     [(set (i32 FPR32Op:$dst),
8736           (Accum (i32 FPR32Op:$Rd),
8737                  (i32 (int_aarch64_neon_sqrdmulh
8738                         (i32 FPR32Op:$Rn),
8739                         (i32 (vector_extract (v4i32 V128:$Rm),
8740                                              VectorIndexS:$idx))))))]> {
8741     bits<2> idx;
8742     let Inst{11} = idx{1};
8743     let Inst{21} = idx{0};
8744   }
8745 }
8746 } // let Predicates = [HasNeon, HasV8_1a]
8747
8748 //----------------------------------------------------------------------------
8749 // Crypto extensions
8750 //----------------------------------------------------------------------------
8751
8752 let Predicates = [HasCrypto] in {
8753 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8754 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8755               list<dag> pat>
8756   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8757     Sched<[WriteV]>{
8758   bits<5> Rd;
8759   bits<5> Rn;
8760   let Inst{31-16} = 0b0100111000101000;
8761   let Inst{15-12} = opc;
8762   let Inst{11-10} = 0b10;
8763   let Inst{9-5}   = Rn;
8764   let Inst{4-0}   = Rd;
8765 }
8766
8767 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8768   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8769             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8770
8771 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8772   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8773             "$Rd = $dst",
8774             [(set (v16i8 V128:$dst),
8775                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8776
8777 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8778 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8779                      dag oops, dag iops, list<dag> pat>
8780   : I<oops, iops, asm,
8781       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8782       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8783     Sched<[WriteV]>{
8784   bits<5> Rd;
8785   bits<5> Rn;
8786   bits<5> Rm;
8787   let Inst{31-21} = 0b01011110000;
8788   let Inst{20-16} = Rm;
8789   let Inst{15}    = 0;
8790   let Inst{14-12} = opc;
8791   let Inst{11-10} = 0b00;
8792   let Inst{9-5}   = Rn;
8793   let Inst{4-0}   = Rd;
8794 }
8795
8796 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8797   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8798                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8799                    [(set (v4i32 FPR128:$dst),
8800                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8801                                  (v4i32 V128:$Rm)))]>;
8802
8803 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8804   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8805                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
8806                    [(set (v4i32 V128:$dst),
8807                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8808                                  (v4i32 V128:$Rm)))]>;
8809
8810 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8811   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8812                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8813                    [(set (v4i32 FPR128:$dst),
8814                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8815                                  (v4i32 V128:$Rm)))]>;
8816
8817 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8818 class SHA2OpInst<bits<4> opc, string asm, string kind,
8819                  string cstr, dag oops, dag iops,
8820                  list<dag> pat>
8821   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8822                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8823     Sched<[WriteV]>{
8824   bits<5> Rd;
8825   bits<5> Rn;
8826   let Inst{31-16} = 0b0101111000101000;
8827   let Inst{15-12} = opc;
8828   let Inst{11-10} = 0b10;
8829   let Inst{9-5}   = Rn;
8830   let Inst{4-0}   = Rd;
8831 }
8832
8833 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8834   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8835                (ins V128:$Rd, V128:$Rn),
8836                [(set (v4i32 V128:$dst),
8837                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8838
8839 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8840   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8841                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8842 } // end of 'let Predicates = [HasCrypto]'
8843
8844 //----------------------------------------------------------------------------
8845 // v8.1 atomic instructions extension:
8846 // * CAS
8847 // * CASP
8848 // * SWP
8849 // * LDOPregister<OP>, and aliases STOPregister<OP>
8850
8851 // Instruction encodings:
8852 //
8853 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
8854 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
8855 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
8856 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
8857 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
8858 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
8859
8860 // Instruction syntax:
8861 //
8862 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8863 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
8864 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
8865 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
8866 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8867 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
8868 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8869 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
8870 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
8871 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
8872
8873 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
8874 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
8875                       string cstr, list<dag> pattern>
8876       : I<oops, iops, asm, operands, cstr, pattern> {
8877   bits<2> Sz;
8878   bit NP;
8879   bit Acq;
8880   bit Rel;
8881   bits<5> Rs;
8882   bits<5> Rn;
8883   bits<5> Rt;
8884   let Inst{31-30} = Sz;
8885   let Inst{29-24} = 0b001000;
8886   let Inst{23} = NP;
8887   let Inst{22} = Acq;
8888   let Inst{21} = 0b1;
8889   let Inst{20-16} = Rs;
8890   let Inst{15} = Rel;
8891   let Inst{14-10} = 0b11111;
8892   let Inst{9-5} = Rn;
8893   let Inst{4-0} = Rt;
8894 }
8895
8896 class BaseCAS<string order, string size, RegisterClass RC>
8897       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8898                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
8899                         "$out = $Rs",[]> {
8900   let NP = 1;
8901 }
8902
8903 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
8904   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
8905   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
8906   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
8907   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
8908 }
8909
8910 class BaseCASP<string order, string size, RegisterOperand RC>
8911       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8912                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
8913                         "$out = $Rs",[]> {
8914   let NP = 0;
8915 }
8916
8917 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
8918   let Sz = 0b00, Acq = Acq, Rel = Rel in 
8919     def s : BaseCASP<order, "", WSeqPairClassOperand>;
8920   let Sz = 0b01, Acq = Acq, Rel = Rel in 
8921     def d : BaseCASP<order, "", XSeqPairClassOperand>;
8922 }
8923
8924 let Predicates = [HasV8_1a] in
8925 class BaseSWP<string order, string size, RegisterClass RC>
8926       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
8927           "\t$Rs, $Rt, [$Rn]","",[]> {
8928   bits<2> Sz;
8929   bit Acq;
8930   bit Rel;
8931   bits<5> Rs;
8932   bits<3> opc = 0b000;
8933   bits<5> Rn;
8934   bits<5> Rt;
8935   let Inst{31-30} = Sz;
8936   let Inst{29-24} = 0b111000;
8937   let Inst{23} = Acq;
8938   let Inst{22} = Rel;
8939   let Inst{21} = 0b1;
8940   let Inst{20-16} = Rs;
8941   let Inst{15} = 0b1;
8942   let Inst{14-12} = opc;
8943   let Inst{11-10} = 0b00;
8944   let Inst{9-5} = Rn;
8945   let Inst{4-0} = Rt;
8946 }
8947
8948 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
8949   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
8950   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
8951   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
8952   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
8953 }
8954
8955 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
8956 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
8957       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
8958           "\t$Rs, $Rt, [$Rn]","",[]> {
8959   bits<2> Sz;
8960   bit Acq;
8961   bit Rel;
8962   bits<5> Rs;
8963   bits<3> opc;
8964   bits<5> Rn;
8965   bits<5> Rt;
8966   let Inst{31-30} = Sz;
8967   let Inst{29-24} = 0b111000;
8968   let Inst{23} = Acq;
8969   let Inst{22} = Rel;
8970   let Inst{21} = 0b1;
8971   let Inst{20-16} = Rs;
8972   let Inst{15} = 0b0;
8973   let Inst{14-12} = opc;
8974   let Inst{11-10} = 0b00;
8975   let Inst{9-5} = Rn;
8976   let Inst{4-0} = Rt;
8977 }
8978
8979 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel, 
8980                         string order> {
8981   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in 
8982     def b : BaseLDOPregister<op, order, "b", GPR32>;
8983   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in 
8984     def h : BaseLDOPregister<op, order, "h", GPR32>;
8985   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in 
8986     def s : BaseLDOPregister<op, order, "", GPR32>;
8987   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in 
8988     def d : BaseLDOPregister<op, order, "", GPR64>;
8989 }
8990
8991 let Predicates = [HasV8_1a] in
8992 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
8993                         Instruction inst> :
8994       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
8995
8996 multiclass STOPregister<string asm, string instr> {
8997   def : BaseSTOPregister<asm # "lb", GPR32, WZR, 
8998                     !cast<Instruction>(instr # "Lb")>;
8999   def : BaseSTOPregister<asm # "lh", GPR32, WZR, 
9000                     !cast<Instruction>(instr # "Lh")>;
9001   def : BaseSTOPregister<asm # "l",  GPR32, WZR, 
9002                     !cast<Instruction>(instr # "Ls")>;
9003   def : BaseSTOPregister<asm # "l",  GPR64, XZR, 
9004                     !cast<Instruction>(instr # "Ld")>;
9005   def : BaseSTOPregister<asm # "b",  GPR32, WZR, 
9006                     !cast<Instruction>(instr # "b")>;
9007   def : BaseSTOPregister<asm # "h",  GPR32, WZR, 
9008                     !cast<Instruction>(instr # "h")>;
9009   def : BaseSTOPregister<asm,        GPR32, WZR, 
9010                     !cast<Instruction>(instr # "s")>;
9011   def : BaseSTOPregister<asm,        GPR64, XZR, 
9012                     !cast<Instruction>(instr # "d")>;
9013 }
9014
9015 //----------------------------------------------------------------------------
9016 // Allow the size specifier tokens to be upper case, not just lower.
9017 def : TokenAlias<".8B", ".8b">;
9018 def : TokenAlias<".4H", ".4h">;
9019 def : TokenAlias<".2S", ".2s">;
9020 def : TokenAlias<".1D", ".1d">;
9021 def : TokenAlias<".16B", ".16b">;
9022 def : TokenAlias<".8H", ".8h">;
9023 def : TokenAlias<".4S", ".4s">;
9024 def : TokenAlias<".2D", ".2d">;
9025 def : TokenAlias<".1Q", ".1q">;
9026 def : TokenAlias<".B", ".b">;
9027 def : TokenAlias<".H", ".h">;
9028 def : TokenAlias<".S", ".s">;
9029 def : TokenAlias<".D", ".d">;
9030 def : TokenAlias<".Q", ".q">;