[AArch64] Implement add/adds/sub/subs/cmp/cmn with negative immediate aliases
[oota-llvm.git] / lib / Target / AArch64 / AArch64InstrFormats.td
1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 //===----------------------------------------------------------------------===//
11 //  Describe AArch64 instructions format here
12 //
13
14 // Format specifies the encoding used by the instruction.  This is part of the
15 // ad-hoc solution used to emit machine instruction encodings by our machine
16 // code emitter.
17 class Format<bits<2> val> {
18   bits<2> Value = val;
19 }
20
21 def PseudoFrm   : Format<0>;
22 def NormalFrm   : Format<1>; // Do we need any others?
23
24 // AArch64 Instruction Format
25 class AArch64Inst<Format f, string cstr> : Instruction {
26   field bits<32> Inst; // Instruction encoding.
27   // Mask of bits that cause an encoding to be UNPREDICTABLE.
28   // If a bit is set, then if the corresponding bit in the
29   // target encoding differs from its value in the "Inst" field,
30   // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
31   field bits<32> Unpredictable = 0;
32   // SoftFail is the generic name for this field, but we alias it so
33   // as to make it more obvious what it means in ARM-land.
34   field bits<32> SoftFail = Unpredictable;
35   let Namespace   = "AArch64";
36   Format F        = f;
37   bits<2> Form    = F.Value;
38   let Pattern     = [];
39   let Constraints = cstr;
40 }
41
42 // Pseudo instructions (don't have encoding information)
43 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
44     : AArch64Inst<PseudoFrm, cstr> {
45   dag OutOperandList = oops;
46   dag InOperandList  = iops;
47   let Pattern        = pattern;
48   let isCodeGenOnly  = 1;
49 }
50
51 // Real instructions (have encoding information)
52 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
53   let Pattern = pattern;
54   let Size = 4;
55 }
56
57 // Normal instructions
58 class I<dag oops, dag iops, string asm, string operands, string cstr,
59         list<dag> pattern>
60     : EncodedI<cstr, pattern> {
61   dag OutOperandList = oops;
62   dag InOperandList  = iops;
63   let AsmString      = !strconcat(asm, operands);
64 }
65
66 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
67 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
68 class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
69
70 // Helper fragment for an extract of the high portion of a 128-bit vector.
71 def extract_high_v16i8 :
72    UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
73 def extract_high_v8i16 :
74    UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
75 def extract_high_v4i32 :
76    UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
77 def extract_high_v2i64 :
78    UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
79
80 //===----------------------------------------------------------------------===//
81 // Asm Operand Classes.
82 //
83
84 // Shifter operand for arithmetic shifted encodings.
85 def ShifterOperand : AsmOperandClass {
86   let Name = "Shifter";
87 }
88
89 // Shifter operand for mov immediate encodings.
90 def MovImm32ShifterOperand : AsmOperandClass {
91   let SuperClasses = [ShifterOperand];
92   let Name = "MovImm32Shifter";
93   let RenderMethod = "addShifterOperands";
94   let DiagnosticType = "InvalidMovImm32Shift";
95 }
96 def MovImm64ShifterOperand : AsmOperandClass {
97   let SuperClasses = [ShifterOperand];
98   let Name = "MovImm64Shifter";
99   let RenderMethod = "addShifterOperands";
100   let DiagnosticType = "InvalidMovImm64Shift";
101 }
102
103 // Shifter operand for arithmetic register shifted encodings.
104 class ArithmeticShifterOperand<int width> : AsmOperandClass {
105   let SuperClasses = [ShifterOperand];
106   let Name = "ArithmeticShifter" # width;
107   let PredicateMethod = "isArithmeticShifter<" # width # ">";
108   let RenderMethod = "addShifterOperands";
109   let DiagnosticType = "AddSubRegShift" # width;
110 }
111
112 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
113 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
114
115 // Shifter operand for logical register shifted encodings.
116 class LogicalShifterOperand<int width> : AsmOperandClass {
117   let SuperClasses = [ShifterOperand];
118   let Name = "LogicalShifter" # width;
119   let PredicateMethod = "isLogicalShifter<" # width # ">";
120   let RenderMethod = "addShifterOperands";
121   let DiagnosticType = "AddSubRegShift" # width;
122 }
123
124 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
125 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
126
127 // Shifter operand for logical vector 128/64-bit shifted encodings.
128 def LogicalVecShifterOperand : AsmOperandClass {
129   let SuperClasses = [ShifterOperand];
130   let Name = "LogicalVecShifter";
131   let RenderMethod = "addShifterOperands";
132 }
133 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
134   let SuperClasses = [LogicalVecShifterOperand];
135   let Name = "LogicalVecHalfWordShifter";
136   let RenderMethod = "addShifterOperands";
137 }
138
139 // The "MSL" shifter on the vector MOVI instruction.
140 def MoveVecShifterOperand : AsmOperandClass {
141   let SuperClasses = [ShifterOperand];
142   let Name = "MoveVecShifter";
143   let RenderMethod = "addShifterOperands";
144 }
145
146 // Extend operand for arithmetic encodings.
147 def ExtendOperand : AsmOperandClass {
148   let Name = "Extend";
149   let DiagnosticType = "AddSubRegExtendLarge";
150 }
151 def ExtendOperand64 : AsmOperandClass {
152   let SuperClasses = [ExtendOperand];
153   let Name = "Extend64";
154   let DiagnosticType = "AddSubRegExtendSmall";
155 }
156 // 'extend' that's a lsl of a 64-bit register.
157 def ExtendOperandLSL64 : AsmOperandClass {
158   let SuperClasses = [ExtendOperand];
159   let Name = "ExtendLSL64";
160   let RenderMethod = "addExtend64Operands";
161   let DiagnosticType = "AddSubRegExtendLarge";
162 }
163
164 // 8-bit floating-point immediate encodings.
165 def FPImmOperand : AsmOperandClass {
166   let Name = "FPImm";
167   let ParserMethod = "tryParseFPImm";
168   let DiagnosticType = "InvalidFPImm";
169 }
170
171 def CondCode : AsmOperandClass {
172   let Name = "CondCode";
173   let DiagnosticType = "InvalidCondCode";
174 }
175
176 // A 32-bit register pasrsed as 64-bit
177 def GPR32as64Operand : AsmOperandClass {
178   let Name = "GPR32as64";
179 }
180 def GPR32as64 : RegisterOperand<GPR32> {
181   let ParserMatchClass = GPR32as64Operand;
182 }
183
184 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
185 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
186 // are encoded as the eight bit value 'abcdefgh'.
187 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
188
189
190 //===----------------------------------------------------------------------===//
191 // Operand Definitions.
192 //
193
194 // ADR[P] instruction labels.
195 def AdrpOperand : AsmOperandClass {
196   let Name = "AdrpLabel";
197   let ParserMethod = "tryParseAdrpLabel";
198   let DiagnosticType = "InvalidLabel";
199 }
200 def adrplabel : Operand<i64> {
201   let EncoderMethod = "getAdrLabelOpValue";
202   let PrintMethod = "printAdrpLabel";
203   let ParserMatchClass = AdrpOperand;
204 }
205
206 def AdrOperand : AsmOperandClass {
207   let Name = "AdrLabel";
208   let ParserMethod = "tryParseAdrLabel";
209   let DiagnosticType = "InvalidLabel";
210 }
211 def adrlabel : Operand<i64> {
212   let EncoderMethod = "getAdrLabelOpValue";
213   let ParserMatchClass = AdrOperand;
214 }
215
216 // simm9 predicate - True if the immediate is in the range [-256, 255].
217 def SImm9Operand : AsmOperandClass {
218   let Name = "SImm9";
219   let DiagnosticType = "InvalidMemoryIndexedSImm9";
220 }
221 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
222   let ParserMatchClass = SImm9Operand;
223 }
224
225 // simm7sN predicate - True if the immediate is a multiple of N in the range
226 // [-64 * N, 63 * N].
227 class SImm7Scaled<int Scale> : AsmOperandClass {
228   let Name = "SImm7s" # Scale;
229   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm7";
230 }
231
232 def SImm7s4Operand : SImm7Scaled<4>;
233 def SImm7s8Operand : SImm7Scaled<8>;
234 def SImm7s16Operand : SImm7Scaled<16>;
235
236 def simm7s4 : Operand<i32> {
237   let ParserMatchClass = SImm7s4Operand;
238   let PrintMethod = "printImmScale<4>";
239 }
240
241 def simm7s8 : Operand<i32> {
242   let ParserMatchClass = SImm7s8Operand;
243   let PrintMethod = "printImmScale<8>";
244 }
245
246 def simm7s16 : Operand<i32> {
247   let ParserMatchClass = SImm7s16Operand;
248   let PrintMethod = "printImmScale<16>";
249 }
250
251 class AsmImmRange<int Low, int High> : AsmOperandClass {
252   let Name = "Imm" # Low # "_" # High;
253   let DiagnosticType = "InvalidImm" # Low # "_" # High;
254 }
255
256 def Imm1_8Operand : AsmImmRange<1, 8>;
257 def Imm1_16Operand : AsmImmRange<1, 16>;
258 def Imm1_32Operand : AsmImmRange<1, 32>;
259 def Imm1_64Operand : AsmImmRange<1, 64>;
260
261 def MovZSymbolG3AsmOperand : AsmOperandClass {
262   let Name = "MovZSymbolG3";
263   let RenderMethod = "addImmOperands";
264 }
265
266 def movz_symbol_g3 : Operand<i32> {
267   let ParserMatchClass = MovZSymbolG3AsmOperand;
268 }
269
270 def MovZSymbolG2AsmOperand : AsmOperandClass {
271   let Name = "MovZSymbolG2";
272   let RenderMethod = "addImmOperands";
273 }
274
275 def movz_symbol_g2 : Operand<i32> {
276   let ParserMatchClass = MovZSymbolG2AsmOperand;
277 }
278
279 def MovZSymbolG1AsmOperand : AsmOperandClass {
280   let Name = "MovZSymbolG1";
281   let RenderMethod = "addImmOperands";
282 }
283
284 def movz_symbol_g1 : Operand<i32> {
285   let ParserMatchClass = MovZSymbolG1AsmOperand;
286 }
287
288 def MovZSymbolG0AsmOperand : AsmOperandClass {
289   let Name = "MovZSymbolG0";
290   let RenderMethod = "addImmOperands";
291 }
292
293 def movz_symbol_g0 : Operand<i32> {
294   let ParserMatchClass = MovZSymbolG0AsmOperand;
295 }
296
297 def MovKSymbolG3AsmOperand : AsmOperandClass {
298   let Name = "MovKSymbolG3";
299   let RenderMethod = "addImmOperands";
300 }
301
302 def movk_symbol_g3 : Operand<i32> {
303   let ParserMatchClass = MovKSymbolG3AsmOperand;
304 }
305
306 def MovKSymbolG2AsmOperand : AsmOperandClass {
307   let Name = "MovKSymbolG2";
308   let RenderMethod = "addImmOperands";
309 }
310
311 def movk_symbol_g2 : Operand<i32> {
312   let ParserMatchClass = MovKSymbolG2AsmOperand;
313 }
314
315 def MovKSymbolG1AsmOperand : AsmOperandClass {
316   let Name = "MovKSymbolG1";
317   let RenderMethod = "addImmOperands";
318 }
319
320 def movk_symbol_g1 : Operand<i32> {
321   let ParserMatchClass = MovKSymbolG1AsmOperand;
322 }
323
324 def MovKSymbolG0AsmOperand : AsmOperandClass {
325   let Name = "MovKSymbolG0";
326   let RenderMethod = "addImmOperands";
327 }
328
329 def movk_symbol_g0 : Operand<i32> {
330   let ParserMatchClass = MovKSymbolG0AsmOperand;
331 }
332
333 class fixedpoint_i32<ValueType FloatVT>
334   : Operand<FloatVT>,
335     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
336   let EncoderMethod = "getFixedPointScaleOpValue";
337   let DecoderMethod = "DecodeFixedPointScaleImm32";
338   let ParserMatchClass = Imm1_32Operand;
339 }
340
341 class fixedpoint_i64<ValueType FloatVT>
342   : Operand<FloatVT>,
343     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
344   let EncoderMethod = "getFixedPointScaleOpValue";
345   let DecoderMethod = "DecodeFixedPointScaleImm64";
346   let ParserMatchClass = Imm1_64Operand;
347 }
348
349 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
350 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
351
352 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
353 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
354
355 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
356   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
357 }]> {
358   let EncoderMethod = "getVecShiftR8OpValue";
359   let DecoderMethod = "DecodeVecShiftR8Imm";
360   let ParserMatchClass = Imm1_8Operand;
361 }
362 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
363   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
364 }]> {
365   let EncoderMethod = "getVecShiftR16OpValue";
366   let DecoderMethod = "DecodeVecShiftR16Imm";
367   let ParserMatchClass = Imm1_16Operand;
368 }
369 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
370   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
371 }]> {
372   let EncoderMethod = "getVecShiftR16OpValue";
373   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
374   let ParserMatchClass = Imm1_8Operand;
375 }
376 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
377   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
378 }]> {
379   let EncoderMethod = "getVecShiftR32OpValue";
380   let DecoderMethod = "DecodeVecShiftR32Imm";
381   let ParserMatchClass = Imm1_32Operand;
382 }
383 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
384   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
385 }]> {
386   let EncoderMethod = "getVecShiftR32OpValue";
387   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
388   let ParserMatchClass = Imm1_16Operand;
389 }
390 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
391   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
392 }]> {
393   let EncoderMethod = "getVecShiftR64OpValue";
394   let DecoderMethod = "DecodeVecShiftR64Imm";
395   let ParserMatchClass = Imm1_64Operand;
396 }
397 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
398   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
399 }]> {
400   let EncoderMethod = "getVecShiftR64OpValue";
401   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
402   let ParserMatchClass = Imm1_32Operand;
403 }
404
405 def Imm0_7Operand : AsmImmRange<0, 7>;
406 def Imm0_15Operand : AsmImmRange<0, 15>;
407 def Imm0_31Operand : AsmImmRange<0, 31>;
408 def Imm0_63Operand : AsmImmRange<0, 63>;
409
410 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
411   return (((uint32_t)Imm) < 8);
412 }]> {
413   let EncoderMethod = "getVecShiftL8OpValue";
414   let DecoderMethod = "DecodeVecShiftL8Imm";
415   let ParserMatchClass = Imm0_7Operand;
416 }
417 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
418   return (((uint32_t)Imm) < 16);
419 }]> {
420   let EncoderMethod = "getVecShiftL16OpValue";
421   let DecoderMethod = "DecodeVecShiftL16Imm";
422   let ParserMatchClass = Imm0_15Operand;
423 }
424 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
425   return (((uint32_t)Imm) < 32);
426 }]> {
427   let EncoderMethod = "getVecShiftL32OpValue";
428   let DecoderMethod = "DecodeVecShiftL32Imm";
429   let ParserMatchClass = Imm0_31Operand;
430 }
431 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
432   return (((uint32_t)Imm) < 64);
433 }]> {
434   let EncoderMethod = "getVecShiftL64OpValue";
435   let DecoderMethod = "DecodeVecShiftL64Imm";
436   let ParserMatchClass = Imm0_63Operand;
437 }
438
439
440 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
441 // instructions for splatting repeating bit patterns across the immediate.
442 def logical_imm32_XFORM : SDNodeXForm<imm, [{
443   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
444   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
445 }]>;
446 def logical_imm64_XFORM : SDNodeXForm<imm, [{
447   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
448   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
449 }]>;
450
451 let DiagnosticType = "LogicalSecondSource" in {
452   def LogicalImm32Operand : AsmOperandClass {
453     let Name = "LogicalImm32";
454   }
455   def LogicalImm64Operand : AsmOperandClass {
456     let Name = "LogicalImm64";
457   }
458   def LogicalImm32NotOperand : AsmOperandClass {
459     let Name = "LogicalImm32Not";
460   }
461   def LogicalImm64NotOperand : AsmOperandClass {
462     let Name = "LogicalImm64Not";
463   }
464 }
465 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
466   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
467 }], logical_imm32_XFORM> {
468   let PrintMethod = "printLogicalImm32";
469   let ParserMatchClass = LogicalImm32Operand;
470 }
471 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
472   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
473 }], logical_imm64_XFORM> {
474   let PrintMethod = "printLogicalImm64";
475   let ParserMatchClass = LogicalImm64Operand;
476 }
477 def logical_imm32_not : Operand<i32> {
478   let ParserMatchClass = LogicalImm32NotOperand;
479 }
480 def logical_imm64_not : Operand<i64> {
481   let ParserMatchClass = LogicalImm64NotOperand;
482 }
483
484 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
485 def Imm0_65535Operand : AsmImmRange<0, 65535>;
486 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
487   return ((uint32_t)Imm) < 65536;
488 }]> {
489   let ParserMatchClass = Imm0_65535Operand;
490   let PrintMethod = "printHexImm";
491 }
492
493 // imm0_255 predicate - True if the immediate is in the range [0,255].
494 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
495 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
496   return ((uint32_t)Imm) < 256;
497 }]> {
498   let ParserMatchClass = Imm0_255Operand;
499   let PrintMethod = "printHexImm";
500 }
501
502 // imm0_127 predicate - True if the immediate is in the range [0,127]
503 def Imm0_127Operand : AsmImmRange<0, 127>;
504 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
505   return ((uint32_t)Imm) < 128;
506 }]> {
507   let ParserMatchClass = Imm0_127Operand;
508   let PrintMethod = "printHexImm";
509 }
510
511 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
512 // for all shift-amounts.
513
514 // imm0_63 predicate - True if the immediate is in the range [0,63]
515 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
516   return ((uint64_t)Imm) < 64;
517 }]> {
518   let ParserMatchClass = Imm0_63Operand;
519 }
520
521 // imm0_31 predicate - True if the immediate is in the range [0,31]
522 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
523   return ((uint64_t)Imm) < 32;
524 }]> {
525   let ParserMatchClass = Imm0_31Operand;
526 }
527
528 // imm0_15 predicate - True if the immediate is in the range [0,15]
529 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
530   return ((uint64_t)Imm) < 16;
531 }]> {
532   let ParserMatchClass = Imm0_15Operand;
533 }
534
535 // imm0_7 predicate - True if the immediate is in the range [0,7]
536 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
537   return ((uint64_t)Imm) < 8;
538 }]> {
539   let ParserMatchClass = Imm0_7Operand;
540 }
541
542 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
543 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
544   return ((uint32_t)Imm) < 16;
545 }]>;
546
547 // An arithmetic shifter operand:
548 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
549 //  {5-0} - imm6
550 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
551   let PrintMethod = "printShifter";
552   let ParserMatchClass = !cast<AsmOperandClass>(
553                          "ArithmeticShifterOperand" # width);
554 }
555
556 def arith_shift32 : arith_shift<i32, 32>;
557 def arith_shift64 : arith_shift<i64, 64>;
558
559 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
560     : Operand<Ty>,
561       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
562   let PrintMethod = "printShiftedRegister";
563   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
564 }
565
566 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
567 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
568
569 // An arithmetic shifter operand:
570 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
571 //  {5-0} - imm6
572 class logical_shift<int width> : Operand<i32> {
573   let PrintMethod = "printShifter";
574   let ParserMatchClass = !cast<AsmOperandClass>(
575                          "LogicalShifterOperand" # width);
576 }
577
578 def logical_shift32 : logical_shift<32>;
579 def logical_shift64 : logical_shift<64>;
580
581 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
582     : Operand<Ty>,
583       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
584   let PrintMethod = "printShiftedRegister";
585   let MIOperandInfo = (ops regclass, shiftop);
586 }
587
588 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
589 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
590
591 // A logical vector shifter operand:
592 //  {7-6} - shift type: 00 = lsl
593 //  {5-0} - imm6: #0, #8, #16, or #24
594 def logical_vec_shift : Operand<i32> {
595   let PrintMethod = "printShifter";
596   let EncoderMethod = "getVecShifterOpValue";
597   let ParserMatchClass = LogicalVecShifterOperand;
598 }
599
600 // A logical vector half-word shifter operand:
601 //  {7-6} - shift type: 00 = lsl
602 //  {5-0} - imm6: #0 or #8
603 def logical_vec_hw_shift : Operand<i32> {
604   let PrintMethod = "printShifter";
605   let EncoderMethod = "getVecShifterOpValue";
606   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
607 }
608
609 // A vector move shifter operand:
610 //  {0} - imm1: #8 or #16
611 def move_vec_shift : Operand<i32> {
612   let PrintMethod = "printShifter";
613   let EncoderMethod = "getMoveVecShifterOpValue";
614   let ParserMatchClass = MoveVecShifterOperand;
615 }
616
617 let DiagnosticType = "AddSubSecondSource" in {
618   def AddSubImmOperand : AsmOperandClass {
619     let Name = "AddSubImm";
620     let ParserMethod = "tryParseAddSubImm";
621   }
622   def AddSubImmNegOperand : AsmOperandClass {
623     let Name = "AddSubImmNeg";
624     let ParserMethod = "tryParseAddSubImm";
625   }
626 }
627 // An ADD/SUB immediate shifter operand:
628 //  second operand:
629 //  {7-6} - shift type: 00 = lsl
630 //  {5-0} - imm6: #0 or #12
631 class addsub_shifted_imm<ValueType Ty>
632     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
633   let PrintMethod = "printAddSubImm";
634   let EncoderMethod = "getAddSubImmOpValue";
635   let ParserMatchClass = AddSubImmOperand;
636   let MIOperandInfo = (ops i32imm, i32imm);
637 }
638
639 class addsub_shifted_imm_neg<ValueType Ty>
640     : Operand<Ty> {
641   let EncoderMethod = "getAddSubImmOpValue";
642   let ParserMatchClass = AddSubImmNegOperand;
643   let MIOperandInfo = (ops i32imm, i32imm);
644 }
645
646 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
647 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
648 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
649 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
650
651 class neg_addsub_shifted_imm<ValueType Ty>
652     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
653   let PrintMethod = "printAddSubImm";
654   let EncoderMethod = "getAddSubImmOpValue";
655   let ParserMatchClass = AddSubImmOperand;
656   let MIOperandInfo = (ops i32imm, i32imm);
657 }
658
659 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
660 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
661
662 // An extend operand:
663 //  {5-3} - extend type
664 //  {2-0} - imm3
665 def arith_extend : Operand<i32> {
666   let PrintMethod = "printArithExtend";
667   let ParserMatchClass = ExtendOperand;
668 }
669 def arith_extend64 : Operand<i32> {
670   let PrintMethod = "printArithExtend";
671   let ParserMatchClass = ExtendOperand64;
672 }
673
674 // 'extend' that's a lsl of a 64-bit register.
675 def arith_extendlsl64 : Operand<i32> {
676   let PrintMethod = "printArithExtend";
677   let ParserMatchClass = ExtendOperandLSL64;
678 }
679
680 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
681                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
682   let PrintMethod = "printExtendedRegister";
683   let MIOperandInfo = (ops GPR32, arith_extend);
684 }
685
686 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
687                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
688   let PrintMethod = "printExtendedRegister";
689   let MIOperandInfo = (ops GPR32, arith_extend64);
690 }
691
692 // Floating-point immediate.
693 def fpimm32 : Operand<f32>,
694               PatLeaf<(f32 fpimm), [{
695       return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
696     }], SDNodeXForm<fpimm, [{
697       APFloat InVal = N->getValueAPF();
698       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
699       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
700     }]>> {
701   let ParserMatchClass = FPImmOperand;
702   let PrintMethod = "printFPImmOperand";
703 }
704 def fpimm64 : Operand<f64>,
705               PatLeaf<(f64 fpimm), [{
706       return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
707     }], SDNodeXForm<fpimm, [{
708       APFloat InVal = N->getValueAPF();
709       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
710       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
711     }]>> {
712   let ParserMatchClass = FPImmOperand;
713   let PrintMethod = "printFPImmOperand";
714 }
715
716 def fpimm8 : Operand<i32> {
717   let ParserMatchClass = FPImmOperand;
718   let PrintMethod = "printFPImmOperand";
719 }
720
721 def fpimm0 : PatLeaf<(fpimm), [{
722   return N->isExactlyValue(+0.0);
723 }]>;
724
725 // Vector lane operands
726 class AsmVectorIndex<string Suffix> : AsmOperandClass {
727   let Name = "VectorIndex" # Suffix;
728   let DiagnosticType = "InvalidIndex" # Suffix;
729 }
730 def VectorIndex1Operand : AsmVectorIndex<"1">;
731 def VectorIndexBOperand : AsmVectorIndex<"B">;
732 def VectorIndexHOperand : AsmVectorIndex<"H">;
733 def VectorIndexSOperand : AsmVectorIndex<"S">;
734 def VectorIndexDOperand : AsmVectorIndex<"D">;
735
736 def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
737   return ((uint64_t)Imm) == 1;
738 }]> {
739   let ParserMatchClass = VectorIndex1Operand;
740   let PrintMethod = "printVectorIndex";
741   let MIOperandInfo = (ops i64imm);
742 }
743 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
744   return ((uint64_t)Imm) < 16;
745 }]> {
746   let ParserMatchClass = VectorIndexBOperand;
747   let PrintMethod = "printVectorIndex";
748   let MIOperandInfo = (ops i64imm);
749 }
750 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
751   return ((uint64_t)Imm) < 8;
752 }]> {
753   let ParserMatchClass = VectorIndexHOperand;
754   let PrintMethod = "printVectorIndex";
755   let MIOperandInfo = (ops i64imm);
756 }
757 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
758   return ((uint64_t)Imm) < 4;
759 }]> {
760   let ParserMatchClass = VectorIndexSOperand;
761   let PrintMethod = "printVectorIndex";
762   let MIOperandInfo = (ops i64imm);
763 }
764 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
765   return ((uint64_t)Imm) < 2;
766 }]> {
767   let ParserMatchClass = VectorIndexDOperand;
768   let PrintMethod = "printVectorIndex";
769   let MIOperandInfo = (ops i64imm);
770 }
771
772 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
773 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
774 // are encoded as the eight bit value 'abcdefgh'.
775 def simdimmtype10 : Operand<i32>,
776                     PatLeaf<(f64 fpimm), [{
777       return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
778                                                .bitcastToAPInt()
779                                                .getZExtValue());
780     }], SDNodeXForm<fpimm, [{
781       APFloat InVal = N->getValueAPF();
782       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
783                                                            .bitcastToAPInt()
784                                                            .getZExtValue());
785       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
786     }]>> {
787   let ParserMatchClass = SIMDImmType10Operand;
788   let PrintMethod = "printSIMDType10Operand";
789 }
790
791
792 //---
793 // System management
794 //---
795
796 // Base encoding for system instruction operands.
797 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
798 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
799                   list<dag> pattern = []>
800     : I<oops, iops, asm, operands, "", pattern> {
801   let Inst{31-22} = 0b1101010100;
802   let Inst{21}    = L;
803 }
804
805 // System instructions which do not have an Rt register.
806 class SimpleSystemI<bit L, dag iops, string asm, string operands,
807                     list<dag> pattern = []>
808     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
809   let Inst{4-0} = 0b11111;
810 }
811
812 // System instructions which have an Rt register.
813 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
814     : BaseSystemI<L, oops, iops, asm, operands>,
815       Sched<[WriteSys]> {
816   bits<5> Rt;
817   let Inst{4-0} = Rt;
818 }
819
820 // Hint instructions that take both a CRm and a 3-bit immediate.
821 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
822 // model patterns with sufficiently fine granularity
823 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
824   class HintI<string mnemonic>
825       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "",
826                       [(int_aarch64_hint imm0_127:$imm)]>,
827         Sched<[WriteHint]> {
828     bits <7> imm;
829     let Inst{20-12} = 0b000110010;
830     let Inst{11-5} = imm;
831   }
832
833 // System instructions taking a single literal operand which encodes into
834 // CRm. op2 differentiates the opcodes.
835 def BarrierAsmOperand : AsmOperandClass {
836   let Name = "Barrier";
837   let ParserMethod = "tryParseBarrierOperand";
838 }
839 def barrier_op : Operand<i32> {
840   let PrintMethod = "printBarrierOption";
841   let ParserMatchClass = BarrierAsmOperand;
842 }
843 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
844                  list<dag> pattern = []>
845     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
846       Sched<[WriteBarrier]> {
847   bits<4> CRm;
848   let Inst{20-12} = 0b000110011;
849   let Inst{11-8} = CRm;
850   let Inst{7-5} = opc;
851 }
852
853 // MRS/MSR system instructions. These have different operand classes because
854 // a different subset of registers can be accessed through each instruction.
855 def MRSSystemRegisterOperand : AsmOperandClass {
856   let Name = "MRSSystemRegister";
857   let ParserMethod = "tryParseSysReg";
858   let DiagnosticType = "MRS";
859 }
860 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
861 def mrs_sysreg_op : Operand<i32> {
862   let ParserMatchClass = MRSSystemRegisterOperand;
863   let DecoderMethod = "DecodeMRSSystemRegister";
864   let PrintMethod = "printMRSSystemRegister";
865 }
866
867 def MSRSystemRegisterOperand : AsmOperandClass {
868   let Name = "MSRSystemRegister";
869   let ParserMethod = "tryParseSysReg";
870   let DiagnosticType = "MSR";
871 }
872 def msr_sysreg_op : Operand<i32> {
873   let ParserMatchClass = MSRSystemRegisterOperand;
874   let DecoderMethod = "DecodeMSRSystemRegister";
875   let PrintMethod = "printMSRSystemRegister";
876 }
877
878 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
879                        "mrs", "\t$Rt, $systemreg"> {
880   bits<16> systemreg;
881   let Inst{20-5} = systemreg;
882 }
883
884 // FIXME: Some of these def NZCV, others don't. Best way to model that?
885 // Explicitly modeling each of the system register as a register class
886 // would do it, but feels like overkill at this point.
887 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
888                        "msr", "\t$systemreg, $Rt"> {
889   bits<16> systemreg;
890   let Inst{20-5} = systemreg;
891 }
892
893 def SystemPStateFieldOperand : AsmOperandClass {
894   let Name = "SystemPStateField";
895   let ParserMethod = "tryParseSysReg";
896 }
897 def pstatefield_op : Operand<i32> {
898   let ParserMatchClass = SystemPStateFieldOperand;
899   let PrintMethod = "printSystemPStateField";
900 }
901
902 let Defs = [NZCV] in
903 class MSRpstateI
904   : SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm),
905                   "msr", "\t$pstate_field, $imm">,
906     Sched<[WriteSys]> {
907   bits<6> pstatefield;
908   bits<4> imm;
909   let Inst{20-19} = 0b00;
910   let Inst{18-16} = pstatefield{5-3};
911   let Inst{15-12} = 0b0100;
912   let Inst{11-8} = imm;
913   let Inst{7-5} = pstatefield{2-0};
914
915   let DecoderMethod = "DecodeSystemPStateInstruction";
916 }
917
918 // SYS and SYSL generic system instructions.
919 def SysCRAsmOperand : AsmOperandClass {
920   let Name = "SysCR";
921   let ParserMethod = "tryParseSysCROperand";
922 }
923
924 def sys_cr_op : Operand<i32> {
925   let PrintMethod = "printSysCROperand";
926   let ParserMatchClass = SysCRAsmOperand;
927 }
928
929 class SystemXtI<bit L, string asm>
930   : RtSystemI<L, (outs),
931        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
932        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
933   bits<3> op1;
934   bits<4> Cn;
935   bits<4> Cm;
936   bits<3> op2;
937   let Inst{20-19} = 0b01;
938   let Inst{18-16} = op1;
939   let Inst{15-12} = Cn;
940   let Inst{11-8}  = Cm;
941   let Inst{7-5}   = op2;
942 }
943
944 class SystemLXtI<bit L, string asm>
945   : RtSystemI<L, (outs),
946        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
947        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
948   bits<3> op1;
949   bits<4> Cn;
950   bits<4> Cm;
951   bits<3> op2;
952   let Inst{20-19} = 0b01;
953   let Inst{18-16} = op1;
954   let Inst{15-12} = Cn;
955   let Inst{11-8}  = Cm;
956   let Inst{7-5}   = op2;
957 }
958
959
960 // Branch (register) instructions:
961 //
962 //  case opc of
963 //    0001 blr
964 //    0000 br
965 //    0101 dret
966 //    0100 eret
967 //    0010 ret
968 //    otherwise UNDEFINED
969 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
970                     string operands, list<dag> pattern>
971     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
972   let Inst{31-25} = 0b1101011;
973   let Inst{24-21} = opc;
974   let Inst{20-16} = 0b11111;
975   let Inst{15-10} = 0b000000;
976   let Inst{4-0}   = 0b00000;
977 }
978
979 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
980     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
981   bits<5> Rn;
982   let Inst{9-5} = Rn;
983 }
984
985 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
986 class SpecialReturn<bits<4> opc, string asm>
987     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
988   let Inst{9-5} = 0b11111;
989 }
990
991 //---
992 // Conditional branch instruction.
993 //---
994
995 // Condition code.
996 // 4-bit immediate. Pretty-printed as <cc>
997 def ccode : Operand<i32> {
998   let PrintMethod = "printCondCode";
999   let ParserMatchClass = CondCode;
1000 }
1001 def inv_ccode : Operand<i32> {
1002   // AL and NV are invalid in the aliases which use inv_ccode
1003   let PrintMethod = "printInverseCondCode";
1004   let ParserMatchClass = CondCode;
1005   let MCOperandPredicate = [{
1006     return MCOp.isImm() &&
1007            MCOp.getImm() != AArch64CC::AL &&
1008            MCOp.getImm() != AArch64CC::NV;
1009   }];
1010 }
1011
1012 // Conditional branch target. 19-bit immediate. The low two bits of the target
1013 // offset are implied zero and so are not part of the immediate.
1014 def PCRelLabel19Operand : AsmOperandClass {
1015   let Name = "PCRelLabel19";
1016   let DiagnosticType = "InvalidLabel";
1017 }
1018 def am_brcond : Operand<OtherVT> {
1019   let EncoderMethod = "getCondBranchTargetOpValue";
1020   let DecoderMethod = "DecodePCRelLabel19";
1021   let PrintMethod = "printAlignedLabel";
1022   let ParserMatchClass = PCRelLabel19Operand;
1023 }
1024
1025 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1026                      "b", ".$cond\t$target", "",
1027                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1028                    Sched<[WriteBr]> {
1029   let isBranch = 1;
1030   let isTerminator = 1;
1031   let Uses = [NZCV];
1032
1033   bits<4> cond;
1034   bits<19> target;
1035   let Inst{31-24} = 0b01010100;
1036   let Inst{23-5} = target;
1037   let Inst{4} = 0;
1038   let Inst{3-0} = cond;
1039 }
1040
1041 //---
1042 // Compare-and-branch instructions.
1043 //---
1044 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1045     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1046          asm, "\t$Rt, $target", "",
1047          [(node regtype:$Rt, bb:$target)]>,
1048       Sched<[WriteBr]> {
1049   let isBranch = 1;
1050   let isTerminator = 1;
1051
1052   bits<5> Rt;
1053   bits<19> target;
1054   let Inst{30-25} = 0b011010;
1055   let Inst{24}    = op;
1056   let Inst{23-5}  = target;
1057   let Inst{4-0}   = Rt;
1058 }
1059
1060 multiclass CmpBranch<bit op, string asm, SDNode node> {
1061   def W : BaseCmpBranch<GPR32, op, asm, node> {
1062     let Inst{31} = 0;
1063   }
1064   def X : BaseCmpBranch<GPR64, op, asm, node> {
1065     let Inst{31} = 1;
1066   }
1067 }
1068
1069 //---
1070 // Test-bit-and-branch instructions.
1071 //---
1072 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1073 // the target offset are implied zero and so are not part of the immediate.
1074 def BranchTarget14Operand : AsmOperandClass {
1075   let Name = "BranchTarget14";
1076 }
1077 def am_tbrcond : Operand<OtherVT> {
1078   let EncoderMethod = "getTestBranchTargetOpValue";
1079   let PrintMethod = "printAlignedLabel";
1080   let ParserMatchClass = BranchTarget14Operand;
1081 }
1082
1083 // AsmOperand classes to emit (or not) special diagnostics
1084 def TBZImm0_31Operand : AsmOperandClass {
1085   let Name = "TBZImm0_31";
1086   let PredicateMethod = "isImm0_31";
1087   let RenderMethod = "addImm0_31Operands";
1088 }
1089 def TBZImm32_63Operand : AsmOperandClass {
1090   let Name = "Imm32_63";
1091   let DiagnosticType = "InvalidImm0_63";
1092 }
1093
1094 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1095   return (((uint32_t)Imm) < 32);
1096 }]> {
1097   let ParserMatchClass = matcher;
1098 }
1099
1100 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1101 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1102
1103 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1104   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1105 }]> {
1106   let ParserMatchClass = TBZImm32_63Operand;
1107 }
1108
1109 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1110                      bit op, string asm, SDNode node>
1111     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1112        asm, "\t$Rt, $bit_off, $target", "",
1113        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1114       Sched<[WriteBr]> {
1115   let isBranch = 1;
1116   let isTerminator = 1;
1117
1118   bits<5> Rt;
1119   bits<6> bit_off;
1120   bits<14> target;
1121
1122   let Inst{30-25} = 0b011011;
1123   let Inst{24}    = op;
1124   let Inst{23-19} = bit_off{4-0};
1125   let Inst{18-5}  = target;
1126   let Inst{4-0}   = Rt;
1127
1128   let DecoderMethod = "DecodeTestAndBranch";
1129 }
1130
1131 multiclass TestBranch<bit op, string asm, SDNode node> {
1132   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1133     let Inst{31} = 0;
1134   }
1135
1136   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1137     let Inst{31} = 1;
1138   }
1139
1140   // Alias X-reg with 0-31 imm to W-Reg.
1141   def : InstAlias<asm # "\t$Rd, $imm, $target",
1142                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1143                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1144   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1145             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1146             tbz_imm0_31_diag:$imm, bb:$target)>;
1147 }
1148
1149 //---
1150 // Unconditional branch (immediate) instructions.
1151 //---
1152 def BranchTarget26Operand : AsmOperandClass {
1153   let Name = "BranchTarget26";
1154   let DiagnosticType = "InvalidLabel";
1155 }
1156 def am_b_target : Operand<OtherVT> {
1157   let EncoderMethod = "getBranchTargetOpValue";
1158   let PrintMethod = "printAlignedLabel";
1159   let ParserMatchClass = BranchTarget26Operand;
1160 }
1161 def am_bl_target : Operand<i64> {
1162   let EncoderMethod = "getBranchTargetOpValue";
1163   let PrintMethod = "printAlignedLabel";
1164   let ParserMatchClass = BranchTarget26Operand;
1165 }
1166
1167 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1168     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1169   bits<26> addr;
1170   let Inst{31}    = op;
1171   let Inst{30-26} = 0b00101;
1172   let Inst{25-0}  = addr;
1173
1174   let DecoderMethod = "DecodeUnconditionalBranch";
1175 }
1176
1177 class BranchImm<bit op, string asm, list<dag> pattern>
1178     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1179 class CallImm<bit op, string asm, list<dag> pattern>
1180     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1181
1182 //---
1183 // Basic one-operand data processing instructions.
1184 //---
1185
1186 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1187 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1188                          SDPatternOperator node>
1189   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1190       [(set regtype:$Rd, (node regtype:$Rn))]>,
1191     Sched<[WriteI, ReadI]> {
1192   bits<5> Rd;
1193   bits<5> Rn;
1194
1195   let Inst{30-13} = 0b101101011000000000;
1196   let Inst{12-10} = opc;
1197   let Inst{9-5}   = Rn;
1198   let Inst{4-0}   = Rd;
1199 }
1200
1201 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1202 multiclass OneOperandData<bits<3> opc, string asm,
1203                           SDPatternOperator node = null_frag> {
1204   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1205     let Inst{31} = 0;
1206   }
1207
1208   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1209     let Inst{31} = 1;
1210   }
1211 }
1212
1213 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1214     : BaseOneOperandData<opc, GPR32, asm, node> {
1215   let Inst{31} = 0;
1216 }
1217
1218 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1219     : BaseOneOperandData<opc, GPR64, asm, node> {
1220   let Inst{31} = 1;
1221 }
1222
1223 //---
1224 // Basic two-operand data processing instructions.
1225 //---
1226 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1227                           list<dag> pattern>
1228     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1229         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1230       Sched<[WriteI, ReadI, ReadI]> {
1231   let Uses = [NZCV];
1232   bits<5> Rd;
1233   bits<5> Rn;
1234   bits<5> Rm;
1235   let Inst{30}    = isSub;
1236   let Inst{28-21} = 0b11010000;
1237   let Inst{20-16} = Rm;
1238   let Inst{15-10} = 0;
1239   let Inst{9-5}   = Rn;
1240   let Inst{4-0}   = Rd;
1241 }
1242
1243 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1244                       SDNode OpNode>
1245     : BaseBaseAddSubCarry<isSub, regtype, asm,
1246         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1247
1248 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1249                               SDNode OpNode>
1250     : BaseBaseAddSubCarry<isSub, regtype, asm,
1251         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1252          (implicit NZCV)]> {
1253   let Defs = [NZCV];
1254 }
1255
1256 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1257                        SDNode OpNode, SDNode OpNode_setflags> {
1258   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1259     let Inst{31} = 0;
1260     let Inst{29} = 0;
1261   }
1262   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1263     let Inst{31} = 1;
1264     let Inst{29} = 0;
1265   }
1266
1267   // Sets flags.
1268   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1269                                     OpNode_setflags> {
1270     let Inst{31} = 0;
1271     let Inst{29} = 1;
1272   }
1273   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1274                                     OpNode_setflags> {
1275     let Inst{31} = 1;
1276     let Inst{29} = 1;
1277   }
1278 }
1279
1280 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1281                      SDPatternOperator OpNode>
1282   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1283       asm, "\t$Rd, $Rn, $Rm", "",
1284       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1285   bits<5> Rd;
1286   bits<5> Rn;
1287   bits<5> Rm;
1288   let Inst{30-21} = 0b0011010110;
1289   let Inst{20-16} = Rm;
1290   let Inst{15-14} = 0b00;
1291   let Inst{13-10} = opc;
1292   let Inst{9-5}   = Rn;
1293   let Inst{4-0}   = Rd;
1294 }
1295
1296 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1297               SDPatternOperator OpNode>
1298     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1299   let Inst{10}    = isSigned;
1300 }
1301
1302 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1303   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1304            Sched<[WriteID32, ReadID, ReadID]> {
1305     let Inst{31} = 0;
1306   }
1307   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1308            Sched<[WriteID64, ReadID, ReadID]> {
1309     let Inst{31} = 1;
1310   }
1311 }
1312
1313 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1314                 SDPatternOperator OpNode = null_frag>
1315   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1316     Sched<[WriteIS, ReadI]> {
1317   let Inst{11-10} = shift_type;
1318 }
1319
1320 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1321   def Wr : BaseShift<shift_type, GPR32, asm> {
1322     let Inst{31} = 0;
1323   }
1324
1325   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1326     let Inst{31} = 1;
1327   }
1328
1329   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1330             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1331                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1332
1333   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1334             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1335
1336   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1337             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1338
1339   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1340             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1341 }
1342
1343 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1344     : InstAlias<asm#" $dst, $src1, $src2",
1345                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1346
1347 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1348                        RegisterClass addtype, string asm,
1349                        list<dag> pattern>
1350   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1351       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1352   bits<5> Rd;
1353   bits<5> Rn;
1354   bits<5> Rm;
1355   bits<5> Ra;
1356   let Inst{30-24} = 0b0011011;
1357   let Inst{23-21} = opc;
1358   let Inst{20-16} = Rm;
1359   let Inst{15}    = isSub;
1360   let Inst{14-10} = Ra;
1361   let Inst{9-5}   = Rn;
1362   let Inst{4-0}   = Rd;
1363 }
1364
1365 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1366   // MADD/MSUB generation is decided by MachineCombiner.cpp
1367   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1368       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1369       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1370     let Inst{31} = 0;
1371   }
1372
1373   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1374       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1375       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1376     let Inst{31} = 1;
1377   }
1378 }
1379
1380 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1381                    SDNode AccNode, SDNode ExtNode>
1382   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1383     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1384                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1385     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1386   let Inst{31} = 1;
1387 }
1388
1389 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1390   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1391       asm, "\t$Rd, $Rn, $Rm", "",
1392       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1393     Sched<[WriteIM64, ReadIM, ReadIM]> {
1394   bits<5> Rd;
1395   bits<5> Rn;
1396   bits<5> Rm;
1397   let Inst{31-24} = 0b10011011;
1398   let Inst{23-21} = opc;
1399   let Inst{20-16} = Rm;
1400   let Inst{15}    = 0;
1401   let Inst{9-5}   = Rn;
1402   let Inst{4-0}   = Rd;
1403
1404   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1405   // (i.e. all bits 1) but is ignored by the processor.
1406   let PostEncoderMethod = "fixMulHigh";
1407 }
1408
1409 class MulAccumWAlias<string asm, Instruction inst>
1410     : InstAlias<asm#" $dst, $src1, $src2",
1411                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1412 class MulAccumXAlias<string asm, Instruction inst>
1413     : InstAlias<asm#" $dst, $src1, $src2",
1414                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1415 class WideMulAccumAlias<string asm, Instruction inst>
1416     : InstAlias<asm#" $dst, $src1, $src2",
1417                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1418
1419 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1420               SDPatternOperator OpNode, string asm>
1421   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1422       asm, "\t$Rd, $Rn, $Rm", "",
1423       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1424     Sched<[WriteISReg, ReadI, ReadISReg]> {
1425   bits<5> Rd;
1426   bits<5> Rn;
1427   bits<5> Rm;
1428
1429   let Inst{31} = sf;
1430   let Inst{30-21} = 0b0011010110;
1431   let Inst{20-16} = Rm;
1432   let Inst{15-13} = 0b010;
1433   let Inst{12} = C;
1434   let Inst{11-10} = sz;
1435   let Inst{9-5} = Rn;
1436   let Inst{4-0} = Rd;
1437   let Predicates = [HasCRC];
1438 }
1439
1440 //---
1441 // Address generation.
1442 //---
1443
1444 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1445     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1446         pattern>,
1447       Sched<[WriteI]> {
1448   bits<5>  Xd;
1449   bits<21> label;
1450   let Inst{31}    = page;
1451   let Inst{30-29} = label{1-0};
1452   let Inst{28-24} = 0b10000;
1453   let Inst{23-5}  = label{20-2};
1454   let Inst{4-0}   = Xd;
1455
1456   let DecoderMethod = "DecodeAdrInstruction";
1457 }
1458
1459 //---
1460 // Move immediate.
1461 //---
1462
1463 def movimm32_imm : Operand<i32> {
1464   let ParserMatchClass = Imm0_65535Operand;
1465   let EncoderMethod = "getMoveWideImmOpValue";
1466   let PrintMethod = "printHexImm";
1467 }
1468 def movimm32_shift : Operand<i32> {
1469   let PrintMethod = "printShifter";
1470   let ParserMatchClass = MovImm32ShifterOperand;
1471 }
1472 def movimm64_shift : Operand<i32> {
1473   let PrintMethod = "printShifter";
1474   let ParserMatchClass = MovImm64ShifterOperand;
1475 }
1476
1477 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1478 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1479                         string asm>
1480   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1481        asm, "\t$Rd, $imm$shift", "", []>,
1482     Sched<[WriteImm]> {
1483   bits<5> Rd;
1484   bits<16> imm;
1485   bits<6> shift;
1486   let Inst{30-29} = opc;
1487   let Inst{28-23} = 0b100101;
1488   let Inst{22-21} = shift{5-4};
1489   let Inst{20-5}  = imm;
1490   let Inst{4-0}   = Rd;
1491
1492   let DecoderMethod = "DecodeMoveImmInstruction";
1493 }
1494
1495 multiclass MoveImmediate<bits<2> opc, string asm> {
1496   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1497     let Inst{31} = 0;
1498   }
1499
1500   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1501     let Inst{31} = 1;
1502   }
1503 }
1504
1505 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1506 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1507                           string asm>
1508   : I<(outs regtype:$Rd),
1509       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1510        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1511     Sched<[WriteI, ReadI]> {
1512   bits<5> Rd;
1513   bits<16> imm;
1514   bits<6> shift;
1515   let Inst{30-29} = opc;
1516   let Inst{28-23} = 0b100101;
1517   let Inst{22-21} = shift{5-4};
1518   let Inst{20-5}  = imm;
1519   let Inst{4-0}   = Rd;
1520
1521   let DecoderMethod = "DecodeMoveImmInstruction";
1522 }
1523
1524 multiclass InsertImmediate<bits<2> opc, string asm> {
1525   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1526     let Inst{31} = 0;
1527   }
1528
1529   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1530     let Inst{31} = 1;
1531   }
1532 }
1533
1534 //---
1535 // Add/Subtract
1536 //---
1537
1538 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1539                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1540                     string asm, SDPatternOperator OpNode>
1541     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1542         asm, "\t$Rd, $Rn, $imm", "",
1543         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1544       Sched<[WriteI, ReadI]>  {
1545   bits<5>  Rd;
1546   bits<5>  Rn;
1547   bits<14> imm;
1548   let Inst{30}    = isSub;
1549   let Inst{29}    = setFlags;
1550   let Inst{28-24} = 0b10001;
1551   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1552   let Inst{21-10} = imm{11-0};
1553   let Inst{9-5}   = Rn;
1554   let Inst{4-0}   = Rd;
1555   let DecoderMethod = "DecodeBaseAddSubImm";
1556 }
1557
1558 class BaseAddSubRegPseudo<RegisterClass regtype,
1559                           SDPatternOperator OpNode>
1560     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1561              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1562       Sched<[WriteI, ReadI, ReadI]>;
1563
1564 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1565                      arith_shifted_reg shifted_regtype, string asm,
1566                      SDPatternOperator OpNode>
1567     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1568         asm, "\t$Rd, $Rn, $Rm", "",
1569         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1570       Sched<[WriteISReg, ReadI, ReadISReg]> {
1571   // The operands are in order to match the 'addr' MI operands, so we
1572   // don't need an encoder method and by-name matching. Just use the default
1573   // in-order handling. Since we're using by-order, make sure the names
1574   // do not match.
1575   bits<5> dst;
1576   bits<5> src1;
1577   bits<5> src2;
1578   bits<8> shift;
1579   let Inst{30}    = isSub;
1580   let Inst{29}    = setFlags;
1581   let Inst{28-24} = 0b01011;
1582   let Inst{23-22} = shift{7-6};
1583   let Inst{21}    = 0;
1584   let Inst{20-16} = src2;
1585   let Inst{15-10} = shift{5-0};
1586   let Inst{9-5}   = src1;
1587   let Inst{4-0}   = dst;
1588
1589   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1590 }
1591
1592 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1593                      RegisterClass src1Regtype, Operand src2Regtype,
1594                      string asm, SDPatternOperator OpNode>
1595     : I<(outs dstRegtype:$R1),
1596         (ins src1Regtype:$R2, src2Regtype:$R3),
1597         asm, "\t$R1, $R2, $R3", "",
1598         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
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-13} = ext{5-3};
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 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1618 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1619                        RegisterClass src1Regtype, RegisterClass src2Regtype,
1620                        Operand ext_op, string asm>
1621     : I<(outs dstRegtype:$Rd),
1622         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1623         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1624       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1625   bits<5> Rd;
1626   bits<5> Rn;
1627   bits<5> Rm;
1628   bits<6> ext;
1629   let Inst{30}    = isSub;
1630   let Inst{29}    = setFlags;
1631   let Inst{28-24} = 0b01011;
1632   let Inst{23-21} = 0b001;
1633   let Inst{20-16} = Rm;
1634   let Inst{15}    = ext{5};
1635   let Inst{12-10} = ext{2-0};
1636   let Inst{9-5}   = Rn;
1637   let Inst{4-0}   = Rd;
1638
1639   let DecoderMethod = "DecodeAddSubERegInstruction";
1640 }
1641
1642 // Aliases for register+register add/subtract.
1643 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1644                      RegisterClass src1Regtype, RegisterClass src2Regtype,
1645                      int shiftExt>
1646     : InstAlias<asm#" $dst, $src1, $src2",
1647                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1648                       shiftExt)>;
1649
1650 multiclass AddSub<bit isSub, string mnemonic, string alias,
1651                   SDPatternOperator OpNode = null_frag> {
1652   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1653   // Add/Subtract immediate
1654   // Increase the weight of the immediate variant to try to match it before
1655   // the extended register variant.
1656   // We used to match the register variant before the immediate when the
1657   // register argument could be implicitly zero-extended.
1658   let AddedComplexity = 6 in
1659   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1660                            mnemonic, OpNode> {
1661     let Inst{31} = 0;
1662   }
1663   let AddedComplexity = 6 in
1664   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1665                            mnemonic, OpNode> {
1666     let Inst{31} = 1;
1667   }
1668
1669   // Add/Subtract register - Only used for CodeGen
1670   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1671   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1672
1673   // Add/Subtract shifted register
1674   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1675                            OpNode> {
1676     let Inst{31} = 0;
1677   }
1678   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1679                            OpNode> {
1680     let Inst{31} = 1;
1681   }
1682   }
1683
1684   // Add/Subtract extended register
1685   let AddedComplexity = 1, hasSideEffects = 0 in {
1686   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1687                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1688     let Inst{31} = 0;
1689   }
1690   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1691                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1692     let Inst{31} = 1;
1693   }
1694   }
1695
1696   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1697                                arith_extendlsl64, mnemonic> {
1698     // UXTX and SXTX only.
1699     let Inst{14-13} = 0b11;
1700     let Inst{31} = 1;
1701   }
1702
1703   // add Rd, Rb, -imm -> sub Rd, Rn, imm
1704   def : InstAlias<alias#" $Rd, $Rn, $imm",
1705                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
1706                       addsub_shifted_imm32_neg:$imm), 0>;
1707   def : InstAlias<alias#" $Rd, $Rn, $imm",
1708                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
1709                        addsub_shifted_imm64_neg:$imm), 0>;
1710
1711   // Register/register aliases with no shift when SP is not used.
1712   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1713                        GPR32, GPR32, GPR32, 0>;
1714   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1715                        GPR64, GPR64, GPR64, 0>;
1716
1717   // Register/register aliases with no shift when either the destination or
1718   // first source register is SP.
1719   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1720                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1721   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1722                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1723   def : AddSubRegAlias<mnemonic,
1724                        !cast<Instruction>(NAME#"Xrx64"),
1725                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1726   def : AddSubRegAlias<mnemonic,
1727                        !cast<Instruction>(NAME#"Xrx64"),
1728                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1729 }
1730
1731 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
1732                    string alias, string cmpAlias> {
1733   let isCompare = 1, Defs = [NZCV] in {
1734   // Add/Subtract immediate
1735   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1736                            mnemonic, OpNode> {
1737     let Inst{31} = 0;
1738   }
1739   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1740                            mnemonic, OpNode> {
1741     let Inst{31} = 1;
1742   }
1743
1744   // Add/Subtract register
1745   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1746   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1747
1748   // Add/Subtract shifted register
1749   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1750                            OpNode> {
1751     let Inst{31} = 0;
1752   }
1753   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1754                            OpNode> {
1755     let Inst{31} = 1;
1756   }
1757
1758   // Add/Subtract extended register
1759   let AddedComplexity = 1 in {
1760   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1761                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1762     let Inst{31} = 0;
1763   }
1764   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1765                            arith_extended_reg32<i64>, mnemonic, OpNode> {
1766     let Inst{31} = 1;
1767   }
1768   }
1769
1770   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1771                                arith_extendlsl64, mnemonic> {
1772     // UXTX and SXTX only.
1773     let Inst{14-13} = 0b11;
1774     let Inst{31} = 1;
1775   }
1776   } // Defs = [NZCV]
1777
1778   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
1779   def : InstAlias<alias#" $Rd, $Rn, $imm",
1780                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
1781                       addsub_shifted_imm32_neg:$imm), 0>;
1782   def : InstAlias<alias#" $Rd, $Rn, $imm",
1783                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
1784                        addsub_shifted_imm64_neg:$imm), 0>;
1785
1786   // Compare aliases
1787   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Wri")
1788                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1789   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Xri")
1790                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1791   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1792                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1793   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1794                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1795   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1796                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1797   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1798                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1799   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1800                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1801
1802   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
1803   def : InstAlias<cmpAlias#" $src, $imm", (!cast<Instruction>(NAME#"Wri")
1804                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
1805   def : InstAlias<cmpAlias#" $src, $imm", (!cast<Instruction>(NAME#"Xri")
1806                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
1807
1808   // Compare shorthands
1809   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1810                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1811   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1812                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1813   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1814                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1815   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1816                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1817
1818   // Register/register aliases with no shift when SP is not used.
1819   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1820                        GPR32, GPR32, GPR32, 0>;
1821   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1822                        GPR64, GPR64, GPR64, 0>;
1823
1824   // Register/register aliases with no shift when the first source register
1825   // is SP.
1826   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1827                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1828   def : AddSubRegAlias<mnemonic,
1829                        !cast<Instruction>(NAME#"Xrx64"),
1830                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1831 }
1832
1833 //---
1834 // Extract
1835 //---
1836 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1837                                       SDTCisPtrTy<3>]>;
1838 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1839
1840 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1841                      list<dag> patterns>
1842     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1843          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1844       Sched<[WriteExtr, ReadExtrHi]> {
1845   bits<5> Rd;
1846   bits<5> Rn;
1847   bits<5> Rm;
1848   bits<6> imm;
1849
1850   let Inst{30-23} = 0b00100111;
1851   let Inst{21}    = 0;
1852   let Inst{20-16} = Rm;
1853   let Inst{15-10} = imm;
1854   let Inst{9-5}   = Rn;
1855   let Inst{4-0}   = Rd;
1856 }
1857
1858 multiclass ExtractImm<string asm> {
1859   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1860                       [(set GPR32:$Rd,
1861                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1862     let Inst{31} = 0;
1863     let Inst{22} = 0;
1864     // imm<5> must be zero.
1865     let imm{5}   = 0;
1866   }
1867   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1868                       [(set GPR64:$Rd,
1869                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1870
1871     let Inst{31} = 1;
1872     let Inst{22} = 1;
1873   }
1874 }
1875
1876 //---
1877 // Bitfield
1878 //---
1879
1880 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1881 class BaseBitfieldImm<bits<2> opc,
1882                       RegisterClass regtype, Operand imm_type, string asm>
1883     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1884          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1885       Sched<[WriteIS, ReadI]> {
1886   bits<5> Rd;
1887   bits<5> Rn;
1888   bits<6> immr;
1889   bits<6> imms;
1890
1891   let Inst{30-29} = opc;
1892   let Inst{28-23} = 0b100110;
1893   let Inst{21-16} = immr;
1894   let Inst{15-10} = imms;
1895   let Inst{9-5}   = Rn;
1896   let Inst{4-0}   = Rd;
1897 }
1898
1899 multiclass BitfieldImm<bits<2> opc, string asm> {
1900   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1901     let Inst{31} = 0;
1902     let Inst{22} = 0;
1903     // imms<5> and immr<5> must be zero, else ReservedValue().
1904     let Inst{21} = 0;
1905     let Inst{15} = 0;
1906   }
1907   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1908     let Inst{31} = 1;
1909     let Inst{22} = 1;
1910   }
1911 }
1912
1913 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1914 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1915                       RegisterClass regtype, Operand imm_type, string asm>
1916     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1917                              imm_type:$imms),
1918          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1919       Sched<[WriteIS, ReadI]> {
1920   bits<5> Rd;
1921   bits<5> Rn;
1922   bits<6> immr;
1923   bits<6> imms;
1924
1925   let Inst{30-29} = opc;
1926   let Inst{28-23} = 0b100110;
1927   let Inst{21-16} = immr;
1928   let Inst{15-10} = imms;
1929   let Inst{9-5}   = Rn;
1930   let Inst{4-0}   = Rd;
1931 }
1932
1933 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1934   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1935     let Inst{31} = 0;
1936     let Inst{22} = 0;
1937     // imms<5> and immr<5> must be zero, else ReservedValue().
1938     let Inst{21} = 0;
1939     let Inst{15} = 0;
1940   }
1941   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1942     let Inst{31} = 1;
1943     let Inst{22} = 1;
1944   }
1945 }
1946
1947 //---
1948 // Logical
1949 //---
1950
1951 // Logical (immediate)
1952 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1953                      RegisterClass sregtype, Operand imm_type, string asm,
1954                      list<dag> pattern>
1955     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1956          asm, "\t$Rd, $Rn, $imm", "", pattern>,
1957       Sched<[WriteI, ReadI]> {
1958   bits<5>  Rd;
1959   bits<5>  Rn;
1960   bits<13> imm;
1961   let Inst{30-29} = opc;
1962   let Inst{28-23} = 0b100100;
1963   let Inst{22}    = imm{12};
1964   let Inst{21-16} = imm{11-6};
1965   let Inst{15-10} = imm{5-0};
1966   let Inst{9-5}   = Rn;
1967   let Inst{4-0}   = Rd;
1968
1969   let DecoderMethod = "DecodeLogicalImmInstruction";
1970 }
1971
1972 // Logical (shifted register)
1973 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1974                       logical_shifted_reg shifted_regtype, string asm,
1975                       list<dag> pattern>
1976     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1977         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1978       Sched<[WriteISReg, ReadI, ReadISReg]> {
1979   // The operands are in order to match the 'addr' MI operands, so we
1980   // don't need an encoder method and by-name matching. Just use the default
1981   // in-order handling. Since we're using by-order, make sure the names
1982   // do not match.
1983   bits<5> dst;
1984   bits<5> src1;
1985   bits<5> src2;
1986   bits<8> shift;
1987   let Inst{30-29} = opc;
1988   let Inst{28-24} = 0b01010;
1989   let Inst{23-22} = shift{7-6};
1990   let Inst{21}    = N;
1991   let Inst{20-16} = src2;
1992   let Inst{15-10} = shift{5-0};
1993   let Inst{9-5}   = src1;
1994   let Inst{4-0}   = dst;
1995
1996   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1997 }
1998
1999 // Aliases for register+register logical instructions.
2000 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2001     : InstAlias<asm#" $dst, $src1, $src2",
2002                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2003
2004 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2005                       string Alias> {
2006   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2007   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2008                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2009                                                logical_imm32:$imm))]> {
2010     let Inst{31} = 0;
2011     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2012   }
2013   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2014   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2015                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2016                                                logical_imm64:$imm))]> {
2017     let Inst{31} = 1;
2018   }
2019
2020   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2021                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2022                       logical_imm32_not:$imm), 0>;
2023   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2024                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2025                        logical_imm64_not:$imm), 0>;
2026 }
2027
2028 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2029                        string Alias> {
2030   let isCompare = 1, Defs = [NZCV] in {
2031   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2032       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2033     let Inst{31} = 0;
2034     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2035   }
2036   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2037       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2038     let Inst{31} = 1;
2039   }
2040   } // end Defs = [NZCV]
2041
2042   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2043                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2044                       logical_imm32_not:$imm), 0>;
2045   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2046                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2047                        logical_imm64_not:$imm), 0>;
2048 }
2049
2050 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2051     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2052              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2053       Sched<[WriteI, ReadI, ReadI]>;
2054
2055 // Split from LogicalImm as not all instructions have both.
2056 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2057                       SDPatternOperator OpNode> {
2058   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2059   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2060   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2061   }
2062
2063   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2064                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2065                                                  logical_shifted_reg32:$Rm))]> {
2066     let Inst{31} = 0;
2067   }
2068   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2069                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2070                                                  logical_shifted_reg64:$Rm))]> {
2071     let Inst{31} = 1;
2072   }
2073
2074   def : LogicalRegAlias<mnemonic,
2075                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2076   def : LogicalRegAlias<mnemonic,
2077                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2078 }
2079
2080 // Split from LogicalReg to allow setting NZCV Defs
2081 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2082                        SDPatternOperator OpNode = null_frag> {
2083   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2084   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2085   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2086
2087   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2088             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2089     let Inst{31} = 0;
2090   }
2091   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2092             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2093     let Inst{31} = 1;
2094   }
2095   } // Defs = [NZCV]
2096
2097   def : LogicalRegAlias<mnemonic,
2098                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2099   def : LogicalRegAlias<mnemonic,
2100                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2101 }
2102
2103 //---
2104 // Conditionally set flags
2105 //---
2106
2107 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2108 class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
2109     : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
2110          asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
2111       Sched<[WriteI, ReadI]> {
2112   let Uses = [NZCV];
2113   let Defs = [NZCV];
2114
2115   bits<5> Rn;
2116   bits<5> imm;
2117   bits<4> nzcv;
2118   bits<4> cond;
2119
2120   let Inst{30}    = op;
2121   let Inst{29-21} = 0b111010010;
2122   let Inst{20-16} = imm;
2123   let Inst{15-12} = cond;
2124   let Inst{11-10} = 0b10;
2125   let Inst{9-5}   = Rn;
2126   let Inst{4}     = 0b0;
2127   let Inst{3-0}   = nzcv;
2128 }
2129
2130 multiclass CondSetFlagsImm<bit op, string asm> {
2131   def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
2132     let Inst{31} = 0;
2133   }
2134   def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
2135     let Inst{31} = 1;
2136   }
2137 }
2138
2139 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2140 class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
2141     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
2142          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
2143       Sched<[WriteI, ReadI, ReadI]> {
2144   let Uses = [NZCV];
2145   let Defs = [NZCV];
2146
2147   bits<5> Rn;
2148   bits<5> Rm;
2149   bits<4> nzcv;
2150   bits<4> cond;
2151
2152   let Inst{30}    = op;
2153   let Inst{29-21} = 0b111010010;
2154   let Inst{20-16} = Rm;
2155   let Inst{15-12} = cond;
2156   let Inst{11-10} = 0b00;
2157   let Inst{9-5}   = Rn;
2158   let Inst{4}     = 0b0;
2159   let Inst{3-0}   = nzcv;
2160 }
2161
2162 multiclass CondSetFlagsReg<bit op, string asm> {
2163   def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
2164     let Inst{31} = 0;
2165   }
2166   def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
2167     let Inst{31} = 1;
2168   }
2169 }
2170
2171 //---
2172 // Conditional select
2173 //---
2174
2175 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2176     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2177          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2178          [(set regtype:$Rd,
2179                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2180       Sched<[WriteI, ReadI, ReadI]> {
2181   let Uses = [NZCV];
2182
2183   bits<5> Rd;
2184   bits<5> Rn;
2185   bits<5> Rm;
2186   bits<4> cond;
2187
2188   let Inst{30}    = op;
2189   let Inst{29-21} = 0b011010100;
2190   let Inst{20-16} = Rm;
2191   let Inst{15-12} = cond;
2192   let Inst{11-10} = op2;
2193   let Inst{9-5}   = Rn;
2194   let Inst{4-0}   = Rd;
2195 }
2196
2197 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2198   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2199     let Inst{31} = 0;
2200   }
2201   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2202     let Inst{31} = 1;
2203   }
2204 }
2205
2206 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2207                        PatFrag frag>
2208     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2209          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2210          [(set regtype:$Rd,
2211                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2212                (i32 imm:$cond), NZCV))]>,
2213       Sched<[WriteI, ReadI, ReadI]> {
2214   let Uses = [NZCV];
2215
2216   bits<5> Rd;
2217   bits<5> Rn;
2218   bits<5> Rm;
2219   bits<4> cond;
2220
2221   let Inst{30}    = op;
2222   let Inst{29-21} = 0b011010100;
2223   let Inst{20-16} = Rm;
2224   let Inst{15-12} = cond;
2225   let Inst{11-10} = op2;
2226   let Inst{9-5}   = Rn;
2227   let Inst{4-0}   = Rd;
2228 }
2229
2230 def inv_cond_XFORM : SDNodeXForm<imm, [{
2231   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2232   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2233                                    MVT::i32);
2234 }]>;
2235
2236 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2237   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2238     let Inst{31} = 0;
2239   }
2240   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2241     let Inst{31} = 1;
2242   }
2243
2244   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2245             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2246                                            (inv_cond_XFORM imm:$cond))>;
2247
2248   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2249             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2250                                            (inv_cond_XFORM imm:$cond))>;
2251 }
2252
2253 //---
2254 // Special Mask Value
2255 //---
2256 def maski8_or_more : Operand<i32>,
2257   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2258 }
2259 def maski16_or_more : Operand<i32>,
2260   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2261 }
2262
2263
2264 //---
2265 // Load/store
2266 //---
2267
2268 // (unsigned immediate)
2269 // Indexed for 8-bit registers. offset is in range [0,4095].
2270 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2271 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2272 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2273 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2274 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2275
2276 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2277   let Name = "UImm12Offset" # Scale;
2278   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2279   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2280   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2281 }
2282
2283 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2284 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2285 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2286 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2287 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2288
2289 class uimm12_scaled<int Scale> : Operand<i64> {
2290   let ParserMatchClass
2291    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2292   let EncoderMethod
2293    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2294   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2295 }
2296
2297 def uimm12s1 : uimm12_scaled<1>;
2298 def uimm12s2 : uimm12_scaled<2>;
2299 def uimm12s4 : uimm12_scaled<4>;
2300 def uimm12s8 : uimm12_scaled<8>;
2301 def uimm12s16 : uimm12_scaled<16>;
2302
2303 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2304                       string asm, list<dag> pattern>
2305     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2306   bits<5> Rt;
2307
2308   bits<5> Rn;
2309   bits<12> offset;
2310
2311   let Inst{31-30} = sz;
2312   let Inst{29-27} = 0b111;
2313   let Inst{26}    = V;
2314   let Inst{25-24} = 0b01;
2315   let Inst{23-22} = opc;
2316   let Inst{21-10} = offset;
2317   let Inst{9-5}   = Rn;
2318   let Inst{4-0}   = Rt;
2319
2320   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2321 }
2322
2323 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2324                   Operand indextype, string asm, list<dag> pattern> {
2325   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2326   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2327                            (ins GPR64sp:$Rn, indextype:$offset),
2328                            asm, pattern>,
2329            Sched<[WriteLD]>;
2330
2331   def : InstAlias<asm # " $Rt, [$Rn]",
2332                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2333 }
2334
2335 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2336              Operand indextype, string asm, list<dag> pattern> {
2337   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2338   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2339                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2340                            asm, pattern>,
2341            Sched<[WriteST]>;
2342
2343   def : InstAlias<asm # " $Rt, [$Rn]",
2344                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2345 }
2346
2347 def PrefetchOperand : AsmOperandClass {
2348   let Name = "Prefetch";
2349   let ParserMethod = "tryParsePrefetch";
2350 }
2351 def prfop : Operand<i32> {
2352   let PrintMethod = "printPrefetchOp";
2353   let ParserMatchClass = PrefetchOperand;
2354 }
2355
2356 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2357 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2358     : BaseLoadStoreUI<sz, V, opc,
2359                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2360                       asm, pat>,
2361       Sched<[WriteLD]>;
2362
2363 //---
2364 // Load literal
2365 //---
2366
2367 // Load literal address: 19-bit immediate. The low two bits of the target
2368 // offset are implied zero and so are not part of the immediate.
2369 def am_ldrlit : Operand<OtherVT> {
2370   let EncoderMethod = "getLoadLiteralOpValue";
2371   let DecoderMethod = "DecodePCRelLabel19";
2372   let PrintMethod = "printAlignedLabel";
2373   let ParserMatchClass = PCRelLabel19Operand;
2374 }
2375
2376 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2377 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2378     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2379         asm, "\t$Rt, $label", "", []>,
2380       Sched<[WriteLD]> {
2381   bits<5> Rt;
2382   bits<19> label;
2383   let Inst{31-30} = opc;
2384   let Inst{29-27} = 0b011;
2385   let Inst{26}    = V;
2386   let Inst{25-24} = 0b00;
2387   let Inst{23-5}  = label;
2388   let Inst{4-0}   = Rt;
2389 }
2390
2391 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2392 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2393     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2394         asm, "\t$Rt, $label", "", pat>,
2395       Sched<[WriteLD]> {
2396   bits<5> Rt;
2397   bits<19> label;
2398   let Inst{31-30} = opc;
2399   let Inst{29-27} = 0b011;
2400   let Inst{26}    = V;
2401   let Inst{25-24} = 0b00;
2402   let Inst{23-5}  = label;
2403   let Inst{4-0}   = Rt;
2404 }
2405
2406 //---
2407 // Load/store register offset
2408 //---
2409
2410 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2411 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2412 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2413 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2414 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2415
2416 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2417 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2418 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2419 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2420 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2421
2422 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2423   let Name = "Mem" # Reg # "Extend" # Width;
2424   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2425   let RenderMethod = "addMemExtendOperands";
2426   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2427 }
2428
2429 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2430   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2431   // the trivial shift.
2432   let RenderMethod = "addMemExtend8Operands";
2433 }
2434 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2435 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2436 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2437 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2438
2439 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2440   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2441   // the trivial shift.
2442   let RenderMethod = "addMemExtend8Operands";
2443 }
2444 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2445 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2446 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2447 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2448
2449 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2450         : Operand<i32> {
2451   let ParserMatchClass = ParserClass;
2452   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2453   let DecoderMethod = "DecodeMemExtend";
2454   let EncoderMethod = "getMemExtendOpValue";
2455   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2456 }
2457
2458 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2459 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2460 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2461 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2462 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2463
2464 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2465 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2466 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2467 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2468 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2469
2470 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2471                   Operand wextend, Operand xextend>  {
2472   // CodeGen-level pattern covering the entire addressing mode.
2473   ComplexPattern Wpat = windex;
2474   ComplexPattern Xpat = xindex;
2475
2476   // Asm-level Operand covering the valid "uxtw #3" style syntax.
2477   Operand Wext = wextend;
2478   Operand Xext = xextend;
2479 }
2480
2481 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2482 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2483 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2484 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2485 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2486                        ro_Xextend128>;
2487
2488 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2489                       string asm, dag ins, dag outs, list<dag> pat>
2490     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2491   bits<5> Rt;
2492   bits<5> Rn;
2493   bits<5> Rm;
2494   bits<2> extend;
2495   let Inst{31-30} = sz;
2496   let Inst{29-27} = 0b111;
2497   let Inst{26}    = V;
2498   let Inst{25-24} = 0b00;
2499   let Inst{23-22} = opc;
2500   let Inst{21}    = 1;
2501   let Inst{20-16} = Rm;
2502   let Inst{15}    = extend{1}; // sign extend Rm?
2503   let Inst{14}    = 1;
2504   let Inst{12}    = extend{0}; // do shift?
2505   let Inst{11-10} = 0b10;
2506   let Inst{9-5}   = Rn;
2507   let Inst{4-0}   = Rt;
2508 }
2509
2510 class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2511   : InstAlias<asm # " $Rt, [$Rn, $Rm]",
2512               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2513
2514 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2515                    string asm, ValueType Ty, SDPatternOperator loadop> {
2516   let AddedComplexity = 10 in
2517   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2518                  (outs regtype:$Rt),
2519                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2520                  [(set (Ty regtype:$Rt),
2521                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2522                                              ro_Wextend8:$extend)))]>,
2523            Sched<[WriteLDIdx, ReadAdrBase]> {
2524     let Inst{13} = 0b0;
2525   }
2526
2527   let AddedComplexity = 10 in
2528   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2529                  (outs regtype:$Rt),
2530                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2531                  [(set (Ty regtype:$Rt),
2532                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2533                                              ro_Xextend8:$extend)))]>,
2534            Sched<[WriteLDIdx, ReadAdrBase]> {
2535     let Inst{13} = 0b1;
2536   }
2537
2538   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2539 }
2540
2541 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2542                     string asm, ValueType Ty, SDPatternOperator storeop> {
2543   let AddedComplexity = 10 in
2544   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2545                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2546                  [(storeop (Ty regtype:$Rt),
2547                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2548                                          ro_Wextend8:$extend))]>,
2549             Sched<[WriteSTIdx, ReadAdrBase]> {
2550     let Inst{13} = 0b0;
2551   }
2552
2553   let AddedComplexity = 10 in
2554   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2555                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2556                  [(storeop (Ty regtype:$Rt),
2557                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2558                                          ro_Xextend8:$extend))]>,
2559             Sched<[WriteSTIdx, ReadAdrBase]> {
2560     let Inst{13} = 0b1;
2561   }
2562
2563   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2564 }
2565
2566 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2567                       string asm, dag ins, dag outs, list<dag> pat>
2568     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2569   bits<5> Rt;
2570   bits<5> Rn;
2571   bits<5> Rm;
2572   bits<2> extend;
2573   let Inst{31-30} = sz;
2574   let Inst{29-27} = 0b111;
2575   let Inst{26}    = V;
2576   let Inst{25-24} = 0b00;
2577   let Inst{23-22} = opc;
2578   let Inst{21}    = 1;
2579   let Inst{20-16} = Rm;
2580   let Inst{15}    = extend{1}; // sign extend Rm?
2581   let Inst{14}    = 1;
2582   let Inst{12}    = extend{0}; // do shift?
2583   let Inst{11-10} = 0b10;
2584   let Inst{9-5}   = Rn;
2585   let Inst{4-0}   = Rt;
2586 }
2587
2588 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2589                     string asm, ValueType Ty, SDPatternOperator loadop> {
2590   let AddedComplexity = 10 in
2591   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2592                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2593                  [(set (Ty regtype:$Rt),
2594                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2595                                               ro_Wextend16:$extend)))]>,
2596             Sched<[WriteLDIdx, ReadAdrBase]> {
2597     let Inst{13} = 0b0;
2598   }
2599
2600   let AddedComplexity = 10 in
2601   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2602                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2603                  [(set (Ty regtype:$Rt),
2604                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2605                                              ro_Xextend16:$extend)))]>,
2606             Sched<[WriteLDIdx, ReadAdrBase]> {
2607     let Inst{13} = 0b1;
2608   }
2609
2610   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2611 }
2612
2613 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2614                      string asm, ValueType Ty, SDPatternOperator storeop> {
2615   let AddedComplexity = 10 in
2616   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2617                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2618                 [(storeop (Ty regtype:$Rt),
2619                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2620                                          ro_Wextend16:$extend))]>,
2621            Sched<[WriteSTIdx, ReadAdrBase]> {
2622     let Inst{13} = 0b0;
2623   }
2624
2625   let AddedComplexity = 10 in
2626   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2627                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2628                 [(storeop (Ty regtype:$Rt),
2629                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2630                                          ro_Xextend16:$extend))]>,
2631            Sched<[WriteSTIdx, ReadAdrBase]> {
2632     let Inst{13} = 0b1;
2633   }
2634
2635   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2636 }
2637
2638 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2639                       string asm, dag ins, dag outs, list<dag> pat>
2640     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2641   bits<5> Rt;
2642   bits<5> Rn;
2643   bits<5> Rm;
2644   bits<2> extend;
2645   let Inst{31-30} = sz;
2646   let Inst{29-27} = 0b111;
2647   let Inst{26}    = V;
2648   let Inst{25-24} = 0b00;
2649   let Inst{23-22} = opc;
2650   let Inst{21}    = 1;
2651   let Inst{20-16} = Rm;
2652   let Inst{15}    = extend{1}; // sign extend Rm?
2653   let Inst{14}    = 1;
2654   let Inst{12}    = extend{0}; // do shift?
2655   let Inst{11-10} = 0b10;
2656   let Inst{9-5}   = Rn;
2657   let Inst{4-0}   = Rt;
2658 }
2659
2660 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2661                     string asm, ValueType Ty, SDPatternOperator loadop> {
2662   let AddedComplexity = 10 in
2663   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2664                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2665                  [(set (Ty regtype:$Rt),
2666                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2667                                               ro_Wextend32:$extend)))]>,
2668            Sched<[WriteLDIdx, ReadAdrBase]> {
2669     let Inst{13} = 0b0;
2670   }
2671
2672   let AddedComplexity = 10 in
2673   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2674                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2675                  [(set (Ty regtype:$Rt),
2676                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2677                                               ro_Xextend32:$extend)))]>,
2678            Sched<[WriteLDIdx, ReadAdrBase]> {
2679     let Inst{13} = 0b1;
2680   }
2681
2682   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2683 }
2684
2685 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2686                      string asm, ValueType Ty, SDPatternOperator storeop> {
2687   let AddedComplexity = 10 in
2688   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2689                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2690                 [(storeop (Ty regtype:$Rt),
2691                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2692                                          ro_Wextend32:$extend))]>,
2693             Sched<[WriteSTIdx, ReadAdrBase]> {
2694     let Inst{13} = 0b0;
2695   }
2696
2697   let AddedComplexity = 10 in
2698   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2699                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2700                 [(storeop (Ty regtype:$Rt),
2701                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2702                                         ro_Xextend32:$extend))]>,
2703             Sched<[WriteSTIdx, ReadAdrBase]> {
2704     let Inst{13} = 0b1;
2705   }
2706
2707   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2708 }
2709
2710 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2711                       string asm, dag ins, dag outs, list<dag> pat>
2712     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2713   bits<5> Rt;
2714   bits<5> Rn;
2715   bits<5> Rm;
2716   bits<2> extend;
2717   let Inst{31-30} = sz;
2718   let Inst{29-27} = 0b111;
2719   let Inst{26}    = V;
2720   let Inst{25-24} = 0b00;
2721   let Inst{23-22} = opc;
2722   let Inst{21}    = 1;
2723   let Inst{20-16} = Rm;
2724   let Inst{15}    = extend{1}; // sign extend Rm?
2725   let Inst{14}    = 1;
2726   let Inst{12}    = extend{0}; // do shift?
2727   let Inst{11-10} = 0b10;
2728   let Inst{9-5}   = Rn;
2729   let Inst{4-0}   = Rt;
2730 }
2731
2732 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2733                     string asm, ValueType Ty, SDPatternOperator loadop> {
2734   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2735   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2736                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2737                 [(set (Ty regtype:$Rt),
2738                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2739                                              ro_Wextend64:$extend)))]>,
2740            Sched<[WriteLDIdx, ReadAdrBase]> {
2741     let Inst{13} = 0b0;
2742   }
2743
2744   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2745   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2746                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2747                  [(set (Ty regtype:$Rt),
2748                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2749                                               ro_Xextend64:$extend)))]>,
2750            Sched<[WriteLDIdx, ReadAdrBase]> {
2751     let Inst{13} = 0b1;
2752   }
2753
2754   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2755 }
2756
2757 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2758                      string asm, ValueType Ty, SDPatternOperator storeop> {
2759   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2760   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2761                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2762                 [(storeop (Ty regtype:$Rt),
2763                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2764                                          ro_Wextend64:$extend))]>,
2765             Sched<[WriteSTIdx, ReadAdrBase]> {
2766     let Inst{13} = 0b0;
2767   }
2768
2769   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2770   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2771                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2772                 [(storeop (Ty regtype:$Rt),
2773                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2774                                          ro_Xextend64:$extend))]>,
2775             Sched<[WriteSTIdx, ReadAdrBase]> {
2776     let Inst{13} = 0b1;
2777   }
2778
2779   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2780 }
2781
2782 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2783                       string asm, dag ins, dag outs, list<dag> pat>
2784     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2785   bits<5> Rt;
2786   bits<5> Rn;
2787   bits<5> Rm;
2788   bits<2> extend;
2789   let Inst{31-30} = sz;
2790   let Inst{29-27} = 0b111;
2791   let Inst{26}    = V;
2792   let Inst{25-24} = 0b00;
2793   let Inst{23-22} = opc;
2794   let Inst{21}    = 1;
2795   let Inst{20-16} = Rm;
2796   let Inst{15}    = extend{1}; // sign extend Rm?
2797   let Inst{14}    = 1;
2798   let Inst{12}    = extend{0}; // do shift?
2799   let Inst{11-10} = 0b10;
2800   let Inst{9-5}   = Rn;
2801   let Inst{4-0}   = Rt;
2802 }
2803
2804 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2805                      string asm, ValueType Ty, SDPatternOperator loadop> {
2806   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2807   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2808                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2809                  [(set (Ty regtype:$Rt),
2810                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2811                                                ro_Wextend128:$extend)))]>,
2812             Sched<[WriteLDIdx, ReadAdrBase]> {
2813     let Inst{13} = 0b0;
2814   }
2815
2816   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2817   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2818                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2819                  [(set (Ty regtype:$Rt),
2820                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2821                                                ro_Xextend128:$extend)))]>,
2822             Sched<[WriteLDIdx, ReadAdrBase]> {
2823     let Inst{13} = 0b1;
2824   }
2825
2826   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2827 }
2828
2829 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2830                       string asm, ValueType Ty, SDPatternOperator storeop> {
2831   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2832   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2833                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2834                 [(storeop (Ty regtype:$Rt),
2835                           (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2836                                           ro_Wextend128:$extend))]>,
2837             Sched<[WriteSTIdx, ReadAdrBase]> {
2838     let Inst{13} = 0b0;
2839   }
2840
2841   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2842   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2843                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2844                 [(storeop (Ty regtype:$Rt),
2845                           (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2846                                           ro_Xextend128:$extend))]>,
2847             Sched<[WriteSTIdx, ReadAdrBase]> {
2848     let Inst{13} = 0b1;
2849   }
2850
2851   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2852 }
2853
2854 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2855 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2856                      string asm, list<dag> pat>
2857     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2858       Sched<[WriteLD]> {
2859   bits<5> Rt;
2860   bits<5> Rn;
2861   bits<5> Rm;
2862   bits<2> extend;
2863   let Inst{31-30} = sz;
2864   let Inst{29-27} = 0b111;
2865   let Inst{26}    = V;
2866   let Inst{25-24} = 0b00;
2867   let Inst{23-22} = opc;
2868   let Inst{21}    = 1;
2869   let Inst{20-16} = Rm;
2870   let Inst{15}    = extend{1}; // sign extend Rm?
2871   let Inst{14}    = 1;
2872   let Inst{12}    = extend{0}; // do shift?
2873   let Inst{11-10} = 0b10;
2874   let Inst{9-5}   = Rn;
2875   let Inst{4-0}   = Rt;
2876 }
2877
2878 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2879   def roW : BasePrefetchRO<sz, V, opc, (outs),
2880                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2881                 asm, [(AArch64Prefetch imm:$Rt,
2882                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2883                                                     ro_Wextend64:$extend))]> {
2884     let Inst{13} = 0b0;
2885   }
2886
2887   def roX : BasePrefetchRO<sz, V, opc, (outs),
2888                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2889                 asm,  [(AArch64Prefetch imm:$Rt,
2890                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2891                                                      ro_Xextend64:$extend))]> {
2892     let Inst{13} = 0b1;
2893   }
2894
2895   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2896                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2897                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2898 }
2899
2900 //---
2901 // Load/store unscaled immediate
2902 //---
2903
2904 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2905 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2906 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2907 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2908 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2909
2910 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2911                            string asm, list<dag> pattern>
2912     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2913   bits<5> Rt;
2914   bits<5> Rn;
2915   bits<9> offset;
2916   let Inst{31-30} = sz;
2917   let Inst{29-27} = 0b111;
2918   let Inst{26}    = V;
2919   let Inst{25-24} = 0b00;
2920   let Inst{23-22} = opc;
2921   let Inst{21}    = 0;
2922   let Inst{20-12} = offset;
2923   let Inst{11-10} = 0b00;
2924   let Inst{9-5}   = Rn;
2925   let Inst{4-0}   = Rt;
2926
2927   let DecoderMethod = "DecodeSignedLdStInstruction";
2928 }
2929
2930 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2931                    string asm, list<dag> pattern> {
2932   let AddedComplexity = 1 in // try this before LoadUI
2933   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2934                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
2935           Sched<[WriteLD]>;
2936
2937   def : InstAlias<asm # " $Rt, [$Rn]",
2938                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2939 }
2940
2941 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2942                          string asm, list<dag> pattern> {
2943   let AddedComplexity = 1 in // try this before StoreUI
2944   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
2945                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
2946                                asm, pattern>,
2947           Sched<[WriteST]>;
2948
2949   def : InstAlias<asm # " $Rt, [$Rn]",
2950                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2951 }
2952
2953 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
2954                             list<dag> pat> {
2955   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2956   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
2957                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
2958                                asm, pat>,
2959           Sched<[WriteLD]>;
2960
2961   def : InstAlias<asm # " $Rt, [$Rn]",
2962                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
2963 }
2964
2965 //---
2966 // Load/store unscaled immediate, unprivileged
2967 //---
2968
2969 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2970                                 dag oops, dag iops, string asm>
2971     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
2972   bits<5> Rt;
2973   bits<5> Rn;
2974   bits<9> offset;
2975   let Inst{31-30} = sz;
2976   let Inst{29-27} = 0b111;
2977   let Inst{26}    = V;
2978   let Inst{25-24} = 0b00;
2979   let Inst{23-22} = opc;
2980   let Inst{21}    = 0;
2981   let Inst{20-12} = offset;
2982   let Inst{11-10} = 0b10;
2983   let Inst{9-5}   = Rn;
2984   let Inst{4-0}   = Rt;
2985
2986   let DecoderMethod = "DecodeSignedLdStInstruction";
2987 }
2988
2989 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
2990                             RegisterClass regtype, string asm> {
2991   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
2992   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
2993                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
2994           Sched<[WriteLD]>;
2995
2996   def : InstAlias<asm # " $Rt, [$Rn]",
2997                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2998 }
2999
3000 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3001                              RegisterClass regtype, string asm> {
3002   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3003   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3004                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3005                                  asm>,
3006           Sched<[WriteST]>;
3007
3008   def : InstAlias<asm # " $Rt, [$Rn]",
3009                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3010 }
3011
3012 //---
3013 // Load/store pre-indexed
3014 //---
3015
3016 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3017                           string asm, string cstr, list<dag> pat>
3018     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3019   bits<5> Rt;
3020   bits<5> Rn;
3021   bits<9> offset;
3022   let Inst{31-30} = sz;
3023   let Inst{29-27} = 0b111;
3024   let Inst{26}    = V;
3025   let Inst{25-24} = 0;
3026   let Inst{23-22} = opc;
3027   let Inst{21}    = 0;
3028   let Inst{20-12} = offset;
3029   let Inst{11-10} = 0b11;
3030   let Inst{9-5}   = Rn;
3031   let Inst{4-0}   = Rt;
3032
3033   let DecoderMethod = "DecodeSignedLdStInstruction";
3034 }
3035
3036 let hasSideEffects = 0 in {
3037 let mayStore = 0, mayLoad = 1 in
3038 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3039              string asm>
3040     : BaseLoadStorePreIdx<sz, V, opc,
3041                      (outs GPR64sp:$wback, regtype:$Rt),
3042                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3043                      "$Rn = $wback,@earlyclobber $wback", []>,
3044       Sched<[WriteLD, WriteAdr]>;
3045
3046 let mayStore = 1, mayLoad = 0 in
3047 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3048                   string asm, SDPatternOperator storeop, ValueType Ty>
3049     : BaseLoadStorePreIdx<sz, V, opc,
3050                       (outs GPR64sp:$wback),
3051                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3052                       asm, "$Rn = $wback,@earlyclobber $wback",
3053       [(set GPR64sp:$wback,
3054             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3055       Sched<[WriteAdr, WriteST]>;
3056 } // hasSideEffects = 0
3057
3058 //---
3059 // Load/store post-indexed
3060 //---
3061
3062 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3063                           string asm, string cstr, list<dag> pat>
3064     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3065   bits<5> Rt;
3066   bits<5> Rn;
3067   bits<9> offset;
3068   let Inst{31-30} = sz;
3069   let Inst{29-27} = 0b111;
3070   let Inst{26}    = V;
3071   let Inst{25-24} = 0b00;
3072   let Inst{23-22} = opc;
3073   let Inst{21}    = 0b0;
3074   let Inst{20-12} = offset;
3075   let Inst{11-10} = 0b01;
3076   let Inst{9-5}   = Rn;
3077   let Inst{4-0}   = Rt;
3078
3079   let DecoderMethod = "DecodeSignedLdStInstruction";
3080 }
3081
3082 let hasSideEffects = 0 in {
3083 let mayStore = 0, mayLoad = 1 in
3084 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3085              string asm>
3086     : BaseLoadStorePostIdx<sz, V, opc,
3087                       (outs GPR64sp:$wback, regtype:$Rt),
3088                       (ins GPR64sp:$Rn, simm9:$offset),
3089                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3090       Sched<[WriteLD, WriteI]>;
3091
3092 let mayStore = 1, mayLoad = 0 in
3093 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3094                    string asm, SDPatternOperator storeop, ValueType Ty>
3095     : BaseLoadStorePostIdx<sz, V, opc,
3096                       (outs GPR64sp:$wback),
3097                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3098                        asm, "$Rn = $wback,@earlyclobber $wback",
3099       [(set GPR64sp:$wback,
3100             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3101     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3102 } // hasSideEffects = 0
3103
3104
3105 //---
3106 // Load/store pair
3107 //---
3108
3109 // (indexed, offset)
3110
3111 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3112                               string asm>
3113     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3114   bits<5> Rt;
3115   bits<5> Rt2;
3116   bits<5> Rn;
3117   bits<7> offset;
3118   let Inst{31-30} = opc;
3119   let Inst{29-27} = 0b101;
3120   let Inst{26}    = V;
3121   let Inst{25-23} = 0b010;
3122   let Inst{22}    = L;
3123   let Inst{21-15} = offset;
3124   let Inst{14-10} = Rt2;
3125   let Inst{9-5}   = Rn;
3126   let Inst{4-0}   = Rt;
3127
3128   let DecoderMethod = "DecodePairLdStInstruction";
3129 }
3130
3131 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3132                           Operand indextype, string asm> {
3133   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3134   def i : BaseLoadStorePairOffset<opc, V, 1,
3135                                   (outs regtype:$Rt, regtype:$Rt2),
3136                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3137           Sched<[WriteLD, WriteLDHi]>;
3138
3139   def : InstAlias<asm # " $Rt, $Rt2, [$Rn]",
3140                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3141                                                   GPR64sp:$Rn, 0)>;
3142 }
3143
3144
3145 multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3146                            Operand indextype, string asm> {
3147   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3148   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3149                                   (ins regtype:$Rt, regtype:$Rt2,
3150                                        GPR64sp:$Rn, indextype:$offset),
3151                                   asm>,
3152           Sched<[WriteSTP]>;
3153
3154   def : InstAlias<asm # " $Rt, $Rt2, [$Rn]",
3155                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3156                                                   GPR64sp:$Rn, 0)>;
3157 }
3158
3159 // (pre-indexed)
3160 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3161                               string asm>
3162     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3163   bits<5> Rt;
3164   bits<5> Rt2;
3165   bits<5> Rn;
3166   bits<7> offset;
3167   let Inst{31-30} = opc;
3168   let Inst{29-27} = 0b101;
3169   let Inst{26}    = V;
3170   let Inst{25-23} = 0b011;
3171   let Inst{22}    = L;
3172   let Inst{21-15} = offset;
3173   let Inst{14-10} = Rt2;
3174   let Inst{9-5}   = Rn;
3175   let Inst{4-0}   = Rt;
3176
3177   let DecoderMethod = "DecodePairLdStInstruction";
3178 }
3179
3180 let hasSideEffects = 0 in {
3181 let mayStore = 0, mayLoad = 1 in
3182 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3183                      Operand indextype, string asm>
3184     : BaseLoadStorePairPreIdx<opc, V, 1,
3185                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3186                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3187       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3188
3189 let mayStore = 1, mayLoad = 0 in
3190 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3191                       Operand indextype, string asm>
3192     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3193                              (ins regtype:$Rt, regtype:$Rt2,
3194                                   GPR64sp:$Rn, indextype:$offset),
3195                              asm>,
3196       Sched<[WriteAdr, WriteSTP]>;
3197 } // hasSideEffects = 0
3198
3199 // (post-indexed)
3200
3201 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3202                               string asm>
3203     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3204   bits<5> Rt;
3205   bits<5> Rt2;
3206   bits<5> Rn;
3207   bits<7> offset;
3208   let Inst{31-30} = opc;
3209   let Inst{29-27} = 0b101;
3210   let Inst{26}    = V;
3211   let Inst{25-23} = 0b001;
3212   let Inst{22}    = L;
3213   let Inst{21-15} = offset;
3214   let Inst{14-10} = Rt2;
3215   let Inst{9-5}   = Rn;
3216   let Inst{4-0}   = Rt;
3217
3218   let DecoderMethod = "DecodePairLdStInstruction";
3219 }
3220
3221 let hasSideEffects = 0 in {
3222 let mayStore = 0, mayLoad = 1 in
3223 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3224                       Operand idxtype, string asm>
3225     : BaseLoadStorePairPostIdx<opc, V, 1,
3226                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3227                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3228       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3229
3230 let mayStore = 1, mayLoad = 0 in
3231 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3232                        Operand idxtype, string asm>
3233     : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
3234                              (ins GPR64sp:$wback, regtype:$Rt, regtype:$Rt2,
3235                                   GPR64sp:$Rn, idxtype:$offset),
3236                              asm>,
3237       Sched<[WriteAdr, WriteSTP]>;
3238 } // hasSideEffects = 0
3239
3240 //  (no-allocate)
3241
3242 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3243                               string asm>
3244     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3245   bits<5> Rt;
3246   bits<5> Rt2;
3247   bits<5> Rn;
3248   bits<7> offset;
3249   let Inst{31-30} = opc;
3250   let Inst{29-27} = 0b101;
3251   let Inst{26}    = V;
3252   let Inst{25-23} = 0b000;
3253   let Inst{22}    = L;
3254   let Inst{21-15} = offset;
3255   let Inst{14-10} = Rt2;
3256   let Inst{9-5}   = Rn;
3257   let Inst{4-0}   = Rt;
3258
3259   let DecoderMethod = "DecodePairLdStInstruction";
3260 }
3261
3262 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3263                            Operand indextype, string asm> {
3264   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3265   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3266                                    (outs regtype:$Rt, regtype:$Rt2),
3267                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3268           Sched<[WriteLD, WriteLDHi]>;
3269
3270
3271   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3272                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3273                                                   GPR64sp:$Rn, 0)>;
3274 }
3275
3276 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3277                       Operand indextype, string asm> {
3278   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3279   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3280                                    (ins regtype:$Rt, regtype:$Rt2,
3281                                         GPR64sp:$Rn, indextype:$offset),
3282                                    asm>,
3283           Sched<[WriteSTP]>;
3284
3285   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3286                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3287                                                   GPR64sp:$Rn, 0)>;
3288 }
3289
3290 //---
3291 // Load/store exclusive
3292 //---
3293
3294 // True exclusive operations write to and/or read from the system's exclusive
3295 // monitors, which as far as a compiler is concerned can be modelled as a
3296 // random shared memory address. Hence LoadExclusive mayStore.
3297 //
3298 // Since these instructions have the undefined register bits set to 1 in
3299 // their canonical form, we need a post encoder method to set those bits
3300 // to 1 when encoding these instructions. We do this using the
3301 // fixLoadStoreExclusive function. This function has template parameters:
3302 //
3303 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3304 //
3305 // hasRs indicates that the instruction uses the Rs field, so we won't set
3306 // it to 1 (and the same for Rt2). We don't need template parameters for
3307 // the other register fields since Rt and Rn are always used.
3308 //
3309 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3310 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3311                              dag oops, dag iops, string asm, string operands>
3312     : I<oops, iops, asm, operands, "", []> {
3313   let Inst{31-30} = sz;
3314   let Inst{29-24} = 0b001000;
3315   let Inst{23}    = o2;
3316   let Inst{22}    = L;
3317   let Inst{21}    = o1;
3318   let Inst{15}    = o0;
3319
3320   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3321 }
3322
3323 // Neither Rs nor Rt2 operands.
3324 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3325                                dag oops, dag iops, string asm, string operands>
3326     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3327   bits<5> Rt;
3328   bits<5> Rn;
3329   let Inst{20-16} = 0b11111;
3330   let Unpredictable{20-16} = 0b11111;
3331   let Inst{14-10} = 0b11111;
3332   let Unpredictable{14-10} = 0b11111;
3333   let Inst{9-5} = Rn;
3334   let Inst{4-0} = Rt;
3335
3336   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3337 }
3338
3339 // Simple load acquires don't set the exclusive monitor
3340 let mayLoad = 1, mayStore = 0 in
3341 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3342                   RegisterClass regtype, string asm>
3343     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3344                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3345       Sched<[WriteLD]>;
3346
3347 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3348                     RegisterClass regtype, string asm>
3349     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3350                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3351       Sched<[WriteLD]>;
3352
3353 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3354                        RegisterClass regtype, string asm>
3355     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3356                              (outs regtype:$Rt, regtype:$Rt2),
3357                              (ins GPR64sp0:$Rn), asm,
3358                              "\t$Rt, $Rt2, [$Rn]">,
3359       Sched<[WriteLD, WriteLDHi]> {
3360   bits<5> Rt;
3361   bits<5> Rt2;
3362   bits<5> Rn;
3363   let Inst{14-10} = Rt2;
3364   let Inst{9-5} = Rn;
3365   let Inst{4-0} = Rt;
3366
3367   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3368 }
3369
3370 // Simple store release operations do not check the exclusive monitor.
3371 let mayLoad = 0, mayStore = 1 in
3372 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3373                    RegisterClass regtype, string asm>
3374     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3375                                (ins regtype:$Rt, GPR64sp0:$Rn),
3376                                asm, "\t$Rt, [$Rn]">,
3377       Sched<[WriteST]>;
3378
3379 let mayLoad = 1, mayStore = 1 in
3380 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3381                      RegisterClass regtype, string asm>
3382     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3383                              (ins regtype:$Rt, GPR64sp0:$Rn),
3384                              asm, "\t$Ws, $Rt, [$Rn]">,
3385       Sched<[WriteSTX]> {
3386   bits<5> Ws;
3387   bits<5> Rt;
3388   bits<5> Rn;
3389   let Inst{20-16} = Ws;
3390   let Inst{9-5} = Rn;
3391   let Inst{4-0} = Rt;
3392
3393   let Constraints = "@earlyclobber $Ws";
3394   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3395 }
3396
3397 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3398                          RegisterClass regtype, string asm>
3399     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3400                              (outs GPR32:$Ws),
3401                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3402                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3403       Sched<[WriteSTX]> {
3404   bits<5> Ws;
3405   bits<5> Rt;
3406   bits<5> Rt2;
3407   bits<5> Rn;
3408   let Inst{20-16} = Ws;
3409   let Inst{14-10} = Rt2;
3410   let Inst{9-5} = Rn;
3411   let Inst{4-0} = Rt;
3412
3413   let Constraints = "@earlyclobber $Ws";
3414 }
3415
3416 //---
3417 // Exception generation
3418 //---
3419
3420 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3421 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3422     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3423       Sched<[WriteSys]> {
3424   bits<16> imm;
3425   let Inst{31-24} = 0b11010100;
3426   let Inst{23-21} = op1;
3427   let Inst{20-5}  = imm;
3428   let Inst{4-2}   = 0b000;
3429   let Inst{1-0}   = ll;
3430 }
3431
3432 let Predicates = [HasFPARMv8] in {
3433
3434 //---
3435 // Floating point to integer conversion
3436 //---
3437
3438 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3439                       RegisterClass srcType, RegisterClass dstType,
3440                       string asm, list<dag> pattern>
3441     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3442          asm, "\t$Rd, $Rn", "", pattern>,
3443       Sched<[WriteFCvt]> {
3444   bits<5> Rd;
3445   bits<5> Rn;
3446   let Inst{30-29} = 0b00;
3447   let Inst{28-24} = 0b11110;
3448   let Inst{23-22} = type;
3449   let Inst{21}    = 1;
3450   let Inst{20-19} = rmode;
3451   let Inst{18-16} = opcode;
3452   let Inst{15-10} = 0;
3453   let Inst{9-5}   = Rn;
3454   let Inst{4-0}   = Rd;
3455 }
3456
3457 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3458 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3459                       RegisterClass srcType, RegisterClass dstType,
3460                       Operand immType, string asm, list<dag> pattern>
3461     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3462          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3463       Sched<[WriteFCvt]> {
3464   bits<5> Rd;
3465   bits<5> Rn;
3466   bits<6> scale;
3467   let Inst{30-29} = 0b00;
3468   let Inst{28-24} = 0b11110;
3469   let Inst{23-22} = type;
3470   let Inst{21}    = 0;
3471   let Inst{20-19} = rmode;
3472   let Inst{18-16} = opcode;
3473   let Inst{15-10} = scale;
3474   let Inst{9-5}   = Rn;
3475   let Inst{4-0}   = Rd;
3476 }
3477
3478 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3479            SDPatternOperator OpN> {
3480   // Unscaled single-precision to 32-bit
3481   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3482                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3483     let Inst{31} = 0; // 32-bit GPR flag
3484   }
3485
3486   // Unscaled single-precision to 64-bit
3487   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3488                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3489     let Inst{31} = 1; // 64-bit GPR flag
3490   }
3491
3492   // Unscaled double-precision to 32-bit
3493   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3494                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3495     let Inst{31} = 0; // 32-bit GPR flag
3496   }
3497
3498   // Unscaled double-precision to 64-bit
3499   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3500                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3501     let Inst{31} = 1; // 64-bit GPR flag
3502   }
3503 }
3504
3505 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3506                              SDPatternOperator OpN> {
3507   // Scaled single-precision to 32-bit
3508   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3509                               fixedpoint_f32_i32, asm,
3510               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3511                                           fixedpoint_f32_i32:$scale)))]> {
3512     let Inst{31} = 0; // 32-bit GPR flag
3513     let scale{5} = 1;
3514   }
3515
3516   // Scaled single-precision to 64-bit
3517   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3518                               fixedpoint_f32_i64, asm,
3519               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3520                                           fixedpoint_f32_i64:$scale)))]> {
3521     let Inst{31} = 1; // 64-bit GPR flag
3522   }
3523
3524   // Scaled double-precision to 32-bit
3525   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3526                               fixedpoint_f64_i32, asm,
3527               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3528                                           fixedpoint_f64_i32:$scale)))]> {
3529     let Inst{31} = 0; // 32-bit GPR flag
3530     let scale{5} = 1;
3531   }
3532
3533   // Scaled double-precision to 64-bit
3534   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3535                               fixedpoint_f64_i64, asm,
3536               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3537                                           fixedpoint_f64_i64:$scale)))]> {
3538     let Inst{31} = 1; // 64-bit GPR flag
3539   }
3540 }
3541
3542 //---
3543 // Integer to floating point conversion
3544 //---
3545
3546 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3547 class BaseIntegerToFP<bit isUnsigned,
3548                       RegisterClass srcType, RegisterClass dstType,
3549                       Operand immType, string asm, list<dag> pattern>
3550     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3551          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3552       Sched<[WriteFCvt]> {
3553   bits<5> Rd;
3554   bits<5> Rn;
3555   bits<6> scale;
3556   let Inst{30-23} = 0b00111100;
3557   let Inst{21-17} = 0b00001;
3558   let Inst{16}    = isUnsigned;
3559   let Inst{15-10} = scale;
3560   let Inst{9-5}   = Rn;
3561   let Inst{4-0}   = Rd;
3562 }
3563
3564 class BaseIntegerToFPUnscaled<bit isUnsigned,
3565                       RegisterClass srcType, RegisterClass dstType,
3566                       ValueType dvt, string asm, SDNode node>
3567     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3568          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3569       Sched<[WriteFCvt]> {
3570   bits<5> Rd;
3571   bits<5> Rn;
3572   bits<6> scale;
3573   let Inst{30-23} = 0b00111100;
3574   let Inst{21-17} = 0b10001;
3575   let Inst{16}    = isUnsigned;
3576   let Inst{15-10} = 0b000000;
3577   let Inst{9-5}   = Rn;
3578   let Inst{4-0}   = Rd;
3579 }
3580
3581 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3582   // Unscaled
3583   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3584     let Inst{31} = 0; // 32-bit GPR flag
3585     let Inst{22} = 0; // 32-bit FPR flag
3586   }
3587
3588   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3589     let Inst{31} = 0; // 32-bit GPR flag
3590     let Inst{22} = 1; // 64-bit FPR flag
3591   }
3592
3593   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3594     let Inst{31} = 1; // 64-bit GPR flag
3595     let Inst{22} = 0; // 32-bit FPR flag
3596   }
3597
3598   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3599     let Inst{31} = 1; // 64-bit GPR flag
3600     let Inst{22} = 1; // 64-bit FPR flag
3601   }
3602
3603   // Scaled
3604   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3605                              [(set FPR32:$Rd,
3606                                    (fdiv (node GPR32:$Rn),
3607                                          fixedpoint_f32_i32:$scale))]> {
3608     let Inst{31} = 0; // 32-bit GPR flag
3609     let Inst{22} = 0; // 32-bit FPR flag
3610     let scale{5} = 1;
3611   }
3612
3613   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3614                              [(set FPR64:$Rd,
3615                                    (fdiv (node GPR32:$Rn),
3616                                          fixedpoint_f64_i32:$scale))]> {
3617     let Inst{31} = 0; // 32-bit GPR flag
3618     let Inst{22} = 1; // 64-bit FPR flag
3619     let scale{5} = 1;
3620   }
3621
3622   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3623                              [(set FPR32:$Rd,
3624                                    (fdiv (node GPR64:$Rn),
3625                                          fixedpoint_f32_i64:$scale))]> {
3626     let Inst{31} = 1; // 64-bit GPR flag
3627     let Inst{22} = 0; // 32-bit FPR flag
3628   }
3629
3630   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3631                              [(set FPR64:$Rd,
3632                                    (fdiv (node GPR64:$Rn),
3633                                          fixedpoint_f64_i64:$scale))]> {
3634     let Inst{31} = 1; // 64-bit GPR flag
3635     let Inst{22} = 1; // 64-bit FPR flag
3636   }
3637 }
3638
3639 //---
3640 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3641 //---
3642
3643 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3644 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3645                       RegisterClass srcType, RegisterClass dstType,
3646                       string asm>
3647     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3648         // We use COPY_TO_REGCLASS for these bitconvert operations.
3649         // copyPhysReg() expands the resultant COPY instructions after
3650         // regalloc is done. This gives greater freedom for the allocator
3651         // and related passes (coalescing, copy propagation, et. al.) to
3652         // be more effective.
3653         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3654       Sched<[WriteFCopy]> {
3655   bits<5> Rd;
3656   bits<5> Rn;
3657   let Inst{30-23} = 0b00111100;
3658   let Inst{21}    = 1;
3659   let Inst{20-19} = rmode;
3660   let Inst{18-16} = opcode;
3661   let Inst{15-10} = 0b000000;
3662   let Inst{9-5}   = Rn;
3663   let Inst{4-0}   = Rd;
3664 }
3665
3666 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3667 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3668                      RegisterClass srcType, RegisterOperand dstType, string asm,
3669                      string kind>
3670     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3671         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3672       Sched<[WriteFCopy]> {
3673   bits<5> Rd;
3674   bits<5> Rn;
3675   let Inst{30-23} = 0b00111101;
3676   let Inst{21}    = 1;
3677   let Inst{20-19} = rmode;
3678   let Inst{18-16} = opcode;
3679   let Inst{15-10} = 0b000000;
3680   let Inst{9-5}   = Rn;
3681   let Inst{4-0}   = Rd;
3682
3683   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3684 }
3685
3686 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3687 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3688                      RegisterOperand srcType, RegisterClass dstType, string asm,
3689                      string kind>
3690     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3691         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3692       Sched<[WriteFCopy]> {
3693   bits<5> Rd;
3694   bits<5> Rn;
3695   let Inst{30-23} = 0b00111101;
3696   let Inst{21}    = 1;
3697   let Inst{20-19} = rmode;
3698   let Inst{18-16} = opcode;
3699   let Inst{15-10} = 0b000000;
3700   let Inst{9-5}   = Rn;
3701   let Inst{4-0}   = Rd;
3702
3703   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3704 }
3705
3706
3707
3708 multiclass UnscaledConversion<string asm> {
3709   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3710     let Inst{31} = 0; // 32-bit GPR flag
3711     let Inst{22} = 0; // 32-bit FPR flag
3712   }
3713
3714   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3715     let Inst{31} = 1; // 64-bit GPR flag
3716     let Inst{22} = 1; // 64-bit FPR flag
3717   }
3718
3719   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3720     let Inst{31} = 0; // 32-bit GPR flag
3721     let Inst{22} = 0; // 32-bit FPR flag
3722   }
3723
3724   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3725     let Inst{31} = 1; // 64-bit GPR flag
3726     let Inst{22} = 1; // 64-bit FPR flag
3727   }
3728
3729   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3730                                              asm, ".d"> {
3731     let Inst{31} = 1;
3732     let Inst{22} = 0;
3733   }
3734
3735   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3736                                                asm, ".d"> {
3737     let Inst{31} = 1;
3738     let Inst{22} = 0;
3739   }
3740 }
3741
3742 //---
3743 // Floating point conversion
3744 //---
3745
3746 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3747                        RegisterClass srcType, string asm, list<dag> pattern>
3748     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3749       Sched<[WriteFCvt]> {
3750   bits<5> Rd;
3751   bits<5> Rn;
3752   let Inst{31-24} = 0b00011110;
3753   let Inst{23-22} = type;
3754   let Inst{21-17} = 0b10001;
3755   let Inst{16-15} = opcode;
3756   let Inst{14-10} = 0b10000;
3757   let Inst{9-5}   = Rn;
3758   let Inst{4-0}   = Rd;
3759 }
3760
3761 multiclass FPConversion<string asm> {
3762   // Double-precision to Half-precision
3763   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3764                              [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3765
3766   // Double-precision to Single-precision
3767   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3768                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3769
3770   // Half-precision to Double-precision
3771   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3772                              [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3773
3774   // Half-precision to Single-precision
3775   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3776                              [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3777
3778   // Single-precision to Double-precision
3779   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3780                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3781
3782   // Single-precision to Half-precision
3783   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3784                              [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3785 }
3786
3787 //---
3788 // Single operand floating point data processing
3789 //---
3790
3791 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3792 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3793                               ValueType vt, string asm, SDPatternOperator node>
3794     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3795          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3796       Sched<[WriteF]> {
3797   bits<5> Rd;
3798   bits<5> Rn;
3799   let Inst{31-23} = 0b000111100;
3800   let Inst{21-19} = 0b100;
3801   let Inst{18-15} = opcode;
3802   let Inst{14-10} = 0b10000;
3803   let Inst{9-5}   = Rn;
3804   let Inst{4-0}   = Rd;
3805 }
3806
3807 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3808                                SDPatternOperator node = null_frag> {
3809   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3810     let Inst{22} = 0; // 32-bit size flag
3811   }
3812
3813   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3814     let Inst{22} = 1; // 64-bit size flag
3815   }
3816 }
3817
3818 //---
3819 // Two operand floating point data processing
3820 //---
3821
3822 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3823 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3824                            string asm, list<dag> pat>
3825     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3826          asm, "\t$Rd, $Rn, $Rm", "", pat>,
3827       Sched<[WriteF]> {
3828   bits<5> Rd;
3829   bits<5> Rn;
3830   bits<5> Rm;
3831   let Inst{31-23} = 0b000111100;
3832   let Inst{21}    = 1;
3833   let Inst{20-16} = Rm;
3834   let Inst{15-12} = opcode;
3835   let Inst{11-10} = 0b10;
3836   let Inst{9-5}   = Rn;
3837   let Inst{4-0}   = Rd;
3838 }
3839
3840 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3841                             SDPatternOperator node = null_frag> {
3842   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3843                          [(set (f32 FPR32:$Rd),
3844                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3845     let Inst{22} = 0; // 32-bit size flag
3846   }
3847
3848   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3849                          [(set (f64 FPR64:$Rd),
3850                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3851     let Inst{22} = 1; // 64-bit size flag
3852   }
3853 }
3854
3855 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3856   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3857                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3858     let Inst{22} = 0; // 32-bit size flag
3859   }
3860
3861   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3862                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3863     let Inst{22} = 1; // 64-bit size flag
3864   }
3865 }
3866
3867
3868 //---
3869 // Three operand floating point data processing
3870 //---
3871
3872 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3873                              RegisterClass regtype, string asm, list<dag> pat>
3874     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3875          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3876       Sched<[WriteFMul]> {
3877   bits<5> Rd;
3878   bits<5> Rn;
3879   bits<5> Rm;
3880   bits<5> Ra;
3881   let Inst{31-23} = 0b000111110;
3882   let Inst{21}    = isNegated;
3883   let Inst{20-16} = Rm;
3884   let Inst{15}    = isSub;
3885   let Inst{14-10} = Ra;
3886   let Inst{9-5}   = Rn;
3887   let Inst{4-0}   = Rd;
3888 }
3889
3890 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3891                               SDPatternOperator node> {
3892   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3893             [(set FPR32:$Rd,
3894                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3895     let Inst{22} = 0; // 32-bit size flag
3896   }
3897
3898   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3899             [(set FPR64:$Rd,
3900                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3901     let Inst{22} = 1; // 64-bit size flag
3902   }
3903 }
3904
3905 //---
3906 // Floating point data comparisons
3907 //---
3908
3909 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3910 class BaseOneOperandFPComparison<bit signalAllNans,
3911                                  RegisterClass regtype, string asm,
3912                                  list<dag> pat>
3913     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3914       Sched<[WriteFCmp]> {
3915   bits<5> Rn;
3916   let Inst{31-23} = 0b000111100;
3917   let Inst{21}    = 1;
3918
3919   let Inst{15-10} = 0b001000;
3920   let Inst{9-5}   = Rn;
3921   let Inst{4}     = signalAllNans;
3922   let Inst{3-0}   = 0b1000;
3923
3924   // Rm should be 0b00000 canonically, but we need to accept any value.
3925   let PostEncoderMethod = "fixOneOperandFPComparison";
3926 }
3927
3928 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3929 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3930                                 string asm, list<dag> pat>
3931     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3932       Sched<[WriteFCmp]> {
3933   bits<5> Rm;
3934   bits<5> Rn;
3935   let Inst{31-23} = 0b000111100;
3936   let Inst{21}    = 1;
3937   let Inst{20-16} = Rm;
3938   let Inst{15-10} = 0b001000;
3939   let Inst{9-5}   = Rn;
3940   let Inst{4}     = signalAllNans;
3941   let Inst{3-0}   = 0b0000;
3942 }
3943
3944 multiclass FPComparison<bit signalAllNans, string asm,
3945                         SDPatternOperator OpNode = null_frag> {
3946   let Defs = [NZCV] in {
3947   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3948       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
3949     let Inst{22} = 0;
3950   }
3951
3952   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3953       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
3954     let Inst{22} = 0;
3955   }
3956
3957   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3958       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
3959     let Inst{22} = 1;
3960   }
3961
3962   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3963       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
3964     let Inst{22} = 1;
3965   }
3966   } // Defs = [NZCV]
3967 }
3968
3969 //---
3970 // Floating point conditional comparisons
3971 //---
3972
3973 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3974 class BaseFPCondComparison<bit signalAllNans,
3975                               RegisterClass regtype, string asm>
3976     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3977          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3978       Sched<[WriteFCmp]> {
3979   bits<5> Rn;
3980   bits<5> Rm;
3981   bits<4> nzcv;
3982   bits<4> cond;
3983
3984   let Inst{31-23} = 0b000111100;
3985   let Inst{21}    = 1;
3986   let Inst{20-16} = Rm;
3987   let Inst{15-12} = cond;
3988   let Inst{11-10} = 0b01;
3989   let Inst{9-5}   = Rn;
3990   let Inst{4}     = signalAllNans;
3991   let Inst{3-0}   = nzcv;
3992 }
3993
3994 multiclass FPCondComparison<bit signalAllNans, string asm> {
3995   let Defs = [NZCV], Uses = [NZCV] in {
3996   def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3997     let Inst{22} = 0;
3998   }
3999
4000   def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
4001     let Inst{22} = 1;
4002   }
4003   } // Defs = [NZCV], Uses = [NZCV]
4004 }
4005
4006 //---
4007 // Floating point conditional select
4008 //---
4009
4010 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4011     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4012          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4013          [(set regtype:$Rd,
4014                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4015                           (i32 imm:$cond), NZCV))]>,
4016       Sched<[WriteF]> {
4017   bits<5> Rd;
4018   bits<5> Rn;
4019   bits<5> Rm;
4020   bits<4> cond;
4021
4022   let Inst{31-23} = 0b000111100;
4023   let Inst{21}    = 1;
4024   let Inst{20-16} = Rm;
4025   let Inst{15-12} = cond;
4026   let Inst{11-10} = 0b11;
4027   let Inst{9-5}   = Rn;
4028   let Inst{4-0}   = Rd;
4029 }
4030
4031 multiclass FPCondSelect<string asm> {
4032   let Uses = [NZCV] in {
4033   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4034     let Inst{22} = 0;
4035   }
4036
4037   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4038     let Inst{22} = 1;
4039   }
4040   } // Uses = [NZCV]
4041 }
4042
4043 //---
4044 // Floating move immediate
4045 //---
4046
4047 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4048   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4049       [(set regtype:$Rd, fpimmtype:$imm)]>,
4050     Sched<[WriteFImm]> {
4051   bits<5> Rd;
4052   bits<8> imm;
4053   let Inst{31-23} = 0b000111100;
4054   let Inst{21}    = 1;
4055   let Inst{20-13} = imm;
4056   let Inst{12-5}  = 0b10000000;
4057   let Inst{4-0}   = Rd;
4058 }
4059
4060 multiclass FPMoveImmediate<string asm> {
4061   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4062     let Inst{22} = 0;
4063   }
4064
4065   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4066     let Inst{22} = 1;
4067   }
4068 }
4069 } // end of 'let Predicates = [HasFPARMv8]'
4070
4071 //----------------------------------------------------------------------------
4072 // AdvSIMD
4073 //----------------------------------------------------------------------------
4074
4075 let Predicates = [HasNEON] in {
4076
4077 //----------------------------------------------------------------------------
4078 // AdvSIMD three register vector instructions
4079 //----------------------------------------------------------------------------
4080
4081 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4082 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4083                         RegisterOperand regtype, string asm, string kind,
4084                         list<dag> pattern>
4085   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4086       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4087       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4088     Sched<[WriteV]> {
4089   bits<5> Rd;
4090   bits<5> Rn;
4091   bits<5> Rm;
4092   let Inst{31}    = 0;
4093   let Inst{30}    = Q;
4094   let Inst{29}    = U;
4095   let Inst{28-24} = 0b01110;
4096   let Inst{23-22} = size;
4097   let Inst{21}    = 1;
4098   let Inst{20-16} = Rm;
4099   let Inst{15-11} = opcode;
4100   let Inst{10}    = 1;
4101   let Inst{9-5}   = Rn;
4102   let Inst{4-0}   = Rd;
4103 }
4104
4105 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4106 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4107                         RegisterOperand regtype, string asm, string kind,
4108                         list<dag> pattern>
4109   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4110       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4111       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4112     Sched<[WriteV]> {
4113   bits<5> Rd;
4114   bits<5> Rn;
4115   bits<5> Rm;
4116   let Inst{31}    = 0;
4117   let Inst{30}    = Q;
4118   let Inst{29}    = U;
4119   let Inst{28-24} = 0b01110;
4120   let Inst{23-22} = size;
4121   let Inst{21}    = 1;
4122   let Inst{20-16} = Rm;
4123   let Inst{15-11} = opcode;
4124   let Inst{10}    = 1;
4125   let Inst{9-5}   = Rn;
4126   let Inst{4-0}   = Rd;
4127 }
4128
4129 // All operand sizes distinguished in the encoding.
4130 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4131                                SDPatternOperator OpNode> {
4132   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4133                                       asm, ".8b",
4134          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4135   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4136                                       asm, ".16b",
4137          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4138   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4139                                       asm, ".4h",
4140          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4141   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4142                                       asm, ".8h",
4143          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4144   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4145                                       asm, ".2s",
4146          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4147   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4148                                       asm, ".4s",
4149          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4150   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
4151                                       asm, ".2d",
4152          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4153 }
4154
4155 // As above, but D sized elements unsupported.
4156 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4157                                   SDPatternOperator OpNode> {
4158   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4159                                       asm, ".8b",
4160         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4161   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4162                                       asm, ".16b",
4163         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4164   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4165                                       asm, ".4h",
4166         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4167   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4168                                       asm, ".8h",
4169         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4170   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4171                                       asm, ".2s",
4172         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4173   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4174                                       asm, ".4s",
4175         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4176 }
4177
4178 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4179                                   SDPatternOperator OpNode> {
4180   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
4181                                       asm, ".8b",
4182       [(set (v8i8 V64:$dst),
4183             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4184   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
4185                                       asm, ".16b",
4186       [(set (v16i8 V128:$dst),
4187             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4188   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
4189                                       asm, ".4h",
4190       [(set (v4i16 V64:$dst),
4191             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4192   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
4193                                       asm, ".8h",
4194       [(set (v8i16 V128:$dst),
4195             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4196   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
4197                                       asm, ".2s",
4198       [(set (v2i32 V64:$dst),
4199             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4200   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
4201                                       asm, ".4s",
4202       [(set (v4i32 V128:$dst),
4203             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4204 }
4205
4206 // As above, but only B sized elements supported.
4207 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4208                                 SDPatternOperator OpNode> {
4209   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4210                                       asm, ".8b",
4211     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4212   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4213                                       asm, ".16b",
4214     [(set (v16i8 V128:$Rd),
4215           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4216 }
4217
4218 // As above, but only S and D sized floating point elements supported.
4219 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
4220                                  string asm, SDPatternOperator OpNode> {
4221   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4222                                       asm, ".2s",
4223         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4224   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4225                                       asm, ".4s",
4226         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4227   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4228                                       asm, ".2d",
4229         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4230 }
4231
4232 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
4233                                     string asm,
4234                                     SDPatternOperator OpNode> {
4235   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4236                                       asm, ".2s",
4237         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4238   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4239                                       asm, ".4s",
4240         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4241   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4242                                       asm, ".2d",
4243         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4244 }
4245
4246 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
4247                                  string asm, SDPatternOperator OpNode> {
4248   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
4249                                       asm, ".2s",
4250      [(set (v2f32 V64:$dst),
4251            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4252   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
4253                                       asm, ".4s",
4254      [(set (v4f32 V128:$dst),
4255            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4256   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
4257                                       asm, ".2d",
4258      [(set (v2f64 V128:$dst),
4259            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4260 }
4261
4262 // As above, but D and B sized elements unsupported.
4263 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4264                                 SDPatternOperator OpNode> {
4265   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4266                                       asm, ".4h",
4267         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4268   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4269                                       asm, ".8h",
4270         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4271   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4272                                       asm, ".2s",
4273         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4274   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4275                                       asm, ".4s",
4276         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4277 }
4278
4279 // Logical three vector ops share opcode bits, and only use B sized elements.
4280 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4281                                   SDPatternOperator OpNode = null_frag> {
4282   def v8i8  : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4283                                      asm, ".8b",
4284                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4285   def v16i8  : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4286                                      asm, ".16b",
4287                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4288
4289   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4290           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4291   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4292           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4293   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4294           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4295
4296   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4297       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4298   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4299       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4300   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4301       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4302 }
4303
4304 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4305                                   string asm, SDPatternOperator OpNode> {
4306   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4307                                      asm, ".8b",
4308              [(set (v8i8 V64:$dst),
4309                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4310   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4311                                      asm, ".16b",
4312              [(set (v16i8 V128:$dst),
4313                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4314                            (v16i8 V128:$Rm)))]>;
4315
4316   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4317                            (v4i16 V64:$RHS))),
4318           (!cast<Instruction>(NAME#"v8i8")
4319             V64:$LHS, V64:$MHS, V64:$RHS)>;
4320   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4321                            (v2i32 V64:$RHS))),
4322           (!cast<Instruction>(NAME#"v8i8")
4323             V64:$LHS, V64:$MHS, V64:$RHS)>;
4324   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4325                            (v1i64 V64:$RHS))),
4326           (!cast<Instruction>(NAME#"v8i8")
4327             V64:$LHS, V64:$MHS, V64:$RHS)>;
4328
4329   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4330                            (v8i16 V128:$RHS))),
4331       (!cast<Instruction>(NAME#"v16i8")
4332         V128:$LHS, V128:$MHS, V128:$RHS)>;
4333   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4334                            (v4i32 V128:$RHS))),
4335       (!cast<Instruction>(NAME#"v16i8")
4336         V128:$LHS, V128:$MHS, V128:$RHS)>;
4337   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4338                            (v2i64 V128:$RHS))),
4339       (!cast<Instruction>(NAME#"v16i8")
4340         V128:$LHS, V128:$MHS, V128:$RHS)>;
4341 }
4342
4343
4344 //----------------------------------------------------------------------------
4345 // AdvSIMD two register vector instructions.
4346 //----------------------------------------------------------------------------
4347
4348 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4349 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4350                         RegisterOperand regtype, string asm, string dstkind,
4351                         string srckind, list<dag> pattern>
4352   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4353       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4354       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4355     Sched<[WriteV]> {
4356   bits<5> Rd;
4357   bits<5> Rn;
4358   let Inst{31}    = 0;
4359   let Inst{30}    = Q;
4360   let Inst{29}    = U;
4361   let Inst{28-24} = 0b01110;
4362   let Inst{23-22} = size;
4363   let Inst{21-17} = 0b10000;
4364   let Inst{16-12} = opcode;
4365   let Inst{11-10} = 0b10;
4366   let Inst{9-5}   = Rn;
4367   let Inst{4-0}   = Rd;
4368 }
4369
4370 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4371 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4372                             RegisterOperand regtype, string asm, string dstkind,
4373                             string srckind, list<dag> pattern>
4374   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4375       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4376       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4377     Sched<[WriteV]> {
4378   bits<5> Rd;
4379   bits<5> Rn;
4380   let Inst{31}    = 0;
4381   let Inst{30}    = Q;
4382   let Inst{29}    = U;
4383   let Inst{28-24} = 0b01110;
4384   let Inst{23-22} = size;
4385   let Inst{21-17} = 0b10000;
4386   let Inst{16-12} = opcode;
4387   let Inst{11-10} = 0b10;
4388   let Inst{9-5}   = Rn;
4389   let Inst{4-0}   = Rd;
4390 }
4391
4392 // Supports B, H, and S element sizes.
4393 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4394                             SDPatternOperator OpNode> {
4395   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4396                                       asm, ".8b", ".8b",
4397                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4398   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4399                                       asm, ".16b", ".16b",
4400                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4401   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4402                                       asm, ".4h", ".4h",
4403                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4404   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4405                                       asm, ".8h", ".8h",
4406                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4407   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4408                                       asm, ".2s", ".2s",
4409                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4410   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4411                                       asm, ".4s", ".4s",
4412                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4413 }
4414
4415 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4416                             RegisterOperand regtype, string asm, string dstkind,
4417                             string srckind, string amount>
4418   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4419       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4420       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4421     Sched<[WriteV]> {
4422   bits<5> Rd;
4423   bits<5> Rn;
4424   let Inst{31}    = 0;
4425   let Inst{30}    = Q;
4426   let Inst{29-24} = 0b101110;
4427   let Inst{23-22} = size;
4428   let Inst{21-10} = 0b100001001110;
4429   let Inst{9-5}   = Rn;
4430   let Inst{4-0}   = Rd;
4431 }
4432
4433 multiclass SIMDVectorLShiftLongBySizeBHS {
4434   let hasSideEffects = 0 in {
4435   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4436                                              "shll", ".8h",  ".8b", "8">;
4437   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4438                                              "shll2", ".8h", ".16b", "8">;
4439   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4440                                              "shll", ".4s",  ".4h", "16">;
4441   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4442                                              "shll2", ".4s", ".8h", "16">;
4443   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4444                                              "shll", ".2d",  ".2s", "32">;
4445   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4446                                              "shll2", ".2d", ".4s", "32">;
4447   }
4448 }
4449
4450 // Supports all element sizes.
4451 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4452                              SDPatternOperator OpNode> {
4453   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4454                                       asm, ".4h", ".8b",
4455                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4456   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4457                                       asm, ".8h", ".16b",
4458                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4459   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4460                                       asm, ".2s", ".4h",
4461                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4462   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4463                                       asm, ".4s", ".8h",
4464                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4465   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4466                                       asm, ".1d", ".2s",
4467                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4468   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4469                                       asm, ".2d", ".4s",
4470                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4471 }
4472
4473 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4474                                  SDPatternOperator OpNode> {
4475   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4476                                           asm, ".4h", ".8b",
4477       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4478                                       (v8i8 V64:$Rn)))]>;
4479   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4480                                           asm, ".8h", ".16b",
4481       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4482                                       (v16i8 V128:$Rn)))]>;
4483   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4484                                           asm, ".2s", ".4h",
4485       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4486                                       (v4i16 V64:$Rn)))]>;
4487   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4488                                           asm, ".4s", ".8h",
4489       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4490                                       (v8i16 V128:$Rn)))]>;
4491   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4492                                           asm, ".1d", ".2s",
4493       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4494                                       (v2i32 V64:$Rn)))]>;
4495   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4496                                           asm, ".2d", ".4s",
4497       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4498                                       (v4i32 V128:$Rn)))]>;
4499 }
4500
4501 // Supports all element sizes, except 1xD.
4502 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4503                                   SDPatternOperator OpNode> {
4504   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4505                                     asm, ".8b", ".8b",
4506     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4507   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4508                                     asm, ".16b", ".16b",
4509     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4510   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4511                                     asm, ".4h", ".4h",
4512     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4513   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4514                                     asm, ".8h", ".8h",
4515     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4516   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4517                                     asm, ".2s", ".2s",
4518     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4519   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4520                                     asm, ".4s", ".4s",
4521     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4522   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4523                                     asm, ".2d", ".2d",
4524     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4525 }
4526
4527 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4528                              SDPatternOperator OpNode = null_frag> {
4529   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4530                                 asm, ".8b", ".8b",
4531     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4532   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4533                                 asm, ".16b", ".16b",
4534     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4535   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4536                                 asm, ".4h", ".4h",
4537     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4538   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4539                                 asm, ".8h", ".8h",
4540     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4541   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4542                                 asm, ".2s", ".2s",
4543     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4544   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4545                                 asm, ".4s", ".4s",
4546     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4547   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4548                                 asm, ".2d", ".2d",
4549     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4550 }
4551
4552
4553 // Supports only B element sizes.
4554 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4555                           SDPatternOperator OpNode> {
4556   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4557                                 asm, ".8b", ".8b",
4558                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4559   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4560                                 asm, ".16b", ".16b",
4561                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4562
4563 }
4564
4565 // Supports only B and H element sizes.
4566 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4567                                 SDPatternOperator OpNode> {
4568   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4569                                 asm, ".8b", ".8b",
4570                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4571   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4572                                 asm, ".16b", ".16b",
4573                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4574   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4575                                 asm, ".4h", ".4h",
4576                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4577   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4578                                 asm, ".8h", ".8h",
4579                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4580 }
4581
4582 // Supports only S and D element sizes, uses high bit of the size field
4583 // as an extra opcode bit.
4584 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4585                            SDPatternOperator OpNode> {
4586   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4587                                 asm, ".2s", ".2s",
4588                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4589   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4590                                 asm, ".4s", ".4s",
4591                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4592   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4593                                 asm, ".2d", ".2d",
4594                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4595 }
4596
4597 // Supports only S element size.
4598 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4599                            SDPatternOperator OpNode> {
4600   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4601                                 asm, ".2s", ".2s",
4602                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4603   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4604                                 asm, ".4s", ".4s",
4605                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4606 }
4607
4608
4609 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4610                            SDPatternOperator OpNode> {
4611   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4612                                 asm, ".2s", ".2s",
4613                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4614   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4615                                 asm, ".4s", ".4s",
4616                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4617   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4618                                 asm, ".2d", ".2d",
4619                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4620 }
4621
4622 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4623                            SDPatternOperator OpNode> {
4624   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4625                                 asm, ".2s", ".2s",
4626                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4627   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4628                                 asm, ".4s", ".4s",
4629                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4630   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4631                                 asm, ".2d", ".2d",
4632                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4633 }
4634
4635
4636 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4637                            RegisterOperand inreg, RegisterOperand outreg,
4638                            string asm, string outkind, string inkind,
4639                            list<dag> pattern>
4640   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4641       "{\t$Rd" # outkind # ", $Rn" # inkind #
4642       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4643     Sched<[WriteV]> {
4644   bits<5> Rd;
4645   bits<5> Rn;
4646   let Inst{31}    = 0;
4647   let Inst{30}    = Q;
4648   let Inst{29}    = U;
4649   let Inst{28-24} = 0b01110;
4650   let Inst{23-22} = size;
4651   let Inst{21-17} = 0b10000;
4652   let Inst{16-12} = opcode;
4653   let Inst{11-10} = 0b10;
4654   let Inst{9-5}   = Rn;
4655   let Inst{4-0}   = Rd;
4656 }
4657
4658 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4659                            RegisterOperand inreg, RegisterOperand outreg,
4660                            string asm, string outkind, string inkind,
4661                            list<dag> pattern>
4662   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4663       "{\t$Rd" # outkind # ", $Rn" # inkind #
4664       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4665     Sched<[WriteV]> {
4666   bits<5> Rd;
4667   bits<5> Rn;
4668   let Inst{31}    = 0;
4669   let Inst{30}    = Q;
4670   let Inst{29}    = U;
4671   let Inst{28-24} = 0b01110;
4672   let Inst{23-22} = size;
4673   let Inst{21-17} = 0b10000;
4674   let Inst{16-12} = opcode;
4675   let Inst{11-10} = 0b10;
4676   let Inst{9-5}   = Rn;
4677   let Inst{4-0}   = Rd;
4678 }
4679
4680 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4681                               SDPatternOperator OpNode> {
4682   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4683                                       asm, ".8b", ".8h",
4684         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4685   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4686                                       asm#"2", ".16b", ".8h", []>;
4687   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4688                                       asm, ".4h", ".4s",
4689         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4690   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4691                                       asm#"2", ".8h", ".4s", []>;
4692   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4693                                       asm, ".2s", ".2d",
4694         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4695   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4696                                       asm#"2", ".4s", ".2d", []>;
4697
4698   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4699             (!cast<Instruction>(NAME # "v16i8")
4700                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4701   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4702             (!cast<Instruction>(NAME # "v8i16")
4703                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4704   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4705             (!cast<Instruction>(NAME # "v4i32")
4706                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4707 }
4708
4709 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4710                            RegisterOperand regtype,
4711                            string asm, string kind, string zero,
4712                            ValueType dty, ValueType sty, SDNode OpNode>
4713   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4714       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4715       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4716       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4717     Sched<[WriteV]> {
4718   bits<5> Rd;
4719   bits<5> Rn;
4720   let Inst{31}    = 0;
4721   let Inst{30}    = Q;
4722   let Inst{29}    = U;
4723   let Inst{28-24} = 0b01110;
4724   let Inst{23-22} = size;
4725   let Inst{21-17} = 0b10000;
4726   let Inst{16-12} = opcode;
4727   let Inst{11-10} = 0b10;
4728   let Inst{9-5}   = Rn;
4729   let Inst{4-0}   = Rd;
4730 }
4731
4732 // Comparisons support all element sizes, except 1xD.
4733 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4734                             SDNode OpNode> {
4735   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4736                                      asm, ".8b", "0",
4737                                      v8i8, v8i8, OpNode>;
4738   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4739                                      asm, ".16b", "0",
4740                                      v16i8, v16i8, OpNode>;
4741   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4742                                      asm, ".4h", "0",
4743                                      v4i16, v4i16, OpNode>;
4744   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4745                                      asm, ".8h", "0",
4746                                      v8i16, v8i16, OpNode>;
4747   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4748                                      asm, ".2s", "0",
4749                                      v2i32, v2i32, OpNode>;
4750   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4751                                      asm, ".4s", "0",
4752                                      v4i32, v4i32, OpNode>;
4753   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4754                                      asm, ".2d", "0",
4755                                      v2i64, v2i64, OpNode>;
4756 }
4757
4758 // FP Comparisons support only S and D element sizes.
4759 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4760                               string asm, SDNode OpNode> {
4761
4762   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4763                                      asm, ".2s", "0.0",
4764                                      v2i32, v2f32, OpNode>;
4765   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4766                                      asm, ".4s", "0.0",
4767                                      v4i32, v4f32, OpNode>;
4768   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4769                                      asm, ".2d", "0.0",
4770                                      v2i64, v2f64, OpNode>;
4771
4772   def : InstAlias<asm # " $Vd.2s, $Vn.2s, #0",
4773                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4774   def : InstAlias<asm # " $Vd.4s, $Vn.4s, #0",
4775                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4776   def : InstAlias<asm # " $Vd.2d, $Vn.2d, #0",
4777                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4778   def : InstAlias<asm # ".2s $Vd, $Vn, #0",
4779                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4780   def : InstAlias<asm # ".4s $Vd, $Vn, #0",
4781                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4782   def : InstAlias<asm # ".2d $Vd, $Vn, #0",
4783                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4784 }
4785
4786 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4787 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4788                              RegisterOperand outtype, RegisterOperand intype,
4789                              string asm, string VdTy, string VnTy,
4790                              list<dag> pattern>
4791   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4792       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4793     Sched<[WriteV]> {
4794   bits<5> Rd;
4795   bits<5> Rn;
4796   let Inst{31}    = 0;
4797   let Inst{30}    = Q;
4798   let Inst{29}    = U;
4799   let Inst{28-24} = 0b01110;
4800   let Inst{23-22} = size;
4801   let Inst{21-17} = 0b10000;
4802   let Inst{16-12} = opcode;
4803   let Inst{11-10} = 0b10;
4804   let Inst{9-5}   = Rn;
4805   let Inst{4-0}   = Rd;
4806 }
4807
4808 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4809                              RegisterOperand outtype, RegisterOperand intype,
4810                              string asm, string VdTy, string VnTy,
4811                              list<dag> pattern>
4812   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4813       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4814     Sched<[WriteV]> {
4815   bits<5> Rd;
4816   bits<5> Rn;
4817   let Inst{31}    = 0;
4818   let Inst{30}    = Q;
4819   let Inst{29}    = U;
4820   let Inst{28-24} = 0b01110;
4821   let Inst{23-22} = size;
4822   let Inst{21-17} = 0b10000;
4823   let Inst{16-12} = opcode;
4824   let Inst{11-10} = 0b10;
4825   let Inst{9-5}   = Rn;
4826   let Inst{4-0}   = Rd;
4827 }
4828
4829 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4830   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4831                                     asm, ".4s", ".4h", []>;
4832   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4833                                     asm#"2", ".4s", ".8h", []>;
4834   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4835                                     asm, ".2d", ".2s", []>;
4836   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4837                                     asm#"2", ".2d", ".4s", []>;
4838 }
4839
4840 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4841   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4842                                     asm, ".4h", ".4s", []>;
4843   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4844                                     asm#"2", ".8h", ".4s", []>;
4845   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4846                                     asm, ".2s", ".2d", []>;
4847   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4848                                     asm#"2", ".4s", ".2d", []>;
4849 }
4850
4851 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4852                                      Intrinsic OpNode> {
4853   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4854                                      asm, ".2s", ".2d",
4855                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4856   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4857                                     asm#"2", ".4s", ".2d", []>;
4858
4859   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4860             (!cast<Instruction>(NAME # "v4f32")
4861                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4862 }
4863
4864 //----------------------------------------------------------------------------
4865 // AdvSIMD three register different-size vector instructions.
4866 //----------------------------------------------------------------------------
4867
4868 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4869 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4870                       RegisterOperand outtype, RegisterOperand intype1,
4871                       RegisterOperand intype2, string asm,
4872                       string outkind, string inkind1, string inkind2,
4873                       list<dag> pattern>
4874   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4875       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4876       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4877     Sched<[WriteV]> {
4878   bits<5> Rd;
4879   bits<5> Rn;
4880   bits<5> Rm;
4881   let Inst{31}    = 0;
4882   let Inst{30}    = size{0};
4883   let Inst{29}    = U;
4884   let Inst{28-24} = 0b01110;
4885   let Inst{23-22} = size{2-1};
4886   let Inst{21}    = 1;
4887   let Inst{20-16} = Rm;
4888   let Inst{15-12} = opcode;
4889   let Inst{11-10} = 0b00;
4890   let Inst{9-5}   = Rn;
4891   let Inst{4-0}   = Rd;
4892 }
4893
4894 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4895 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4896                       RegisterOperand outtype, RegisterOperand intype1,
4897                       RegisterOperand intype2, string asm,
4898                       string outkind, string inkind1, string inkind2,
4899                       list<dag> pattern>
4900   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4901       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4902       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4903     Sched<[WriteV]> {
4904   bits<5> Rd;
4905   bits<5> Rn;
4906   bits<5> Rm;
4907   let Inst{31}    = 0;
4908   let Inst{30}    = size{0};
4909   let Inst{29}    = U;
4910   let Inst{28-24} = 0b01110;
4911   let Inst{23-22} = size{2-1};
4912   let Inst{21}    = 1;
4913   let Inst{20-16} = Rm;
4914   let Inst{15-12} = opcode;
4915   let Inst{11-10} = 0b00;
4916   let Inst{9-5}   = Rn;
4917   let Inst{4-0}   = Rd;
4918 }
4919
4920 // FIXME: TableGen doesn't know how to deal with expanded types that also
4921 //        change the element count (in this case, placing the results in
4922 //        the high elements of the result register rather than the low
4923 //        elements). Until that's fixed, we can't code-gen those.
4924 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4925                                     Intrinsic IntOp> {
4926   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4927                                                   V64, V128, V128,
4928                                                   asm, ".8b", ".8h", ".8h",
4929      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4930   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4931                                                   V128, V128, V128,
4932                                                   asm#"2", ".16b", ".8h", ".8h",
4933      []>;
4934   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4935                                                   V64, V128, V128,
4936                                                   asm, ".4h", ".4s", ".4s",
4937      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4938   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4939                                                   V128, V128, V128,
4940                                                   asm#"2", ".8h", ".4s", ".4s",
4941      []>;
4942   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4943                                                   V64, V128, V128,
4944                                                   asm, ".2s", ".2d", ".2d",
4945      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4946   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4947                                                   V128, V128, V128,
4948                                                   asm#"2", ".4s", ".2d", ".2d",
4949      []>;
4950
4951
4952   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4953   // a version attached to an instruction.
4954   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4955                                                    (v8i16 V128:$Rm))),
4956             (!cast<Instruction>(NAME # "v8i16_v16i8")
4957                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4958                 V128:$Rn, V128:$Rm)>;
4959   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4960                                                     (v4i32 V128:$Rm))),
4961             (!cast<Instruction>(NAME # "v4i32_v8i16")
4962                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4963                 V128:$Rn, V128:$Rm)>;
4964   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4965                                                     (v2i64 V128:$Rm))),
4966             (!cast<Instruction>(NAME # "v2i64_v4i32")
4967                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4968                 V128:$Rn, V128:$Rm)>;
4969 }
4970
4971 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4972                                       Intrinsic IntOp> {
4973   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4974                                             V128, V64, V64,
4975                                             asm, ".8h", ".8b", ".8b",
4976       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4977   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4978                                             V128, V128, V128,
4979                                             asm#"2", ".8h", ".16b", ".16b", []>;
4980   let Predicates = [HasCrypto] in {
4981     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4982                                               V128, V64, V64,
4983                                               asm, ".1q", ".1d", ".1d", []>;
4984     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4985                                               V128, V128, V128,
4986                                               asm#"2", ".1q", ".2d", ".2d", []>;
4987   }
4988
4989   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4990                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
4991       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4992 }
4993
4994 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4995                                  SDPatternOperator OpNode> {
4996   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4997                                                   V128, V64, V64,
4998                                                   asm, ".4s", ".4h", ".4h",
4999       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5000   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5001                                                   V128, V128, V128,
5002                                                   asm#"2", ".4s", ".8h", ".8h",
5003       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5004                                       (extract_high_v8i16 V128:$Rm)))]>;
5005   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5006                                                   V128, V64, V64,
5007                                                   asm, ".2d", ".2s", ".2s",
5008       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5009   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5010                                                   V128, V128, V128,
5011                                                   asm#"2", ".2d", ".4s", ".4s",
5012       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5013                                       (extract_high_v4i32 V128:$Rm)))]>;
5014 }
5015
5016 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5017                                   SDPatternOperator OpNode = null_frag> {
5018   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5019                                                   V128, V64, V64,
5020                                                   asm, ".8h", ".8b", ".8b",
5021       [(set (v8i16 V128:$Rd),
5022             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5023   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5024                                                  V128, V128, V128,
5025                                                  asm#"2", ".8h", ".16b", ".16b",
5026       [(set (v8i16 V128:$Rd),
5027             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5028                                 (extract_high_v16i8 V128:$Rm)))))]>;
5029   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5030                                                   V128, V64, V64,
5031                                                   asm, ".4s", ".4h", ".4h",
5032       [(set (v4i32 V128:$Rd),
5033             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5034   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5035                                                   V128, V128, V128,
5036                                                   asm#"2", ".4s", ".8h", ".8h",
5037       [(set (v4i32 V128:$Rd),
5038             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5039                                   (extract_high_v8i16 V128:$Rm)))))]>;
5040   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5041                                                   V128, V64, V64,
5042                                                   asm, ".2d", ".2s", ".2s",
5043       [(set (v2i64 V128:$Rd),
5044             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5045   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5046                                                   V128, V128, V128,
5047                                                   asm#"2", ".2d", ".4s", ".4s",
5048       [(set (v2i64 V128:$Rd),
5049             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5050                                  (extract_high_v4i32 V128:$Rm)))))]>;
5051 }
5052
5053 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5054                                           string asm,
5055                                           SDPatternOperator OpNode> {
5056   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5057                                                   V128, V64, V64,
5058                                                   asm, ".8h", ".8b", ".8b",
5059     [(set (v8i16 V128:$dst),
5060           (add (v8i16 V128:$Rd),
5061                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5062   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5063                                                  V128, V128, V128,
5064                                                  asm#"2", ".8h", ".16b", ".16b",
5065     [(set (v8i16 V128:$dst),
5066           (add (v8i16 V128:$Rd),
5067                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5068                                    (extract_high_v16i8 V128:$Rm))))))]>;
5069   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5070                                                   V128, V64, V64,
5071                                                   asm, ".4s", ".4h", ".4h",
5072     [(set (v4i32 V128:$dst),
5073           (add (v4i32 V128:$Rd),
5074                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5075   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5076                                                   V128, V128, V128,
5077                                                   asm#"2", ".4s", ".8h", ".8h",
5078     [(set (v4i32 V128:$dst),
5079           (add (v4i32 V128:$Rd),
5080                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5081                                     (extract_high_v8i16 V128:$Rm))))))]>;
5082   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5083                                                   V128, V64, V64,
5084                                                   asm, ".2d", ".2s", ".2s",
5085     [(set (v2i64 V128:$dst),
5086           (add (v2i64 V128:$Rd),
5087                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5088   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5089                                                   V128, V128, V128,
5090                                                   asm#"2", ".2d", ".4s", ".4s",
5091     [(set (v2i64 V128:$dst),
5092           (add (v2i64 V128:$Rd),
5093                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5094                                     (extract_high_v4i32 V128:$Rm))))))]>;
5095 }
5096
5097 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5098                                   SDPatternOperator OpNode = null_frag> {
5099   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5100                                                   V128, V64, V64,
5101                                                   asm, ".8h", ".8b", ".8b",
5102       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5103   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5104                                                  V128, V128, V128,
5105                                                  asm#"2", ".8h", ".16b", ".16b",
5106       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5107                                       (extract_high_v16i8 V128:$Rm)))]>;
5108   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5109                                                   V128, V64, V64,
5110                                                   asm, ".4s", ".4h", ".4h",
5111       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5112   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5113                                                   V128, V128, V128,
5114                                                   asm#"2", ".4s", ".8h", ".8h",
5115       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5116                                       (extract_high_v8i16 V128:$Rm)))]>;
5117   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5118                                                   V128, V64, V64,
5119                                                   asm, ".2d", ".2s", ".2s",
5120       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5121   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5122                                                   V128, V128, V128,
5123                                                   asm#"2", ".2d", ".4s", ".4s",
5124       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5125                                       (extract_high_v4i32 V128:$Rm)))]>;
5126 }
5127
5128 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5129                                       string asm,
5130                                       SDPatternOperator OpNode> {
5131   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5132                                                   V128, V64, V64,
5133                                                   asm, ".8h", ".8b", ".8b",
5134     [(set (v8i16 V128:$dst),
5135           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5136   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5137                                                  V128, V128, V128,
5138                                                  asm#"2", ".8h", ".16b", ".16b",
5139     [(set (v8i16 V128:$dst),
5140           (OpNode (v8i16 V128:$Rd),
5141                   (extract_high_v16i8 V128:$Rn),
5142                   (extract_high_v16i8 V128:$Rm)))]>;
5143   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5144                                                   V128, V64, V64,
5145                                                   asm, ".4s", ".4h", ".4h",
5146     [(set (v4i32 V128:$dst),
5147           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5148   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5149                                                   V128, V128, V128,
5150                                                   asm#"2", ".4s", ".8h", ".8h",
5151     [(set (v4i32 V128:$dst),
5152           (OpNode (v4i32 V128:$Rd),
5153                   (extract_high_v8i16 V128:$Rn),
5154                   (extract_high_v8i16 V128:$Rm)))]>;
5155   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5156                                                   V128, V64, V64,
5157                                                   asm, ".2d", ".2s", ".2s",
5158     [(set (v2i64 V128:$dst),
5159           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5160   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5161                                                   V128, V128, V128,
5162                                                   asm#"2", ".2d", ".4s", ".4s",
5163     [(set (v2i64 V128:$dst),
5164           (OpNode (v2i64 V128:$Rd),
5165                   (extract_high_v4i32 V128:$Rn),
5166                   (extract_high_v4i32 V128:$Rm)))]>;
5167 }
5168
5169 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5170                                            SDPatternOperator Accum> {
5171   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5172                                                   V128, V64, V64,
5173                                                   asm, ".4s", ".4h", ".4h",
5174     [(set (v4i32 V128:$dst),
5175           (Accum (v4i32 V128:$Rd),
5176                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5177                                                 (v4i16 V64:$Rm)))))]>;
5178   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5179                                                   V128, V128, V128,
5180                                                   asm#"2", ".4s", ".8h", ".8h",
5181     [(set (v4i32 V128:$dst),
5182           (Accum (v4i32 V128:$Rd),
5183                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5184                                             (extract_high_v8i16 V128:$Rm)))))]>;
5185   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5186                                                   V128, V64, V64,
5187                                                   asm, ".2d", ".2s", ".2s",
5188     [(set (v2i64 V128:$dst),
5189           (Accum (v2i64 V128:$Rd),
5190                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5191                                                 (v2i32 V64:$Rm)))))]>;
5192   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5193                                                   V128, V128, V128,
5194                                                   asm#"2", ".2d", ".4s", ".4s",
5195     [(set (v2i64 V128:$dst),
5196           (Accum (v2i64 V128:$Rd),
5197                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5198                                             (extract_high_v4i32 V128:$Rm)))))]>;
5199 }
5200
5201 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5202                                   SDPatternOperator OpNode> {
5203   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5204                                                   V128, V128, V64,
5205                                                   asm, ".8h", ".8h", ".8b",
5206        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5207   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5208                                                   V128, V128, V128,
5209                                                   asm#"2", ".8h", ".8h", ".16b",
5210        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5211                                        (extract_high_v16i8 V128:$Rm)))]>;
5212   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5213                                                   V128, V128, V64,
5214                                                   asm, ".4s", ".4s", ".4h",
5215        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5216   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5217                                                   V128, V128, V128,
5218                                                   asm#"2", ".4s", ".4s", ".8h",
5219        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5220                                        (extract_high_v8i16 V128:$Rm)))]>;
5221   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5222                                                   V128, V128, V64,
5223                                                   asm, ".2d", ".2d", ".2s",
5224        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5225   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5226                                                   V128, V128, V128,
5227                                                   asm#"2", ".2d", ".2d", ".4s",
5228        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5229                                        (extract_high_v4i32 V128:$Rm)))]>;
5230 }
5231
5232 //----------------------------------------------------------------------------
5233 // AdvSIMD bitwise extract from vector
5234 //----------------------------------------------------------------------------
5235
5236 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5237                              string asm, string kind>
5238   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5239       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5240       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5241       [(set (vty regtype:$Rd),
5242             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5243     Sched<[WriteV]> {
5244   bits<5> Rd;
5245   bits<5> Rn;
5246   bits<5> Rm;
5247   bits<4> imm;
5248   let Inst{31}    = 0;
5249   let Inst{30}    = size;
5250   let Inst{29-21} = 0b101110000;
5251   let Inst{20-16} = Rm;
5252   let Inst{15}    = 0;
5253   let Inst{14-11} = imm;
5254   let Inst{10}    = 0;
5255   let Inst{9-5}   = Rn;
5256   let Inst{4-0}   = Rd;
5257 }
5258
5259
5260 multiclass SIMDBitwiseExtract<string asm> {
5261   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5262     let imm{3} = 0;
5263   }
5264   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5265 }
5266
5267 //----------------------------------------------------------------------------
5268 // AdvSIMD zip vector
5269 //----------------------------------------------------------------------------
5270
5271 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5272                         string asm, string kind, SDNode OpNode, ValueType valty>
5273   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5274       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5275       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5276       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5277     Sched<[WriteV]> {
5278   bits<5> Rd;
5279   bits<5> Rn;
5280   bits<5> Rm;
5281   let Inst{31}    = 0;
5282   let Inst{30}    = size{0};
5283   let Inst{29-24} = 0b001110;
5284   let Inst{23-22} = size{2-1};
5285   let Inst{21}    = 0;
5286   let Inst{20-16} = Rm;
5287   let Inst{15}    = 0;
5288   let Inst{14-12} = opc;
5289   let Inst{11-10} = 0b10;
5290   let Inst{9-5}   = Rn;
5291   let Inst{4-0}   = Rd;
5292 }
5293
5294 multiclass SIMDZipVector<bits<3>opc, string asm,
5295                          SDNode OpNode> {
5296   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5297       asm, ".8b", OpNode, v8i8>;
5298   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5299       asm, ".16b", OpNode, v16i8>;
5300   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5301       asm, ".4h", OpNode, v4i16>;
5302   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5303       asm, ".8h", OpNode, v8i16>;
5304   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5305       asm, ".2s", OpNode, v2i32>;
5306   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5307       asm, ".4s", OpNode, v4i32>;
5308   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5309       asm, ".2d", OpNode, v2i64>;
5310
5311   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5312         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5313   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5314         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5315   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5316         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5317   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5318         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5319   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5320         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5321 }
5322
5323 //----------------------------------------------------------------------------
5324 // AdvSIMD three register scalar instructions
5325 //----------------------------------------------------------------------------
5326
5327 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5328 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5329                         RegisterClass regtype, string asm,
5330                         list<dag> pattern>
5331   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5332       "\t$Rd, $Rn, $Rm", "", pattern>,
5333     Sched<[WriteV]> {
5334   bits<5> Rd;
5335   bits<5> Rn;
5336   bits<5> Rm;
5337   let Inst{31-30} = 0b01;
5338   let Inst{29}    = U;
5339   let Inst{28-24} = 0b11110;
5340   let Inst{23-22} = size;
5341   let Inst{21}    = 1;
5342   let Inst{20-16} = Rm;
5343   let Inst{15-11} = opcode;
5344   let Inst{10}    = 1;
5345   let Inst{9-5}   = Rn;
5346   let Inst{4-0}   = Rd;
5347 }
5348
5349 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5350 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5351                         dag oops, dag iops, string asm,
5352             list<dag> pattern>
5353   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5354     Sched<[WriteV]> {
5355   bits<5> Rd;
5356   bits<5> Rn;
5357   bits<5> Rm;
5358   let Inst{31-30} = 0b01;
5359   let Inst{29}    = U;
5360   let Inst{28-24} = 0b11110;
5361   let Inst{23-22} = size;
5362   let Inst{21}    = R;
5363   let Inst{20-16} = Rm;
5364   let Inst{15-11} = opcode;
5365   let Inst{10}    = 1;
5366   let Inst{9-5}   = Rn;
5367   let Inst{4-0}   = Rd;
5368 }
5369
5370 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5371                             SDPatternOperator OpNode> {
5372   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5373     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5374 }
5375
5376 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5377                                SDPatternOperator OpNode> {
5378   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5379     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5380   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5381   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5382   def v1i8   : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5383
5384   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5385             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5386   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5387             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5388 }
5389
5390 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5391                              SDPatternOperator OpNode> {
5392   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5393                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5394   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5395 }
5396
5397 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5398                                  SDPatternOperator OpNode = null_frag> {
5399   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5400                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm), 
5401                                      asm, []>;
5402   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5403                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm), 
5404                                      asm, []>;
5405 }
5406
5407 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5408                              SDPatternOperator OpNode = null_frag> {
5409   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5410     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5411       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5412     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5413       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5414   }
5415
5416   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5417             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5418 }
5419
5420 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5421                                 SDPatternOperator OpNode = null_frag> {
5422   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5423     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5424       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5425     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5426       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5427   }
5428
5429   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5430             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5431 }
5432
5433 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5434               dag oops, dag iops, string asm, string cstr, list<dag> pat>
5435   : I<oops, iops, asm,
5436       "\t$Rd, $Rn, $Rm", cstr, pat>,
5437     Sched<[WriteV]> {
5438   bits<5> Rd;
5439   bits<5> Rn;
5440   bits<5> Rm;
5441   let Inst{31-30} = 0b01;
5442   let Inst{29}    = U;
5443   let Inst{28-24} = 0b11110;
5444   let Inst{23-22} = size;
5445   let Inst{21}    = 1;
5446   let Inst{20-16} = Rm;
5447   let Inst{15-11} = opcode;
5448   let Inst{10}    = 0;
5449   let Inst{9-5}   = Rn;
5450   let Inst{4-0}   = Rd;
5451 }
5452
5453 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5454 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5455                                   SDPatternOperator OpNode = null_frag> {
5456   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5457                                       (outs FPR32:$Rd),
5458                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5459   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5460                                       (outs FPR64:$Rd),
5461                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5462             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5463 }
5464
5465 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5466 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5467                                   SDPatternOperator OpNode = null_frag> {
5468   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5469                                       (outs FPR32:$dst),
5470                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5471                                       asm, "$Rd = $dst", []>;
5472   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5473                                       (outs FPR64:$dst),
5474                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5475                                       asm, "$Rd = $dst",
5476             [(set (i64 FPR64:$dst),
5477                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5478 }
5479
5480 //----------------------------------------------------------------------------
5481 // AdvSIMD two register scalar instructions
5482 //----------------------------------------------------------------------------
5483
5484 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5485 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5486                         RegisterClass regtype, RegisterClass regtype2,
5487                         string asm, list<dag> pat>
5488   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5489       "\t$Rd, $Rn", "", pat>,
5490     Sched<[WriteV]> {
5491   bits<5> Rd;
5492   bits<5> Rn;
5493   let Inst{31-30} = 0b01;
5494   let Inst{29}    = U;
5495   let Inst{28-24} = 0b11110;
5496   let Inst{23-22} = size;
5497   let Inst{21-17} = 0b10000;
5498   let Inst{16-12} = opcode;
5499   let Inst{11-10} = 0b10;
5500   let Inst{9-5}   = Rn;
5501   let Inst{4-0}   = Rd;
5502 }
5503
5504 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5505 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5506                         RegisterClass regtype, RegisterClass regtype2,
5507                         string asm, list<dag> pat>
5508   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5509       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5510     Sched<[WriteV]> {
5511   bits<5> Rd;
5512   bits<5> Rn;
5513   let Inst{31-30} = 0b01;
5514   let Inst{29}    = U;
5515   let Inst{28-24} = 0b11110;
5516   let Inst{23-22} = size;
5517   let Inst{21-17} = 0b10000;
5518   let Inst{16-12} = opcode;
5519   let Inst{11-10} = 0b10;
5520   let Inst{9-5}   = Rn;
5521   let Inst{4-0}   = Rd;
5522 }
5523
5524
5525 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5526 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5527                         RegisterClass regtype, string asm, string zero>
5528   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5529       "\t$Rd, $Rn, #" # zero, "", []>,
5530     Sched<[WriteV]> {
5531   bits<5> Rd;
5532   bits<5> Rn;
5533   let Inst{31-30} = 0b01;
5534   let Inst{29}    = U;
5535   let Inst{28-24} = 0b11110;
5536   let Inst{23-22} = size;
5537   let Inst{21-17} = 0b10000;
5538   let Inst{16-12} = opcode;
5539   let Inst{11-10} = 0b10;
5540   let Inst{9-5}   = Rn;
5541   let Inst{4-0}   = Rd;
5542 }
5543
5544 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5545   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5546      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5547     Sched<[WriteV]> {
5548   bits<5> Rd;
5549   bits<5> Rn;
5550   let Inst{31-17} = 0b011111100110000;
5551   let Inst{16-12} = opcode;
5552   let Inst{11-10} = 0b10;
5553   let Inst{9-5}   = Rn;
5554   let Inst{4-0}   = Rd;
5555 }
5556
5557 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5558                              SDPatternOperator OpNode> {
5559   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5560
5561   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5562             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5563 }
5564
5565 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5566                               SDPatternOperator OpNode> {
5567   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5568   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5569
5570   def : InstAlias<asm # " $Rd, $Rn, #0",
5571                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5572   def : InstAlias<asm # " $Rd, $Rn, #0",
5573                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5574
5575   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5576             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5577 }
5578
5579 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5580                           SDPatternOperator OpNode = null_frag> {
5581   def v1i64       : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5582     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5583
5584   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5585             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5586 }
5587
5588 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5589   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5590   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5591 }
5592
5593 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5594                               SDPatternOperator OpNode> {
5595   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5596                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5597   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5598                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5599 }
5600
5601 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5602                              SDPatternOperator OpNode = null_frag> {
5603   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5604     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5605            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5606     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5607            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5608     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5609     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5610   }
5611
5612   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5613             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5614 }
5615
5616 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5617                                  Intrinsic OpNode> {
5618   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5619     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5620         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5621     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5622         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5623     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5624     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5625   }
5626
5627   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5628             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5629 }
5630
5631
5632
5633 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5634 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5635                                  SDPatternOperator OpNode = null_frag> {
5636   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5637         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5638   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5639   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5640 }
5641
5642 //----------------------------------------------------------------------------
5643 // AdvSIMD scalar pairwise instructions
5644 //----------------------------------------------------------------------------
5645
5646 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5647 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5648                         RegisterOperand regtype, RegisterOperand vectype,
5649                         string asm, string kind>
5650   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5651       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5652     Sched<[WriteV]> {
5653   bits<5> Rd;
5654   bits<5> Rn;
5655   let Inst{31-30} = 0b01;
5656   let Inst{29}    = U;
5657   let Inst{28-24} = 0b11110;
5658   let Inst{23-22} = size;
5659   let Inst{21-17} = 0b11000;
5660   let Inst{16-12} = opcode;
5661   let Inst{11-10} = 0b10;
5662   let Inst{9-5}   = Rn;
5663   let Inst{4-0}   = Rd;
5664 }
5665
5666 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5667   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5668                                       asm, ".2d">;
5669 }
5670
5671 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5672   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5673                                       asm, ".2s">;
5674   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5675                                       asm, ".2d">;
5676 }
5677
5678 //----------------------------------------------------------------------------
5679 // AdvSIMD across lanes instructions
5680 //----------------------------------------------------------------------------
5681
5682 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5683 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5684                           RegisterClass regtype, RegisterOperand vectype,
5685                           string asm, string kind, list<dag> pattern>
5686   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5687       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5688     Sched<[WriteV]> {
5689   bits<5> Rd;
5690   bits<5> Rn;
5691   let Inst{31}    = 0;
5692   let Inst{30}    = Q;
5693   let Inst{29}    = U;
5694   let Inst{28-24} = 0b01110;
5695   let Inst{23-22} = size;
5696   let Inst{21-17} = 0b11000;
5697   let Inst{16-12} = opcode;
5698   let Inst{11-10} = 0b10;
5699   let Inst{9-5}   = Rn;
5700   let Inst{4-0}   = Rd;
5701 }
5702
5703 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5704                               string asm> {
5705   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5706                                    asm, ".8b", []>;
5707   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5708                                    asm, ".16b", []>;
5709   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5710                                    asm, ".4h", []>;
5711   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5712                                    asm, ".8h", []>;
5713   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5714                                    asm, ".4s", []>;
5715 }
5716
5717 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5718   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5719                                    asm, ".8b", []>;
5720   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5721                                    asm, ".16b", []>;
5722   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5723                                    asm, ".4h", []>;
5724   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5725                                    asm, ".8h", []>;
5726   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5727                                    asm, ".4s", []>;
5728 }
5729
5730 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5731                             Intrinsic intOp> {
5732   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5733                                    asm, ".4s",
5734         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5735 }
5736
5737 //----------------------------------------------------------------------------
5738 // AdvSIMD INS/DUP instructions
5739 //----------------------------------------------------------------------------
5740
5741 // FIXME: There has got to be a better way to factor these. ugh.
5742
5743 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5744                      string operands, string constraints, list<dag> pattern>
5745   : I<outs, ins, asm, operands, constraints, pattern>,
5746     Sched<[WriteV]> {
5747   bits<5> Rd;
5748   bits<5> Rn;
5749   let Inst{31} = 0;
5750   let Inst{30} = Q;
5751   let Inst{29} = op;
5752   let Inst{28-21} = 0b01110000;
5753   let Inst{15} = 0;
5754   let Inst{10} = 1;
5755   let Inst{9-5} = Rn;
5756   let Inst{4-0} = Rd;
5757 }
5758
5759 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5760                       RegisterOperand vecreg, RegisterClass regtype>
5761   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5762                    "{\t$Rd" # size # ", $Rn" #
5763                    "|" # size # "\t$Rd, $Rn}", "",
5764                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
5765   let Inst{20-16} = imm5;
5766   let Inst{14-11} = 0b0001;
5767 }
5768
5769 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5770                          ValueType vectype, ValueType insreg,
5771                          RegisterOperand vecreg, Operand idxtype,
5772                          ValueType elttype, SDNode OpNode>
5773   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5774                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5775                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5776                  [(set (vectype vecreg:$Rd),
5777                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5778   let Inst{14-11} = 0b0000;
5779 }
5780
5781 class SIMDDup64FromElement
5782   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5783                        VectorIndexD, i64, AArch64duplane64> {
5784   bits<1> idx;
5785   let Inst{20} = idx;
5786   let Inst{19-16} = 0b1000;
5787 }
5788
5789 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5790                            RegisterOperand vecreg>
5791   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5792                        VectorIndexS, i64, AArch64duplane32> {
5793   bits<2> idx;
5794   let Inst{20-19} = idx;
5795   let Inst{18-16} = 0b100;
5796 }
5797
5798 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5799                            RegisterOperand vecreg>
5800   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5801                        VectorIndexH, i64, AArch64duplane16> {
5802   bits<3> idx;
5803   let Inst{20-18} = idx;
5804   let Inst{17-16} = 0b10;
5805 }
5806
5807 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5808                           RegisterOperand vecreg>
5809   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5810                        VectorIndexB, i64, AArch64duplane8> {
5811   bits<4> idx;
5812   let Inst{20-17} = idx;
5813   let Inst{16} = 1;
5814 }
5815
5816 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5817                   Operand idxtype, string asm, list<dag> pattern>
5818   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5819                    "{\t$Rd, $Rn" # size # "$idx" #
5820                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5821   let Inst{14-11} = imm4;
5822 }
5823
5824 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5825                Operand idxtype>
5826   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5827 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5828                Operand idxtype>
5829   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5830       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5831
5832 class SIMDMovAlias<string asm, string size, Instruction inst,
5833                    RegisterClass regtype, Operand idxtype>
5834     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5835                     "|" # size # "\t$dst, $src$idx}",
5836                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5837
5838 multiclass SMov {
5839   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5840     bits<4> idx;
5841     let Inst{20-17} = idx;
5842     let Inst{16} = 1;
5843   }
5844   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5845     bits<4> idx;
5846     let Inst{20-17} = idx;
5847     let Inst{16} = 1;
5848   }
5849   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5850     bits<3> idx;
5851     let Inst{20-18} = idx;
5852     let Inst{17-16} = 0b10;
5853   }
5854   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5855     bits<3> idx;
5856     let Inst{20-18} = idx;
5857     let Inst{17-16} = 0b10;
5858   }
5859   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5860     bits<2> idx;
5861     let Inst{20-19} = idx;
5862     let Inst{18-16} = 0b100;
5863   }
5864 }
5865
5866 multiclass UMov {
5867   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5868     bits<4> idx;
5869     let Inst{20-17} = idx;
5870     let Inst{16} = 1;
5871   }
5872   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5873     bits<3> idx;
5874     let Inst{20-18} = idx;
5875     let Inst{17-16} = 0b10;
5876   }
5877   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5878     bits<2> idx;
5879     let Inst{20-19} = idx;
5880     let Inst{18-16} = 0b100;
5881   }
5882   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5883     bits<1> idx;
5884     let Inst{20} = idx;
5885     let Inst{19-16} = 0b1000;
5886   }
5887   def : SIMDMovAlias<"mov", ".s",
5888                      !cast<Instruction>(NAME#"vi32"),
5889                      GPR32, VectorIndexS>;
5890   def : SIMDMovAlias<"mov", ".d",
5891                      !cast<Instruction>(NAME#"vi64"),
5892                      GPR64, VectorIndexD>;
5893 }
5894
5895 class SIMDInsFromMain<string size, ValueType vectype,
5896                       RegisterClass regtype, Operand idxtype>
5897   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5898                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5899                    "{\t$Rd" # size # "$idx, $Rn" #
5900                    "|" # size # "\t$Rd$idx, $Rn}",
5901                    "$Rd = $dst",
5902             [(set V128:$dst,
5903               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5904   let Inst{14-11} = 0b0011;
5905 }
5906
5907 class SIMDInsFromElement<string size, ValueType vectype,
5908                          ValueType elttype, Operand idxtype>
5909   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5910                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5911                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5912                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
5913                    "$Rd = $dst",
5914          [(set V128:$dst,
5915                (vector_insert
5916                  (vectype V128:$Rd),
5917                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5918                  idxtype:$idx))]>;
5919
5920 class SIMDInsMainMovAlias<string size, Instruction inst,
5921                           RegisterClass regtype, Operand idxtype>
5922     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5923                         "|" # size #"\t$dst$idx, $src}",
5924                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5925 class SIMDInsElementMovAlias<string size, Instruction inst,
5926                              Operand idxtype>
5927     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5928                       # "|" # size #" $dst$idx, $src$idx2}",
5929                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5930
5931
5932 multiclass SIMDIns {
5933   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5934     bits<4> idx;
5935     let Inst{20-17} = idx;
5936     let Inst{16} = 1;
5937   }
5938   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5939     bits<3> idx;
5940     let Inst{20-18} = idx;
5941     let Inst{17-16} = 0b10;
5942   }
5943   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5944     bits<2> idx;
5945     let Inst{20-19} = idx;
5946     let Inst{18-16} = 0b100;
5947   }
5948   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5949     bits<1> idx;
5950     let Inst{20} = idx;
5951     let Inst{19-16} = 0b1000;
5952   }
5953
5954   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5955     bits<4> idx;
5956     bits<4> idx2;
5957     let Inst{20-17} = idx;
5958     let Inst{16} = 1;
5959     let Inst{14-11} = idx2;
5960   }
5961   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5962     bits<3> idx;
5963     bits<3> idx2;
5964     let Inst{20-18} = idx;
5965     let Inst{17-16} = 0b10;
5966     let Inst{14-12} = idx2;
5967     let Inst{11} = {?};
5968   }
5969   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5970     bits<2> idx;
5971     bits<2> idx2;
5972     let Inst{20-19} = idx;
5973     let Inst{18-16} = 0b100;
5974     let Inst{14-13} = idx2;
5975     let Inst{12-11} = {?,?};
5976   }
5977   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5978     bits<1> idx;
5979     bits<1> idx2;
5980     let Inst{20} = idx;
5981     let Inst{19-16} = 0b1000;
5982     let Inst{14} = idx2;
5983     let Inst{13-11} = {?,?,?};
5984   }
5985
5986   // For all forms of the INS instruction, the "mov" mnemonic is the
5987   // preferred alias. Why they didn't just call the instruction "mov" in
5988   // the first place is a very good question indeed...
5989   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5990                          GPR32, VectorIndexB>;
5991   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5992                          GPR32, VectorIndexH>;
5993   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5994                          GPR32, VectorIndexS>;
5995   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5996                          GPR64, VectorIndexD>;
5997
5998   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5999                          VectorIndexB>;
6000   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6001                          VectorIndexH>;
6002   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6003                          VectorIndexS>;
6004   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6005                          VectorIndexD>;
6006 }
6007
6008 //----------------------------------------------------------------------------
6009 // AdvSIMD TBL/TBX
6010 //----------------------------------------------------------------------------
6011
6012 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6013 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6014                           RegisterOperand listtype, string asm, string kind>
6015   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6016        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6017     Sched<[WriteV]> {
6018   bits<5> Vd;
6019   bits<5> Vn;
6020   bits<5> Vm;
6021   let Inst{31}    = 0;
6022   let Inst{30}    = Q;
6023   let Inst{29-21} = 0b001110000;
6024   let Inst{20-16} = Vm;
6025   let Inst{15}    = 0;
6026   let Inst{14-13} = len;
6027   let Inst{12}    = op;
6028   let Inst{11-10} = 0b00;
6029   let Inst{9-5}   = Vn;
6030   let Inst{4-0}   = Vd;
6031 }
6032
6033 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6034 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6035                           RegisterOperand listtype, string asm, string kind>
6036   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6037        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6038     Sched<[WriteV]> {
6039   bits<5> Vd;
6040   bits<5> Vn;
6041   bits<5> Vm;
6042   let Inst{31}    = 0;
6043   let Inst{30}    = Q;
6044   let Inst{29-21} = 0b001110000;
6045   let Inst{20-16} = Vm;
6046   let Inst{15}    = 0;
6047   let Inst{14-13} = len;
6048   let Inst{12}    = op;
6049   let Inst{11-10} = 0b00;
6050   let Inst{9-5}   = Vn;
6051   let Inst{4-0}   = Vd;
6052 }
6053
6054 class SIMDTableLookupAlias<string asm, Instruction inst,
6055                           RegisterOperand vectype, RegisterOperand listtype>
6056     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6057                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6058
6059 multiclass SIMDTableLookup<bit op, string asm> {
6060   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6061                                       asm, ".8b">;
6062   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6063                                       asm, ".8b">;
6064   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6065                                       asm, ".8b">;
6066   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6067                                       asm, ".8b">;
6068   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6069                                       asm, ".16b">;
6070   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6071                                       asm, ".16b">;
6072   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6073                                       asm, ".16b">;
6074   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6075                                       asm, ".16b">;
6076
6077   def : SIMDTableLookupAlias<asm # ".8b",
6078                          !cast<Instruction>(NAME#"v8i8One"),
6079                          V64, VecListOne128>;
6080   def : SIMDTableLookupAlias<asm # ".8b",
6081                          !cast<Instruction>(NAME#"v8i8Two"),
6082                          V64, VecListTwo128>;
6083   def : SIMDTableLookupAlias<asm # ".8b",
6084                          !cast<Instruction>(NAME#"v8i8Three"),
6085                          V64, VecListThree128>;
6086   def : SIMDTableLookupAlias<asm # ".8b",
6087                          !cast<Instruction>(NAME#"v8i8Four"),
6088                          V64, VecListFour128>;
6089   def : SIMDTableLookupAlias<asm # ".16b",
6090                          !cast<Instruction>(NAME#"v16i8One"),
6091                          V128, VecListOne128>;
6092   def : SIMDTableLookupAlias<asm # ".16b",
6093                          !cast<Instruction>(NAME#"v16i8Two"),
6094                          V128, VecListTwo128>;
6095   def : SIMDTableLookupAlias<asm # ".16b",
6096                          !cast<Instruction>(NAME#"v16i8Three"),
6097                          V128, VecListThree128>;
6098   def : SIMDTableLookupAlias<asm # ".16b",
6099                          !cast<Instruction>(NAME#"v16i8Four"),
6100                          V128, VecListFour128>;
6101 }
6102
6103 multiclass SIMDTableLookupTied<bit op, string asm> {
6104   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6105                                       asm, ".8b">;
6106   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6107                                       asm, ".8b">;
6108   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6109                                       asm, ".8b">;
6110   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6111                                       asm, ".8b">;
6112   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6113                                       asm, ".16b">;
6114   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6115                                       asm, ".16b">;
6116   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6117                                       asm, ".16b">;
6118   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6119                                       asm, ".16b">;
6120
6121   def : SIMDTableLookupAlias<asm # ".8b",
6122                          !cast<Instruction>(NAME#"v8i8One"),
6123                          V64, VecListOne128>;
6124   def : SIMDTableLookupAlias<asm # ".8b",
6125                          !cast<Instruction>(NAME#"v8i8Two"),
6126                          V64, VecListTwo128>;
6127   def : SIMDTableLookupAlias<asm # ".8b",
6128                          !cast<Instruction>(NAME#"v8i8Three"),
6129                          V64, VecListThree128>;
6130   def : SIMDTableLookupAlias<asm # ".8b",
6131                          !cast<Instruction>(NAME#"v8i8Four"),
6132                          V64, VecListFour128>;
6133   def : SIMDTableLookupAlias<asm # ".16b",
6134                          !cast<Instruction>(NAME#"v16i8One"),
6135                          V128, VecListOne128>;
6136   def : SIMDTableLookupAlias<asm # ".16b",
6137                          !cast<Instruction>(NAME#"v16i8Two"),
6138                          V128, VecListTwo128>;
6139   def : SIMDTableLookupAlias<asm # ".16b",
6140                          !cast<Instruction>(NAME#"v16i8Three"),
6141                          V128, VecListThree128>;
6142   def : SIMDTableLookupAlias<asm # ".16b",
6143                          !cast<Instruction>(NAME#"v16i8Four"),
6144                          V128, VecListFour128>;
6145 }
6146
6147
6148 //----------------------------------------------------------------------------
6149 // AdvSIMD scalar CPY
6150 //----------------------------------------------------------------------------
6151 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6152 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6153                         string kind, Operand idxtype>
6154   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6155        "{\t$dst, $src" # kind # "$idx" #
6156        "|\t$dst, $src$idx}", "", []>,
6157     Sched<[WriteV]> {
6158   bits<5> dst;
6159   bits<5> src;
6160   let Inst{31-21} = 0b01011110000;
6161   let Inst{15-10} = 0b000001;
6162   let Inst{9-5}   = src;
6163   let Inst{4-0}   = dst;
6164 }
6165
6166 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6167       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6168     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6169                     # "|\t$dst, $src$index}",
6170                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6171
6172
6173 multiclass SIMDScalarCPY<string asm> {
6174   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6175     bits<4> idx;
6176     let Inst{20-17} = idx;
6177     let Inst{16} = 1;
6178   }
6179   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6180     bits<3> idx;
6181     let Inst{20-18} = idx;
6182     let Inst{17-16} = 0b10;
6183   }
6184   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6185     bits<2> idx;
6186     let Inst{20-19} = idx;
6187     let Inst{18-16} = 0b100;
6188   }
6189   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6190     bits<1> idx;
6191     let Inst{20} = idx;
6192     let Inst{19-16} = 0b1000;
6193   }
6194
6195   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6196                                                           VectorIndexD:$idx)))),
6197             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6198
6199   // 'DUP' mnemonic aliases.
6200   def : SIMDScalarCPYAlias<"dup", ".b",
6201                            !cast<Instruction>(NAME#"i8"),
6202                            FPR8, V128, VectorIndexB>;
6203   def : SIMDScalarCPYAlias<"dup", ".h",
6204                            !cast<Instruction>(NAME#"i16"),
6205                            FPR16, V128, VectorIndexH>;
6206   def : SIMDScalarCPYAlias<"dup", ".s",
6207                            !cast<Instruction>(NAME#"i32"),
6208                            FPR32, V128, VectorIndexS>;
6209   def : SIMDScalarCPYAlias<"dup", ".d",
6210                            !cast<Instruction>(NAME#"i64"),
6211                            FPR64, V128, VectorIndexD>;
6212 }
6213
6214 //----------------------------------------------------------------------------
6215 // AdvSIMD modified immediate instructions
6216 //----------------------------------------------------------------------------
6217
6218 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
6219                           string asm, string op_string,
6220                           string cstr, list<dag> pattern>
6221   : I<oops, iops, asm, op_string, cstr, pattern>,
6222     Sched<[WriteV]> {
6223   bits<5> Rd;
6224   bits<8> imm8;
6225   let Inst{31}    = 0;
6226   let Inst{30}    = Q;
6227   let Inst{29}    = op;
6228   let Inst{28-19} = 0b0111100000;
6229   let Inst{18-16} = imm8{7-5};
6230   let Inst{11-10} = 0b01;
6231   let Inst{9-5}   = imm8{4-0};
6232   let Inst{4-0}   = Rd;
6233 }
6234
6235 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
6236                                 Operand immtype, dag opt_shift_iop,
6237                                 string opt_shift, string asm, string kind,
6238                                 list<dag> pattern>
6239   : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
6240                         !con((ins immtype:$imm8), opt_shift_iop), asm,
6241                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
6242                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6243                         "", pattern> {
6244   let DecoderMethod = "DecodeModImmInstruction";
6245 }
6246
6247 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6248                                 Operand immtype, dag opt_shift_iop,
6249                                 string opt_shift, string asm, string kind,
6250                                 list<dag> pattern>
6251   : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
6252                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6253                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6254                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6255                         "$Rd = $dst", pattern> {
6256   let DecoderMethod = "DecodeModImmTiedInstruction";
6257 }
6258
6259 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6260                                      RegisterOperand vectype, string asm,
6261                                      string kind, list<dag> pattern>
6262   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6263                               (ins logical_vec_shift:$shift),
6264                               "$shift", asm, kind, pattern> {
6265   bits<2> shift;
6266   let Inst{15}    = b15_b12{1};
6267   let Inst{14-13} = shift;
6268   let Inst{12}    = b15_b12{0};
6269 }
6270
6271 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6272                                      RegisterOperand vectype, string asm,
6273                                      string kind, list<dag> pattern>
6274   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6275                               (ins logical_vec_shift:$shift),
6276                               "$shift", asm, kind, pattern> {
6277   bits<2> shift;
6278   let Inst{15}    = b15_b12{1};
6279   let Inst{14-13} = shift;
6280   let Inst{12}    = b15_b12{0};
6281 }
6282
6283
6284 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6285                                          RegisterOperand vectype, string asm,
6286                                          string kind, list<dag> pattern>
6287   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6288                               (ins logical_vec_hw_shift:$shift),
6289                               "$shift", asm, kind, pattern> {
6290   bits<2> shift;
6291   let Inst{15} = b15_b12{1};
6292   let Inst{14} = 0;
6293   let Inst{13} = shift{0};
6294   let Inst{12} = b15_b12{0};
6295 }
6296
6297 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6298                                          RegisterOperand vectype, string asm,
6299                                          string kind, list<dag> pattern>
6300   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6301                               (ins logical_vec_hw_shift:$shift),
6302                               "$shift", asm, kind, pattern> {
6303   bits<2> shift;
6304   let Inst{15} = b15_b12{1};
6305   let Inst{14} = 0;
6306   let Inst{13} = shift{0};
6307   let Inst{12} = b15_b12{0};
6308 }
6309
6310 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6311                                       string asm> {
6312   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6313                                                  asm, ".4h", []>;
6314   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6315                                                  asm, ".8h", []>;
6316
6317   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6318                                              asm, ".2s", []>;
6319   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6320                                              asm, ".4s", []>;
6321 }
6322
6323 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6324                                       bits<2> w_cmode, string asm,
6325                                       SDNode OpNode> {
6326   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6327                                                  asm, ".4h",
6328              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6329                                              imm0_255:$imm8,
6330                                              (i32 imm:$shift)))]>;
6331   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6332                                                  asm, ".8h",
6333              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6334                                               imm0_255:$imm8,
6335                                               (i32 imm:$shift)))]>;
6336
6337   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6338                                              asm, ".2s",
6339              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6340                                              imm0_255:$imm8,
6341                                              (i32 imm:$shift)))]>;
6342   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6343                                              asm, ".4s",
6344              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6345                                               imm0_255:$imm8,
6346                                               (i32 imm:$shift)))]>;
6347 }
6348
6349 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6350                              RegisterOperand vectype, string asm,
6351                              string kind, list<dag> pattern>
6352   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6353                               (ins move_vec_shift:$shift),
6354                               "$shift", asm, kind, pattern> {
6355   bits<1> shift;
6356   let Inst{15-13} = cmode{3-1};
6357   let Inst{12}    = shift;
6358 }
6359
6360 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
6361                                    RegisterOperand vectype,
6362                                    Operand imm_type, string asm,
6363                                    string kind, list<dag> pattern>
6364   : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
6365                               asm, kind, pattern> {
6366   let Inst{15-12} = cmode;
6367 }
6368
6369 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6370                                    list<dag> pattern>
6371   : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6372                         "\t$Rd, $imm8", "", pattern> {
6373   let Inst{15-12} = cmode;
6374   let DecoderMethod = "DecodeModImmInstruction";
6375 }
6376
6377 //----------------------------------------------------------------------------
6378 // AdvSIMD indexed element
6379 //----------------------------------------------------------------------------
6380
6381 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6382 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6383                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6384                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6385                       string apple_kind, string dst_kind, string lhs_kind,
6386                       string rhs_kind, list<dag> pattern>
6387   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6388       asm,
6389       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6390       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6391     Sched<[WriteV]> {
6392   bits<5> Rd;
6393   bits<5> Rn;
6394   bits<5> Rm;
6395
6396   let Inst{31}    = 0;
6397   let Inst{30}    = Q;
6398   let Inst{29}    = U;
6399   let Inst{28}    = Scalar;
6400   let Inst{27-24} = 0b1111;
6401   let Inst{23-22} = size;
6402   // Bit 21 must be set by the derived class.
6403   let Inst{20-16} = Rm;
6404   let Inst{15-12} = opc;
6405   // Bit 11 must be set by the derived class.
6406   let Inst{10}    = 0;
6407   let Inst{9-5}   = Rn;
6408   let Inst{4-0}   = Rd;
6409 }
6410
6411 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6412 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6413                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6414                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6415                       string apple_kind, string dst_kind, string lhs_kind,
6416                       string rhs_kind, list<dag> pattern>
6417   : I<(outs dst_reg:$dst),
6418       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6419       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6420       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6421     Sched<[WriteV]> {
6422   bits<5> Rd;
6423   bits<5> Rn;
6424   bits<5> Rm;
6425
6426   let Inst{31}    = 0;
6427   let Inst{30}    = Q;
6428   let Inst{29}    = U;
6429   let Inst{28}    = Scalar;
6430   let Inst{27-24} = 0b1111;
6431   let Inst{23-22} = size;
6432   // Bit 21 must be set by the derived class.
6433   let Inst{20-16} = Rm;
6434   let Inst{15-12} = opc;
6435   // Bit 11 must be set by the derived class.
6436   let Inst{10}    = 0;
6437   let Inst{9-5}   = Rn;
6438   let Inst{4-0}   = Rd;
6439 }
6440
6441 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
6442                            SDPatternOperator OpNode> {
6443   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6444                                       V64, V64,
6445                                       V128, VectorIndexS,
6446                                       asm, ".2s", ".2s", ".2s", ".s",
6447     [(set (v2f32 V64:$Rd),
6448         (OpNode (v2f32 V64:$Rn),
6449          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6450     bits<2> idx;
6451     let Inst{11} = idx{1};
6452     let Inst{21} = idx{0};
6453   }
6454
6455   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6456                                       V128, V128,
6457                                       V128, VectorIndexS,
6458                                       asm, ".4s", ".4s", ".4s", ".s",
6459     [(set (v4f32 V128:$Rd),
6460         (OpNode (v4f32 V128:$Rn),
6461          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6462     bits<2> idx;
6463     let Inst{11} = idx{1};
6464     let Inst{21} = idx{0};
6465   }
6466
6467   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6468                                       V128, V128,
6469                                       V128, VectorIndexD,
6470                                       asm, ".2d", ".2d", ".2d", ".d",
6471     [(set (v2f64 V128:$Rd),
6472         (OpNode (v2f64 V128:$Rn),
6473          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6474     bits<1> idx;
6475     let Inst{11} = idx{0};
6476     let Inst{21} = 0;
6477   }
6478
6479   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6480                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6481                                       asm, ".s", "", "", ".s",
6482     [(set (f32 FPR32Op:$Rd),
6483           (OpNode (f32 FPR32Op:$Rn),
6484                   (f32 (vector_extract (v4f32 V128:$Rm),
6485                                        VectorIndexS:$idx))))]> {
6486     bits<2> idx;
6487     let Inst{11} = idx{1};
6488     let Inst{21} = idx{0};
6489   }
6490
6491   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6492                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6493                                       asm, ".d", "", "", ".d",
6494     [(set (f64 FPR64Op:$Rd),
6495           (OpNode (f64 FPR64Op:$Rn),
6496                   (f64 (vector_extract (v2f64 V128:$Rm),
6497                                        VectorIndexD:$idx))))]> {
6498     bits<1> idx;
6499     let Inst{11} = idx{0};
6500     let Inst{21} = 0;
6501   }
6502 }
6503
6504 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6505   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6506   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6507                            (AArch64duplane32 (v4f32 V128:$Rm),
6508                                            VectorIndexS:$idx))),
6509             (!cast<Instruction>(INST # v2i32_indexed)
6510                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6511   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6512                            (AArch64dup (f32 FPR32Op:$Rm)))),
6513             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6514                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6515
6516
6517   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6518   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6519                            (AArch64duplane32 (v4f32 V128:$Rm),
6520                                            VectorIndexS:$idx))),
6521             (!cast<Instruction>(INST # "v4i32_indexed")
6522                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6523   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6524                            (AArch64dup (f32 FPR32Op:$Rm)))),
6525             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6526                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6527
6528   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6529   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6530                            (AArch64duplane64 (v2f64 V128:$Rm),
6531                                            VectorIndexD:$idx))),
6532             (!cast<Instruction>(INST # "v2i64_indexed")
6533                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6534   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6535                            (AArch64dup (f64 FPR64Op:$Rm)))),
6536             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6537                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6538
6539   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6540   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6541                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6542             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6543                 V128:$Rm, VectorIndexS:$idx)>;
6544   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6545                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6546             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6547                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6548
6549   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6550   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6551                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6552             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6553                 V128:$Rm, VectorIndexD:$idx)>;
6554 }
6555
6556 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6557   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6558                                           V128, VectorIndexS,
6559                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6560     bits<2> idx;
6561     let Inst{11} = idx{1};
6562     let Inst{21} = idx{0};
6563   }
6564
6565   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6566                                       V128, V128,
6567                                       V128, VectorIndexS,
6568                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6569     bits<2> idx;
6570     let Inst{11} = idx{1};
6571     let Inst{21} = idx{0};
6572   }
6573
6574   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6575                                       V128, V128,
6576                                       V128, VectorIndexD,
6577                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6578     bits<1> idx;
6579     let Inst{11} = idx{0};
6580     let Inst{21} = 0;
6581   }
6582
6583
6584   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6585                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6586                                       asm, ".s", "", "", ".s", []> {
6587     bits<2> idx;
6588     let Inst{11} = idx{1};
6589     let Inst{21} = idx{0};
6590   }
6591
6592   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6593                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6594                                       asm, ".d", "", "", ".d", []> {
6595     bits<1> idx;
6596     let Inst{11} = idx{0};
6597     let Inst{21} = 0;
6598   }
6599 }
6600
6601 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6602                          SDPatternOperator OpNode> {
6603   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6604                                       V128_lo, VectorIndexH,
6605                                       asm, ".4h", ".4h", ".4h", ".h",
6606     [(set (v4i16 V64:$Rd),
6607         (OpNode (v4i16 V64:$Rn),
6608          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6609     bits<3> idx;
6610     let Inst{11} = idx{2};
6611     let Inst{21} = idx{1};
6612     let Inst{20} = idx{0};
6613   }
6614
6615   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6616                                       V128, V128,
6617                                       V128_lo, VectorIndexH,
6618                                       asm, ".8h", ".8h", ".8h", ".h",
6619     [(set (v8i16 V128:$Rd),
6620        (OpNode (v8i16 V128:$Rn),
6621          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6622     bits<3> idx;
6623     let Inst{11} = idx{2};
6624     let Inst{21} = idx{1};
6625     let Inst{20} = idx{0};
6626   }
6627
6628   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6629                                       V64, V64,
6630                                       V128, VectorIndexS,
6631                                       asm, ".2s", ".2s", ".2s",  ".s",
6632     [(set (v2i32 V64:$Rd),
6633        (OpNode (v2i32 V64:$Rn),
6634           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6635     bits<2> idx;
6636     let Inst{11} = idx{1};
6637     let Inst{21} = idx{0};
6638   }
6639
6640   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6641                                       V128, V128,
6642                                       V128, VectorIndexS,
6643                                       asm, ".4s", ".4s", ".4s", ".s",
6644     [(set (v4i32 V128:$Rd),
6645        (OpNode (v4i32 V128:$Rn),
6646           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6647     bits<2> idx;
6648     let Inst{11} = idx{1};
6649     let Inst{21} = idx{0};
6650   }
6651
6652   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6653                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6654                                       asm, ".h", "", "", ".h", []> {
6655     bits<3> idx;
6656     let Inst{11} = idx{2};
6657     let Inst{21} = idx{1};
6658     let Inst{20} = idx{0};
6659   }
6660
6661   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6662                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6663                                       asm, ".s", "", "", ".s",
6664       [(set (i32 FPR32Op:$Rd),
6665             (OpNode FPR32Op:$Rn,
6666                     (i32 (vector_extract (v4i32 V128:$Rm),
6667                                          VectorIndexS:$idx))))]> {
6668     bits<2> idx;
6669     let Inst{11} = idx{1};
6670     let Inst{21} = idx{0};
6671   }
6672 }
6673
6674 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6675                                SDPatternOperator OpNode> {
6676   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6677                                       V64, V64,
6678                                       V128_lo, VectorIndexH,
6679                                       asm, ".4h", ".4h", ".4h", ".h",
6680     [(set (v4i16 V64:$Rd),
6681         (OpNode (v4i16 V64:$Rn),
6682          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6683     bits<3> idx;
6684     let Inst{11} = idx{2};
6685     let Inst{21} = idx{1};
6686     let Inst{20} = idx{0};
6687   }
6688
6689   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6690                                       V128, V128,
6691                                       V128_lo, VectorIndexH,
6692                                       asm, ".8h", ".8h", ".8h", ".h",
6693     [(set (v8i16 V128:$Rd),
6694        (OpNode (v8i16 V128:$Rn),
6695          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6696     bits<3> idx;
6697     let Inst{11} = idx{2};
6698     let Inst{21} = idx{1};
6699     let Inst{20} = idx{0};
6700   }
6701
6702   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6703                                       V64, V64,
6704                                       V128, VectorIndexS,
6705                                       asm, ".2s", ".2s", ".2s", ".s",
6706     [(set (v2i32 V64:$Rd),
6707        (OpNode (v2i32 V64:$Rn),
6708           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6709     bits<2> idx;
6710     let Inst{11} = idx{1};
6711     let Inst{21} = idx{0};
6712   }
6713
6714   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6715                                       V128, V128,
6716                                       V128, VectorIndexS,
6717                                       asm, ".4s", ".4s", ".4s", ".s",
6718     [(set (v4i32 V128:$Rd),
6719        (OpNode (v4i32 V128:$Rn),
6720           (v4i32 (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
6727 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6728                                    SDPatternOperator OpNode> {
6729   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6730                                           V128_lo, VectorIndexH,
6731                                           asm, ".4h", ".4h", ".4h", ".h",
6732     [(set (v4i16 V64:$dst),
6733         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6734          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6735     bits<3> idx;
6736     let Inst{11} = idx{2};
6737     let Inst{21} = idx{1};
6738     let Inst{20} = idx{0};
6739   }
6740
6741   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6742                                       V128, V128,
6743                                       V128_lo, VectorIndexH,
6744                                       asm, ".8h", ".8h", ".8h", ".h",
6745     [(set (v8i16 V128:$dst),
6746        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6747          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6748     bits<3> idx;
6749     let Inst{11} = idx{2};
6750     let Inst{21} = idx{1};
6751     let Inst{20} = idx{0};
6752   }
6753
6754   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6755                                       V64, V64,
6756                                       V128, VectorIndexS,
6757                                       asm, ".2s", ".2s", ".2s", ".s",
6758     [(set (v2i32 V64:$dst),
6759        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6760           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6761     bits<2> idx;
6762     let Inst{11} = idx{1};
6763     let Inst{21} = idx{0};
6764   }
6765
6766   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6767                                       V128, V128,
6768                                       V128, VectorIndexS,
6769                                       asm, ".4s", ".4s", ".4s", ".s",
6770     [(set (v4i32 V128:$dst),
6771        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6772           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6773     bits<2> idx;
6774     let Inst{11} = idx{1};
6775     let Inst{21} = idx{0};
6776   }
6777 }
6778
6779 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6780                              SDPatternOperator OpNode> {
6781   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6782                                       V128, V64,
6783                                       V128_lo, VectorIndexH,
6784                                       asm, ".4s", ".4s", ".4h", ".h",
6785     [(set (v4i32 V128:$Rd),
6786         (OpNode (v4i16 V64:$Rn),
6787          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6788     bits<3> idx;
6789     let Inst{11} = idx{2};
6790     let Inst{21} = idx{1};
6791     let Inst{20} = idx{0};
6792   }
6793
6794   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6795                                       V128, V128,
6796                                       V128_lo, VectorIndexH,
6797                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6798     [(set (v4i32 V128:$Rd),
6799           (OpNode (extract_high_v8i16 V128:$Rn),
6800                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6801                                                       VectorIndexH:$idx))))]> {
6802
6803     bits<3> idx;
6804     let Inst{11} = idx{2};
6805     let Inst{21} = idx{1};
6806     let Inst{20} = idx{0};
6807   }
6808
6809   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6810                                       V128, V64,
6811                                       V128, VectorIndexS,
6812                                       asm, ".2d", ".2d", ".2s", ".s",
6813     [(set (v2i64 V128:$Rd),
6814         (OpNode (v2i32 V64:$Rn),
6815          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6816     bits<2> idx;
6817     let Inst{11} = idx{1};
6818     let Inst{21} = idx{0};
6819   }
6820
6821   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6822                                       V128, V128,
6823                                       V128, VectorIndexS,
6824                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6825     [(set (v2i64 V128:$Rd),
6826           (OpNode (extract_high_v4i32 V128:$Rn),
6827                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
6828                                                       VectorIndexS:$idx))))]> {
6829     bits<2> idx;
6830     let Inst{11} = idx{1};
6831     let Inst{21} = idx{0};
6832   }
6833
6834   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6835                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6836                                       asm, ".h", "", "", ".h", []> {
6837     bits<3> idx;
6838     let Inst{11} = idx{2};
6839     let Inst{21} = idx{1};
6840     let Inst{20} = idx{0};
6841   }
6842
6843   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6844                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6845                                       asm, ".s", "", "", ".s", []> {
6846     bits<2> idx;
6847     let Inst{11} = idx{1};
6848     let Inst{21} = idx{0};
6849   }
6850 }
6851
6852 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6853                                        SDPatternOperator Accum> {
6854   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6855                                       V128, V64,
6856                                       V128_lo, VectorIndexH,
6857                                       asm, ".4s", ".4s", ".4h", ".h",
6858     [(set (v4i32 V128:$dst),
6859           (Accum (v4i32 V128:$Rd),
6860                  (v4i32 (int_aarch64_neon_sqdmull
6861                              (v4i16 V64:$Rn),
6862                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6863                                                     VectorIndexH:$idx))))))]> {
6864     bits<3> idx;
6865     let Inst{11} = idx{2};
6866     let Inst{21} = idx{1};
6867     let Inst{20} = idx{0};
6868   }
6869
6870   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6871   // intermediate EXTRACT_SUBREG would be untyped.
6872   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6873                 (i32 (vector_extract (v4i32
6874                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6875                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6876                                                     VectorIndexH:$idx)))),
6877                          (i64 0))))),
6878             (EXTRACT_SUBREG
6879                 (!cast<Instruction>(NAME # v4i16_indexed)
6880                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6881                     V128_lo:$Rm, VectorIndexH:$idx),
6882                 ssub)>;
6883
6884   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6885                                       V128, V128,
6886                                       V128_lo, VectorIndexH,
6887                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6888     [(set (v4i32 V128:$dst),
6889           (Accum (v4i32 V128:$Rd),
6890                  (v4i32 (int_aarch64_neon_sqdmull
6891                             (extract_high_v8i16 V128:$Rn),
6892                             (extract_high_v8i16
6893                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6894                                                 VectorIndexH:$idx))))))]> {
6895     bits<3> idx;
6896     let Inst{11} = idx{2};
6897     let Inst{21} = idx{1};
6898     let Inst{20} = idx{0};
6899   }
6900
6901   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6902                                       V128, V64,
6903                                       V128, VectorIndexS,
6904                                       asm, ".2d", ".2d", ".2s", ".s",
6905     [(set (v2i64 V128:$dst),
6906         (Accum (v2i64 V128:$Rd),
6907                (v2i64 (int_aarch64_neon_sqdmull
6908                           (v2i32 V64:$Rn),
6909                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
6910                                                  VectorIndexS:$idx))))))]> {
6911     bits<2> idx;
6912     let Inst{11} = idx{1};
6913     let Inst{21} = idx{0};
6914   }
6915
6916   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6917                                       V128, V128,
6918                                       V128, VectorIndexS,
6919                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6920     [(set (v2i64 V128:$dst),
6921           (Accum (v2i64 V128:$Rd),
6922                  (v2i64 (int_aarch64_neon_sqdmull
6923                             (extract_high_v4i32 V128:$Rn),
6924                             (extract_high_v4i32
6925                                 (AArch64duplane32 (v4i32 V128:$Rm),
6926                                                 VectorIndexS:$idx))))))]> {
6927     bits<2> idx;
6928     let Inst{11} = idx{1};
6929     let Inst{21} = idx{0};
6930   }
6931
6932   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6933                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6934                                       asm, ".h", "", "", ".h", []> {
6935     bits<3> idx;
6936     let Inst{11} = idx{2};
6937     let Inst{21} = idx{1};
6938     let Inst{20} = idx{0};
6939   }
6940
6941
6942   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6943                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6944                                       asm, ".s", "", "", ".s",
6945     [(set (i64 FPR64Op:$dst),
6946           (Accum (i64 FPR64Op:$Rd),
6947                  (i64 (int_aarch64_neon_sqdmulls_scalar
6948                             (i32 FPR32Op:$Rn),
6949                             (i32 (vector_extract (v4i32 V128:$Rm),
6950                                                  VectorIndexS:$idx))))))]> {
6951
6952     bits<2> idx;
6953     let Inst{11} = idx{1};
6954     let Inst{21} = idx{0};
6955   }
6956 }
6957
6958 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6959                                    SDPatternOperator OpNode> {
6960   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6961   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6962                                       V128, V64,
6963                                       V128_lo, VectorIndexH,
6964                                       asm, ".4s", ".4s", ".4h", ".h",
6965     [(set (v4i32 V128:$Rd),
6966         (OpNode (v4i16 V64:$Rn),
6967          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6968     bits<3> idx;
6969     let Inst{11} = idx{2};
6970     let Inst{21} = idx{1};
6971     let Inst{20} = idx{0};
6972   }
6973
6974   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6975                                       V128, V128,
6976                                       V128_lo, VectorIndexH,
6977                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6978     [(set (v4i32 V128:$Rd),
6979           (OpNode (extract_high_v8i16 V128:$Rn),
6980                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6981                                                       VectorIndexH:$idx))))]> {
6982
6983     bits<3> idx;
6984     let Inst{11} = idx{2};
6985     let Inst{21} = idx{1};
6986     let Inst{20} = idx{0};
6987   }
6988
6989   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6990                                       V128, V64,
6991                                       V128, VectorIndexS,
6992                                       asm, ".2d", ".2d", ".2s", ".s",
6993     [(set (v2i64 V128:$Rd),
6994         (OpNode (v2i32 V64:$Rn),
6995          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6996     bits<2> idx;
6997     let Inst{11} = idx{1};
6998     let Inst{21} = idx{0};
6999   }
7000
7001   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7002                                       V128, V128,
7003                                       V128, VectorIndexS,
7004                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7005     [(set (v2i64 V128:$Rd),
7006           (OpNode (extract_high_v4i32 V128:$Rn),
7007                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7008                                                       VectorIndexS:$idx))))]> {
7009     bits<2> idx;
7010     let Inst{11} = idx{1};
7011     let Inst{21} = idx{0};
7012   }
7013   }
7014 }
7015
7016 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7017                                        SDPatternOperator OpNode> {
7018   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7019   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7020                                       V128, V64,
7021                                       V128_lo, VectorIndexH,
7022                                       asm, ".4s", ".4s", ".4h", ".h",
7023     [(set (v4i32 V128:$dst),
7024         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7025          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7026     bits<3> idx;
7027     let Inst{11} = idx{2};
7028     let Inst{21} = idx{1};
7029     let Inst{20} = idx{0};
7030   }
7031
7032   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7033                                       V128, V128,
7034                                       V128_lo, VectorIndexH,
7035                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7036     [(set (v4i32 V128:$dst),
7037           (OpNode (v4i32 V128:$Rd),
7038                   (extract_high_v8i16 V128:$Rn),
7039                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7040                                                       VectorIndexH:$idx))))]> {
7041     bits<3> idx;
7042     let Inst{11} = idx{2};
7043     let Inst{21} = idx{1};
7044     let Inst{20} = idx{0};
7045   }
7046
7047   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7048                                       V128, V64,
7049                                       V128, VectorIndexS,
7050                                       asm, ".2d", ".2d", ".2s", ".s",
7051     [(set (v2i64 V128:$dst),
7052         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7053          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7054     bits<2> idx;
7055     let Inst{11} = idx{1};
7056     let Inst{21} = idx{0};
7057   }
7058
7059   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7060                                       V128, V128,
7061                                       V128, VectorIndexS,
7062                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7063     [(set (v2i64 V128:$dst),
7064           (OpNode (v2i64 V128:$Rd),
7065                   (extract_high_v4i32 V128:$Rn),
7066                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7067                                                       VectorIndexS:$idx))))]> {
7068     bits<2> idx;
7069     let Inst{11} = idx{1};
7070     let Inst{21} = idx{0};
7071   }
7072   }
7073 }
7074
7075 //----------------------------------------------------------------------------
7076 // AdvSIMD scalar shift by immediate
7077 //----------------------------------------------------------------------------
7078
7079 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7080 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7081                      RegisterClass regtype1, RegisterClass regtype2,
7082                      Operand immtype, string asm, list<dag> pattern>
7083   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7084       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7085     Sched<[WriteV]> {
7086   bits<5> Rd;
7087   bits<5> Rn;
7088   bits<7> imm;
7089   let Inst{31-30} = 0b01;
7090   let Inst{29}    = U;
7091   let Inst{28-23} = 0b111110;
7092   let Inst{22-16} = fixed_imm;
7093   let Inst{15-11} = opc;
7094   let Inst{10}    = 1;
7095   let Inst{9-5} = Rn;
7096   let Inst{4-0} = Rd;
7097 }
7098
7099 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7100 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7101                      RegisterClass regtype1, RegisterClass regtype2,
7102                      Operand immtype, string asm, list<dag> pattern>
7103   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7104       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7105     Sched<[WriteV]> {
7106   bits<5> Rd;
7107   bits<5> Rn;
7108   bits<7> imm;
7109   let Inst{31-30} = 0b01;
7110   let Inst{29}    = U;
7111   let Inst{28-23} = 0b111110;
7112   let Inst{22-16} = fixed_imm;
7113   let Inst{15-11} = opc;
7114   let Inst{10}    = 1;
7115   let Inst{9-5} = Rn;
7116   let Inst{4-0} = Rd;
7117 }
7118
7119
7120 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
7121   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7122                               FPR32, FPR32, vecshiftR32, asm, []> {
7123     let Inst{20-16} = imm{4-0};
7124   }
7125
7126   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7127                               FPR64, FPR64, vecshiftR64, asm, []> {
7128     let Inst{21-16} = imm{5-0};
7129   }
7130 }
7131
7132 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7133                              SDPatternOperator OpNode> {
7134   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7135                               FPR64, FPR64, vecshiftR64, asm,
7136   [(set (i64 FPR64:$Rd),
7137      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7138     let Inst{21-16} = imm{5-0};
7139   }
7140
7141   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7142             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7143 }
7144
7145 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7146                                  SDPatternOperator OpNode = null_frag> {
7147   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7148                               FPR64, FPR64, vecshiftR64, asm,
7149   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7150                                                    (i32 vecshiftR64:$imm)))]> {
7151     let Inst{21-16} = imm{5-0};
7152   }
7153
7154   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7155                            (i32 vecshiftR64:$imm))),
7156             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7157                                             vecshiftR64:$imm)>;
7158 }
7159
7160 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7161                              SDPatternOperator OpNode> {
7162   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7163                               FPR64, FPR64, vecshiftL64, asm,
7164     [(set (v1i64 FPR64:$Rd),
7165        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7166     let Inst{21-16} = imm{5-0};
7167   }
7168 }
7169
7170 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7171 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7172   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7173                               FPR64, FPR64, vecshiftL64, asm, []> {
7174     let Inst{21-16} = imm{5-0};
7175   }
7176 }
7177
7178 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7179 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7180                                SDPatternOperator OpNode = null_frag> {
7181   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7182                               FPR8, FPR16, vecshiftR8, asm, []> {
7183     let Inst{18-16} = imm{2-0};
7184   }
7185
7186   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7187                               FPR16, FPR32, vecshiftR16, asm, []> {
7188     let Inst{19-16} = imm{3-0};
7189   }
7190
7191   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7192                               FPR32, FPR64, vecshiftR32, asm,
7193     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7194     let Inst{20-16} = imm{4-0};
7195   }
7196 }
7197
7198 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7199                                 SDPatternOperator OpNode> {
7200   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7201                               FPR8, FPR8, vecshiftL8, asm, []> {
7202     let Inst{18-16} = imm{2-0};
7203   }
7204
7205   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7206                               FPR16, FPR16, vecshiftL16, asm, []> {
7207     let Inst{19-16} = imm{3-0};
7208   }
7209
7210   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7211                               FPR32, FPR32, vecshiftL32, asm,
7212     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7213     let Inst{20-16} = imm{4-0};
7214   }
7215
7216   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7217                               FPR64, FPR64, vecshiftL64, asm,
7218     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7219     let Inst{21-16} = imm{5-0};
7220   }
7221
7222   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7223             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7224 }
7225
7226 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7227   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7228                               FPR8, FPR8, vecshiftR8, asm, []> {
7229     let Inst{18-16} = imm{2-0};
7230   }
7231
7232   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7233                               FPR16, FPR16, vecshiftR16, asm, []> {
7234     let Inst{19-16} = imm{3-0};
7235   }
7236
7237   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7238                               FPR32, FPR32, vecshiftR32, asm, []> {
7239     let Inst{20-16} = imm{4-0};
7240   }
7241
7242   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7243                               FPR64, FPR64, vecshiftR64, asm, []> {
7244     let Inst{21-16} = imm{5-0};
7245   }
7246 }
7247
7248 //----------------------------------------------------------------------------
7249 // AdvSIMD vector x indexed element
7250 //----------------------------------------------------------------------------
7251
7252 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7253 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7254                      RegisterOperand dst_reg, RegisterOperand src_reg,
7255                      Operand immtype,
7256                      string asm, string dst_kind, string src_kind,
7257                      list<dag> pattern>
7258   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7259       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7260            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7261     Sched<[WriteV]> {
7262   bits<5> Rd;
7263   bits<5> Rn;
7264   let Inst{31}    = 0;
7265   let Inst{30}    = Q;
7266   let Inst{29}    = U;
7267   let Inst{28-23} = 0b011110;
7268   let Inst{22-16} = fixed_imm;
7269   let Inst{15-11} = opc;
7270   let Inst{10}    = 1;
7271   let Inst{9-5}   = Rn;
7272   let Inst{4-0}   = Rd;
7273 }
7274
7275 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7276 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7277                      RegisterOperand vectype1, RegisterOperand vectype2,
7278                      Operand immtype,
7279                      string asm, string dst_kind, string src_kind,
7280                      list<dag> pattern>
7281   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7282       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7283            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7284     Sched<[WriteV]> {
7285   bits<5> Rd;
7286   bits<5> Rn;
7287   let Inst{31}    = 0;
7288   let Inst{30}    = Q;
7289   let Inst{29}    = U;
7290   let Inst{28-23} = 0b011110;
7291   let Inst{22-16} = fixed_imm;
7292   let Inst{15-11} = opc;
7293   let Inst{10}    = 1;
7294   let Inst{9-5}   = Rn;
7295   let Inst{4-0}   = Rd;
7296 }
7297
7298 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7299                               Intrinsic OpNode> {
7300   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7301                                   V64, V64, vecshiftR32,
7302                                   asm, ".2s", ".2s",
7303       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
7304     bits<5> imm;
7305     let Inst{20-16} = imm;
7306   }
7307
7308   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7309                                   V128, V128, vecshiftR32,
7310                                   asm, ".4s", ".4s",
7311       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7312     bits<5> imm;
7313     let Inst{20-16} = imm;
7314   }
7315
7316   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7317                                   V128, V128, vecshiftR64,
7318                                   asm, ".2d", ".2d",
7319       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7320     bits<6> imm;
7321     let Inst{21-16} = imm;
7322   }
7323 }
7324
7325 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
7326                                   Intrinsic OpNode> {
7327   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7328                                   V64, V64, vecshiftR32,
7329                                   asm, ".2s", ".2s",
7330       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7331     bits<5> imm;
7332     let Inst{20-16} = imm;
7333   }
7334
7335   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7336                                   V128, V128, vecshiftR32,
7337                                   asm, ".4s", ".4s",
7338       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7339     bits<5> imm;
7340     let Inst{20-16} = imm;
7341   }
7342
7343   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7344                                   V128, V128, vecshiftR64,
7345                                   asm, ".2d", ".2d",
7346       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7347     bits<6> imm;
7348     let Inst{21-16} = imm;
7349   }
7350 }
7351
7352 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7353                                      SDPatternOperator OpNode> {
7354   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7355                                   V64, V128, vecshiftR16Narrow,
7356                                   asm, ".8b", ".8h",
7357       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7358     bits<3> imm;
7359     let Inst{18-16} = imm;
7360   }
7361
7362   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7363                                   V128, V128, vecshiftR16Narrow,
7364                                   asm#"2", ".16b", ".8h", []> {
7365     bits<3> imm;
7366     let Inst{18-16} = imm;
7367     let hasSideEffects = 0;
7368   }
7369
7370   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7371                                   V64, V128, vecshiftR32Narrow,
7372                                   asm, ".4h", ".4s",
7373       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7374     bits<4> imm;
7375     let Inst{19-16} = imm;
7376   }
7377
7378   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7379                                   V128, V128, vecshiftR32Narrow,
7380                                   asm#"2", ".8h", ".4s", []> {
7381     bits<4> imm;
7382     let Inst{19-16} = imm;
7383     let hasSideEffects = 0;
7384   }
7385
7386   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7387                                   V64, V128, vecshiftR64Narrow,
7388                                   asm, ".2s", ".2d",
7389       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7390     bits<5> imm;
7391     let Inst{20-16} = imm;
7392   }
7393
7394   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7395                                   V128, V128, vecshiftR64Narrow,
7396                                   asm#"2", ".4s", ".2d", []> {
7397     bits<5> imm;
7398     let Inst{20-16} = imm;
7399     let hasSideEffects = 0;
7400   }
7401
7402   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7403   // themselves, so put them here instead.
7404
7405   // Patterns involving what's effectively an insert high and a normal
7406   // intrinsic, represented by CONCAT_VECTORS.
7407   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7408                                                    vecshiftR16Narrow:$imm)),
7409             (!cast<Instruction>(NAME # "v16i8_shift")
7410                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7411                 V128:$Rn, vecshiftR16Narrow:$imm)>;
7412   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7413                                                      vecshiftR32Narrow:$imm)),
7414             (!cast<Instruction>(NAME # "v8i16_shift")
7415                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7416                 V128:$Rn, vecshiftR32Narrow:$imm)>;
7417   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7418                                                      vecshiftR64Narrow:$imm)),
7419             (!cast<Instruction>(NAME # "v4i32_shift")
7420                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7421                 V128:$Rn, vecshiftR64Narrow:$imm)>;
7422 }
7423
7424 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7425                                 SDPatternOperator OpNode> {
7426   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7427                                   V64, V64, vecshiftL8,
7428                                   asm, ".8b", ".8b",
7429                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7430                        (i32 vecshiftL8:$imm)))]> {
7431     bits<3> imm;
7432     let Inst{18-16} = imm;
7433   }
7434
7435   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7436                                   V128, V128, vecshiftL8,
7437                                   asm, ".16b", ".16b",
7438              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7439                    (i32 vecshiftL8:$imm)))]> {
7440     bits<3> imm;
7441     let Inst{18-16} = imm;
7442   }
7443
7444   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7445                                   V64, V64, vecshiftL16,
7446                                   asm, ".4h", ".4h",
7447               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7448                     (i32 vecshiftL16:$imm)))]> {
7449     bits<4> imm;
7450     let Inst{19-16} = imm;
7451   }
7452
7453   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7454                                   V128, V128, vecshiftL16,
7455                                   asm, ".8h", ".8h",
7456             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7457                   (i32 vecshiftL16:$imm)))]> {
7458     bits<4> imm;
7459     let Inst{19-16} = imm;
7460   }
7461
7462   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7463                                   V64, V64, vecshiftL32,
7464                                   asm, ".2s", ".2s",
7465               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7466                     (i32 vecshiftL32:$imm)))]> {
7467     bits<5> imm;
7468     let Inst{20-16} = imm;
7469   }
7470
7471   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7472                                   V128, V128, vecshiftL32,
7473                                   asm, ".4s", ".4s",
7474             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7475                   (i32 vecshiftL32:$imm)))]> {
7476     bits<5> imm;
7477     let Inst{20-16} = imm;
7478   }
7479
7480   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7481                                   V128, V128, vecshiftL64,
7482                                   asm, ".2d", ".2d",
7483             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7484                   (i32 vecshiftL64:$imm)))]> {
7485     bits<6> imm;
7486     let Inst{21-16} = imm;
7487   }
7488 }
7489
7490 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7491                                 SDPatternOperator OpNode> {
7492   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7493                                   V64, V64, vecshiftR8,
7494                                   asm, ".8b", ".8b",
7495                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7496                        (i32 vecshiftR8:$imm)))]> {
7497     bits<3> imm;
7498     let Inst{18-16} = imm;
7499   }
7500
7501   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7502                                   V128, V128, vecshiftR8,
7503                                   asm, ".16b", ".16b",
7504              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7505                    (i32 vecshiftR8:$imm)))]> {
7506     bits<3> imm;
7507     let Inst{18-16} = imm;
7508   }
7509
7510   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7511                                   V64, V64, vecshiftR16,
7512                                   asm, ".4h", ".4h",
7513               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7514                     (i32 vecshiftR16:$imm)))]> {
7515     bits<4> imm;
7516     let Inst{19-16} = imm;
7517   }
7518
7519   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7520                                   V128, V128, vecshiftR16,
7521                                   asm, ".8h", ".8h",
7522             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7523                   (i32 vecshiftR16:$imm)))]> {
7524     bits<4> imm;
7525     let Inst{19-16} = imm;
7526   }
7527
7528   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7529                                   V64, V64, vecshiftR32,
7530                                   asm, ".2s", ".2s",
7531               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7532                     (i32 vecshiftR32:$imm)))]> {
7533     bits<5> imm;
7534     let Inst{20-16} = imm;
7535   }
7536
7537   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7538                                   V128, V128, vecshiftR32,
7539                                   asm, ".4s", ".4s",
7540             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7541                   (i32 vecshiftR32:$imm)))]> {
7542     bits<5> imm;
7543     let Inst{20-16} = imm;
7544   }
7545
7546   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7547                                   V128, V128, vecshiftR64,
7548                                   asm, ".2d", ".2d",
7549             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7550                   (i32 vecshiftR64:$imm)))]> {
7551     bits<6> imm;
7552     let Inst{21-16} = imm;
7553   }
7554 }
7555
7556 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7557 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7558                                     SDPatternOperator OpNode = null_frag> {
7559   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7560                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
7561                  [(set (v8i8 V64:$dst),
7562                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7563                            (i32 vecshiftR8:$imm)))]> {
7564     bits<3> imm;
7565     let Inst{18-16} = imm;
7566   }
7567
7568   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7569                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
7570              [(set (v16i8 V128:$dst),
7571                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7572                        (i32 vecshiftR8:$imm)))]> {
7573     bits<3> imm;
7574     let Inst{18-16} = imm;
7575   }
7576
7577   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7578                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
7579               [(set (v4i16 V64:$dst),
7580                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7581                         (i32 vecshiftR16:$imm)))]> {
7582     bits<4> imm;
7583     let Inst{19-16} = imm;
7584   }
7585
7586   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7587                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
7588             [(set (v8i16 V128:$dst),
7589               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7590                       (i32 vecshiftR16:$imm)))]> {
7591     bits<4> imm;
7592     let Inst{19-16} = imm;
7593   }
7594
7595   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7596                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
7597               [(set (v2i32 V64:$dst),
7598                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7599                         (i32 vecshiftR32:$imm)))]> {
7600     bits<5> imm;
7601     let Inst{20-16} = imm;
7602   }
7603
7604   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7605                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
7606             [(set (v4i32 V128:$dst),
7607               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7608                       (i32 vecshiftR32:$imm)))]> {
7609     bits<5> imm;
7610     let Inst{20-16} = imm;
7611   }
7612
7613   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7614                                   V128, V128, vecshiftR64,
7615                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7616               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7617                       (i32 vecshiftR64:$imm)))]> {
7618     bits<6> imm;
7619     let Inst{21-16} = imm;
7620   }
7621 }
7622
7623 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7624                                     SDPatternOperator OpNode = null_frag> {
7625   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7626                                   V64, V64, vecshiftL8,
7627                                   asm, ".8b", ".8b",
7628                     [(set (v8i8 V64:$dst),
7629                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7630                                   (i32 vecshiftL8:$imm)))]> {
7631     bits<3> imm;
7632     let Inst{18-16} = imm;
7633   }
7634
7635   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7636                                   V128, V128, vecshiftL8,
7637                                   asm, ".16b", ".16b",
7638                     [(set (v16i8 V128:$dst),
7639                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7640                                   (i32 vecshiftL8:$imm)))]> {
7641     bits<3> imm;
7642     let Inst{18-16} = imm;
7643   }
7644
7645   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7646                                   V64, V64, vecshiftL16,
7647                                   asm, ".4h", ".4h",
7648                     [(set (v4i16 V64:$dst),
7649                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7650                                    (i32 vecshiftL16:$imm)))]> {
7651     bits<4> imm;
7652     let Inst{19-16} = imm;
7653   }
7654
7655   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7656                                   V128, V128, vecshiftL16,
7657                                   asm, ".8h", ".8h",
7658                     [(set (v8i16 V128:$dst),
7659                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7660                                   (i32 vecshiftL16:$imm)))]> {
7661     bits<4> imm;
7662     let Inst{19-16} = imm;
7663   }
7664
7665   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7666                                   V64, V64, vecshiftL32,
7667                                   asm, ".2s", ".2s",
7668                     [(set (v2i32 V64:$dst),
7669                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7670                                   (i32 vecshiftL32:$imm)))]> {
7671     bits<5> imm;
7672     let Inst{20-16} = imm;
7673   }
7674
7675   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7676                                   V128, V128, vecshiftL32,
7677                                   asm, ".4s", ".4s",
7678                     [(set (v4i32 V128:$dst),
7679                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7680                                   (i32 vecshiftL32:$imm)))]> {
7681     bits<5> imm;
7682     let Inst{20-16} = imm;
7683   }
7684
7685   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7686                                   V128, V128, vecshiftL64,
7687                                   asm, ".2d", ".2d",
7688                     [(set (v2i64 V128:$dst),
7689                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7690                                   (i32 vecshiftL64:$imm)))]> {
7691     bits<6> imm;
7692     let Inst{21-16} = imm;
7693   }
7694 }
7695
7696 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7697                                    SDPatternOperator OpNode> {
7698   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7699                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
7700       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7701     bits<3> imm;
7702     let Inst{18-16} = imm;
7703   }
7704
7705   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7706                                   V128, V128, vecshiftL8,
7707                                   asm#"2", ".8h", ".16b",
7708       [(set (v8i16 V128:$Rd),
7709             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7710     bits<3> imm;
7711     let Inst{18-16} = imm;
7712   }
7713
7714   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7715                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
7716       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7717     bits<4> imm;
7718     let Inst{19-16} = imm;
7719   }
7720
7721   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7722                                   V128, V128, vecshiftL16,
7723                                   asm#"2", ".4s", ".8h",
7724       [(set (v4i32 V128:$Rd),
7725             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7726
7727     bits<4> imm;
7728     let Inst{19-16} = imm;
7729   }
7730
7731   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7732                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
7733       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7734     bits<5> imm;
7735     let Inst{20-16} = imm;
7736   }
7737
7738   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7739                                   V128, V128, vecshiftL32,
7740                                   asm#"2", ".2d", ".4s",
7741       [(set (v2i64 V128:$Rd),
7742             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7743     bits<5> imm;
7744     let Inst{20-16} = imm;
7745   }
7746 }
7747
7748
7749 //---
7750 // Vector load/store
7751 //---
7752 // SIMD ldX/stX no-index memory references don't allow the optional
7753 // ", #0" constant and handle post-indexing explicitly, so we use
7754 // a more specialized parse method for them. Otherwise, it's the same as
7755 // the general GPR64sp handling.
7756
7757 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7758                    string asm, dag oops, dag iops, list<dag> pattern>
7759   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
7760   bits<5> Vt;
7761   bits<5> Rn;
7762   let Inst{31} = 0;
7763   let Inst{30} = Q;
7764   let Inst{29-23} = 0b0011000;
7765   let Inst{22} = L;
7766   let Inst{21-16} = 0b000000;
7767   let Inst{15-12} = opcode;
7768   let Inst{11-10} = size;
7769   let Inst{9-5} = Rn;
7770   let Inst{4-0} = Vt;
7771 }
7772
7773 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7774                        string asm, dag oops, dag iops>
7775   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
7776   bits<5> Vt;
7777   bits<5> Rn;
7778   bits<5> Xm;
7779   let Inst{31} = 0;
7780   let Inst{30} = Q;
7781   let Inst{29-23} = 0b0011001;
7782   let Inst{22} = L;
7783   let Inst{21} = 0;
7784   let Inst{20-16} = Xm;
7785   let Inst{15-12} = opcode;
7786   let Inst{11-10} = size;
7787   let Inst{9-5} = Rn;
7788   let Inst{4-0} = Vt;
7789 }
7790
7791 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7792 // register post-index addressing from the zero register.
7793 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7794                            int Offset, int Size> {
7795   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7796   //      "ld1\t$Vt, [$Rn], #16"
7797   // may get mapped to
7798   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
7799   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
7800                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7801                       GPR64sp:$Rn,
7802                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7803                       XZR), 1>;
7804
7805   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7806   //      "ld1.8b\t$Vt, [$Rn], #16"
7807   // may get mapped to
7808   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
7809   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
7810                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7811                       GPR64sp:$Rn,
7812                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7813                       XZR), 0>;
7814
7815   // E.g. "ld1.8b { v0, v1 }, [x1]"
7816   //      "ld1\t$Vt, [$Rn]"
7817   // may get mapped to
7818   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
7819   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
7820                   (!cast<Instruction>(NAME # Count # "v" # layout)
7821                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7822                       GPR64sp:$Rn), 0>;
7823
7824   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7825   //      "ld1\t$Vt, [$Rn], $Xm"
7826   // may get mapped to
7827   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
7828   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
7829                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7830                       GPR64sp:$Rn,
7831                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7832                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7833 }
7834
7835 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7836                        int Offset64, bits<4> opcode> {
7837   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7838     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7839                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7840                            (ins GPR64sp:$Rn), []>;
7841     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7842                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7843                            (ins GPR64sp:$Rn), []>;
7844     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7845                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7846                            (ins GPR64sp:$Rn), []>;
7847     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7848                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7849                            (ins GPR64sp:$Rn), []>;
7850     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7851                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7852                            (ins GPR64sp:$Rn), []>;
7853     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7854                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7855                            (ins GPR64sp:$Rn), []>;
7856     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7857                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7858                            (ins GPR64sp:$Rn), []>;
7859
7860
7861     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7862                        (outs GPR64sp:$wback,
7863                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
7864                        (ins GPR64sp:$Rn,
7865                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7866     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7867                        (outs GPR64sp:$wback,
7868                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
7869                        (ins GPR64sp:$Rn,
7870                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7871     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7872                        (outs GPR64sp:$wback,
7873                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
7874                        (ins GPR64sp:$Rn,
7875                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7876     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7877                        (outs GPR64sp:$wback,
7878                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
7879                        (ins GPR64sp:$Rn,
7880                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7881     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7882                        (outs GPR64sp:$wback,
7883                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
7884                        (ins GPR64sp:$Rn,
7885                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7886     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7887                        (outs GPR64sp:$wback,
7888                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
7889                        (ins GPR64sp:$Rn,
7890                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7891     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7892                        (outs GPR64sp:$wback,
7893                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
7894                        (ins GPR64sp:$Rn,
7895                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7896   }
7897
7898   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7899   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7900   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7901   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7902   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7903   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7904   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7905 }
7906
7907 // Only ld1/st1 has a v1d version.
7908 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7909                        int Offset64, bits<4> opcode> {
7910   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7911     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7912                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7913                                  GPR64sp:$Rn), []>;
7914     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7915                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7916                                 GPR64sp:$Rn), []>;
7917     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7918                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7919                                 GPR64sp:$Rn), []>;
7920     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7921                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7922                                 GPR64sp:$Rn), []>;
7923     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7924                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7925                                 GPR64sp:$Rn), []>;
7926     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7927                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7928                                 GPR64sp:$Rn), []>;
7929     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7930                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7931                                 GPR64sp:$Rn), []>;
7932
7933     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
7934                        (outs GPR64sp:$wback),
7935                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7936                             GPR64sp:$Rn,
7937                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7938     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
7939                        (outs GPR64sp:$wback),
7940                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7941                             GPR64sp:$Rn,
7942                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7943     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
7944                        (outs GPR64sp:$wback),
7945                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7946                             GPR64sp:$Rn,
7947                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7948     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
7949                        (outs GPR64sp:$wback),
7950                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7951                             GPR64sp:$Rn,
7952                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7953     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
7954                        (outs GPR64sp:$wback),
7955                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7956                             GPR64sp:$Rn,
7957                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7958     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
7959                        (outs GPR64sp:$wback),
7960                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7961                             GPR64sp:$Rn,
7962                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7963     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
7964                        (outs GPR64sp:$wback),
7965                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7966                             GPR64sp:$Rn,
7967                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7968   }
7969
7970   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7971   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7972   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7973   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7974   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7975   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7976   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7977 }
7978
7979 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7980                        int Offset128, int Offset64, bits<4> opcode>
7981   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7982
7983   // LD1 instructions have extra "1d" variants.
7984   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7985     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7986                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7987                            (ins GPR64sp:$Rn), []>;
7988
7989     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7990                        (outs GPR64sp:$wback,
7991                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
7992                        (ins GPR64sp:$Rn,
7993                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7994   }
7995
7996   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7997 }
7998
7999 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
8000                        int Offset128, int Offset64, bits<4> opcode>
8001   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
8002
8003   // ST1 instructions have extra "1d" variants.
8004   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8005     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8006                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8007                                 GPR64sp:$Rn), []>;
8008
8009     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8010                        (outs GPR64sp:$wback),
8011                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8012                             GPR64sp:$Rn,
8013                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8014   }
8015
8016   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8017 }
8018
8019 multiclass SIMDLd1Multiple<string asm> {
8020   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8021   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8022   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8023   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8024 }
8025
8026 multiclass SIMDSt1Multiple<string asm> {
8027   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8028   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8029   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8030   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8031 }
8032
8033 multiclass SIMDLd2Multiple<string asm> {
8034   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8035 }
8036
8037 multiclass SIMDSt2Multiple<string asm> {
8038   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8039 }
8040
8041 multiclass SIMDLd3Multiple<string asm> {
8042   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8043 }
8044
8045 multiclass SIMDSt3Multiple<string asm> {
8046   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8047 }
8048
8049 multiclass SIMDLd4Multiple<string asm> {
8050   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8051 }
8052
8053 multiclass SIMDSt4Multiple<string asm> {
8054   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8055 }
8056
8057 //---
8058 // AdvSIMD Load/store single-element
8059 //---
8060
8061 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8062                          string asm, string operands, string cst,
8063                          dag oops, dag iops, list<dag> pattern>
8064   : I<oops, iops, asm, operands, cst, pattern> {
8065   bits<5> Vt;
8066   bits<5> Rn;
8067   let Inst{31} = 0;
8068   let Inst{29-24} = 0b001101;
8069   let Inst{22} = L;
8070   let Inst{21} = R;
8071   let Inst{15-13} = opcode;
8072   let Inst{9-5} = Rn;
8073   let Inst{4-0} = Vt;
8074 }
8075
8076 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8077                          string asm, string operands, string cst,
8078                          dag oops, dag iops, list<dag> pattern>
8079   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8080   bits<5> Vt;
8081   bits<5> Rn;
8082   let Inst{31} = 0;
8083   let Inst{29-24} = 0b001101;
8084   let Inst{22} = L;
8085   let Inst{21} = R;
8086   let Inst{15-13} = opcode;
8087   let Inst{9-5} = Rn;
8088   let Inst{4-0} = Vt;
8089 }
8090
8091
8092 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8093 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8094                   Operand listtype>
8095   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8096                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
8097                        []> {
8098   let Inst{30} = Q;
8099   let Inst{23} = 0;
8100   let Inst{20-16} = 0b00000;
8101   let Inst{12} = S;
8102   let Inst{11-10} = size;
8103 }
8104 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8105 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8106                       string asm, Operand listtype, Operand GPR64pi>
8107   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8108                        "$Rn = $wback",
8109                        (outs GPR64sp:$wback, listtype:$Vt),
8110                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8111   bits<5> Xm;
8112   let Inst{30} = Q;
8113   let Inst{23} = 1;
8114   let Inst{20-16} = Xm;
8115   let Inst{12} = S;
8116   let Inst{11-10} = size;
8117 }
8118
8119 multiclass SIMDLdrAliases<string asm, string layout, string Count,
8120                           int Offset, int Size> {
8121   // E.g. "ld1r { v0.8b }, [x1], #1"
8122   //      "ld1r.8b\t$Vt, [$Rn], #1"
8123   // may get mapped to
8124   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8125   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8126                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8127                       GPR64sp:$Rn,
8128                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8129                       XZR), 1>;
8130
8131   // E.g. "ld1r.8b { v0 }, [x1], #1"
8132   //      "ld1r.8b\t$Vt, [$Rn], #1"
8133   // may get mapped to
8134   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8135   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8136                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8137                       GPR64sp:$Rn,
8138                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8139                       XZR), 0>;
8140
8141   // E.g. "ld1r.8b { v0 }, [x1]"
8142   //      "ld1r.8b\t$Vt, [$Rn]"
8143   // may get mapped to
8144   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8145   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8146                   (!cast<Instruction>(NAME # "v" # layout)
8147                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8148                       GPR64sp:$Rn), 0>;
8149
8150   // E.g. "ld1r.8b { v0 }, [x1], x2"
8151   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
8152   // may get mapped to
8153   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8154   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8155                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8156                       GPR64sp:$Rn,
8157                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8158                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8159 }
8160
8161 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8162   int Offset1, int Offset2, int Offset4, int Offset8> {
8163   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8164                         !cast<Operand>("VecList" # Count # "8b")>;
8165   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8166                         !cast<Operand>("VecList" # Count #"16b")>;
8167   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8168                         !cast<Operand>("VecList" # Count #"4h")>;
8169   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8170                         !cast<Operand>("VecList" # Count #"8h")>;
8171   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8172                         !cast<Operand>("VecList" # Count #"2s")>;
8173   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8174                         !cast<Operand>("VecList" # Count #"4s")>;
8175   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8176                         !cast<Operand>("VecList" # Count #"1d")>;
8177   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8178                         !cast<Operand>("VecList" # Count #"2d")>;
8179
8180   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8181                                  !cast<Operand>("VecList" # Count # "8b"),
8182                                  !cast<Operand>("GPR64pi" # Offset1)>;
8183   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8184                                  !cast<Operand>("VecList" # Count # "16b"),
8185                                  !cast<Operand>("GPR64pi" # Offset1)>;
8186   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8187                                  !cast<Operand>("VecList" # Count # "4h"),
8188                                  !cast<Operand>("GPR64pi" # Offset2)>;
8189   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8190                                  !cast<Operand>("VecList" # Count # "8h"),
8191                                  !cast<Operand>("GPR64pi" # Offset2)>;
8192   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8193                                  !cast<Operand>("VecList" # Count # "2s"),
8194                                  !cast<Operand>("GPR64pi" # Offset4)>;
8195   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8196                                  !cast<Operand>("VecList" # Count # "4s"),
8197                                  !cast<Operand>("GPR64pi" # Offset4)>;
8198   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8199                                  !cast<Operand>("VecList" # Count # "1d"),
8200                                  !cast<Operand>("GPR64pi" # Offset8)>;
8201   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8202                                  !cast<Operand>("VecList" # Count # "2d"),
8203                                  !cast<Operand>("GPR64pi" # Offset8)>;
8204
8205   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
8206   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8207   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
8208   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
8209   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
8210   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
8211   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
8212   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
8213 }
8214
8215 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8216                       dag oops, dag iops, list<dag> pattern>
8217   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8218                        pattern> {
8219   // idx encoded in Q:S:size fields.
8220   bits<4> idx;
8221   let Inst{30} = idx{3};
8222   let Inst{23} = 0;
8223   let Inst{20-16} = 0b00000;
8224   let Inst{12} = idx{2};
8225   let Inst{11-10} = idx{1-0};
8226 }
8227 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8228                       dag oops, dag iops, list<dag> pattern>
8229   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8230                            oops, iops, pattern> {
8231   // idx encoded in Q:S:size fields.
8232   bits<4> idx;
8233   let Inst{30} = idx{3};
8234   let Inst{23} = 0;
8235   let Inst{20-16} = 0b00000;
8236   let Inst{12} = idx{2};
8237   let Inst{11-10} = idx{1-0};
8238 }
8239 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8240                           dag oops, dag iops>
8241   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8242                        "$Rn = $wback", oops, iops, []> {
8243   // idx encoded in Q:S:size fields.
8244   bits<4> idx;
8245   bits<5> Xm;
8246   let Inst{30} = idx{3};
8247   let Inst{23} = 1;
8248   let Inst{20-16} = Xm;
8249   let Inst{12} = idx{2};
8250   let Inst{11-10} = idx{1-0};
8251 }
8252 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8253                           dag oops, dag iops>
8254   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8255                            "$Rn = $wback", oops, iops, []> {
8256   // idx encoded in Q:S:size fields.
8257   bits<4> idx;
8258   bits<5> Xm;
8259   let Inst{30} = idx{3};
8260   let Inst{23} = 1;
8261   let Inst{20-16} = Xm;
8262   let Inst{12} = idx{2};
8263   let Inst{11-10} = idx{1-0};
8264 }
8265
8266 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8267                       dag oops, dag iops, list<dag> pattern>
8268   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8269                        pattern> {
8270   // idx encoded in Q:S:size<1> fields.
8271   bits<3> idx;
8272   let Inst{30} = idx{2};
8273   let Inst{23} = 0;
8274   let Inst{20-16} = 0b00000;
8275   let Inst{12} = idx{1};
8276   let Inst{11} = idx{0};
8277   let Inst{10} = size;
8278 }
8279 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8280                       dag oops, dag iops, list<dag> pattern>
8281   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8282                            oops, iops, pattern> {
8283   // idx encoded in Q:S:size<1> fields.
8284   bits<3> idx;
8285   let Inst{30} = idx{2};
8286   let Inst{23} = 0;
8287   let Inst{20-16} = 0b00000;
8288   let Inst{12} = idx{1};
8289   let Inst{11} = idx{0};
8290   let Inst{10} = size;
8291 }
8292
8293 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8294                           dag oops, dag iops>
8295   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8296                        "$Rn = $wback", oops, iops, []> {
8297   // idx encoded in Q:S:size<1> fields.
8298   bits<3> idx;
8299   bits<5> Xm;
8300   let Inst{30} = idx{2};
8301   let Inst{23} = 1;
8302   let Inst{20-16} = Xm;
8303   let Inst{12} = idx{1};
8304   let Inst{11} = idx{0};
8305   let Inst{10} = size;
8306 }
8307 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8308                           dag oops, dag iops>
8309   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8310                            "$Rn = $wback", oops, iops, []> {
8311   // idx encoded in Q:S:size<1> fields.
8312   bits<3> idx;
8313   bits<5> Xm;
8314   let Inst{30} = idx{2};
8315   let Inst{23} = 1;
8316   let Inst{20-16} = Xm;
8317   let Inst{12} = idx{1};
8318   let Inst{11} = idx{0};
8319   let Inst{10} = size;
8320 }
8321 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8322                       dag oops, dag iops, list<dag> pattern>
8323   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8324                        pattern> {
8325   // idx encoded in Q:S fields.
8326   bits<2> idx;
8327   let Inst{30} = idx{1};
8328   let Inst{23} = 0;
8329   let Inst{20-16} = 0b00000;
8330   let Inst{12} = idx{0};
8331   let Inst{11-10} = size;
8332 }
8333 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8334                       dag oops, dag iops, list<dag> pattern>
8335   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8336                            oops, iops, pattern> {
8337   // idx encoded in Q:S fields.
8338   bits<2> idx;
8339   let Inst{30} = idx{1};
8340   let Inst{23} = 0;
8341   let Inst{20-16} = 0b00000;
8342   let Inst{12} = idx{0};
8343   let Inst{11-10} = size;
8344 }
8345 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8346                           string asm, dag oops, dag iops>
8347   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8348                        "$Rn = $wback", oops, iops, []> {
8349   // idx encoded in Q:S fields.
8350   bits<2> idx;
8351   bits<5> Xm;
8352   let Inst{30} = idx{1};
8353   let Inst{23} = 1;
8354   let Inst{20-16} = Xm;
8355   let Inst{12} = idx{0};
8356   let Inst{11-10} = size;
8357 }
8358 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8359                           string asm, dag oops, dag iops>
8360   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8361                            "$Rn = $wback", oops, iops, []> {
8362   // idx encoded in Q:S fields.
8363   bits<2> idx;
8364   bits<5> Xm;
8365   let Inst{30} = idx{1};
8366   let Inst{23} = 1;
8367   let Inst{20-16} = Xm;
8368   let Inst{12} = idx{0};
8369   let Inst{11-10} = size;
8370 }
8371 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8372                       dag oops, dag iops, list<dag> pattern>
8373   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8374                        pattern> {
8375   // idx encoded in Q field.
8376   bits<1> idx;
8377   let Inst{30} = idx;
8378   let Inst{23} = 0;
8379   let Inst{20-16} = 0b00000;
8380   let Inst{12} = 0;
8381   let Inst{11-10} = size;
8382 }
8383 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8384                       dag oops, dag iops, list<dag> pattern>
8385   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8386                            oops, iops, pattern> {
8387   // idx encoded in Q field.
8388   bits<1> idx;
8389   let Inst{30} = idx;
8390   let Inst{23} = 0;
8391   let Inst{20-16} = 0b00000;
8392   let Inst{12} = 0;
8393   let Inst{11-10} = size;
8394 }
8395 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8396                           string asm, dag oops, dag iops>
8397   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8398                        "$Rn = $wback", oops, iops, []> {
8399   // idx encoded in Q field.
8400   bits<1> idx;
8401   bits<5> Xm;
8402   let Inst{30} = idx;
8403   let Inst{23} = 1;
8404   let Inst{20-16} = Xm;
8405   let Inst{12} = 0;
8406   let Inst{11-10} = size;
8407 }
8408 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8409                           string asm, dag oops, dag iops>
8410   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8411                            "$Rn = $wback", oops, iops, []> {
8412   // idx encoded in Q field.
8413   bits<1> idx;
8414   bits<5> Xm;
8415   let Inst{30} = idx;
8416   let Inst{23} = 1;
8417   let Inst{20-16} = Xm;
8418   let Inst{12} = 0;
8419   let Inst{11-10} = size;
8420 }
8421
8422 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8423 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8424                          RegisterOperand listtype,
8425                          RegisterOperand GPR64pi> {
8426   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8427                            (outs listtype:$dst),
8428                            (ins listtype:$Vt, VectorIndexB:$idx,
8429                                 GPR64sp:$Rn), []>;
8430
8431   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8432                             (outs GPR64sp:$wback, listtype:$dst),
8433                             (ins listtype:$Vt, VectorIndexB:$idx,
8434                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8435 }
8436 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8437 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8438                          RegisterOperand listtype,
8439                          RegisterOperand GPR64pi> {
8440   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8441                             (outs listtype:$dst),
8442                             (ins listtype:$Vt, VectorIndexH:$idx,
8443                                  GPR64sp:$Rn), []>;
8444
8445   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8446                             (outs GPR64sp:$wback, listtype:$dst),
8447                             (ins listtype:$Vt, VectorIndexH:$idx,
8448                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8449 }
8450 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8451 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8452                          RegisterOperand listtype,
8453                          RegisterOperand GPR64pi> {
8454   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8455                             (outs listtype:$dst),
8456                             (ins listtype:$Vt, VectorIndexS:$idx,
8457                                  GPR64sp:$Rn), []>;
8458
8459   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8460                             (outs GPR64sp:$wback, listtype:$dst),
8461                             (ins listtype:$Vt, VectorIndexS:$idx,
8462                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8463 }
8464 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8465 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8466                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8467   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8468                             (outs listtype:$dst),
8469                             (ins listtype:$Vt, VectorIndexD:$idx,
8470                                  GPR64sp:$Rn), []>;
8471
8472   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8473                             (outs GPR64sp:$wback, listtype:$dst),
8474                             (ins listtype:$Vt, VectorIndexD:$idx,
8475                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8476 }
8477 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8478 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8479                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8480   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8481                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8482                                         GPR64sp:$Rn), []>;
8483
8484   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8485                                     (outs GPR64sp:$wback),
8486                                     (ins listtype:$Vt, VectorIndexB:$idx,
8487                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
8488 }
8489 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8490 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8491                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8492   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8493                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8494                                          GPR64sp:$Rn), []>;
8495
8496   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8497                             (outs GPR64sp:$wback),
8498                             (ins listtype:$Vt, VectorIndexH:$idx,
8499                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8500 }
8501 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8502 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8503                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8504   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8505                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8506                                          GPR64sp:$Rn), []>;
8507
8508   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8509                             (outs GPR64sp:$wback),
8510                             (ins listtype:$Vt, VectorIndexS:$idx,
8511                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8512 }
8513 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8514 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8515                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8516   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8517                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8518                                          GPR64sp:$Rn), []>;
8519
8520   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8521                             (outs GPR64sp:$wback),
8522                             (ins listtype:$Vt, VectorIndexD:$idx,
8523                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8524 }
8525
8526 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8527                                  string Count, int Offset, Operand idxtype> {
8528   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8529   //      "ld1\t$Vt, [$Rn], #1"
8530   // may get mapped to
8531   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8532   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8533                   (!cast<Instruction>(NAME # Type  # "_POST")
8534                       GPR64sp:$Rn,
8535                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8536                       idxtype:$idx, XZR), 1>;
8537
8538   // E.g. "ld1.8b { v0 }[0], [x1], #1"
8539   //      "ld1.8b\t$Vt, [$Rn], #1"
8540   // may get mapped to
8541   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8542   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
8543                   (!cast<Instruction>(NAME # Type # "_POST")
8544                       GPR64sp:$Rn,
8545                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8546                       idxtype:$idx, XZR), 0>;
8547
8548   // E.g. "ld1.8b { v0 }[0], [x1]"
8549   //      "ld1.8b\t$Vt, [$Rn]"
8550   // may get mapped to
8551   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8552   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
8553                       (!cast<Instruction>(NAME # Type)
8554                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8555                          idxtype:$idx, GPR64sp:$Rn), 0>;
8556
8557   // E.g. "ld1.8b { v0 }[0], [x1], x2"
8558   //      "ld1.8b\t$Vt, [$Rn], $Xm"
8559   // may get mapped to
8560   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8561   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
8562                       (!cast<Instruction>(NAME # Type # "_POST")
8563                          GPR64sp:$Rn,
8564                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8565                          idxtype:$idx,
8566                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8567 }
8568
8569 multiclass SIMDLdSt1SingleAliases<string asm> {
8570   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
8571   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8572   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8573   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8574 }
8575
8576 multiclass SIMDLdSt2SingleAliases<string asm> {
8577   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
8578   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
8579   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
8580   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8581 }
8582
8583 multiclass SIMDLdSt3SingleAliases<string asm> {
8584   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
8585   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
8586   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8587   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8588 }
8589
8590 multiclass SIMDLdSt4SingleAliases<string asm> {
8591   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
8592   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
8593   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8594   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8595 }
8596 } // end of 'let Predicates = [HasNEON]'
8597
8598 //----------------------------------------------------------------------------
8599 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
8600 //----------------------------------------------------------------------------
8601
8602 let Predicates = [HasNEON, HasV8_1a] in {
8603
8604 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
8605                                     RegisterOperand regtype, string asm, 
8606                                     string kind, list<dag> pattern>
8607   : BaseSIMDThreeSameVectorTied<Q, U, size, opcode, regtype, asm, kind, 
8608                                 pattern> {
8609   let Inst{21}=0;
8610 }
8611 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
8612                                              SDPatternOperator Accum> {
8613   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
8614     [(set (v4i16 V64:$dst),
8615           (Accum (v4i16 V64:$Rd),
8616                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
8617                                                    (v4i16 V64:$Rm)))))]>;         
8618   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
8619     [(set (v8i16 V128:$dst),
8620           (Accum (v8i16 V128:$Rd),
8621                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
8622                                                    (v8i16 V128:$Rm)))))]>;
8623   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
8624     [(set (v2i32 V64:$dst),
8625           (Accum (v2i32 V64:$Rd),
8626                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
8627                                                    (v2i32 V64:$Rm)))))]>;
8628   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
8629     [(set (v4i32 V128:$dst),
8630           (Accum (v4i32 V128:$Rd),
8631                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
8632                                                    (v4i32 V128:$Rm)))))]>;
8633 }
8634
8635 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
8636                                      SDPatternOperator Accum> {
8637   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8638                                           V64, V64, V128_lo, VectorIndexH,
8639                                           asm, ".4h", ".4h", ".4h", ".h",
8640     [(set (v4i16 V64:$dst),
8641           (Accum (v4i16 V64:$Rd),
8642                  (v4i16 (int_aarch64_neon_sqrdmulh
8643                           (v4i16 V64:$Rn),
8644                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8645                                                     VectorIndexH:$idx))))))]> {
8646     bits<3> idx;
8647     let Inst{11} = idx{2};
8648     let Inst{21} = idx{1};
8649     let Inst{20} = idx{0};
8650   }
8651
8652   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8653                                           V128, V128, V128_lo, VectorIndexH,
8654                                           asm, ".8h", ".8h", ".8h", ".h",
8655     [(set (v8i16 V128:$dst),
8656           (Accum (v8i16 V128:$Rd),
8657                  (v8i16 (int_aarch64_neon_sqrdmulh
8658                           (v8i16 V128:$Rn),
8659                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8660                                                    VectorIndexH:$idx))))))]> {
8661     bits<3> idx;
8662     let Inst{11} = idx{2};
8663     let Inst{21} = idx{1};
8664     let Inst{20} = idx{0};
8665   }
8666
8667   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8668                                           V64, V64, V128, VectorIndexS,
8669                                           asm, ".2s", ".2s", ".2s", ".s",
8670     [(set (v2i32 V64:$dst),
8671         (Accum (v2i32 V64:$Rd),
8672                (v2i32 (int_aarch64_neon_sqrdmulh
8673                         (v2i32 V64:$Rn),
8674                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8675                                                  VectorIndexS:$idx))))))]> {
8676     bits<2> idx;
8677     let Inst{11} = idx{1};
8678     let Inst{21} = idx{0};
8679   }
8680
8681   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but 
8682   // an intermediate EXTRACT_SUBREG would be untyped.
8683   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we 
8684   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
8685   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8686                        (i32 (vector_extract 
8687                                (v4i32 (insert_subvector
8688                                        (undef), 
8689                                         (v2i32 (int_aarch64_neon_sqrdmulh 
8690                                                  (v2i32 V64:$Rn),
8691                                                  (v2i32 (AArch64duplane32 
8692                                                           (v4i32 V128:$Rm),
8693                                                           VectorIndexS:$idx)))),
8694                                       (i32 0))),
8695                                (i64 0))))),
8696             (EXTRACT_SUBREG
8697                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
8698                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), 
8699                                                 FPR32Op:$Rd, 
8700                                                 ssub)), 
8701                           V64:$Rn,
8702                           V128:$Rm, 
8703                           VectorIndexS:$idx)),
8704                 ssub)>;
8705
8706   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8707                                           V128, V128, V128, VectorIndexS,
8708                                           asm, ".4s", ".4s", ".4s", ".s",
8709     [(set (v4i32 V128:$dst),
8710           (Accum (v4i32 V128:$Rd),
8711                  (v4i32 (int_aarch64_neon_sqrdmulh
8712                           (v4i32 V128:$Rn),
8713                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8714                                                    VectorIndexS:$idx))))))]> {
8715     bits<2> idx;
8716     let Inst{11} = idx{1};
8717     let Inst{21} = idx{0};
8718   }
8719
8720   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
8721   // an intermediate EXTRACT_SUBREG would be untyped.
8722   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8723                         (i32 (vector_extract 
8724                                (v4i32 (int_aarch64_neon_sqrdmulh 
8725                                         (v4i32 V128:$Rn),
8726                                         (v4i32 (AArch64duplane32 
8727                                                  (v4i32 V128:$Rm),
8728                                                  VectorIndexS:$idx)))),
8729                                (i64 0))))),
8730             (EXTRACT_SUBREG
8731                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
8732                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), 
8733                                                FPR32Op:$Rd, 
8734                                                ssub)), 
8735                          V128:$Rn,
8736                          V128:$Rm, 
8737                          VectorIndexS:$idx)),
8738                 ssub)>;
8739
8740   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8741                                         FPR16Op, FPR16Op, V128_lo,
8742                                         VectorIndexH, asm, ".h", "", "", ".h", 
8743                                         []> {
8744     bits<3> idx;
8745     let Inst{11} = idx{2};
8746     let Inst{21} = idx{1};
8747     let Inst{20} = idx{0};
8748   }
8749
8750   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8751                                         FPR32Op, FPR32Op, V128, VectorIndexS,
8752                                         asm, ".s", "", "", ".s",
8753     [(set (i32 FPR32Op:$dst),
8754           (Accum (i32 FPR32Op:$Rd),
8755                  (i32 (int_aarch64_neon_sqrdmulh
8756                         (i32 FPR32Op:$Rn),
8757                         (i32 (vector_extract (v4i32 V128:$Rm),
8758                                              VectorIndexS:$idx))))))]> {
8759     bits<2> idx;
8760     let Inst{11} = idx{1};
8761     let Inst{21} = idx{0};
8762   }
8763 }
8764 } // let Predicates = [HasNeon, HasV8_1a]
8765
8766 //----------------------------------------------------------------------------
8767 // Crypto extensions
8768 //----------------------------------------------------------------------------
8769
8770 let Predicates = [HasCrypto] in {
8771 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8772 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8773               list<dag> pat>
8774   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8775     Sched<[WriteV]>{
8776   bits<5> Rd;
8777   bits<5> Rn;
8778   let Inst{31-16} = 0b0100111000101000;
8779   let Inst{15-12} = opc;
8780   let Inst{11-10} = 0b10;
8781   let Inst{9-5}   = Rn;
8782   let Inst{4-0}   = Rd;
8783 }
8784
8785 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8786   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8787             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8788
8789 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8790   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8791             "$Rd = $dst",
8792             [(set (v16i8 V128:$dst),
8793                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8794
8795 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8796 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8797                      dag oops, dag iops, list<dag> pat>
8798   : I<oops, iops, asm,
8799       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8800       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8801     Sched<[WriteV]>{
8802   bits<5> Rd;
8803   bits<5> Rn;
8804   bits<5> Rm;
8805   let Inst{31-21} = 0b01011110000;
8806   let Inst{20-16} = Rm;
8807   let Inst{15}    = 0;
8808   let Inst{14-12} = opc;
8809   let Inst{11-10} = 0b00;
8810   let Inst{9-5}   = Rn;
8811   let Inst{4-0}   = Rd;
8812 }
8813
8814 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8815   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8816                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8817                    [(set (v4i32 FPR128:$dst),
8818                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8819                                  (v4i32 V128:$Rm)))]>;
8820
8821 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8822   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8823                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
8824                    [(set (v4i32 V128:$dst),
8825                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8826                                  (v4i32 V128:$Rm)))]>;
8827
8828 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8829   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8830                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8831                    [(set (v4i32 FPR128:$dst),
8832                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8833                                  (v4i32 V128:$Rm)))]>;
8834
8835 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8836 class SHA2OpInst<bits<4> opc, string asm, string kind,
8837                  string cstr, dag oops, dag iops,
8838                  list<dag> pat>
8839   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8840                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8841     Sched<[WriteV]>{
8842   bits<5> Rd;
8843   bits<5> Rn;
8844   let Inst{31-16} = 0b0101111000101000;
8845   let Inst{15-12} = opc;
8846   let Inst{11-10} = 0b10;
8847   let Inst{9-5}   = Rn;
8848   let Inst{4-0}   = Rd;
8849 }
8850
8851 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8852   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8853                (ins V128:$Rd, V128:$Rn),
8854                [(set (v4i32 V128:$dst),
8855                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8856
8857 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8858   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8859                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8860 } // end of 'let Predicates = [HasCrypto]'
8861
8862 //----------------------------------------------------------------------------
8863 // v8.1 atomic instructions extension:
8864 // * CAS
8865 // * CASP
8866 // * SWP
8867 // * LDOPregister<OP>, and aliases STOPregister<OP>
8868
8869 // Instruction encodings:
8870 //
8871 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
8872 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
8873 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
8874 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
8875 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
8876 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
8877
8878 // Instruction syntax:
8879 //
8880 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8881 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
8882 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
8883 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
8884 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8885 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
8886 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8887 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
8888 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
8889 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
8890
8891 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
8892 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
8893                       string cstr, list<dag> pattern>
8894       : I<oops, iops, asm, operands, cstr, pattern> {
8895   bits<2> Sz;
8896   bit NP;
8897   bit Acq;
8898   bit Rel;
8899   bits<5> Rs;
8900   bits<5> Rn;
8901   bits<5> Rt;
8902   let Inst{31-30} = Sz;
8903   let Inst{29-24} = 0b001000;
8904   let Inst{23} = NP;
8905   let Inst{22} = Acq;
8906   let Inst{21} = 0b1;
8907   let Inst{20-16} = Rs;
8908   let Inst{15} = Rel;
8909   let Inst{14-10} = 0b11111;
8910   let Inst{9-5} = Rn;
8911   let Inst{4-0} = Rt;
8912 }
8913
8914 class BaseCAS<string order, string size, RegisterClass RC>
8915       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8916                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
8917                         "$out = $Rs",[]> {
8918   let NP = 1;
8919 }
8920
8921 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
8922   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
8923   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
8924   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
8925   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
8926 }
8927
8928 class BaseCASP<string order, string size, RegisterOperand RC>
8929       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8930                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
8931                         "$out = $Rs",[]> {
8932   let NP = 0;
8933 }
8934
8935 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
8936   let Sz = 0b00, Acq = Acq, Rel = Rel in 
8937     def s : BaseCASP<order, "", WSeqPairClassOperand>;
8938   let Sz = 0b01, Acq = Acq, Rel = Rel in 
8939     def d : BaseCASP<order, "", XSeqPairClassOperand>;
8940 }
8941
8942 let Predicates = [HasV8_1a] in
8943 class BaseSWP<string order, string size, RegisterClass RC>
8944       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
8945           "\t$Rs, $Rt, [$Rn]","",[]> {
8946   bits<2> Sz;
8947   bit Acq;
8948   bit Rel;
8949   bits<5> Rs;
8950   bits<3> opc = 0b000;
8951   bits<5> Rn;
8952   bits<5> Rt;
8953   let Inst{31-30} = Sz;
8954   let Inst{29-24} = 0b111000;
8955   let Inst{23} = Acq;
8956   let Inst{22} = Rel;
8957   let Inst{21} = 0b1;
8958   let Inst{20-16} = Rs;
8959   let Inst{15} = 0b1;
8960   let Inst{14-12} = opc;
8961   let Inst{11-10} = 0b00;
8962   let Inst{9-5} = Rn;
8963   let Inst{4-0} = Rt;
8964 }
8965
8966 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
8967   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
8968   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
8969   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
8970   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
8971 }
8972
8973 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
8974 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
8975       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
8976           "\t$Rs, $Rt, [$Rn]","",[]> {
8977   bits<2> Sz;
8978   bit Acq;
8979   bit Rel;
8980   bits<5> Rs;
8981   bits<3> opc;
8982   bits<5> Rn;
8983   bits<5> Rt;
8984   let Inst{31-30} = Sz;
8985   let Inst{29-24} = 0b111000;
8986   let Inst{23} = Acq;
8987   let Inst{22} = Rel;
8988   let Inst{21} = 0b1;
8989   let Inst{20-16} = Rs;
8990   let Inst{15} = 0b0;
8991   let Inst{14-12} = opc;
8992   let Inst{11-10} = 0b00;
8993   let Inst{9-5} = Rn;
8994   let Inst{4-0} = Rt;
8995 }
8996
8997 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel, 
8998                         string order> {
8999   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in 
9000     def b : BaseLDOPregister<op, order, "b", GPR32>;
9001   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in 
9002     def h : BaseLDOPregister<op, order, "h", GPR32>;
9003   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in 
9004     def s : BaseLDOPregister<op, order, "", GPR32>;
9005   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in 
9006     def d : BaseLDOPregister<op, order, "", GPR64>;
9007 }
9008
9009 let Predicates = [HasV8_1a] in
9010 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
9011                         Instruction inst> :
9012       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
9013
9014 multiclass STOPregister<string asm, string instr> {
9015   def : BaseSTOPregister<asm # "lb", GPR32, WZR, 
9016                     !cast<Instruction>(instr # "Lb")>;
9017   def : BaseSTOPregister<asm # "lh", GPR32, WZR, 
9018                     !cast<Instruction>(instr # "Lh")>;
9019   def : BaseSTOPregister<asm # "l",  GPR32, WZR, 
9020                     !cast<Instruction>(instr # "Ls")>;
9021   def : BaseSTOPregister<asm # "l",  GPR64, XZR, 
9022                     !cast<Instruction>(instr # "Ld")>;
9023   def : BaseSTOPregister<asm # "b",  GPR32, WZR, 
9024                     !cast<Instruction>(instr # "b")>;
9025   def : BaseSTOPregister<asm # "h",  GPR32, WZR, 
9026                     !cast<Instruction>(instr # "h")>;
9027   def : BaseSTOPregister<asm,        GPR32, WZR, 
9028                     !cast<Instruction>(instr # "s")>;
9029   def : BaseSTOPregister<asm,        GPR64, XZR, 
9030                     !cast<Instruction>(instr # "d")>;
9031 }
9032
9033 //----------------------------------------------------------------------------
9034 // Allow the size specifier tokens to be upper case, not just lower.
9035 def : TokenAlias<".8B", ".8b">;
9036 def : TokenAlias<".4H", ".4h">;
9037 def : TokenAlias<".2S", ".2s">;
9038 def : TokenAlias<".1D", ".1d">;
9039 def : TokenAlias<".16B", ".16b">;
9040 def : TokenAlias<".8H", ".8h">;
9041 def : TokenAlias<".4S", ".4s">;
9042 def : TokenAlias<".2D", ".2d">;
9043 def : TokenAlias<".1Q", ".1q">;
9044 def : TokenAlias<".B", ".b">;
9045 def : TokenAlias<".H", ".h">;
9046 def : TokenAlias<".S", ".s">;
9047 def : TokenAlias<".D", ".d">;
9048 def : TokenAlias<".Q", ".q">;