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