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