[ARM] Enable shrink-wrapping by default.
[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 def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
252 def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
253 def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
254 def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
255 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
256
257 class AsmImmRange<int Low, int High> : AsmOperandClass {
258   let Name = "Imm" # Low # "_" # High;
259   let DiagnosticType = "InvalidImm" # Low # "_" # High;
260 }
261
262 def Imm1_8Operand : AsmImmRange<1, 8>;
263 def Imm1_16Operand : AsmImmRange<1, 16>;
264 def Imm1_32Operand : AsmImmRange<1, 32>;
265 def Imm1_64Operand : AsmImmRange<1, 64>;
266
267 def MovZSymbolG3AsmOperand : AsmOperandClass {
268   let Name = "MovZSymbolG3";
269   let RenderMethod = "addImmOperands";
270 }
271
272 def movz_symbol_g3 : Operand<i32> {
273   let ParserMatchClass = MovZSymbolG3AsmOperand;
274 }
275
276 def MovZSymbolG2AsmOperand : AsmOperandClass {
277   let Name = "MovZSymbolG2";
278   let RenderMethod = "addImmOperands";
279 }
280
281 def movz_symbol_g2 : Operand<i32> {
282   let ParserMatchClass = MovZSymbolG2AsmOperand;
283 }
284
285 def MovZSymbolG1AsmOperand : AsmOperandClass {
286   let Name = "MovZSymbolG1";
287   let RenderMethod = "addImmOperands";
288 }
289
290 def movz_symbol_g1 : Operand<i32> {
291   let ParserMatchClass = MovZSymbolG1AsmOperand;
292 }
293
294 def MovZSymbolG0AsmOperand : AsmOperandClass {
295   let Name = "MovZSymbolG0";
296   let RenderMethod = "addImmOperands";
297 }
298
299 def movz_symbol_g0 : Operand<i32> {
300   let ParserMatchClass = MovZSymbolG0AsmOperand;
301 }
302
303 def MovKSymbolG3AsmOperand : AsmOperandClass {
304   let Name = "MovKSymbolG3";
305   let RenderMethod = "addImmOperands";
306 }
307
308 def movk_symbol_g3 : Operand<i32> {
309   let ParserMatchClass = MovKSymbolG3AsmOperand;
310 }
311
312 def MovKSymbolG2AsmOperand : AsmOperandClass {
313   let Name = "MovKSymbolG2";
314   let RenderMethod = "addImmOperands";
315 }
316
317 def movk_symbol_g2 : Operand<i32> {
318   let ParserMatchClass = MovKSymbolG2AsmOperand;
319 }
320
321 def MovKSymbolG1AsmOperand : AsmOperandClass {
322   let Name = "MovKSymbolG1";
323   let RenderMethod = "addImmOperands";
324 }
325
326 def movk_symbol_g1 : Operand<i32> {
327   let ParserMatchClass = MovKSymbolG1AsmOperand;
328 }
329
330 def MovKSymbolG0AsmOperand : AsmOperandClass {
331   let Name = "MovKSymbolG0";
332   let RenderMethod = "addImmOperands";
333 }
334
335 def movk_symbol_g0 : Operand<i32> {
336   let ParserMatchClass = MovKSymbolG0AsmOperand;
337 }
338
339 class fixedpoint_i32<ValueType FloatVT>
340   : Operand<FloatVT>,
341     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
342   let EncoderMethod = "getFixedPointScaleOpValue";
343   let DecoderMethod = "DecodeFixedPointScaleImm32";
344   let ParserMatchClass = Imm1_32Operand;
345 }
346
347 class fixedpoint_i64<ValueType FloatVT>
348   : Operand<FloatVT>,
349     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
350   let EncoderMethod = "getFixedPointScaleOpValue";
351   let DecoderMethod = "DecodeFixedPointScaleImm64";
352   let ParserMatchClass = Imm1_64Operand;
353 }
354
355 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
356 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
357
358 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
359 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
360
361 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
362   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
363 }]> {
364   let EncoderMethod = "getVecShiftR8OpValue";
365   let DecoderMethod = "DecodeVecShiftR8Imm";
366   let ParserMatchClass = Imm1_8Operand;
367 }
368 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
369   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
370 }]> {
371   let EncoderMethod = "getVecShiftR16OpValue";
372   let DecoderMethod = "DecodeVecShiftR16Imm";
373   let ParserMatchClass = Imm1_16Operand;
374 }
375 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
376   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
377 }]> {
378   let EncoderMethod = "getVecShiftR16OpValue";
379   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
380   let ParserMatchClass = Imm1_8Operand;
381 }
382 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
383   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
384 }]> {
385   let EncoderMethod = "getVecShiftR32OpValue";
386   let DecoderMethod = "DecodeVecShiftR32Imm";
387   let ParserMatchClass = Imm1_32Operand;
388 }
389 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
390   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
391 }]> {
392   let EncoderMethod = "getVecShiftR32OpValue";
393   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
394   let ParserMatchClass = Imm1_16Operand;
395 }
396 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
397   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
398 }]> {
399   let EncoderMethod = "getVecShiftR64OpValue";
400   let DecoderMethod = "DecodeVecShiftR64Imm";
401   let ParserMatchClass = Imm1_64Operand;
402 }
403 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
404   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
405 }]> {
406   let EncoderMethod = "getVecShiftR64OpValue";
407   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
408   let ParserMatchClass = Imm1_32Operand;
409 }
410
411 def Imm0_1Operand : AsmImmRange<0, 1>;
412 def Imm0_7Operand : AsmImmRange<0, 7>;
413 def Imm0_15Operand : AsmImmRange<0, 15>;
414 def Imm0_31Operand : AsmImmRange<0, 31>;
415 def Imm0_63Operand : AsmImmRange<0, 63>;
416
417 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
418   return (((uint32_t)Imm) < 8);
419 }]> {
420   let EncoderMethod = "getVecShiftL8OpValue";
421   let DecoderMethod = "DecodeVecShiftL8Imm";
422   let ParserMatchClass = Imm0_7Operand;
423 }
424 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
425   return (((uint32_t)Imm) < 16);
426 }]> {
427   let EncoderMethod = "getVecShiftL16OpValue";
428   let DecoderMethod = "DecodeVecShiftL16Imm";
429   let ParserMatchClass = Imm0_15Operand;
430 }
431 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
432   return (((uint32_t)Imm) < 32);
433 }]> {
434   let EncoderMethod = "getVecShiftL32OpValue";
435   let DecoderMethod = "DecodeVecShiftL32Imm";
436   let ParserMatchClass = Imm0_31Operand;
437 }
438 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
439   return (((uint32_t)Imm) < 64);
440 }]> {
441   let EncoderMethod = "getVecShiftL64OpValue";
442   let DecoderMethod = "DecodeVecShiftL64Imm";
443   let ParserMatchClass = Imm0_63Operand;
444 }
445
446
447 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
448 // instructions for splatting repeating bit patterns across the immediate.
449 def logical_imm32_XFORM : SDNodeXForm<imm, [{
450   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
451   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
452 }]>;
453 def logical_imm64_XFORM : SDNodeXForm<imm, [{
454   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
455   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
456 }]>;
457
458 let DiagnosticType = "LogicalSecondSource" in {
459   def LogicalImm32Operand : AsmOperandClass {
460     let Name = "LogicalImm32";
461   }
462   def LogicalImm64Operand : AsmOperandClass {
463     let Name = "LogicalImm64";
464   }
465   def LogicalImm32NotOperand : AsmOperandClass {
466     let Name = "LogicalImm32Not";
467   }
468   def LogicalImm64NotOperand : AsmOperandClass {
469     let Name = "LogicalImm64Not";
470   }
471 }
472 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
473   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
474 }], logical_imm32_XFORM> {
475   let PrintMethod = "printLogicalImm32";
476   let ParserMatchClass = LogicalImm32Operand;
477 }
478 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
479   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
480 }], logical_imm64_XFORM> {
481   let PrintMethod = "printLogicalImm64";
482   let ParserMatchClass = LogicalImm64Operand;
483 }
484 def logical_imm32_not : Operand<i32> {
485   let ParserMatchClass = LogicalImm32NotOperand;
486 }
487 def logical_imm64_not : Operand<i64> {
488   let ParserMatchClass = LogicalImm64NotOperand;
489 }
490
491 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
492 def Imm0_65535Operand : AsmImmRange<0, 65535>;
493 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
494   return ((uint32_t)Imm) < 65536;
495 }]> {
496   let ParserMatchClass = Imm0_65535Operand;
497   let PrintMethod = "printHexImm";
498 }
499
500 // imm0_255 predicate - True if the immediate is in the range [0,255].
501 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
502 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
503   return ((uint32_t)Imm) < 256;
504 }]> {
505   let ParserMatchClass = Imm0_255Operand;
506   let PrintMethod = "printHexImm";
507 }
508
509 // imm0_127 predicate - True if the immediate is in the range [0,127]
510 def Imm0_127Operand : AsmImmRange<0, 127>;
511 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
512   return ((uint32_t)Imm) < 128;
513 }]> {
514   let ParserMatchClass = Imm0_127Operand;
515   let PrintMethod = "printHexImm";
516 }
517
518 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
519 // for all shift-amounts.
520
521 // imm0_63 predicate - True if the immediate is in the range [0,63]
522 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
523   return ((uint64_t)Imm) < 64;
524 }]> {
525   let ParserMatchClass = Imm0_63Operand;
526 }
527
528 // imm0_31 predicate - True if the immediate is in the range [0,31]
529 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
530   return ((uint64_t)Imm) < 32;
531 }]> {
532   let ParserMatchClass = Imm0_31Operand;
533 }
534
535 // True if the 32-bit immediate is in the range [0,31]
536 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
537   return ((uint64_t)Imm) < 32;
538 }]> {
539   let ParserMatchClass = Imm0_31Operand;
540 }
541
542 // imm0_1 predicate - True if the immediate is in the range [0,1]
543 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
544   return ((uint64_t)Imm) < 2;
545 }]> {
546   let ParserMatchClass = Imm0_1Operand;
547 }
548
549 // imm0_15 predicate - True if the immediate is in the range [0,15]
550 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
551   return ((uint64_t)Imm) < 16;
552 }]> {
553   let ParserMatchClass = Imm0_15Operand;
554 }
555
556 // imm0_7 predicate - True if the immediate is in the range [0,7]
557 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
558   return ((uint64_t)Imm) < 8;
559 }]> {
560   let ParserMatchClass = Imm0_7Operand;
561 }
562
563 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
564 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
565   return ((uint32_t)Imm) < 16;
566 }]> {
567   let ParserMatchClass = Imm0_15Operand;
568 }
569
570 // An arithmetic shifter operand:
571 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
572 //  {5-0} - imm6
573 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
574   let PrintMethod = "printShifter";
575   let ParserMatchClass = !cast<AsmOperandClass>(
576                          "ArithmeticShifterOperand" # width);
577 }
578
579 def arith_shift32 : arith_shift<i32, 32>;
580 def arith_shift64 : arith_shift<i64, 64>;
581
582 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
583     : Operand<Ty>,
584       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
585   let PrintMethod = "printShiftedRegister";
586   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
587 }
588
589 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
590 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
591
592 // An arithmetic shifter operand:
593 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
594 //  {5-0} - imm6
595 class logical_shift<int width> : Operand<i32> {
596   let PrintMethod = "printShifter";
597   let ParserMatchClass = !cast<AsmOperandClass>(
598                          "LogicalShifterOperand" # width);
599 }
600
601 def logical_shift32 : logical_shift<32>;
602 def logical_shift64 : logical_shift<64>;
603
604 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
605     : Operand<Ty>,
606       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
607   let PrintMethod = "printShiftedRegister";
608   let MIOperandInfo = (ops regclass, shiftop);
609 }
610
611 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
612 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
613
614 // A logical vector shifter operand:
615 //  {7-6} - shift type: 00 = lsl
616 //  {5-0} - imm6: #0, #8, #16, or #24
617 def logical_vec_shift : Operand<i32> {
618   let PrintMethod = "printShifter";
619   let EncoderMethod = "getVecShifterOpValue";
620   let ParserMatchClass = LogicalVecShifterOperand;
621 }
622
623 // A logical vector half-word shifter operand:
624 //  {7-6} - shift type: 00 = lsl
625 //  {5-0} - imm6: #0 or #8
626 def logical_vec_hw_shift : Operand<i32> {
627   let PrintMethod = "printShifter";
628   let EncoderMethod = "getVecShifterOpValue";
629   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
630 }
631
632 // A vector move shifter operand:
633 //  {0} - imm1: #8 or #16
634 def move_vec_shift : Operand<i32> {
635   let PrintMethod = "printShifter";
636   let EncoderMethod = "getMoveVecShifterOpValue";
637   let ParserMatchClass = MoveVecShifterOperand;
638 }
639
640 let DiagnosticType = "AddSubSecondSource" in {
641   def AddSubImmOperand : AsmOperandClass {
642     let Name = "AddSubImm";
643     let ParserMethod = "tryParseAddSubImm";
644   }
645   def AddSubImmNegOperand : AsmOperandClass {
646     let Name = "AddSubImmNeg";
647     let ParserMethod = "tryParseAddSubImm";
648   }
649 }
650 // An ADD/SUB immediate shifter operand:
651 //  second operand:
652 //  {7-6} - shift type: 00 = lsl
653 //  {5-0} - imm6: #0 or #12
654 class addsub_shifted_imm<ValueType Ty>
655     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
656   let PrintMethod = "printAddSubImm";
657   let EncoderMethod = "getAddSubImmOpValue";
658   let ParserMatchClass = AddSubImmOperand;
659   let MIOperandInfo = (ops i32imm, i32imm);
660 }
661
662 class addsub_shifted_imm_neg<ValueType Ty>
663     : Operand<Ty> {
664   let EncoderMethod = "getAddSubImmOpValue";
665   let ParserMatchClass = AddSubImmNegOperand;
666   let MIOperandInfo = (ops i32imm, i32imm);
667 }
668
669 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
670 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
671 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
672 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
673
674 class neg_addsub_shifted_imm<ValueType Ty>
675     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
676   let PrintMethod = "printAddSubImm";
677   let EncoderMethod = "getAddSubImmOpValue";
678   let ParserMatchClass = AddSubImmOperand;
679   let MIOperandInfo = (ops i32imm, i32imm);
680 }
681
682 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
683 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
684
685 // An extend operand:
686 //  {5-3} - extend type
687 //  {2-0} - imm3
688 def arith_extend : Operand<i32> {
689   let PrintMethod = "printArithExtend";
690   let ParserMatchClass = ExtendOperand;
691 }
692 def arith_extend64 : Operand<i32> {
693   let PrintMethod = "printArithExtend";
694   let ParserMatchClass = ExtendOperand64;
695 }
696
697 // 'extend' that's a lsl of a 64-bit register.
698 def arith_extendlsl64 : Operand<i32> {
699   let PrintMethod = "printArithExtend";
700   let ParserMatchClass = ExtendOperandLSL64;
701 }
702
703 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
704                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
705   let PrintMethod = "printExtendedRegister";
706   let MIOperandInfo = (ops GPR32, arith_extend);
707 }
708
709 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
710                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
711   let PrintMethod = "printExtendedRegister";
712   let MIOperandInfo = (ops GPR32, arith_extend64);
713 }
714
715 // Floating-point immediate.
716 def fpimm32 : Operand<f32>,
717               PatLeaf<(f32 fpimm), [{
718       return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
719     }], SDNodeXForm<fpimm, [{
720       APFloat InVal = N->getValueAPF();
721       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
722       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
723     }]>> {
724   let ParserMatchClass = FPImmOperand;
725   let PrintMethod = "printFPImmOperand";
726 }
727 def fpimm64 : Operand<f64>,
728               PatLeaf<(f64 fpimm), [{
729       return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
730     }], SDNodeXForm<fpimm, [{
731       APFloat InVal = N->getValueAPF();
732       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
733       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
734     }]>> {
735   let ParserMatchClass = FPImmOperand;
736   let PrintMethod = "printFPImmOperand";
737 }
738
739 def fpimm8 : Operand<i32> {
740   let ParserMatchClass = FPImmOperand;
741   let PrintMethod = "printFPImmOperand";
742 }
743
744 def fpimm0 : PatLeaf<(fpimm), [{
745   return N->isExactlyValue(+0.0);
746 }]>;
747
748 // Vector lane operands
749 class AsmVectorIndex<string Suffix> : AsmOperandClass {
750   let Name = "VectorIndex" # Suffix;
751   let DiagnosticType = "InvalidIndex" # Suffix;
752 }
753 def VectorIndex1Operand : AsmVectorIndex<"1">;
754 def VectorIndexBOperand : AsmVectorIndex<"B">;
755 def VectorIndexHOperand : AsmVectorIndex<"H">;
756 def VectorIndexSOperand : AsmVectorIndex<"S">;
757 def VectorIndexDOperand : AsmVectorIndex<"D">;
758
759 def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
760   return ((uint64_t)Imm) == 1;
761 }]> {
762   let ParserMatchClass = VectorIndex1Operand;
763   let PrintMethod = "printVectorIndex";
764   let MIOperandInfo = (ops i64imm);
765 }
766 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
767   return ((uint64_t)Imm) < 16;
768 }]> {
769   let ParserMatchClass = VectorIndexBOperand;
770   let PrintMethod = "printVectorIndex";
771   let MIOperandInfo = (ops i64imm);
772 }
773 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
774   return ((uint64_t)Imm) < 8;
775 }]> {
776   let ParserMatchClass = VectorIndexHOperand;
777   let PrintMethod = "printVectorIndex";
778   let MIOperandInfo = (ops i64imm);
779 }
780 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
781   return ((uint64_t)Imm) < 4;
782 }]> {
783   let ParserMatchClass = VectorIndexSOperand;
784   let PrintMethod = "printVectorIndex";
785   let MIOperandInfo = (ops i64imm);
786 }
787 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
788   return ((uint64_t)Imm) < 2;
789 }]> {
790   let ParserMatchClass = VectorIndexDOperand;
791   let PrintMethod = "printVectorIndex";
792   let MIOperandInfo = (ops i64imm);
793 }
794
795 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
796 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
797 // are encoded as the eight bit value 'abcdefgh'.
798 def simdimmtype10 : Operand<i32>,
799                     PatLeaf<(f64 fpimm), [{
800       return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
801                                                .bitcastToAPInt()
802                                                .getZExtValue());
803     }], SDNodeXForm<fpimm, [{
804       APFloat InVal = N->getValueAPF();
805       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
806                                                            .bitcastToAPInt()
807                                                            .getZExtValue());
808       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
809     }]>> {
810   let ParserMatchClass = SIMDImmType10Operand;
811   let PrintMethod = "printSIMDType10Operand";
812 }
813
814
815 //---
816 // System management
817 //---
818
819 // Base encoding for system instruction operands.
820 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
821 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
822                   list<dag> pattern = []>
823     : I<oops, iops, asm, operands, "", pattern> {
824   let Inst{31-22} = 0b1101010100;
825   let Inst{21}    = L;
826 }
827
828 // System instructions which do not have an Rt register.
829 class SimpleSystemI<bit L, dag iops, string asm, string operands,
830                     list<dag> pattern = []>
831     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
832   let Inst{4-0} = 0b11111;
833 }
834
835 // System instructions which have an Rt register.
836 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
837     : BaseSystemI<L, oops, iops, asm, operands>,
838       Sched<[WriteSys]> {
839   bits<5> Rt;
840   let Inst{4-0} = Rt;
841 }
842
843 // Hint instructions that take both a CRm and a 3-bit immediate.
844 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
845 // model patterns with sufficiently fine granularity
846 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
847   class HintI<string mnemonic>
848       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
849                       [(int_aarch64_hint imm0_127:$imm)]>,
850         Sched<[WriteHint]> {
851     bits <7> imm;
852     let Inst{20-12} = 0b000110010;
853     let Inst{11-5} = imm;
854   }
855
856 // System instructions taking a single literal operand which encodes into
857 // CRm. op2 differentiates the opcodes.
858 def BarrierAsmOperand : AsmOperandClass {
859   let Name = "Barrier";
860   let ParserMethod = "tryParseBarrierOperand";
861 }
862 def barrier_op : Operand<i32> {
863   let PrintMethod = "printBarrierOption";
864   let ParserMatchClass = BarrierAsmOperand;
865 }
866 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
867                  list<dag> pattern = []>
868     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
869       Sched<[WriteBarrier]> {
870   bits<4> CRm;
871   let Inst{20-12} = 0b000110011;
872   let Inst{11-8} = CRm;
873   let Inst{7-5} = opc;
874 }
875
876 // MRS/MSR system instructions. These have different operand classes because
877 // a different subset of registers can be accessed through each instruction.
878 def MRSSystemRegisterOperand : AsmOperandClass {
879   let Name = "MRSSystemRegister";
880   let ParserMethod = "tryParseSysReg";
881   let DiagnosticType = "MRS";
882 }
883 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
884 def mrs_sysreg_op : Operand<i32> {
885   let ParserMatchClass = MRSSystemRegisterOperand;
886   let DecoderMethod = "DecodeMRSSystemRegister";
887   let PrintMethod = "printMRSSystemRegister";
888 }
889
890 def MSRSystemRegisterOperand : AsmOperandClass {
891   let Name = "MSRSystemRegister";
892   let ParserMethod = "tryParseSysReg";
893   let DiagnosticType = "MSR";
894 }
895 def msr_sysreg_op : Operand<i32> {
896   let ParserMatchClass = MSRSystemRegisterOperand;
897   let DecoderMethod = "DecodeMSRSystemRegister";
898   let PrintMethod = "printMSRSystemRegister";
899 }
900
901 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
902                        "mrs", "\t$Rt, $systemreg"> {
903   bits<16> systemreg;
904   let Inst{20-5} = systemreg;
905 }
906
907 // FIXME: Some of these def NZCV, others don't. Best way to model that?
908 // Explicitly modeling each of the system register as a register class
909 // would do it, but feels like overkill at this point.
910 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
911                        "msr", "\t$systemreg, $Rt"> {
912   bits<16> systemreg;
913   let Inst{20-5} = systemreg;
914 }
915
916 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
917   let Name = "SystemPStateFieldWithImm0_15";
918   let ParserMethod = "tryParseSysReg";
919 }
920 def pstatefield4_op : Operand<i32> {
921   let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
922   let PrintMethod = "printSystemPStateField";
923 }
924
925 let Defs = [NZCV] in
926 class MSRpstateImm0_15
927   : SimpleSystemI<0, (ins pstatefield4_op:$pstatefield, imm0_15:$imm),
928                   "msr", "\t$pstatefield, $imm">,
929     Sched<[WriteSys]> {
930   bits<6> pstatefield;
931   bits<4> imm;
932   let Inst{20-19} = 0b00;
933   let Inst{18-16} = pstatefield{5-3};
934   let Inst{15-12} = 0b0100;
935   let Inst{11-8} = imm;
936   let Inst{7-5} = pstatefield{2-0};
937
938   let DecoderMethod = "DecodeSystemPStateInstruction";
939   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
940   // Fail the decoder should attempt to decode the instruction as MSRI.
941   let hasCompleteDecoder = 0;
942 }
943
944 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
945   let Name = "SystemPStateFieldWithImm0_1";
946   let ParserMethod = "tryParseSysReg";
947 }
948 def pstatefield1_op : Operand<i32> {
949   let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
950   let PrintMethod = "printSystemPStateField";
951 }
952
953 let Defs = [NZCV] in
954 class MSRpstateImm0_1
955   : SimpleSystemI<0, (ins pstatefield1_op:$pstatefield, imm0_1:$imm),
956                   "msr", "\t$pstatefield, $imm">,
957     Sched<[WriteSys]> {
958   bits<6> pstatefield;
959   bit imm;
960   let Inst{20-19} = 0b00;
961   let Inst{18-16} = pstatefield{5-3};
962   let Inst{15-9} = 0b0100000;
963   let Inst{8} = imm;
964   let Inst{7-5} = pstatefield{2-0};
965
966   let DecoderMethod = "DecodeSystemPStateInstruction";
967   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
968   // Fail the decoder should attempt to decode the instruction as MSRI.
969   let hasCompleteDecoder = 0;
970 }
971
972 // SYS and SYSL generic system instructions.
973 def SysCRAsmOperand : AsmOperandClass {
974   let Name = "SysCR";
975   let ParserMethod = "tryParseSysCROperand";
976 }
977
978 def sys_cr_op : Operand<i32> {
979   let PrintMethod = "printSysCROperand";
980   let ParserMatchClass = SysCRAsmOperand;
981 }
982
983 class SystemXtI<bit L, string asm>
984   : RtSystemI<L, (outs),
985        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
986        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
987   bits<3> op1;
988   bits<4> Cn;
989   bits<4> Cm;
990   bits<3> op2;
991   let Inst{20-19} = 0b01;
992   let Inst{18-16} = op1;
993   let Inst{15-12} = Cn;
994   let Inst{11-8}  = Cm;
995   let Inst{7-5}   = op2;
996 }
997
998 class SystemLXtI<bit L, string asm>
999   : RtSystemI<L, (outs),
1000        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1001        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1002   bits<3> op1;
1003   bits<4> Cn;
1004   bits<4> Cm;
1005   bits<3> op2;
1006   let Inst{20-19} = 0b01;
1007   let Inst{18-16} = op1;
1008   let Inst{15-12} = Cn;
1009   let Inst{11-8}  = Cm;
1010   let Inst{7-5}   = op2;
1011 }
1012
1013
1014 // Branch (register) instructions:
1015 //
1016 //  case opc of
1017 //    0001 blr
1018 //    0000 br
1019 //    0101 dret
1020 //    0100 eret
1021 //    0010 ret
1022 //    otherwise UNDEFINED
1023 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1024                     string operands, list<dag> pattern>
1025     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1026   let Inst{31-25} = 0b1101011;
1027   let Inst{24-21} = opc;
1028   let Inst{20-16} = 0b11111;
1029   let Inst{15-10} = 0b000000;
1030   let Inst{4-0}   = 0b00000;
1031 }
1032
1033 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1034     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1035   bits<5> Rn;
1036   let Inst{9-5} = Rn;
1037 }
1038
1039 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1040 class SpecialReturn<bits<4> opc, string asm>
1041     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1042   let Inst{9-5} = 0b11111;
1043 }
1044
1045 //---
1046 // Conditional branch instruction.
1047 //---
1048
1049 // Condition code.
1050 // 4-bit immediate. Pretty-printed as <cc>
1051 def ccode : Operand<i32> {
1052   let PrintMethod = "printCondCode";
1053   let ParserMatchClass = CondCode;
1054 }
1055 def inv_ccode : Operand<i32> {
1056   // AL and NV are invalid in the aliases which use inv_ccode
1057   let PrintMethod = "printInverseCondCode";
1058   let ParserMatchClass = CondCode;
1059   let MCOperandPredicate = [{
1060     return MCOp.isImm() &&
1061            MCOp.getImm() != AArch64CC::AL &&
1062            MCOp.getImm() != AArch64CC::NV;
1063   }];
1064 }
1065
1066 // Conditional branch target. 19-bit immediate. The low two bits of the target
1067 // offset are implied zero and so are not part of the immediate.
1068 def PCRelLabel19Operand : AsmOperandClass {
1069   let Name = "PCRelLabel19";
1070   let DiagnosticType = "InvalidLabel";
1071 }
1072 def am_brcond : Operand<OtherVT> {
1073   let EncoderMethod = "getCondBranchTargetOpValue";
1074   let DecoderMethod = "DecodePCRelLabel19";
1075   let PrintMethod = "printAlignedLabel";
1076   let ParserMatchClass = PCRelLabel19Operand;
1077 }
1078
1079 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1080                      "b", ".$cond\t$target", "",
1081                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1082                    Sched<[WriteBr]> {
1083   let isBranch = 1;
1084   let isTerminator = 1;
1085   let Uses = [NZCV];
1086
1087   bits<4> cond;
1088   bits<19> target;
1089   let Inst{31-24} = 0b01010100;
1090   let Inst{23-5} = target;
1091   let Inst{4} = 0;
1092   let Inst{3-0} = cond;
1093 }
1094
1095 //---
1096 // Compare-and-branch instructions.
1097 //---
1098 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1099     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1100          asm, "\t$Rt, $target", "",
1101          [(node regtype:$Rt, bb:$target)]>,
1102       Sched<[WriteBr]> {
1103   let isBranch = 1;
1104   let isTerminator = 1;
1105
1106   bits<5> Rt;
1107   bits<19> target;
1108   let Inst{30-25} = 0b011010;
1109   let Inst{24}    = op;
1110   let Inst{23-5}  = target;
1111   let Inst{4-0}   = Rt;
1112 }
1113
1114 multiclass CmpBranch<bit op, string asm, SDNode node> {
1115   def W : BaseCmpBranch<GPR32, op, asm, node> {
1116     let Inst{31} = 0;
1117   }
1118   def X : BaseCmpBranch<GPR64, op, asm, node> {
1119     let Inst{31} = 1;
1120   }
1121 }
1122
1123 //---
1124 // Test-bit-and-branch instructions.
1125 //---
1126 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1127 // the target offset are implied zero and so are not part of the immediate.
1128 def BranchTarget14Operand : AsmOperandClass {
1129   let Name = "BranchTarget14";
1130 }
1131 def am_tbrcond : Operand<OtherVT> {
1132   let EncoderMethod = "getTestBranchTargetOpValue";
1133   let PrintMethod = "printAlignedLabel";
1134   let ParserMatchClass = BranchTarget14Operand;
1135 }
1136
1137 // AsmOperand classes to emit (or not) special diagnostics
1138 def TBZImm0_31Operand : AsmOperandClass {
1139   let Name = "TBZImm0_31";
1140   let PredicateMethod = "isImm0_31";
1141   let RenderMethod = "addImm0_31Operands";
1142 }
1143 def TBZImm32_63Operand : AsmOperandClass {
1144   let Name = "Imm32_63";
1145   let DiagnosticType = "InvalidImm0_63";
1146 }
1147
1148 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1149   return (((uint32_t)Imm) < 32);
1150 }]> {
1151   let ParserMatchClass = matcher;
1152 }
1153
1154 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1155 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1156
1157 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1158   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1159 }]> {
1160   let ParserMatchClass = TBZImm32_63Operand;
1161 }
1162
1163 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1164                      bit op, string asm, SDNode node>
1165     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1166        asm, "\t$Rt, $bit_off, $target", "",
1167        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1168       Sched<[WriteBr]> {
1169   let isBranch = 1;
1170   let isTerminator = 1;
1171
1172   bits<5> Rt;
1173   bits<6> bit_off;
1174   bits<14> target;
1175
1176   let Inst{30-25} = 0b011011;
1177   let Inst{24}    = op;
1178   let Inst{23-19} = bit_off{4-0};
1179   let Inst{18-5}  = target;
1180   let Inst{4-0}   = Rt;
1181
1182   let DecoderMethod = "DecodeTestAndBranch";
1183 }
1184
1185 multiclass TestBranch<bit op, string asm, SDNode node> {
1186   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1187     let Inst{31} = 0;
1188   }
1189
1190   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1191     let Inst{31} = 1;
1192   }
1193
1194   // Alias X-reg with 0-31 imm to W-Reg.
1195   def : InstAlias<asm # "\t$Rd, $imm, $target",
1196                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1197                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1198   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1199             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1200             tbz_imm0_31_diag:$imm, bb:$target)>;
1201 }
1202
1203 //---
1204 // Unconditional branch (immediate) instructions.
1205 //---
1206 def BranchTarget26Operand : AsmOperandClass {
1207   let Name = "BranchTarget26";
1208   let DiagnosticType = "InvalidLabel";
1209 }
1210 def am_b_target : Operand<OtherVT> {
1211   let EncoderMethod = "getBranchTargetOpValue";
1212   let PrintMethod = "printAlignedLabel";
1213   let ParserMatchClass = BranchTarget26Operand;
1214 }
1215 def am_bl_target : Operand<i64> {
1216   let EncoderMethod = "getBranchTargetOpValue";
1217   let PrintMethod = "printAlignedLabel";
1218   let ParserMatchClass = BranchTarget26Operand;
1219 }
1220
1221 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1222     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1223   bits<26> addr;
1224   let Inst{31}    = op;
1225   let Inst{30-26} = 0b00101;
1226   let Inst{25-0}  = addr;
1227
1228   let DecoderMethod = "DecodeUnconditionalBranch";
1229 }
1230
1231 class BranchImm<bit op, string asm, list<dag> pattern>
1232     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1233 class CallImm<bit op, string asm, list<dag> pattern>
1234     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1235
1236 //---
1237 // Basic one-operand data processing instructions.
1238 //---
1239
1240 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1241 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1242                          SDPatternOperator node>
1243   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1244       [(set regtype:$Rd, (node regtype:$Rn))]>,
1245     Sched<[WriteI, ReadI]> {
1246   bits<5> Rd;
1247   bits<5> Rn;
1248
1249   let Inst{30-13} = 0b101101011000000000;
1250   let Inst{12-10} = opc;
1251   let Inst{9-5}   = Rn;
1252   let Inst{4-0}   = Rd;
1253 }
1254
1255 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1256 multiclass OneOperandData<bits<3> opc, string asm,
1257                           SDPatternOperator node = null_frag> {
1258   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1259     let Inst{31} = 0;
1260   }
1261
1262   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1263     let Inst{31} = 1;
1264   }
1265 }
1266
1267 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1268     : BaseOneOperandData<opc, GPR32, asm, node> {
1269   let Inst{31} = 0;
1270 }
1271
1272 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1273     : BaseOneOperandData<opc, GPR64, asm, node> {
1274   let Inst{31} = 1;
1275 }
1276
1277 //---
1278 // Basic two-operand data processing instructions.
1279 //---
1280 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1281                           list<dag> pattern>
1282     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1283         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1284       Sched<[WriteI, ReadI, ReadI]> {
1285   let Uses = [NZCV];
1286   bits<5> Rd;
1287   bits<5> Rn;
1288   bits<5> Rm;
1289   let Inst{30}    = isSub;
1290   let Inst{28-21} = 0b11010000;
1291   let Inst{20-16} = Rm;
1292   let Inst{15-10} = 0;
1293   let Inst{9-5}   = Rn;
1294   let Inst{4-0}   = Rd;
1295 }
1296
1297 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1298                       SDNode OpNode>
1299     : BaseBaseAddSubCarry<isSub, regtype, asm,
1300         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1301
1302 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1303                               SDNode OpNode>
1304     : BaseBaseAddSubCarry<isSub, regtype, asm,
1305         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1306          (implicit NZCV)]> {
1307   let Defs = [NZCV];
1308 }
1309
1310 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1311                        SDNode OpNode, SDNode OpNode_setflags> {
1312   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1313     let Inst{31} = 0;
1314     let Inst{29} = 0;
1315   }
1316   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1317     let Inst{31} = 1;
1318     let Inst{29} = 0;
1319   }
1320
1321   // Sets flags.
1322   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1323                                     OpNode_setflags> {
1324     let Inst{31} = 0;
1325     let Inst{29} = 1;
1326   }
1327   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1328                                     OpNode_setflags> {
1329     let Inst{31} = 1;
1330     let Inst{29} = 1;
1331   }
1332 }
1333
1334 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1335                      SDPatternOperator OpNode>
1336   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1337       asm, "\t$Rd, $Rn, $Rm", "",
1338       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1339   bits<5> Rd;
1340   bits<5> Rn;
1341   bits<5> Rm;
1342   let Inst{30-21} = 0b0011010110;
1343   let Inst{20-16} = Rm;
1344   let Inst{15-14} = 0b00;
1345   let Inst{13-10} = opc;
1346   let Inst{9-5}   = Rn;
1347   let Inst{4-0}   = Rd;
1348 }
1349
1350 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1351               SDPatternOperator OpNode>
1352     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1353   let Inst{10}    = isSigned;
1354 }
1355
1356 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1357   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1358            Sched<[WriteID32, ReadID, ReadID]> {
1359     let Inst{31} = 0;
1360   }
1361   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1362            Sched<[WriteID64, ReadID, ReadID]> {
1363     let Inst{31} = 1;
1364   }
1365 }
1366
1367 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1368                 SDPatternOperator OpNode = null_frag>
1369   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1370     Sched<[WriteIS, ReadI]> {
1371   let Inst{11-10} = shift_type;
1372 }
1373
1374 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1375   def Wr : BaseShift<shift_type, GPR32, asm> {
1376     let Inst{31} = 0;
1377   }
1378
1379   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1380     let Inst{31} = 1;
1381   }
1382
1383   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1384             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1385                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1386
1387   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1388             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1389
1390   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1391             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1392
1393   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1394             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1395 }
1396
1397 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1398     : InstAlias<asm#"\t$dst, $src1, $src2",
1399                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1400
1401 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1402                        RegisterClass addtype, string asm,
1403                        list<dag> pattern>
1404   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1405       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1406   bits<5> Rd;
1407   bits<5> Rn;
1408   bits<5> Rm;
1409   bits<5> Ra;
1410   let Inst{30-24} = 0b0011011;
1411   let Inst{23-21} = opc;
1412   let Inst{20-16} = Rm;
1413   let Inst{15}    = isSub;
1414   let Inst{14-10} = Ra;
1415   let Inst{9-5}   = Rn;
1416   let Inst{4-0}   = Rd;
1417 }
1418
1419 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1420   // MADD/MSUB generation is decided by MachineCombiner.cpp
1421   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1422       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1423       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1424     let Inst{31} = 0;
1425   }
1426
1427   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1428       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1429       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1430     let Inst{31} = 1;
1431   }
1432 }
1433
1434 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1435                    SDNode AccNode, SDNode ExtNode>
1436   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1437     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1438                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1439     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1440   let Inst{31} = 1;
1441 }
1442
1443 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1444   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1445       asm, "\t$Rd, $Rn, $Rm", "",
1446       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1447     Sched<[WriteIM64, ReadIM, ReadIM]> {
1448   bits<5> Rd;
1449   bits<5> Rn;
1450   bits<5> Rm;
1451   let Inst{31-24} = 0b10011011;
1452   let Inst{23-21} = opc;
1453   let Inst{20-16} = Rm;
1454   let Inst{15}    = 0;
1455   let Inst{9-5}   = Rn;
1456   let Inst{4-0}   = Rd;
1457
1458   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1459   // (i.e. all bits 1) but is ignored by the processor.
1460   let PostEncoderMethod = "fixMulHigh";
1461 }
1462
1463 class MulAccumWAlias<string asm, Instruction inst>
1464     : InstAlias<asm#"\t$dst, $src1, $src2",
1465                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1466 class MulAccumXAlias<string asm, Instruction inst>
1467     : InstAlias<asm#"\t$dst, $src1, $src2",
1468                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1469 class WideMulAccumAlias<string asm, Instruction inst>
1470     : InstAlias<asm#"\t$dst, $src1, $src2",
1471                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1472
1473 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1474               SDPatternOperator OpNode, string asm>
1475   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1476       asm, "\t$Rd, $Rn, $Rm", "",
1477       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1478     Sched<[WriteISReg, ReadI, ReadISReg]> {
1479   bits<5> Rd;
1480   bits<5> Rn;
1481   bits<5> Rm;
1482
1483   let Inst{31} = sf;
1484   let Inst{30-21} = 0b0011010110;
1485   let Inst{20-16} = Rm;
1486   let Inst{15-13} = 0b010;
1487   let Inst{12} = C;
1488   let Inst{11-10} = sz;
1489   let Inst{9-5} = Rn;
1490   let Inst{4-0} = Rd;
1491   let Predicates = [HasCRC];
1492 }
1493
1494 //---
1495 // Address generation.
1496 //---
1497
1498 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1499     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1500         pattern>,
1501       Sched<[WriteI]> {
1502   bits<5>  Xd;
1503   bits<21> label;
1504   let Inst{31}    = page;
1505   let Inst{30-29} = label{1-0};
1506   let Inst{28-24} = 0b10000;
1507   let Inst{23-5}  = label{20-2};
1508   let Inst{4-0}   = Xd;
1509
1510   let DecoderMethod = "DecodeAdrInstruction";
1511 }
1512
1513 //---
1514 // Move immediate.
1515 //---
1516
1517 def movimm32_imm : Operand<i32> {
1518   let ParserMatchClass = Imm0_65535Operand;
1519   let EncoderMethod = "getMoveWideImmOpValue";
1520   let PrintMethod = "printHexImm";
1521 }
1522 def movimm32_shift : Operand<i32> {
1523   let PrintMethod = "printShifter";
1524   let ParserMatchClass = MovImm32ShifterOperand;
1525 }
1526 def movimm64_shift : Operand<i32> {
1527   let PrintMethod = "printShifter";
1528   let ParserMatchClass = MovImm64ShifterOperand;
1529 }
1530
1531 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1532 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1533                         string asm>
1534   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1535        asm, "\t$Rd, $imm$shift", "", []>,
1536     Sched<[WriteImm]> {
1537   bits<5> Rd;
1538   bits<16> imm;
1539   bits<6> shift;
1540   let Inst{30-29} = opc;
1541   let Inst{28-23} = 0b100101;
1542   let Inst{22-21} = shift{5-4};
1543   let Inst{20-5}  = imm;
1544   let Inst{4-0}   = Rd;
1545
1546   let DecoderMethod = "DecodeMoveImmInstruction";
1547 }
1548
1549 multiclass MoveImmediate<bits<2> opc, string asm> {
1550   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1551     let Inst{31} = 0;
1552   }
1553
1554   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1555     let Inst{31} = 1;
1556   }
1557 }
1558
1559 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1560 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1561                           string asm>
1562   : I<(outs regtype:$Rd),
1563       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1564        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1565     Sched<[WriteI, ReadI]> {
1566   bits<5> Rd;
1567   bits<16> imm;
1568   bits<6> shift;
1569   let Inst{30-29} = opc;
1570   let Inst{28-23} = 0b100101;
1571   let Inst{22-21} = shift{5-4};
1572   let Inst{20-5}  = imm;
1573   let Inst{4-0}   = Rd;
1574
1575   let DecoderMethod = "DecodeMoveImmInstruction";
1576 }
1577
1578 multiclass InsertImmediate<bits<2> opc, string asm> {
1579   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1580     let Inst{31} = 0;
1581   }
1582
1583   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1584     let Inst{31} = 1;
1585   }
1586 }
1587
1588 //---
1589 // Add/Subtract
1590 //---
1591
1592 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1593                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1594                     string asm, SDPatternOperator OpNode>
1595     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1596         asm, "\t$Rd, $Rn, $imm", "",
1597         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1598       Sched<[WriteI, ReadI]>  {
1599   bits<5>  Rd;
1600   bits<5>  Rn;
1601   bits<14> imm;
1602   let Inst{30}    = isSub;
1603   let Inst{29}    = setFlags;
1604   let Inst{28-24} = 0b10001;
1605   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1606   let Inst{21-10} = imm{11-0};
1607   let Inst{9-5}   = Rn;
1608   let Inst{4-0}   = Rd;
1609   let DecoderMethod = "DecodeBaseAddSubImm";
1610 }
1611
1612 class BaseAddSubRegPseudo<RegisterClass regtype,
1613                           SDPatternOperator OpNode>
1614     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1615              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1616       Sched<[WriteI, ReadI, ReadI]>;
1617
1618 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1619                      arith_shifted_reg shifted_regtype, string asm,
1620                      SDPatternOperator OpNode>
1621     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1622         asm, "\t$Rd, $Rn, $Rm", "",
1623         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1624       Sched<[WriteISReg, ReadI, ReadISReg]> {
1625   // The operands are in order to match the 'addr' MI operands, so we
1626   // don't need an encoder method and by-name matching. Just use the default
1627   // in-order handling. Since we're using by-order, make sure the names
1628   // do not match.
1629   bits<5> dst;
1630   bits<5> src1;
1631   bits<5> src2;
1632   bits<8> shift;
1633   let Inst{30}    = isSub;
1634   let Inst{29}    = setFlags;
1635   let Inst{28-24} = 0b01011;
1636   let Inst{23-22} = shift{7-6};
1637   let Inst{21}    = 0;
1638   let Inst{20-16} = src2;
1639   let Inst{15-10} = shift{5-0};
1640   let Inst{9-5}   = src1;
1641   let Inst{4-0}   = dst;
1642
1643   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1644 }
1645
1646 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1647                      RegisterClass src1Regtype, Operand src2Regtype,
1648                      string asm, SDPatternOperator OpNode>
1649     : I<(outs dstRegtype:$R1),
1650         (ins src1Regtype:$R2, src2Regtype:$R3),
1651         asm, "\t$R1, $R2, $R3", "",
1652         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1653       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1654   bits<5> Rd;
1655   bits<5> Rn;
1656   bits<5> Rm;
1657   bits<6> ext;
1658   let Inst{30}    = isSub;
1659   let Inst{29}    = setFlags;
1660   let Inst{28-24} = 0b01011;
1661   let Inst{23-21} = 0b001;
1662   let Inst{20-16} = Rm;
1663   let Inst{15-13} = ext{5-3};
1664   let Inst{12-10} = ext{2-0};
1665   let Inst{9-5}   = Rn;
1666   let Inst{4-0}   = Rd;
1667
1668   let DecoderMethod = "DecodeAddSubERegInstruction";
1669 }
1670
1671 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1672 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1673                        RegisterClass src1Regtype, RegisterClass src2Regtype,
1674                        Operand ext_op, string asm>
1675     : I<(outs dstRegtype:$Rd),
1676         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1677         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1678       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1679   bits<5> Rd;
1680   bits<5> Rn;
1681   bits<5> Rm;
1682   bits<6> ext;
1683   let Inst{30}    = isSub;
1684   let Inst{29}    = setFlags;
1685   let Inst{28-24} = 0b01011;
1686   let Inst{23-21} = 0b001;
1687   let Inst{20-16} = Rm;
1688   let Inst{15}    = ext{5};
1689   let Inst{12-10} = ext{2-0};
1690   let Inst{9-5}   = Rn;
1691   let Inst{4-0}   = Rd;
1692
1693   let DecoderMethod = "DecodeAddSubERegInstruction";
1694 }
1695
1696 // Aliases for register+register add/subtract.
1697 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1698                      RegisterClass src1Regtype, RegisterClass src2Regtype,
1699                      int shiftExt>
1700     : InstAlias<asm#"\t$dst, $src1, $src2",
1701                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1702                       shiftExt)>;
1703
1704 multiclass AddSub<bit isSub, string mnemonic, string alias,
1705                   SDPatternOperator OpNode = null_frag> {
1706   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1707   // Add/Subtract immediate
1708   // Increase the weight of the immediate variant to try to match it before
1709   // the extended register variant.
1710   // We used to match the register variant before the immediate when the
1711   // register argument could be implicitly zero-extended.
1712   let AddedComplexity = 6 in
1713   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1714                            mnemonic, OpNode> {
1715     let Inst{31} = 0;
1716   }
1717   let AddedComplexity = 6 in
1718   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1719                            mnemonic, OpNode> {
1720     let Inst{31} = 1;
1721   }
1722
1723   // Add/Subtract register - Only used for CodeGen
1724   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1725   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1726
1727   // Add/Subtract shifted register
1728   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1729                            OpNode> {
1730     let Inst{31} = 0;
1731   }
1732   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1733                            OpNode> {
1734     let Inst{31} = 1;
1735   }
1736   }
1737
1738   // Add/Subtract extended register
1739   let AddedComplexity = 1, hasSideEffects = 0 in {
1740   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1741                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1742     let Inst{31} = 0;
1743   }
1744   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1745                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1746     let Inst{31} = 1;
1747   }
1748   }
1749
1750   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1751                                arith_extendlsl64, mnemonic> {
1752     // UXTX and SXTX only.
1753     let Inst{14-13} = 0b11;
1754     let Inst{31} = 1;
1755   }
1756
1757   // add Rd, Rb, -imm -> sub Rd, Rn, imm
1758   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1759                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
1760                       addsub_shifted_imm32_neg:$imm), 0>;
1761   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1762                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
1763                        addsub_shifted_imm64_neg:$imm), 0>;
1764
1765   // Register/register aliases with no shift when SP is not used.
1766   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1767                        GPR32, GPR32, GPR32, 0>;
1768   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1769                        GPR64, GPR64, GPR64, 0>;
1770
1771   // Register/register aliases with no shift when either the destination or
1772   // first source register is SP.
1773   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1774                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1775   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1776                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1777   def : AddSubRegAlias<mnemonic,
1778                        !cast<Instruction>(NAME#"Xrx64"),
1779                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1780   def : AddSubRegAlias<mnemonic,
1781                        !cast<Instruction>(NAME#"Xrx64"),
1782                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1783 }
1784
1785 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
1786                    string alias, string cmpAlias> {
1787   let isCompare = 1, Defs = [NZCV] in {
1788   // Add/Subtract immediate
1789   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1790                            mnemonic, OpNode> {
1791     let Inst{31} = 0;
1792   }
1793   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1794                            mnemonic, OpNode> {
1795     let Inst{31} = 1;
1796   }
1797
1798   // Add/Subtract register
1799   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1800   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1801
1802   // Add/Subtract shifted register
1803   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1804                            OpNode> {
1805     let Inst{31} = 0;
1806   }
1807   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1808                            OpNode> {
1809     let Inst{31} = 1;
1810   }
1811
1812   // Add/Subtract extended register
1813   let AddedComplexity = 1 in {
1814   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1815                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1816     let Inst{31} = 0;
1817   }
1818   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1819                            arith_extended_reg32<i64>, mnemonic, OpNode> {
1820     let Inst{31} = 1;
1821   }
1822   }
1823
1824   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1825                                arith_extendlsl64, mnemonic> {
1826     // UXTX and SXTX only.
1827     let Inst{14-13} = 0b11;
1828     let Inst{31} = 1;
1829   }
1830   } // Defs = [NZCV]
1831
1832   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
1833   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1834                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
1835                       addsub_shifted_imm32_neg:$imm), 0>;
1836   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1837                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
1838                        addsub_shifted_imm64_neg:$imm), 0>;
1839
1840   // Compare aliases
1841   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1842                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1843   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1844                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1845   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1846                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1847   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1848                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1849   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1850                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1851   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1852                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1853   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1854                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1855
1856   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
1857   def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1858                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
1859   def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1860                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
1861
1862   // Compare shorthands
1863   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1864                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1865   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1866                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1867   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1868                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1869   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1870                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1871
1872   // Register/register aliases with no shift when SP is not used.
1873   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1874                        GPR32, GPR32, GPR32, 0>;
1875   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1876                        GPR64, GPR64, GPR64, 0>;
1877
1878   // Register/register aliases with no shift when the first source register
1879   // is SP.
1880   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1881                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1882   def : AddSubRegAlias<mnemonic,
1883                        !cast<Instruction>(NAME#"Xrx64"),
1884                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1885 }
1886
1887 //---
1888 // Extract
1889 //---
1890 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1891                                       SDTCisPtrTy<3>]>;
1892 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1893
1894 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1895                      list<dag> patterns>
1896     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1897          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1898       Sched<[WriteExtr, ReadExtrHi]> {
1899   bits<5> Rd;
1900   bits<5> Rn;
1901   bits<5> Rm;
1902   bits<6> imm;
1903
1904   let Inst{30-23} = 0b00100111;
1905   let Inst{21}    = 0;
1906   let Inst{20-16} = Rm;
1907   let Inst{15-10} = imm;
1908   let Inst{9-5}   = Rn;
1909   let Inst{4-0}   = Rd;
1910 }
1911
1912 multiclass ExtractImm<string asm> {
1913   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1914                       [(set GPR32:$Rd,
1915                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1916     let Inst{31} = 0;
1917     let Inst{22} = 0;
1918     // imm<5> must be zero.
1919     let imm{5}   = 0;
1920   }
1921   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1922                       [(set GPR64:$Rd,
1923                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1924
1925     let Inst{31} = 1;
1926     let Inst{22} = 1;
1927   }
1928 }
1929
1930 //---
1931 // Bitfield
1932 //---
1933
1934 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1935 class BaseBitfieldImm<bits<2> opc,
1936                       RegisterClass regtype, Operand imm_type, string asm>
1937     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1938          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1939       Sched<[WriteIS, ReadI]> {
1940   bits<5> Rd;
1941   bits<5> Rn;
1942   bits<6> immr;
1943   bits<6> imms;
1944
1945   let Inst{30-29} = opc;
1946   let Inst{28-23} = 0b100110;
1947   let Inst{21-16} = immr;
1948   let Inst{15-10} = imms;
1949   let Inst{9-5}   = Rn;
1950   let Inst{4-0}   = Rd;
1951 }
1952
1953 multiclass BitfieldImm<bits<2> opc, string asm> {
1954   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1955     let Inst{31} = 0;
1956     let Inst{22} = 0;
1957     // imms<5> and immr<5> must be zero, else ReservedValue().
1958     let Inst{21} = 0;
1959     let Inst{15} = 0;
1960   }
1961   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1962     let Inst{31} = 1;
1963     let Inst{22} = 1;
1964   }
1965 }
1966
1967 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1968 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1969                       RegisterClass regtype, Operand imm_type, string asm>
1970     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1971                              imm_type:$imms),
1972          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1973       Sched<[WriteIS, ReadI]> {
1974   bits<5> Rd;
1975   bits<5> Rn;
1976   bits<6> immr;
1977   bits<6> imms;
1978
1979   let Inst{30-29} = opc;
1980   let Inst{28-23} = 0b100110;
1981   let Inst{21-16} = immr;
1982   let Inst{15-10} = imms;
1983   let Inst{9-5}   = Rn;
1984   let Inst{4-0}   = Rd;
1985 }
1986
1987 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1988   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1989     let Inst{31} = 0;
1990     let Inst{22} = 0;
1991     // imms<5> and immr<5> must be zero, else ReservedValue().
1992     let Inst{21} = 0;
1993     let Inst{15} = 0;
1994   }
1995   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1996     let Inst{31} = 1;
1997     let Inst{22} = 1;
1998   }
1999 }
2000
2001 //---
2002 // Logical
2003 //---
2004
2005 // Logical (immediate)
2006 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2007                      RegisterClass sregtype, Operand imm_type, string asm,
2008                      list<dag> pattern>
2009     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2010          asm, "\t$Rd, $Rn, $imm", "", pattern>,
2011       Sched<[WriteI, ReadI]> {
2012   bits<5>  Rd;
2013   bits<5>  Rn;
2014   bits<13> imm;
2015   let Inst{30-29} = opc;
2016   let Inst{28-23} = 0b100100;
2017   let Inst{22}    = imm{12};
2018   let Inst{21-16} = imm{11-6};
2019   let Inst{15-10} = imm{5-0};
2020   let Inst{9-5}   = Rn;
2021   let Inst{4-0}   = Rd;
2022
2023   let DecoderMethod = "DecodeLogicalImmInstruction";
2024 }
2025
2026 // Logical (shifted register)
2027 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2028                       logical_shifted_reg shifted_regtype, string asm,
2029                       list<dag> pattern>
2030     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2031         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2032       Sched<[WriteISReg, ReadI, ReadISReg]> {
2033   // The operands are in order to match the 'addr' MI operands, so we
2034   // don't need an encoder method and by-name matching. Just use the default
2035   // in-order handling. Since we're using by-order, make sure the names
2036   // do not match.
2037   bits<5> dst;
2038   bits<5> src1;
2039   bits<5> src2;
2040   bits<8> shift;
2041   let Inst{30-29} = opc;
2042   let Inst{28-24} = 0b01010;
2043   let Inst{23-22} = shift{7-6};
2044   let Inst{21}    = N;
2045   let Inst{20-16} = src2;
2046   let Inst{15-10} = shift{5-0};
2047   let Inst{9-5}   = src1;
2048   let Inst{4-0}   = dst;
2049
2050   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2051 }
2052
2053 // Aliases for register+register logical instructions.
2054 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2055     : InstAlias<asm#"\t$dst, $src1, $src2",
2056                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2057
2058 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2059                       string Alias> {
2060   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2061   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2062                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2063                                                logical_imm32:$imm))]> {
2064     let Inst{31} = 0;
2065     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2066   }
2067   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2068   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2069                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2070                                                logical_imm64:$imm))]> {
2071     let Inst{31} = 1;
2072   }
2073
2074   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2075                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2076                       logical_imm32_not:$imm), 0>;
2077   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2078                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2079                        logical_imm64_not:$imm), 0>;
2080 }
2081
2082 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2083                        string Alias> {
2084   let isCompare = 1, Defs = [NZCV] in {
2085   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2086       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2087     let Inst{31} = 0;
2088     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2089   }
2090   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2091       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2092     let Inst{31} = 1;
2093   }
2094   } // end Defs = [NZCV]
2095
2096   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2097                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2098                       logical_imm32_not:$imm), 0>;
2099   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2100                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2101                        logical_imm64_not:$imm), 0>;
2102 }
2103
2104 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2105     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2106              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2107       Sched<[WriteI, ReadI, ReadI]>;
2108
2109 // Split from LogicalImm as not all instructions have both.
2110 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2111                       SDPatternOperator OpNode> {
2112   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2113   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2114   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2115   }
2116
2117   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2118                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2119                                                  logical_shifted_reg32:$Rm))]> {
2120     let Inst{31} = 0;
2121   }
2122   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2123                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2124                                                  logical_shifted_reg64:$Rm))]> {
2125     let Inst{31} = 1;
2126   }
2127
2128   def : LogicalRegAlias<mnemonic,
2129                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2130   def : LogicalRegAlias<mnemonic,
2131                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2132 }
2133
2134 // Split from LogicalReg to allow setting NZCV Defs
2135 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2136                        SDPatternOperator OpNode = null_frag> {
2137   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2138   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2139   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2140
2141   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2142             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2143     let Inst{31} = 0;
2144   }
2145   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2146             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2147     let Inst{31} = 1;
2148   }
2149   } // Defs = [NZCV]
2150
2151   def : LogicalRegAlias<mnemonic,
2152                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2153   def : LogicalRegAlias<mnemonic,
2154                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2155 }
2156
2157 //---
2158 // Conditionally set flags
2159 //---
2160
2161 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2162 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2163                             string mnemonic, SDNode OpNode>
2164     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2165          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2166          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2167                              (i32 imm:$cond), NZCV))]>,
2168       Sched<[WriteI, ReadI]> {
2169   let Uses = [NZCV];
2170   let Defs = [NZCV];
2171
2172   bits<5> Rn;
2173   bits<5> imm;
2174   bits<4> nzcv;
2175   bits<4> cond;
2176
2177   let Inst{30}    = op;
2178   let Inst{29-21} = 0b111010010;
2179   let Inst{20-16} = imm;
2180   let Inst{15-12} = cond;
2181   let Inst{11-10} = 0b10;
2182   let Inst{9-5}   = Rn;
2183   let Inst{4}     = 0b0;
2184   let Inst{3-0}   = nzcv;
2185 }
2186
2187 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2188 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2189                             SDNode OpNode>
2190     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2191          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2192          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2193                              (i32 imm:$cond), NZCV))]>,
2194       Sched<[WriteI, ReadI, ReadI]> {
2195   let Uses = [NZCV];
2196   let Defs = [NZCV];
2197
2198   bits<5> Rn;
2199   bits<5> Rm;
2200   bits<4> nzcv;
2201   bits<4> cond;
2202
2203   let Inst{30}    = op;
2204   let Inst{29-21} = 0b111010010;
2205   let Inst{20-16} = Rm;
2206   let Inst{15-12} = cond;
2207   let Inst{11-10} = 0b00;
2208   let Inst{9-5}   = Rn;
2209   let Inst{4}     = 0b0;
2210   let Inst{3-0}   = nzcv;
2211 }
2212
2213 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2214   // immediate operand variants
2215   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2216     let Inst{31} = 0;
2217   }
2218   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2219     let Inst{31} = 1;
2220   }
2221   // register operand variants
2222   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2223     let Inst{31} = 0;
2224   }
2225   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2226     let Inst{31} = 1;
2227   }
2228 }
2229
2230 //---
2231 // Conditional select
2232 //---
2233
2234 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2235     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2236          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2237          [(set regtype:$Rd,
2238                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2239       Sched<[WriteI, ReadI, ReadI]> {
2240   let Uses = [NZCV];
2241
2242   bits<5> Rd;
2243   bits<5> Rn;
2244   bits<5> Rm;
2245   bits<4> cond;
2246
2247   let Inst{30}    = op;
2248   let Inst{29-21} = 0b011010100;
2249   let Inst{20-16} = Rm;
2250   let Inst{15-12} = cond;
2251   let Inst{11-10} = op2;
2252   let Inst{9-5}   = Rn;
2253   let Inst{4-0}   = Rd;
2254 }
2255
2256 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2257   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2258     let Inst{31} = 0;
2259   }
2260   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2261     let Inst{31} = 1;
2262   }
2263 }
2264
2265 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2266                        PatFrag frag>
2267     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2268          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2269          [(set regtype:$Rd,
2270                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2271                (i32 imm:$cond), NZCV))]>,
2272       Sched<[WriteI, ReadI, ReadI]> {
2273   let Uses = [NZCV];
2274
2275   bits<5> Rd;
2276   bits<5> Rn;
2277   bits<5> Rm;
2278   bits<4> cond;
2279
2280   let Inst{30}    = op;
2281   let Inst{29-21} = 0b011010100;
2282   let Inst{20-16} = Rm;
2283   let Inst{15-12} = cond;
2284   let Inst{11-10} = op2;
2285   let Inst{9-5}   = Rn;
2286   let Inst{4-0}   = Rd;
2287 }
2288
2289 def inv_cond_XFORM : SDNodeXForm<imm, [{
2290   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2291   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2292                                    MVT::i32);
2293 }]>;
2294
2295 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2296   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2297     let Inst{31} = 0;
2298   }
2299   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2300     let Inst{31} = 1;
2301   }
2302
2303   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2304             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2305                                            (inv_cond_XFORM imm:$cond))>;
2306
2307   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2308             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2309                                            (inv_cond_XFORM imm:$cond))>;
2310 }
2311
2312 //---
2313 // Special Mask Value
2314 //---
2315 def maski8_or_more : Operand<i32>,
2316   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2317 }
2318 def maski16_or_more : Operand<i32>,
2319   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2320 }
2321
2322
2323 //---
2324 // Load/store
2325 //---
2326
2327 // (unsigned immediate)
2328 // Indexed for 8-bit registers. offset is in range [0,4095].
2329 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2330 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2331 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2332 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2333 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2334
2335 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2336   let Name = "UImm12Offset" # Scale;
2337   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2338   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2339   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2340 }
2341
2342 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2343 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2344 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2345 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2346 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2347
2348 class uimm12_scaled<int Scale> : Operand<i64> {
2349   let ParserMatchClass
2350    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2351   let EncoderMethod
2352    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2353   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2354 }
2355
2356 def uimm12s1 : uimm12_scaled<1>;
2357 def uimm12s2 : uimm12_scaled<2>;
2358 def uimm12s4 : uimm12_scaled<4>;
2359 def uimm12s8 : uimm12_scaled<8>;
2360 def uimm12s16 : uimm12_scaled<16>;
2361
2362 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2363                       string asm, list<dag> pattern>
2364     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2365   bits<5> Rt;
2366
2367   bits<5> Rn;
2368   bits<12> offset;
2369
2370   let Inst{31-30} = sz;
2371   let Inst{29-27} = 0b111;
2372   let Inst{26}    = V;
2373   let Inst{25-24} = 0b01;
2374   let Inst{23-22} = opc;
2375   let Inst{21-10} = offset;
2376   let Inst{9-5}   = Rn;
2377   let Inst{4-0}   = Rt;
2378
2379   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2380 }
2381
2382 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2383                   Operand indextype, string asm, list<dag> pattern> {
2384   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2385   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2386                            (ins GPR64sp:$Rn, indextype:$offset),
2387                            asm, pattern>,
2388            Sched<[WriteLD]>;
2389
2390   def : InstAlias<asm # "\t$Rt, [$Rn]",
2391                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2392 }
2393
2394 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2395              Operand indextype, string asm, list<dag> pattern> {
2396   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2397   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2398                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2399                            asm, pattern>,
2400            Sched<[WriteST]>;
2401
2402   def : InstAlias<asm # "\t$Rt, [$Rn]",
2403                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2404 }
2405
2406 def PrefetchOperand : AsmOperandClass {
2407   let Name = "Prefetch";
2408   let ParserMethod = "tryParsePrefetch";
2409 }
2410 def prfop : Operand<i32> {
2411   let PrintMethod = "printPrefetchOp";
2412   let ParserMatchClass = PrefetchOperand;
2413 }
2414
2415 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2416 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2417     : BaseLoadStoreUI<sz, V, opc,
2418                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2419                       asm, pat>,
2420       Sched<[WriteLD]>;
2421
2422 //---
2423 // Load literal
2424 //---
2425
2426 // Load literal address: 19-bit immediate. The low two bits of the target
2427 // offset are implied zero and so are not part of the immediate.
2428 def am_ldrlit : Operand<OtherVT> {
2429   let EncoderMethod = "getLoadLiteralOpValue";
2430   let DecoderMethod = "DecodePCRelLabel19";
2431   let PrintMethod = "printAlignedLabel";
2432   let ParserMatchClass = PCRelLabel19Operand;
2433 }
2434
2435 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2436 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2437     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2438         asm, "\t$Rt, $label", "", []>,
2439       Sched<[WriteLD]> {
2440   bits<5> Rt;
2441   bits<19> label;
2442   let Inst{31-30} = opc;
2443   let Inst{29-27} = 0b011;
2444   let Inst{26}    = V;
2445   let Inst{25-24} = 0b00;
2446   let Inst{23-5}  = label;
2447   let Inst{4-0}   = Rt;
2448 }
2449
2450 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2451 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2452     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2453         asm, "\t$Rt, $label", "", pat>,
2454       Sched<[WriteLD]> {
2455   bits<5> Rt;
2456   bits<19> label;
2457   let Inst{31-30} = opc;
2458   let Inst{29-27} = 0b011;
2459   let Inst{26}    = V;
2460   let Inst{25-24} = 0b00;
2461   let Inst{23-5}  = label;
2462   let Inst{4-0}   = Rt;
2463 }
2464
2465 //---
2466 // Load/store register offset
2467 //---
2468
2469 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2470 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2471 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2472 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2473 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2474
2475 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2476 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2477 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2478 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2479 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2480
2481 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2482   let Name = "Mem" # Reg # "Extend" # Width;
2483   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2484   let RenderMethod = "addMemExtendOperands";
2485   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2486 }
2487
2488 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2489   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2490   // the trivial shift.
2491   let RenderMethod = "addMemExtend8Operands";
2492 }
2493 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2494 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2495 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2496 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2497
2498 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2499   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2500   // the trivial shift.
2501   let RenderMethod = "addMemExtend8Operands";
2502 }
2503 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2504 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2505 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2506 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2507
2508 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2509         : Operand<i32> {
2510   let ParserMatchClass = ParserClass;
2511   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2512   let DecoderMethod = "DecodeMemExtend";
2513   let EncoderMethod = "getMemExtendOpValue";
2514   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2515 }
2516
2517 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2518 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2519 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2520 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2521 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2522
2523 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2524 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2525 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2526 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2527 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2528
2529 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2530                   Operand wextend, Operand xextend>  {
2531   // CodeGen-level pattern covering the entire addressing mode.
2532   ComplexPattern Wpat = windex;
2533   ComplexPattern Xpat = xindex;
2534
2535   // Asm-level Operand covering the valid "uxtw #3" style syntax.
2536   Operand Wext = wextend;
2537   Operand Xext = xextend;
2538 }
2539
2540 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2541 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2542 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2543 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2544 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2545                        ro_Xextend128>;
2546
2547 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2548                       string asm, dag ins, dag outs, list<dag> pat>
2549     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2550   bits<5> Rt;
2551   bits<5> Rn;
2552   bits<5> Rm;
2553   bits<2> extend;
2554   let Inst{31-30} = sz;
2555   let Inst{29-27} = 0b111;
2556   let Inst{26}    = V;
2557   let Inst{25-24} = 0b00;
2558   let Inst{23-22} = opc;
2559   let Inst{21}    = 1;
2560   let Inst{20-16} = Rm;
2561   let Inst{15}    = extend{1}; // sign extend Rm?
2562   let Inst{14}    = 1;
2563   let Inst{12}    = extend{0}; // do shift?
2564   let Inst{11-10} = 0b10;
2565   let Inst{9-5}   = Rn;
2566   let Inst{4-0}   = Rt;
2567 }
2568
2569 class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2570   : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
2571               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2572
2573 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2574                    string asm, ValueType Ty, SDPatternOperator loadop> {
2575   let AddedComplexity = 10 in
2576   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2577                  (outs regtype:$Rt),
2578                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2579                  [(set (Ty regtype:$Rt),
2580                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2581                                              ro_Wextend8:$extend)))]>,
2582            Sched<[WriteLDIdx, ReadAdrBase]> {
2583     let Inst{13} = 0b0;
2584   }
2585
2586   let AddedComplexity = 10 in
2587   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2588                  (outs regtype:$Rt),
2589                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2590                  [(set (Ty regtype:$Rt),
2591                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2592                                              ro_Xextend8:$extend)))]>,
2593            Sched<[WriteLDIdx, ReadAdrBase]> {
2594     let Inst{13} = 0b1;
2595   }
2596
2597   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2598 }
2599
2600 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2601                     string asm, ValueType Ty, SDPatternOperator storeop> {
2602   let AddedComplexity = 10 in
2603   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2604                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2605                  [(storeop (Ty regtype:$Rt),
2606                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2607                                          ro_Wextend8:$extend))]>,
2608             Sched<[WriteSTIdx, ReadAdrBase]> {
2609     let Inst{13} = 0b0;
2610   }
2611
2612   let AddedComplexity = 10 in
2613   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2614                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2615                  [(storeop (Ty regtype:$Rt),
2616                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2617                                          ro_Xextend8:$extend))]>,
2618             Sched<[WriteSTIdx, ReadAdrBase]> {
2619     let Inst{13} = 0b1;
2620   }
2621
2622   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2623 }
2624
2625 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2626                       string asm, dag ins, dag outs, list<dag> pat>
2627     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2628   bits<5> Rt;
2629   bits<5> Rn;
2630   bits<5> Rm;
2631   bits<2> extend;
2632   let Inst{31-30} = sz;
2633   let Inst{29-27} = 0b111;
2634   let Inst{26}    = V;
2635   let Inst{25-24} = 0b00;
2636   let Inst{23-22} = opc;
2637   let Inst{21}    = 1;
2638   let Inst{20-16} = Rm;
2639   let Inst{15}    = extend{1}; // sign extend Rm?
2640   let Inst{14}    = 1;
2641   let Inst{12}    = extend{0}; // do shift?
2642   let Inst{11-10} = 0b10;
2643   let Inst{9-5}   = Rn;
2644   let Inst{4-0}   = Rt;
2645 }
2646
2647 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2648                     string asm, ValueType Ty, SDPatternOperator loadop> {
2649   let AddedComplexity = 10 in
2650   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2651                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2652                  [(set (Ty regtype:$Rt),
2653                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2654                                               ro_Wextend16:$extend)))]>,
2655             Sched<[WriteLDIdx, ReadAdrBase]> {
2656     let Inst{13} = 0b0;
2657   }
2658
2659   let AddedComplexity = 10 in
2660   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2661                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2662                  [(set (Ty regtype:$Rt),
2663                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2664                                              ro_Xextend16:$extend)))]>,
2665             Sched<[WriteLDIdx, ReadAdrBase]> {
2666     let Inst{13} = 0b1;
2667   }
2668
2669   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2670 }
2671
2672 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2673                      string asm, ValueType Ty, SDPatternOperator storeop> {
2674   let AddedComplexity = 10 in
2675   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2676                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2677                 [(storeop (Ty regtype:$Rt),
2678                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2679                                          ro_Wextend16:$extend))]>,
2680            Sched<[WriteSTIdx, ReadAdrBase]> {
2681     let Inst{13} = 0b0;
2682   }
2683
2684   let AddedComplexity = 10 in
2685   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2686                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2687                 [(storeop (Ty regtype:$Rt),
2688                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2689                                          ro_Xextend16:$extend))]>,
2690            Sched<[WriteSTIdx, ReadAdrBase]> {
2691     let Inst{13} = 0b1;
2692   }
2693
2694   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2695 }
2696
2697 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2698                       string asm, dag ins, dag outs, list<dag> pat>
2699     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2700   bits<5> Rt;
2701   bits<5> Rn;
2702   bits<5> Rm;
2703   bits<2> extend;
2704   let Inst{31-30} = sz;
2705   let Inst{29-27} = 0b111;
2706   let Inst{26}    = V;
2707   let Inst{25-24} = 0b00;
2708   let Inst{23-22} = opc;
2709   let Inst{21}    = 1;
2710   let Inst{20-16} = Rm;
2711   let Inst{15}    = extend{1}; // sign extend Rm?
2712   let Inst{14}    = 1;
2713   let Inst{12}    = extend{0}; // do shift?
2714   let Inst{11-10} = 0b10;
2715   let Inst{9-5}   = Rn;
2716   let Inst{4-0}   = Rt;
2717 }
2718
2719 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2720                     string asm, ValueType Ty, SDPatternOperator loadop> {
2721   let AddedComplexity = 10 in
2722   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2723                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2724                  [(set (Ty regtype:$Rt),
2725                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2726                                               ro_Wextend32:$extend)))]>,
2727            Sched<[WriteLDIdx, ReadAdrBase]> {
2728     let Inst{13} = 0b0;
2729   }
2730
2731   let AddedComplexity = 10 in
2732   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2733                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2734                  [(set (Ty regtype:$Rt),
2735                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2736                                               ro_Xextend32:$extend)))]>,
2737            Sched<[WriteLDIdx, ReadAdrBase]> {
2738     let Inst{13} = 0b1;
2739   }
2740
2741   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2742 }
2743
2744 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2745                      string asm, ValueType Ty, SDPatternOperator storeop> {
2746   let AddedComplexity = 10 in
2747   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2748                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2749                 [(storeop (Ty regtype:$Rt),
2750                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2751                                          ro_Wextend32:$extend))]>,
2752             Sched<[WriteSTIdx, ReadAdrBase]> {
2753     let Inst{13} = 0b0;
2754   }
2755
2756   let AddedComplexity = 10 in
2757   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2758                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2759                 [(storeop (Ty regtype:$Rt),
2760                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2761                                         ro_Xextend32:$extend))]>,
2762             Sched<[WriteSTIdx, ReadAdrBase]> {
2763     let Inst{13} = 0b1;
2764   }
2765
2766   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2767 }
2768
2769 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2770                       string asm, dag ins, dag outs, list<dag> pat>
2771     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2772   bits<5> Rt;
2773   bits<5> Rn;
2774   bits<5> Rm;
2775   bits<2> extend;
2776   let Inst{31-30} = sz;
2777   let Inst{29-27} = 0b111;
2778   let Inst{26}    = V;
2779   let Inst{25-24} = 0b00;
2780   let Inst{23-22} = opc;
2781   let Inst{21}    = 1;
2782   let Inst{20-16} = Rm;
2783   let Inst{15}    = extend{1}; // sign extend Rm?
2784   let Inst{14}    = 1;
2785   let Inst{12}    = extend{0}; // do shift?
2786   let Inst{11-10} = 0b10;
2787   let Inst{9-5}   = Rn;
2788   let Inst{4-0}   = Rt;
2789 }
2790
2791 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2792                     string asm, ValueType Ty, SDPatternOperator loadop> {
2793   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2794   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2795                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2796                 [(set (Ty regtype:$Rt),
2797                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2798                                              ro_Wextend64:$extend)))]>,
2799            Sched<[WriteLDIdx, ReadAdrBase]> {
2800     let Inst{13} = 0b0;
2801   }
2802
2803   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2804   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2805                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2806                  [(set (Ty regtype:$Rt),
2807                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2808                                               ro_Xextend64:$extend)))]>,
2809            Sched<[WriteLDIdx, ReadAdrBase]> {
2810     let Inst{13} = 0b1;
2811   }
2812
2813   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2814 }
2815
2816 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2817                      string asm, ValueType Ty, SDPatternOperator storeop> {
2818   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2819   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2820                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2821                 [(storeop (Ty regtype:$Rt),
2822                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2823                                          ro_Wextend64:$extend))]>,
2824             Sched<[WriteSTIdx, ReadAdrBase]> {
2825     let Inst{13} = 0b0;
2826   }
2827
2828   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2829   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2830                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2831                 [(storeop (Ty regtype:$Rt),
2832                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2833                                          ro_Xextend64:$extend))]>,
2834             Sched<[WriteSTIdx, ReadAdrBase]> {
2835     let Inst{13} = 0b1;
2836   }
2837
2838   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2839 }
2840
2841 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2842                       string asm, dag ins, dag outs, list<dag> pat>
2843     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2844   bits<5> Rt;
2845   bits<5> Rn;
2846   bits<5> Rm;
2847   bits<2> extend;
2848   let Inst{31-30} = sz;
2849   let Inst{29-27} = 0b111;
2850   let Inst{26}    = V;
2851   let Inst{25-24} = 0b00;
2852   let Inst{23-22} = opc;
2853   let Inst{21}    = 1;
2854   let Inst{20-16} = Rm;
2855   let Inst{15}    = extend{1}; // sign extend Rm?
2856   let Inst{14}    = 1;
2857   let Inst{12}    = extend{0}; // do shift?
2858   let Inst{11-10} = 0b10;
2859   let Inst{9-5}   = Rn;
2860   let Inst{4-0}   = Rt;
2861 }
2862
2863 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2864                      string asm, ValueType Ty, SDPatternOperator loadop> {
2865   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2866   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2867                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2868                  [(set (Ty regtype:$Rt),
2869                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2870                                                ro_Wextend128:$extend)))]>,
2871             Sched<[WriteLDIdx, ReadAdrBase]> {
2872     let Inst{13} = 0b0;
2873   }
2874
2875   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2876   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2877                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2878                  [(set (Ty regtype:$Rt),
2879                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2880                                                ro_Xextend128:$extend)))]>,
2881             Sched<[WriteLDIdx, ReadAdrBase]> {
2882     let Inst{13} = 0b1;
2883   }
2884
2885   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2886 }
2887
2888 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2889                       string asm, ValueType Ty, SDPatternOperator storeop> {
2890   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2891   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2892                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2893                 [(storeop (Ty regtype:$Rt),
2894                           (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2895                                           ro_Wextend128:$extend))]>,
2896             Sched<[WriteSTIdx, ReadAdrBase]> {
2897     let Inst{13} = 0b0;
2898   }
2899
2900   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2901   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2902                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2903                 [(storeop (Ty regtype:$Rt),
2904                           (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2905                                           ro_Xextend128:$extend))]>,
2906             Sched<[WriteSTIdx, ReadAdrBase]> {
2907     let Inst{13} = 0b1;
2908   }
2909
2910   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2911 }
2912
2913 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2914 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2915                      string asm, list<dag> pat>
2916     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2917       Sched<[WriteLD]> {
2918   bits<5> Rt;
2919   bits<5> Rn;
2920   bits<5> Rm;
2921   bits<2> extend;
2922   let Inst{31-30} = sz;
2923   let Inst{29-27} = 0b111;
2924   let Inst{26}    = V;
2925   let Inst{25-24} = 0b00;
2926   let Inst{23-22} = opc;
2927   let Inst{21}    = 1;
2928   let Inst{20-16} = Rm;
2929   let Inst{15}    = extend{1}; // sign extend Rm?
2930   let Inst{14}    = 1;
2931   let Inst{12}    = extend{0}; // do shift?
2932   let Inst{11-10} = 0b10;
2933   let Inst{9-5}   = Rn;
2934   let Inst{4-0}   = Rt;
2935 }
2936
2937 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2938   def roW : BasePrefetchRO<sz, V, opc, (outs),
2939                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2940                 asm, [(AArch64Prefetch imm:$Rt,
2941                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2942                                                     ro_Wextend64:$extend))]> {
2943     let Inst{13} = 0b0;
2944   }
2945
2946   def roX : BasePrefetchRO<sz, V, opc, (outs),
2947                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2948                 asm,  [(AArch64Prefetch imm:$Rt,
2949                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2950                                                      ro_Xextend64:$extend))]> {
2951     let Inst{13} = 0b1;
2952   }
2953
2954   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2955                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2956                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2957 }
2958
2959 //---
2960 // Load/store unscaled immediate
2961 //---
2962
2963 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2964 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2965 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2966 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2967 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2968
2969 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2970                            string asm, list<dag> pattern>
2971     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
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} = 0b00;
2983   let Inst{9-5}   = Rn;
2984   let Inst{4-0}   = Rt;
2985
2986   let DecoderMethod = "DecodeSignedLdStInstruction";
2987 }
2988
2989 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2990                    string asm, list<dag> pattern> {
2991   let AddedComplexity = 1 in // try this before LoadUI
2992   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2993                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
2994           Sched<[WriteLD]>;
2995
2996   def : InstAlias<asm # "\t$Rt, [$Rn]",
2997                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2998 }
2999
3000 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3001                          string asm, list<dag> pattern> {
3002   let AddedComplexity = 1 in // try this before StoreUI
3003   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3004                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3005                                asm, pattern>,
3006           Sched<[WriteST]>;
3007
3008   def : InstAlias<asm # "\t$Rt, [$Rn]",
3009                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3010 }
3011
3012 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3013                             list<dag> pat> {
3014   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3015   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3016                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3017                                asm, pat>,
3018           Sched<[WriteLD]>;
3019
3020   def : InstAlias<asm # "\t$Rt, [$Rn]",
3021                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3022 }
3023
3024 //---
3025 // Load/store unscaled immediate, unprivileged
3026 //---
3027
3028 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3029                                 dag oops, dag iops, string asm>
3030     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3031   bits<5> Rt;
3032   bits<5> Rn;
3033   bits<9> offset;
3034   let Inst{31-30} = sz;
3035   let Inst{29-27} = 0b111;
3036   let Inst{26}    = V;
3037   let Inst{25-24} = 0b00;
3038   let Inst{23-22} = opc;
3039   let Inst{21}    = 0;
3040   let Inst{20-12} = offset;
3041   let Inst{11-10} = 0b10;
3042   let Inst{9-5}   = Rn;
3043   let Inst{4-0}   = Rt;
3044
3045   let DecoderMethod = "DecodeSignedLdStInstruction";
3046 }
3047
3048 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3049                             RegisterClass regtype, string asm> {
3050   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3051   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3052                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
3053           Sched<[WriteLD]>;
3054
3055   def : InstAlias<asm # "\t$Rt, [$Rn]",
3056                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3057 }
3058
3059 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3060                              RegisterClass regtype, string asm> {
3061   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3062   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3063                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3064                                  asm>,
3065           Sched<[WriteST]>;
3066
3067   def : InstAlias<asm # "\t$Rt, [$Rn]",
3068                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3069 }
3070
3071 //---
3072 // Load/store pre-indexed
3073 //---
3074
3075 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3076                           string asm, string cstr, list<dag> pat>
3077     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3078   bits<5> Rt;
3079   bits<5> Rn;
3080   bits<9> offset;
3081   let Inst{31-30} = sz;
3082   let Inst{29-27} = 0b111;
3083   let Inst{26}    = V;
3084   let Inst{25-24} = 0;
3085   let Inst{23-22} = opc;
3086   let Inst{21}    = 0;
3087   let Inst{20-12} = offset;
3088   let Inst{11-10} = 0b11;
3089   let Inst{9-5}   = Rn;
3090   let Inst{4-0}   = Rt;
3091
3092   let DecoderMethod = "DecodeSignedLdStInstruction";
3093 }
3094
3095 let hasSideEffects = 0 in {
3096 let mayStore = 0, mayLoad = 1 in
3097 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3098              string asm>
3099     : BaseLoadStorePreIdx<sz, V, opc,
3100                      (outs GPR64sp:$wback, regtype:$Rt),
3101                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3102                      "$Rn = $wback,@earlyclobber $wback", []>,
3103       Sched<[WriteLD, WriteAdr]>;
3104
3105 let mayStore = 1, mayLoad = 0 in
3106 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3107                   string asm, SDPatternOperator storeop, ValueType Ty>
3108     : BaseLoadStorePreIdx<sz, V, opc,
3109                       (outs GPR64sp:$wback),
3110                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3111                       asm, "$Rn = $wback,@earlyclobber $wback",
3112       [(set GPR64sp:$wback,
3113             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3114       Sched<[WriteAdr, WriteST]>;
3115 } // hasSideEffects = 0
3116
3117 //---
3118 // Load/store post-indexed
3119 //---
3120
3121 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3122                           string asm, string cstr, list<dag> pat>
3123     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3124   bits<5> Rt;
3125   bits<5> Rn;
3126   bits<9> offset;
3127   let Inst{31-30} = sz;
3128   let Inst{29-27} = 0b111;
3129   let Inst{26}    = V;
3130   let Inst{25-24} = 0b00;
3131   let Inst{23-22} = opc;
3132   let Inst{21}    = 0b0;
3133   let Inst{20-12} = offset;
3134   let Inst{11-10} = 0b01;
3135   let Inst{9-5}   = Rn;
3136   let Inst{4-0}   = Rt;
3137
3138   let DecoderMethod = "DecodeSignedLdStInstruction";
3139 }
3140
3141 let hasSideEffects = 0 in {
3142 let mayStore = 0, mayLoad = 1 in
3143 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3144              string asm>
3145     : BaseLoadStorePostIdx<sz, V, opc,
3146                       (outs GPR64sp:$wback, regtype:$Rt),
3147                       (ins GPR64sp:$Rn, simm9:$offset),
3148                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3149       Sched<[WriteLD, WriteI]>;
3150
3151 let mayStore = 1, mayLoad = 0 in
3152 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3153                    string asm, SDPatternOperator storeop, ValueType Ty>
3154     : BaseLoadStorePostIdx<sz, V, opc,
3155                       (outs GPR64sp:$wback),
3156                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3157                        asm, "$Rn = $wback,@earlyclobber $wback",
3158       [(set GPR64sp:$wback,
3159             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3160     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3161 } // hasSideEffects = 0
3162
3163
3164 //---
3165 // Load/store pair
3166 //---
3167
3168 // (indexed, offset)
3169
3170 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3171                               string asm>
3172     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3173   bits<5> Rt;
3174   bits<5> Rt2;
3175   bits<5> Rn;
3176   bits<7> offset;
3177   let Inst{31-30} = opc;
3178   let Inst{29-27} = 0b101;
3179   let Inst{26}    = V;
3180   let Inst{25-23} = 0b010;
3181   let Inst{22}    = L;
3182   let Inst{21-15} = offset;
3183   let Inst{14-10} = Rt2;
3184   let Inst{9-5}   = Rn;
3185   let Inst{4-0}   = Rt;
3186
3187   let DecoderMethod = "DecodePairLdStInstruction";
3188 }
3189
3190 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3191                           Operand indextype, string asm> {
3192   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3193   def i : BaseLoadStorePairOffset<opc, V, 1,
3194                                   (outs regtype:$Rt, regtype:$Rt2),
3195                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3196           Sched<[WriteLD, WriteLDHi]>;
3197
3198   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3199                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3200                                                   GPR64sp:$Rn, 0)>;
3201 }
3202
3203
3204 multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3205                            Operand indextype, string asm> {
3206   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3207   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3208                                   (ins regtype:$Rt, regtype:$Rt2,
3209                                        GPR64sp:$Rn, indextype:$offset),
3210                                   asm>,
3211           Sched<[WriteSTP]>;
3212
3213   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3214                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3215                                                   GPR64sp:$Rn, 0)>;
3216 }
3217
3218 // (pre-indexed)
3219 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3220                               string asm>
3221     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3222   bits<5> Rt;
3223   bits<5> Rt2;
3224   bits<5> Rn;
3225   bits<7> offset;
3226   let Inst{31-30} = opc;
3227   let Inst{29-27} = 0b101;
3228   let Inst{26}    = V;
3229   let Inst{25-23} = 0b011;
3230   let Inst{22}    = L;
3231   let Inst{21-15} = offset;
3232   let Inst{14-10} = Rt2;
3233   let Inst{9-5}   = Rn;
3234   let Inst{4-0}   = Rt;
3235
3236   let DecoderMethod = "DecodePairLdStInstruction";
3237 }
3238
3239 let hasSideEffects = 0 in {
3240 let mayStore = 0, mayLoad = 1 in
3241 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3242                      Operand indextype, string asm>
3243     : BaseLoadStorePairPreIdx<opc, V, 1,
3244                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3245                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3246       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3247
3248 let mayStore = 1, mayLoad = 0 in
3249 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3250                       Operand indextype, string asm>
3251     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3252                              (ins regtype:$Rt, regtype:$Rt2,
3253                                   GPR64sp:$Rn, indextype:$offset),
3254                              asm>,
3255       Sched<[WriteAdr, WriteSTP]>;
3256 } // hasSideEffects = 0
3257
3258 // (post-indexed)
3259
3260 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3261                               string asm>
3262     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3263   bits<5> Rt;
3264   bits<5> Rt2;
3265   bits<5> Rn;
3266   bits<7> offset;
3267   let Inst{31-30} = opc;
3268   let Inst{29-27} = 0b101;
3269   let Inst{26}    = V;
3270   let Inst{25-23} = 0b001;
3271   let Inst{22}    = L;
3272   let Inst{21-15} = offset;
3273   let Inst{14-10} = Rt2;
3274   let Inst{9-5}   = Rn;
3275   let Inst{4-0}   = Rt;
3276
3277   let DecoderMethod = "DecodePairLdStInstruction";
3278 }
3279
3280 let hasSideEffects = 0 in {
3281 let mayStore = 0, mayLoad = 1 in
3282 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3283                       Operand idxtype, string asm>
3284     : BaseLoadStorePairPostIdx<opc, V, 1,
3285                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3286                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3287       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3288
3289 let mayStore = 1, mayLoad = 0 in
3290 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3291                        Operand idxtype, string asm>
3292     : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3293                              (ins regtype:$Rt, regtype:$Rt2,
3294                                   GPR64sp:$Rn, idxtype:$offset),
3295                              asm>,
3296       Sched<[WriteAdr, WriteSTP]>;
3297 } // hasSideEffects = 0
3298
3299 //  (no-allocate)
3300
3301 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3302                               string asm>
3303     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3304   bits<5> Rt;
3305   bits<5> Rt2;
3306   bits<5> Rn;
3307   bits<7> offset;
3308   let Inst{31-30} = opc;
3309   let Inst{29-27} = 0b101;
3310   let Inst{26}    = V;
3311   let Inst{25-23} = 0b000;
3312   let Inst{22}    = L;
3313   let Inst{21-15} = offset;
3314   let Inst{14-10} = Rt2;
3315   let Inst{9-5}   = Rn;
3316   let Inst{4-0}   = Rt;
3317
3318   let DecoderMethod = "DecodePairLdStInstruction";
3319 }
3320
3321 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3322                            Operand indextype, string asm> {
3323   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3324   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3325                                    (outs regtype:$Rt, regtype:$Rt2),
3326                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3327           Sched<[WriteLD, WriteLDHi]>;
3328
3329
3330   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3331                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3332                                                   GPR64sp:$Rn, 0)>;
3333 }
3334
3335 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3336                       Operand indextype, string asm> {
3337   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3338   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3339                                    (ins regtype:$Rt, regtype:$Rt2,
3340                                         GPR64sp:$Rn, indextype:$offset),
3341                                    asm>,
3342           Sched<[WriteSTP]>;
3343
3344   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3345                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3346                                                   GPR64sp:$Rn, 0)>;
3347 }
3348
3349 //---
3350 // Load/store exclusive
3351 //---
3352
3353 // True exclusive operations write to and/or read from the system's exclusive
3354 // monitors, which as far as a compiler is concerned can be modelled as a
3355 // random shared memory address. Hence LoadExclusive mayStore.
3356 //
3357 // Since these instructions have the undefined register bits set to 1 in
3358 // their canonical form, we need a post encoder method to set those bits
3359 // to 1 when encoding these instructions. We do this using the
3360 // fixLoadStoreExclusive function. This function has template parameters:
3361 //
3362 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3363 //
3364 // hasRs indicates that the instruction uses the Rs field, so we won't set
3365 // it to 1 (and the same for Rt2). We don't need template parameters for
3366 // the other register fields since Rt and Rn are always used.
3367 //
3368 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3369 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3370                              dag oops, dag iops, string asm, string operands>
3371     : I<oops, iops, asm, operands, "", []> {
3372   let Inst{31-30} = sz;
3373   let Inst{29-24} = 0b001000;
3374   let Inst{23}    = o2;
3375   let Inst{22}    = L;
3376   let Inst{21}    = o1;
3377   let Inst{15}    = o0;
3378
3379   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3380 }
3381
3382 // Neither Rs nor Rt2 operands.
3383 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3384                                dag oops, dag iops, string asm, string operands>
3385     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3386   bits<5> Rt;
3387   bits<5> Rn;
3388   let Inst{20-16} = 0b11111;
3389   let Unpredictable{20-16} = 0b11111;
3390   let Inst{14-10} = 0b11111;
3391   let Unpredictable{14-10} = 0b11111;
3392   let Inst{9-5} = Rn;
3393   let Inst{4-0} = Rt;
3394
3395   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3396 }
3397
3398 // Simple load acquires don't set the exclusive monitor
3399 let mayLoad = 1, mayStore = 0 in
3400 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3401                   RegisterClass regtype, string asm>
3402     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3403                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3404       Sched<[WriteLD]>;
3405
3406 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3407                     RegisterClass regtype, string asm>
3408     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3409                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3410       Sched<[WriteLD]>;
3411
3412 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3413                        RegisterClass regtype, string asm>
3414     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3415                              (outs regtype:$Rt, regtype:$Rt2),
3416                              (ins GPR64sp0:$Rn), asm,
3417                              "\t$Rt, $Rt2, [$Rn]">,
3418       Sched<[WriteLD, WriteLDHi]> {
3419   bits<5> Rt;
3420   bits<5> Rt2;
3421   bits<5> Rn;
3422   let Inst{14-10} = Rt2;
3423   let Inst{9-5} = Rn;
3424   let Inst{4-0} = Rt;
3425
3426   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3427 }
3428
3429 // Simple store release operations do not check the exclusive monitor.
3430 let mayLoad = 0, mayStore = 1 in
3431 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3432                    RegisterClass regtype, string asm>
3433     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3434                                (ins regtype:$Rt, GPR64sp0:$Rn),
3435                                asm, "\t$Rt, [$Rn]">,
3436       Sched<[WriteST]>;
3437
3438 let mayLoad = 1, mayStore = 1 in
3439 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3440                      RegisterClass regtype, string asm>
3441     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3442                              (ins regtype:$Rt, GPR64sp0:$Rn),
3443                              asm, "\t$Ws, $Rt, [$Rn]">,
3444       Sched<[WriteSTX]> {
3445   bits<5> Ws;
3446   bits<5> Rt;
3447   bits<5> Rn;
3448   let Inst{20-16} = Ws;
3449   let Inst{9-5} = Rn;
3450   let Inst{4-0} = Rt;
3451
3452   let Constraints = "@earlyclobber $Ws";
3453   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3454 }
3455
3456 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3457                          RegisterClass regtype, string asm>
3458     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3459                              (outs GPR32:$Ws),
3460                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3461                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3462       Sched<[WriteSTX]> {
3463   bits<5> Ws;
3464   bits<5> Rt;
3465   bits<5> Rt2;
3466   bits<5> Rn;
3467   let Inst{20-16} = Ws;
3468   let Inst{14-10} = Rt2;
3469   let Inst{9-5} = Rn;
3470   let Inst{4-0} = Rt;
3471
3472   let Constraints = "@earlyclobber $Ws";
3473 }
3474
3475 //---
3476 // Exception generation
3477 //---
3478
3479 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3480 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3481     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3482       Sched<[WriteSys]> {
3483   bits<16> imm;
3484   let Inst{31-24} = 0b11010100;
3485   let Inst{23-21} = op1;
3486   let Inst{20-5}  = imm;
3487   let Inst{4-2}   = 0b000;
3488   let Inst{1-0}   = ll;
3489 }
3490
3491 let Predicates = [HasFPARMv8] in {
3492
3493 //---
3494 // Floating point to integer conversion
3495 //---
3496
3497 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3498                       RegisterClass srcType, RegisterClass dstType,
3499                       string asm, list<dag> pattern>
3500     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3501          asm, "\t$Rd, $Rn", "", pattern>,
3502       Sched<[WriteFCvt]> {
3503   bits<5> Rd;
3504   bits<5> Rn;
3505   let Inst{30-29} = 0b00;
3506   let Inst{28-24} = 0b11110;
3507   let Inst{23-22} = type;
3508   let Inst{21}    = 1;
3509   let Inst{20-19} = rmode;
3510   let Inst{18-16} = opcode;
3511   let Inst{15-10} = 0;
3512   let Inst{9-5}   = Rn;
3513   let Inst{4-0}   = Rd;
3514 }
3515
3516 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3517 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3518                       RegisterClass srcType, RegisterClass dstType,
3519                       Operand immType, string asm, list<dag> pattern>
3520     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3521          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3522       Sched<[WriteFCvt]> {
3523   bits<5> Rd;
3524   bits<5> Rn;
3525   bits<6> scale;
3526   let Inst{30-29} = 0b00;
3527   let Inst{28-24} = 0b11110;
3528   let Inst{23-22} = type;
3529   let Inst{21}    = 0;
3530   let Inst{20-19} = rmode;
3531   let Inst{18-16} = opcode;
3532   let Inst{15-10} = scale;
3533   let Inst{9-5}   = Rn;
3534   let Inst{4-0}   = Rd;
3535 }
3536
3537 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3538            SDPatternOperator OpN> {
3539   // Unscaled single-precision to 32-bit
3540   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3541                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3542     let Inst{31} = 0; // 32-bit GPR flag
3543   }
3544
3545   // Unscaled single-precision to 64-bit
3546   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3547                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3548     let Inst{31} = 1; // 64-bit GPR flag
3549   }
3550
3551   // Unscaled double-precision to 32-bit
3552   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3553                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3554     let Inst{31} = 0; // 32-bit GPR flag
3555   }
3556
3557   // Unscaled double-precision to 64-bit
3558   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3559                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3560     let Inst{31} = 1; // 64-bit GPR flag
3561   }
3562 }
3563
3564 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3565                              SDPatternOperator OpN> {
3566   // Scaled single-precision to 32-bit
3567   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3568                               fixedpoint_f32_i32, asm,
3569               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3570                                           fixedpoint_f32_i32:$scale)))]> {
3571     let Inst{31} = 0; // 32-bit GPR flag
3572     let scale{5} = 1;
3573   }
3574
3575   // Scaled single-precision to 64-bit
3576   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3577                               fixedpoint_f32_i64, asm,
3578               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3579                                           fixedpoint_f32_i64:$scale)))]> {
3580     let Inst{31} = 1; // 64-bit GPR flag
3581   }
3582
3583   // Scaled double-precision to 32-bit
3584   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3585                               fixedpoint_f64_i32, asm,
3586               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3587                                           fixedpoint_f64_i32:$scale)))]> {
3588     let Inst{31} = 0; // 32-bit GPR flag
3589     let scale{5} = 1;
3590   }
3591
3592   // Scaled double-precision to 64-bit
3593   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3594                               fixedpoint_f64_i64, asm,
3595               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3596                                           fixedpoint_f64_i64:$scale)))]> {
3597     let Inst{31} = 1; // 64-bit GPR flag
3598   }
3599 }
3600
3601 //---
3602 // Integer to floating point conversion
3603 //---
3604
3605 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3606 class BaseIntegerToFP<bit isUnsigned,
3607                       RegisterClass srcType, RegisterClass dstType,
3608                       Operand immType, string asm, list<dag> pattern>
3609     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3610          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3611       Sched<[WriteFCvt]> {
3612   bits<5> Rd;
3613   bits<5> Rn;
3614   bits<6> scale;
3615   let Inst{30-23} = 0b00111100;
3616   let Inst{21-17} = 0b00001;
3617   let Inst{16}    = isUnsigned;
3618   let Inst{15-10} = scale;
3619   let Inst{9-5}   = Rn;
3620   let Inst{4-0}   = Rd;
3621 }
3622
3623 class BaseIntegerToFPUnscaled<bit isUnsigned,
3624                       RegisterClass srcType, RegisterClass dstType,
3625                       ValueType dvt, string asm, SDNode node>
3626     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3627          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3628       Sched<[WriteFCvt]> {
3629   bits<5> Rd;
3630   bits<5> Rn;
3631   bits<6> scale;
3632   let Inst{30-23} = 0b00111100;
3633   let Inst{21-17} = 0b10001;
3634   let Inst{16}    = isUnsigned;
3635   let Inst{15-10} = 0b000000;
3636   let Inst{9-5}   = Rn;
3637   let Inst{4-0}   = Rd;
3638 }
3639
3640 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3641   // Unscaled
3642   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3643     let Inst{31} = 0; // 32-bit GPR flag
3644     let Inst{22} = 0; // 32-bit FPR flag
3645   }
3646
3647   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3648     let Inst{31} = 0; // 32-bit GPR flag
3649     let Inst{22} = 1; // 64-bit FPR flag
3650   }
3651
3652   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3653     let Inst{31} = 1; // 64-bit GPR flag
3654     let Inst{22} = 0; // 32-bit FPR flag
3655   }
3656
3657   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3658     let Inst{31} = 1; // 64-bit GPR flag
3659     let Inst{22} = 1; // 64-bit FPR flag
3660   }
3661
3662   // Scaled
3663   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3664                              [(set FPR32:$Rd,
3665                                    (fdiv (node GPR32:$Rn),
3666                                          fixedpoint_f32_i32:$scale))]> {
3667     let Inst{31} = 0; // 32-bit GPR flag
3668     let Inst{22} = 0; // 32-bit FPR flag
3669     let scale{5} = 1;
3670   }
3671
3672   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3673                              [(set FPR64:$Rd,
3674                                    (fdiv (node GPR32:$Rn),
3675                                          fixedpoint_f64_i32:$scale))]> {
3676     let Inst{31} = 0; // 32-bit GPR flag
3677     let Inst{22} = 1; // 64-bit FPR flag
3678     let scale{5} = 1;
3679   }
3680
3681   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3682                              [(set FPR32:$Rd,
3683                                    (fdiv (node GPR64:$Rn),
3684                                          fixedpoint_f32_i64:$scale))]> {
3685     let Inst{31} = 1; // 64-bit GPR flag
3686     let Inst{22} = 0; // 32-bit FPR flag
3687   }
3688
3689   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3690                              [(set FPR64:$Rd,
3691                                    (fdiv (node GPR64:$Rn),
3692                                          fixedpoint_f64_i64:$scale))]> {
3693     let Inst{31} = 1; // 64-bit GPR flag
3694     let Inst{22} = 1; // 64-bit FPR flag
3695   }
3696 }
3697
3698 //---
3699 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3700 //---
3701
3702 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3703 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3704                       RegisterClass srcType, RegisterClass dstType,
3705                       string asm>
3706     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3707         // We use COPY_TO_REGCLASS for these bitconvert operations.
3708         // copyPhysReg() expands the resultant COPY instructions after
3709         // regalloc is done. This gives greater freedom for the allocator
3710         // and related passes (coalescing, copy propagation, et. al.) to
3711         // be more effective.
3712         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3713       Sched<[WriteFCopy]> {
3714   bits<5> Rd;
3715   bits<5> Rn;
3716   let Inst{30-23} = 0b00111100;
3717   let Inst{21}    = 1;
3718   let Inst{20-19} = rmode;
3719   let Inst{18-16} = opcode;
3720   let Inst{15-10} = 0b000000;
3721   let Inst{9-5}   = Rn;
3722   let Inst{4-0}   = Rd;
3723 }
3724
3725 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3726 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3727                      RegisterClass srcType, RegisterOperand dstType, string asm,
3728                      string kind>
3729     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3730         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3731       Sched<[WriteFCopy]> {
3732   bits<5> Rd;
3733   bits<5> Rn;
3734   let Inst{30-23} = 0b00111101;
3735   let Inst{21}    = 1;
3736   let Inst{20-19} = rmode;
3737   let Inst{18-16} = opcode;
3738   let Inst{15-10} = 0b000000;
3739   let Inst{9-5}   = Rn;
3740   let Inst{4-0}   = Rd;
3741
3742   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3743 }
3744
3745 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3746 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3747                      RegisterOperand srcType, RegisterClass dstType, string asm,
3748                      string kind>
3749     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3750         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3751       Sched<[WriteFCopy]> {
3752   bits<5> Rd;
3753   bits<5> Rn;
3754   let Inst{30-23} = 0b00111101;
3755   let Inst{21}    = 1;
3756   let Inst{20-19} = rmode;
3757   let Inst{18-16} = opcode;
3758   let Inst{15-10} = 0b000000;
3759   let Inst{9-5}   = Rn;
3760   let Inst{4-0}   = Rd;
3761
3762   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3763 }
3764
3765
3766
3767 multiclass UnscaledConversion<string asm> {
3768   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3769     let Inst{31} = 0; // 32-bit GPR flag
3770     let Inst{22} = 0; // 32-bit FPR flag
3771   }
3772
3773   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3774     let Inst{31} = 1; // 64-bit GPR flag
3775     let Inst{22} = 1; // 64-bit FPR flag
3776   }
3777
3778   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3779     let Inst{31} = 0; // 32-bit GPR flag
3780     let Inst{22} = 0; // 32-bit FPR flag
3781   }
3782
3783   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3784     let Inst{31} = 1; // 64-bit GPR flag
3785     let Inst{22} = 1; // 64-bit FPR flag
3786   }
3787
3788   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3789                                              asm, ".d"> {
3790     let Inst{31} = 1;
3791     let Inst{22} = 0;
3792   }
3793
3794   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3795                                                asm, ".d"> {
3796     let Inst{31} = 1;
3797     let Inst{22} = 0;
3798   }
3799 }
3800
3801 //---
3802 // Floating point conversion
3803 //---
3804
3805 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3806                        RegisterClass srcType, string asm, list<dag> pattern>
3807     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3808       Sched<[WriteFCvt]> {
3809   bits<5> Rd;
3810   bits<5> Rn;
3811   let Inst{31-24} = 0b00011110;
3812   let Inst{23-22} = type;
3813   let Inst{21-17} = 0b10001;
3814   let Inst{16-15} = opcode;
3815   let Inst{14-10} = 0b10000;
3816   let Inst{9-5}   = Rn;
3817   let Inst{4-0}   = Rd;
3818 }
3819
3820 multiclass FPConversion<string asm> {
3821   // Double-precision to Half-precision
3822   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3823                              [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3824
3825   // Double-precision to Single-precision
3826   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3827                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3828
3829   // Half-precision to Double-precision
3830   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3831                              [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3832
3833   // Half-precision to Single-precision
3834   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3835                              [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3836
3837   // Single-precision to Double-precision
3838   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3839                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3840
3841   // Single-precision to Half-precision
3842   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3843                              [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3844 }
3845
3846 //---
3847 // Single operand floating point data processing
3848 //---
3849
3850 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3851 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3852                               ValueType vt, string asm, SDPatternOperator node>
3853     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3854          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3855       Sched<[WriteF]> {
3856   bits<5> Rd;
3857   bits<5> Rn;
3858   let Inst{31-23} = 0b000111100;
3859   let Inst{21-19} = 0b100;
3860   let Inst{18-15} = opcode;
3861   let Inst{14-10} = 0b10000;
3862   let Inst{9-5}   = Rn;
3863   let Inst{4-0}   = Rd;
3864 }
3865
3866 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3867                                SDPatternOperator node = null_frag> {
3868   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3869     let Inst{22} = 0; // 32-bit size flag
3870   }
3871
3872   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3873     let Inst{22} = 1; // 64-bit size flag
3874   }
3875 }
3876
3877 //---
3878 // Two operand floating point data processing
3879 //---
3880
3881 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3882 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3883                            string asm, list<dag> pat>
3884     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3885          asm, "\t$Rd, $Rn, $Rm", "", pat>,
3886       Sched<[WriteF]> {
3887   bits<5> Rd;
3888   bits<5> Rn;
3889   bits<5> Rm;
3890   let Inst{31-23} = 0b000111100;
3891   let Inst{21}    = 1;
3892   let Inst{20-16} = Rm;
3893   let Inst{15-12} = opcode;
3894   let Inst{11-10} = 0b10;
3895   let Inst{9-5}   = Rn;
3896   let Inst{4-0}   = Rd;
3897 }
3898
3899 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3900                             SDPatternOperator node = null_frag> {
3901   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3902                          [(set (f32 FPR32:$Rd),
3903                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3904     let Inst{22} = 0; // 32-bit size flag
3905   }
3906
3907   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3908                          [(set (f64 FPR64:$Rd),
3909                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3910     let Inst{22} = 1; // 64-bit size flag
3911   }
3912 }
3913
3914 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3915   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3916                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3917     let Inst{22} = 0; // 32-bit size flag
3918   }
3919
3920   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3921                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3922     let Inst{22} = 1; // 64-bit size flag
3923   }
3924 }
3925
3926
3927 //---
3928 // Three operand floating point data processing
3929 //---
3930
3931 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3932                              RegisterClass regtype, string asm, list<dag> pat>
3933     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3934          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3935       Sched<[WriteFMul]> {
3936   bits<5> Rd;
3937   bits<5> Rn;
3938   bits<5> Rm;
3939   bits<5> Ra;
3940   let Inst{31-23} = 0b000111110;
3941   let Inst{21}    = isNegated;
3942   let Inst{20-16} = Rm;
3943   let Inst{15}    = isSub;
3944   let Inst{14-10} = Ra;
3945   let Inst{9-5}   = Rn;
3946   let Inst{4-0}   = Rd;
3947 }
3948
3949 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3950                               SDPatternOperator node> {
3951   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3952             [(set FPR32:$Rd,
3953                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3954     let Inst{22} = 0; // 32-bit size flag
3955   }
3956
3957   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3958             [(set FPR64:$Rd,
3959                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3960     let Inst{22} = 1; // 64-bit size flag
3961   }
3962 }
3963
3964 //---
3965 // Floating point data comparisons
3966 //---
3967
3968 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3969 class BaseOneOperandFPComparison<bit signalAllNans,
3970                                  RegisterClass regtype, string asm,
3971                                  list<dag> pat>
3972     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3973       Sched<[WriteFCmp]> {
3974   bits<5> Rn;
3975   let Inst{31-23} = 0b000111100;
3976   let Inst{21}    = 1;
3977
3978   let Inst{15-10} = 0b001000;
3979   let Inst{9-5}   = Rn;
3980   let Inst{4}     = signalAllNans;
3981   let Inst{3-0}   = 0b1000;
3982
3983   // Rm should be 0b00000 canonically, but we need to accept any value.
3984   let PostEncoderMethod = "fixOneOperandFPComparison";
3985 }
3986
3987 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3988 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3989                                 string asm, list<dag> pat>
3990     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3991       Sched<[WriteFCmp]> {
3992   bits<5> Rm;
3993   bits<5> Rn;
3994   let Inst{31-23} = 0b000111100;
3995   let Inst{21}    = 1;
3996   let Inst{20-16} = Rm;
3997   let Inst{15-10} = 0b001000;
3998   let Inst{9-5}   = Rn;
3999   let Inst{4}     = signalAllNans;
4000   let Inst{3-0}   = 0b0000;
4001 }
4002
4003 multiclass FPComparison<bit signalAllNans, string asm,
4004                         SDPatternOperator OpNode = null_frag> {
4005   let Defs = [NZCV] in {
4006   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4007       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4008     let Inst{22} = 0;
4009   }
4010
4011   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4012       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4013     let Inst{22} = 0;
4014   }
4015
4016   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4017       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4018     let Inst{22} = 1;
4019   }
4020
4021   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4022       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4023     let Inst{22} = 1;
4024   }
4025   } // Defs = [NZCV]
4026 }
4027
4028 //---
4029 // Floating point conditional comparisons
4030 //---
4031
4032 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4033 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4034                            string mnemonic, list<dag> pat>
4035     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4036          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4037       Sched<[WriteFCmp]> {
4038   let Uses = [NZCV];
4039   let Defs = [NZCV];
4040
4041   bits<5> Rn;
4042   bits<5> Rm;
4043   bits<4> nzcv;
4044   bits<4> cond;
4045
4046   let Inst{31-23} = 0b000111100;
4047   let Inst{21}    = 1;
4048   let Inst{20-16} = Rm;
4049   let Inst{15-12} = cond;
4050   let Inst{11-10} = 0b01;
4051   let Inst{9-5}   = Rn;
4052   let Inst{4}     = signalAllNans;
4053   let Inst{3-0}   = nzcv;
4054 }
4055
4056 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4057                             SDPatternOperator OpNode = null_frag> {
4058   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4059       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4060                           (i32 imm:$cond), NZCV))]> {
4061     let Inst{22} = 0;
4062   }
4063   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4064       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4065                           (i32 imm:$cond), NZCV))]> {
4066     let Inst{22} = 1;
4067   }
4068 }
4069
4070 //---
4071 // Floating point conditional select
4072 //---
4073
4074 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4075     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4076          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4077          [(set regtype:$Rd,
4078                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4079                           (i32 imm:$cond), NZCV))]>,
4080       Sched<[WriteF]> {
4081   bits<5> Rd;
4082   bits<5> Rn;
4083   bits<5> Rm;
4084   bits<4> cond;
4085
4086   let Inst{31-23} = 0b000111100;
4087   let Inst{21}    = 1;
4088   let Inst{20-16} = Rm;
4089   let Inst{15-12} = cond;
4090   let Inst{11-10} = 0b11;
4091   let Inst{9-5}   = Rn;
4092   let Inst{4-0}   = Rd;
4093 }
4094
4095 multiclass FPCondSelect<string asm> {
4096   let Uses = [NZCV] in {
4097   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4098     let Inst{22} = 0;
4099   }
4100
4101   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4102     let Inst{22} = 1;
4103   }
4104   } // Uses = [NZCV]
4105 }
4106
4107 //---
4108 // Floating move immediate
4109 //---
4110
4111 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4112   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4113       [(set regtype:$Rd, fpimmtype:$imm)]>,
4114     Sched<[WriteFImm]> {
4115   bits<5> Rd;
4116   bits<8> imm;
4117   let Inst{31-23} = 0b000111100;
4118   let Inst{21}    = 1;
4119   let Inst{20-13} = imm;
4120   let Inst{12-5}  = 0b10000000;
4121   let Inst{4-0}   = Rd;
4122 }
4123
4124 multiclass FPMoveImmediate<string asm> {
4125   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4126     let Inst{22} = 0;
4127   }
4128
4129   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4130     let Inst{22} = 1;
4131   }
4132 }
4133 } // end of 'let Predicates = [HasFPARMv8]'
4134
4135 //----------------------------------------------------------------------------
4136 // AdvSIMD
4137 //----------------------------------------------------------------------------
4138
4139 let Predicates = [HasNEON] in {
4140
4141 //----------------------------------------------------------------------------
4142 // AdvSIMD three register vector instructions
4143 //----------------------------------------------------------------------------
4144
4145 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4146 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4147                         RegisterOperand regtype, string asm, string kind,
4148                         list<dag> pattern>
4149   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4150       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4151       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4152     Sched<[WriteV]> {
4153   bits<5> Rd;
4154   bits<5> Rn;
4155   bits<5> Rm;
4156   let Inst{31}    = 0;
4157   let Inst{30}    = Q;
4158   let Inst{29}    = U;
4159   let Inst{28-24} = 0b01110;
4160   let Inst{23-22} = size;
4161   let Inst{21}    = 1;
4162   let Inst{20-16} = Rm;
4163   let Inst{15-11} = opcode;
4164   let Inst{10}    = 1;
4165   let Inst{9-5}   = Rn;
4166   let Inst{4-0}   = Rd;
4167 }
4168
4169 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4170 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4171                         RegisterOperand regtype, string asm, string kind,
4172                         list<dag> pattern>
4173   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4174       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4175       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4176     Sched<[WriteV]> {
4177   bits<5> Rd;
4178   bits<5> Rn;
4179   bits<5> Rm;
4180   let Inst{31}    = 0;
4181   let Inst{30}    = Q;
4182   let Inst{29}    = U;
4183   let Inst{28-24} = 0b01110;
4184   let Inst{23-22} = size;
4185   let Inst{21}    = 1;
4186   let Inst{20-16} = Rm;
4187   let Inst{15-11} = opcode;
4188   let Inst{10}    = 1;
4189   let Inst{9-5}   = Rn;
4190   let Inst{4-0}   = Rd;
4191 }
4192
4193 // All operand sizes distinguished in the encoding.
4194 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4195                                SDPatternOperator OpNode> {
4196   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4197                                       asm, ".8b",
4198          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4199   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4200                                       asm, ".16b",
4201          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4202   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4203                                       asm, ".4h",
4204          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4205   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4206                                       asm, ".8h",
4207          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4208   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4209                                       asm, ".2s",
4210          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4211   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4212                                       asm, ".4s",
4213          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4214   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
4215                                       asm, ".2d",
4216          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4217 }
4218
4219 // As above, but D sized elements unsupported.
4220 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4221                                   SDPatternOperator OpNode> {
4222   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4223                                       asm, ".8b",
4224         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4225   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4226                                       asm, ".16b",
4227         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4228   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4229                                       asm, ".4h",
4230         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4231   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4232                                       asm, ".8h",
4233         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4234   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4235                                       asm, ".2s",
4236         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4237   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4238                                       asm, ".4s",
4239         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4240 }
4241
4242 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4243                                   SDPatternOperator OpNode> {
4244   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
4245                                       asm, ".8b",
4246       [(set (v8i8 V64:$dst),
4247             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4248   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
4249                                       asm, ".16b",
4250       [(set (v16i8 V128:$dst),
4251             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4252   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
4253                                       asm, ".4h",
4254       [(set (v4i16 V64:$dst),
4255             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4256   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
4257                                       asm, ".8h",
4258       [(set (v8i16 V128:$dst),
4259             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4260   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
4261                                       asm, ".2s",
4262       [(set (v2i32 V64:$dst),
4263             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4264   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
4265                                       asm, ".4s",
4266       [(set (v4i32 V128:$dst),
4267             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4268 }
4269
4270 // As above, but only B sized elements supported.
4271 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4272                                 SDPatternOperator OpNode> {
4273   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4274                                       asm, ".8b",
4275     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4276   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4277                                       asm, ".16b",
4278     [(set (v16i8 V128:$Rd),
4279           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4280 }
4281
4282 // As above, but only S and D sized floating point elements supported.
4283 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
4284                                  string asm, SDPatternOperator OpNode> {
4285   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4286                                       asm, ".2s",
4287         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4288   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4289                                       asm, ".4s",
4290         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4291   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4292                                       asm, ".2d",
4293         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4294 }
4295
4296 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
4297                                     string asm,
4298                                     SDPatternOperator OpNode> {
4299   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4300                                       asm, ".2s",
4301         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4302   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4303                                       asm, ".4s",
4304         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4305   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4306                                       asm, ".2d",
4307         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4308 }
4309
4310 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
4311                                  string asm, SDPatternOperator OpNode> {
4312   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
4313                                       asm, ".2s",
4314      [(set (v2f32 V64:$dst),
4315            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4316   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
4317                                       asm, ".4s",
4318      [(set (v4f32 V128:$dst),
4319            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4320   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
4321                                       asm, ".2d",
4322      [(set (v2f64 V128:$dst),
4323            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4324 }
4325
4326 // As above, but D and B sized elements unsupported.
4327 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4328                                 SDPatternOperator OpNode> {
4329   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4330                                       asm, ".4h",
4331         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4332   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4333                                       asm, ".8h",
4334         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4335   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4336                                       asm, ".2s",
4337         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4338   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4339                                       asm, ".4s",
4340         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4341 }
4342
4343 // Logical three vector ops share opcode bits, and only use B sized elements.
4344 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4345                                   SDPatternOperator OpNode = null_frag> {
4346   def v8i8  : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4347                                      asm, ".8b",
4348                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4349   def v16i8  : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4350                                      asm, ".16b",
4351                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4352
4353   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4354           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4355   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4356           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4357   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4358           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4359
4360   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4361       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4362   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4363       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4364   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4365       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4366 }
4367
4368 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4369                                   string asm, SDPatternOperator OpNode> {
4370   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4371                                      asm, ".8b",
4372              [(set (v8i8 V64:$dst),
4373                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4374   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4375                                      asm, ".16b",
4376              [(set (v16i8 V128:$dst),
4377                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4378                            (v16i8 V128:$Rm)))]>;
4379
4380   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4381                            (v4i16 V64:$RHS))),
4382           (!cast<Instruction>(NAME#"v8i8")
4383             V64:$LHS, V64:$MHS, V64:$RHS)>;
4384   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4385                            (v2i32 V64:$RHS))),
4386           (!cast<Instruction>(NAME#"v8i8")
4387             V64:$LHS, V64:$MHS, V64:$RHS)>;
4388   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4389                            (v1i64 V64:$RHS))),
4390           (!cast<Instruction>(NAME#"v8i8")
4391             V64:$LHS, V64:$MHS, V64:$RHS)>;
4392
4393   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4394                            (v8i16 V128:$RHS))),
4395       (!cast<Instruction>(NAME#"v16i8")
4396         V128:$LHS, V128:$MHS, V128:$RHS)>;
4397   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4398                            (v4i32 V128:$RHS))),
4399       (!cast<Instruction>(NAME#"v16i8")
4400         V128:$LHS, V128:$MHS, V128:$RHS)>;
4401   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4402                            (v2i64 V128:$RHS))),
4403       (!cast<Instruction>(NAME#"v16i8")
4404         V128:$LHS, V128:$MHS, V128:$RHS)>;
4405 }
4406
4407
4408 //----------------------------------------------------------------------------
4409 // AdvSIMD two register vector instructions.
4410 //----------------------------------------------------------------------------
4411
4412 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4413 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4414                         RegisterOperand regtype, string asm, string dstkind,
4415                         string srckind, list<dag> pattern>
4416   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4417       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4418       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4419     Sched<[WriteV]> {
4420   bits<5> Rd;
4421   bits<5> Rn;
4422   let Inst{31}    = 0;
4423   let Inst{30}    = Q;
4424   let Inst{29}    = U;
4425   let Inst{28-24} = 0b01110;
4426   let Inst{23-22} = size;
4427   let Inst{21-17} = 0b10000;
4428   let Inst{16-12} = opcode;
4429   let Inst{11-10} = 0b10;
4430   let Inst{9-5}   = Rn;
4431   let Inst{4-0}   = Rd;
4432 }
4433
4434 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4435 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4436                             RegisterOperand regtype, string asm, string dstkind,
4437                             string srckind, list<dag> pattern>
4438   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4439       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4440       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4441     Sched<[WriteV]> {
4442   bits<5> Rd;
4443   bits<5> Rn;
4444   let Inst{31}    = 0;
4445   let Inst{30}    = Q;
4446   let Inst{29}    = U;
4447   let Inst{28-24} = 0b01110;
4448   let Inst{23-22} = size;
4449   let Inst{21-17} = 0b10000;
4450   let Inst{16-12} = opcode;
4451   let Inst{11-10} = 0b10;
4452   let Inst{9-5}   = Rn;
4453   let Inst{4-0}   = Rd;
4454 }
4455
4456 // Supports B, H, and S element sizes.
4457 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4458                             SDPatternOperator OpNode> {
4459   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4460                                       asm, ".8b", ".8b",
4461                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4462   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4463                                       asm, ".16b", ".16b",
4464                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4465   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4466                                       asm, ".4h", ".4h",
4467                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4468   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4469                                       asm, ".8h", ".8h",
4470                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4471   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4472                                       asm, ".2s", ".2s",
4473                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4474   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4475                                       asm, ".4s", ".4s",
4476                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4477 }
4478
4479 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4480                             RegisterOperand regtype, string asm, string dstkind,
4481                             string srckind, string amount>
4482   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4483       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4484       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4485     Sched<[WriteV]> {
4486   bits<5> Rd;
4487   bits<5> Rn;
4488   let Inst{31}    = 0;
4489   let Inst{30}    = Q;
4490   let Inst{29-24} = 0b101110;
4491   let Inst{23-22} = size;
4492   let Inst{21-10} = 0b100001001110;
4493   let Inst{9-5}   = Rn;
4494   let Inst{4-0}   = Rd;
4495 }
4496
4497 multiclass SIMDVectorLShiftLongBySizeBHS {
4498   let hasSideEffects = 0 in {
4499   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4500                                              "shll", ".8h",  ".8b", "8">;
4501   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4502                                              "shll2", ".8h", ".16b", "8">;
4503   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4504                                              "shll", ".4s",  ".4h", "16">;
4505   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4506                                              "shll2", ".4s", ".8h", "16">;
4507   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4508                                              "shll", ".2d",  ".2s", "32">;
4509   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4510                                              "shll2", ".2d", ".4s", "32">;
4511   }
4512 }
4513
4514 // Supports all element sizes.
4515 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4516                              SDPatternOperator OpNode> {
4517   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4518                                       asm, ".4h", ".8b",
4519                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4520   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4521                                       asm, ".8h", ".16b",
4522                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4523   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4524                                       asm, ".2s", ".4h",
4525                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4526   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4527                                       asm, ".4s", ".8h",
4528                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4529   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4530                                       asm, ".1d", ".2s",
4531                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4532   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4533                                       asm, ".2d", ".4s",
4534                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4535 }
4536
4537 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4538                                  SDPatternOperator OpNode> {
4539   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4540                                           asm, ".4h", ".8b",
4541       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4542                                       (v8i8 V64:$Rn)))]>;
4543   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4544                                           asm, ".8h", ".16b",
4545       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4546                                       (v16i8 V128:$Rn)))]>;
4547   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4548                                           asm, ".2s", ".4h",
4549       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4550                                       (v4i16 V64:$Rn)))]>;
4551   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4552                                           asm, ".4s", ".8h",
4553       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4554                                       (v8i16 V128:$Rn)))]>;
4555   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4556                                           asm, ".1d", ".2s",
4557       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4558                                       (v2i32 V64:$Rn)))]>;
4559   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4560                                           asm, ".2d", ".4s",
4561       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4562                                       (v4i32 V128:$Rn)))]>;
4563 }
4564
4565 // Supports all element sizes, except 1xD.
4566 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4567                                   SDPatternOperator OpNode> {
4568   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4569                                     asm, ".8b", ".8b",
4570     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4571   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4572                                     asm, ".16b", ".16b",
4573     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4574   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4575                                     asm, ".4h", ".4h",
4576     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4577   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4578                                     asm, ".8h", ".8h",
4579     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4580   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4581                                     asm, ".2s", ".2s",
4582     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4583   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4584                                     asm, ".4s", ".4s",
4585     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4586   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4587                                     asm, ".2d", ".2d",
4588     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4589 }
4590
4591 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4592                              SDPatternOperator OpNode = null_frag> {
4593   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4594                                 asm, ".8b", ".8b",
4595     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4596   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4597                                 asm, ".16b", ".16b",
4598     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4599   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4600                                 asm, ".4h", ".4h",
4601     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4602   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4603                                 asm, ".8h", ".8h",
4604     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4605   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4606                                 asm, ".2s", ".2s",
4607     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4608   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4609                                 asm, ".4s", ".4s",
4610     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4611   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4612                                 asm, ".2d", ".2d",
4613     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4614 }
4615
4616
4617 // Supports only B element sizes.
4618 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4619                           SDPatternOperator OpNode> {
4620   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4621                                 asm, ".8b", ".8b",
4622                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4623   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4624                                 asm, ".16b", ".16b",
4625                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4626
4627 }
4628
4629 // Supports only B and H element sizes.
4630 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4631                                 SDPatternOperator OpNode> {
4632   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4633                                 asm, ".8b", ".8b",
4634                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4635   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4636                                 asm, ".16b", ".16b",
4637                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4638   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4639                                 asm, ".4h", ".4h",
4640                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4641   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4642                                 asm, ".8h", ".8h",
4643                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4644 }
4645
4646 // Supports only S and D element sizes, uses high bit of the size field
4647 // as an extra opcode bit.
4648 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4649                            SDPatternOperator OpNode> {
4650   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4651                                 asm, ".2s", ".2s",
4652                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4653   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4654                                 asm, ".4s", ".4s",
4655                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4656   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4657                                 asm, ".2d", ".2d",
4658                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4659 }
4660
4661 // Supports only S element size.
4662 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4663                            SDPatternOperator OpNode> {
4664   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4665                                 asm, ".2s", ".2s",
4666                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4667   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4668                                 asm, ".4s", ".4s",
4669                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4670 }
4671
4672
4673 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4674                            SDPatternOperator OpNode> {
4675   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4676                                 asm, ".2s", ".2s",
4677                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4678   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4679                                 asm, ".4s", ".4s",
4680                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4681   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4682                                 asm, ".2d", ".2d",
4683                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4684 }
4685
4686 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4687                            SDPatternOperator OpNode> {
4688   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4689                                 asm, ".2s", ".2s",
4690                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4691   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4692                                 asm, ".4s", ".4s",
4693                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4694   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4695                                 asm, ".2d", ".2d",
4696                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4697 }
4698
4699
4700 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4701                            RegisterOperand inreg, RegisterOperand outreg,
4702                            string asm, string outkind, string inkind,
4703                            list<dag> pattern>
4704   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4705       "{\t$Rd" # outkind # ", $Rn" # inkind #
4706       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4707     Sched<[WriteV]> {
4708   bits<5> Rd;
4709   bits<5> Rn;
4710   let Inst{31}    = 0;
4711   let Inst{30}    = Q;
4712   let Inst{29}    = U;
4713   let Inst{28-24} = 0b01110;
4714   let Inst{23-22} = size;
4715   let Inst{21-17} = 0b10000;
4716   let Inst{16-12} = opcode;
4717   let Inst{11-10} = 0b10;
4718   let Inst{9-5}   = Rn;
4719   let Inst{4-0}   = Rd;
4720 }
4721
4722 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4723                            RegisterOperand inreg, RegisterOperand outreg,
4724                            string asm, string outkind, string inkind,
4725                            list<dag> pattern>
4726   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4727       "{\t$Rd" # outkind # ", $Rn" # inkind #
4728       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4729     Sched<[WriteV]> {
4730   bits<5> Rd;
4731   bits<5> Rn;
4732   let Inst{31}    = 0;
4733   let Inst{30}    = Q;
4734   let Inst{29}    = U;
4735   let Inst{28-24} = 0b01110;
4736   let Inst{23-22} = size;
4737   let Inst{21-17} = 0b10000;
4738   let Inst{16-12} = opcode;
4739   let Inst{11-10} = 0b10;
4740   let Inst{9-5}   = Rn;
4741   let Inst{4-0}   = Rd;
4742 }
4743
4744 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4745                               SDPatternOperator OpNode> {
4746   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4747                                       asm, ".8b", ".8h",
4748         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4749   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4750                                       asm#"2", ".16b", ".8h", []>;
4751   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4752                                       asm, ".4h", ".4s",
4753         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4754   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4755                                       asm#"2", ".8h", ".4s", []>;
4756   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4757                                       asm, ".2s", ".2d",
4758         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4759   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4760                                       asm#"2", ".4s", ".2d", []>;
4761
4762   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4763             (!cast<Instruction>(NAME # "v16i8")
4764                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4765   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4766             (!cast<Instruction>(NAME # "v8i16")
4767                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4768   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4769             (!cast<Instruction>(NAME # "v4i32")
4770                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4771 }
4772
4773 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4774                            RegisterOperand regtype,
4775                            string asm, string kind, string zero,
4776                            ValueType dty, ValueType sty, SDNode OpNode>
4777   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4778       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4779       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4780       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4781     Sched<[WriteV]> {
4782   bits<5> Rd;
4783   bits<5> Rn;
4784   let Inst{31}    = 0;
4785   let Inst{30}    = Q;
4786   let Inst{29}    = U;
4787   let Inst{28-24} = 0b01110;
4788   let Inst{23-22} = size;
4789   let Inst{21-17} = 0b10000;
4790   let Inst{16-12} = opcode;
4791   let Inst{11-10} = 0b10;
4792   let Inst{9-5}   = Rn;
4793   let Inst{4-0}   = Rd;
4794 }
4795
4796 // Comparisons support all element sizes, except 1xD.
4797 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4798                             SDNode OpNode> {
4799   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4800                                      asm, ".8b", "0",
4801                                      v8i8, v8i8, OpNode>;
4802   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4803                                      asm, ".16b", "0",
4804                                      v16i8, v16i8, OpNode>;
4805   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4806                                      asm, ".4h", "0",
4807                                      v4i16, v4i16, OpNode>;
4808   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4809                                      asm, ".8h", "0",
4810                                      v8i16, v8i16, OpNode>;
4811   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4812                                      asm, ".2s", "0",
4813                                      v2i32, v2i32, OpNode>;
4814   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4815                                      asm, ".4s", "0",
4816                                      v4i32, v4i32, OpNode>;
4817   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4818                                      asm, ".2d", "0",
4819                                      v2i64, v2i64, OpNode>;
4820 }
4821
4822 // FP Comparisons support only S and D element sizes.
4823 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4824                               string asm, SDNode OpNode> {
4825
4826   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4827                                      asm, ".2s", "0.0",
4828                                      v2i32, v2f32, OpNode>;
4829   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4830                                      asm, ".4s", "0.0",
4831                                      v4i32, v4f32, OpNode>;
4832   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4833                                      asm, ".2d", "0.0",
4834                                      v2i64, v2f64, OpNode>;
4835
4836   def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
4837                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4838   def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
4839                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4840   def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
4841                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4842   def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
4843                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4844   def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
4845                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4846   def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
4847                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4848 }
4849
4850 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4851 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4852                              RegisterOperand outtype, RegisterOperand intype,
4853                              string asm, string VdTy, string VnTy,
4854                              list<dag> pattern>
4855   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4856       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4857     Sched<[WriteV]> {
4858   bits<5> Rd;
4859   bits<5> Rn;
4860   let Inst{31}    = 0;
4861   let Inst{30}    = Q;
4862   let Inst{29}    = U;
4863   let Inst{28-24} = 0b01110;
4864   let Inst{23-22} = size;
4865   let Inst{21-17} = 0b10000;
4866   let Inst{16-12} = opcode;
4867   let Inst{11-10} = 0b10;
4868   let Inst{9-5}   = Rn;
4869   let Inst{4-0}   = Rd;
4870 }
4871
4872 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4873                              RegisterOperand outtype, RegisterOperand intype,
4874                              string asm, string VdTy, string VnTy,
4875                              list<dag> pattern>
4876   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4877       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4878     Sched<[WriteV]> {
4879   bits<5> Rd;
4880   bits<5> Rn;
4881   let Inst{31}    = 0;
4882   let Inst{30}    = Q;
4883   let Inst{29}    = U;
4884   let Inst{28-24} = 0b01110;
4885   let Inst{23-22} = size;
4886   let Inst{21-17} = 0b10000;
4887   let Inst{16-12} = opcode;
4888   let Inst{11-10} = 0b10;
4889   let Inst{9-5}   = Rn;
4890   let Inst{4-0}   = Rd;
4891 }
4892
4893 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4894   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4895                                     asm, ".4s", ".4h", []>;
4896   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4897                                     asm#"2", ".4s", ".8h", []>;
4898   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4899                                     asm, ".2d", ".2s", []>;
4900   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4901                                     asm#"2", ".2d", ".4s", []>;
4902 }
4903
4904 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4905   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4906                                     asm, ".4h", ".4s", []>;
4907   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4908                                     asm#"2", ".8h", ".4s", []>;
4909   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4910                                     asm, ".2s", ".2d", []>;
4911   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4912                                     asm#"2", ".4s", ".2d", []>;
4913 }
4914
4915 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4916                                      Intrinsic OpNode> {
4917   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4918                                      asm, ".2s", ".2d",
4919                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4920   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4921                                     asm#"2", ".4s", ".2d", []>;
4922
4923   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4924             (!cast<Instruction>(NAME # "v4f32")
4925                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4926 }
4927
4928 //----------------------------------------------------------------------------
4929 // AdvSIMD three register different-size vector instructions.
4930 //----------------------------------------------------------------------------
4931
4932 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4933 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4934                       RegisterOperand outtype, RegisterOperand intype1,
4935                       RegisterOperand intype2, string asm,
4936                       string outkind, string inkind1, string inkind2,
4937                       list<dag> pattern>
4938   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4939       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4940       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4941     Sched<[WriteV]> {
4942   bits<5> Rd;
4943   bits<5> Rn;
4944   bits<5> Rm;
4945   let Inst{31}    = 0;
4946   let Inst{30}    = size{0};
4947   let Inst{29}    = U;
4948   let Inst{28-24} = 0b01110;
4949   let Inst{23-22} = size{2-1};
4950   let Inst{21}    = 1;
4951   let Inst{20-16} = Rm;
4952   let Inst{15-12} = opcode;
4953   let Inst{11-10} = 0b00;
4954   let Inst{9-5}   = Rn;
4955   let Inst{4-0}   = Rd;
4956 }
4957
4958 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4959 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4960                       RegisterOperand outtype, RegisterOperand intype1,
4961                       RegisterOperand intype2, string asm,
4962                       string outkind, string inkind1, string inkind2,
4963                       list<dag> pattern>
4964   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4965       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4966       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4967     Sched<[WriteV]> {
4968   bits<5> Rd;
4969   bits<5> Rn;
4970   bits<5> Rm;
4971   let Inst{31}    = 0;
4972   let Inst{30}    = size{0};
4973   let Inst{29}    = U;
4974   let Inst{28-24} = 0b01110;
4975   let Inst{23-22} = size{2-1};
4976   let Inst{21}    = 1;
4977   let Inst{20-16} = Rm;
4978   let Inst{15-12} = opcode;
4979   let Inst{11-10} = 0b00;
4980   let Inst{9-5}   = Rn;
4981   let Inst{4-0}   = Rd;
4982 }
4983
4984 // FIXME: TableGen doesn't know how to deal with expanded types that also
4985 //        change the element count (in this case, placing the results in
4986 //        the high elements of the result register rather than the low
4987 //        elements). Until that's fixed, we can't code-gen those.
4988 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4989                                     Intrinsic IntOp> {
4990   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4991                                                   V64, V128, V128,
4992                                                   asm, ".8b", ".8h", ".8h",
4993      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4994   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4995                                                   V128, V128, V128,
4996                                                   asm#"2", ".16b", ".8h", ".8h",
4997      []>;
4998   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4999                                                   V64, V128, V128,
5000                                                   asm, ".4h", ".4s", ".4s",
5001      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5002   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5003                                                   V128, V128, V128,
5004                                                   asm#"2", ".8h", ".4s", ".4s",
5005      []>;
5006   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5007                                                   V64, V128, V128,
5008                                                   asm, ".2s", ".2d", ".2d",
5009      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5010   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5011                                                   V128, V128, V128,
5012                                                   asm#"2", ".4s", ".2d", ".2d",
5013      []>;
5014
5015
5016   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5017   // a version attached to an instruction.
5018   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5019                                                    (v8i16 V128:$Rm))),
5020             (!cast<Instruction>(NAME # "v8i16_v16i8")
5021                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5022                 V128:$Rn, V128:$Rm)>;
5023   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5024                                                     (v4i32 V128:$Rm))),
5025             (!cast<Instruction>(NAME # "v4i32_v8i16")
5026                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5027                 V128:$Rn, V128:$Rm)>;
5028   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5029                                                     (v2i64 V128:$Rm))),
5030             (!cast<Instruction>(NAME # "v2i64_v4i32")
5031                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5032                 V128:$Rn, V128:$Rm)>;
5033 }
5034
5035 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5036                                       Intrinsic IntOp> {
5037   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5038                                             V128, V64, V64,
5039                                             asm, ".8h", ".8b", ".8b",
5040       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5041   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5042                                             V128, V128, V128,
5043                                             asm#"2", ".8h", ".16b", ".16b", []>;
5044   let Predicates = [HasCrypto] in {
5045     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5046                                               V128, V64, V64,
5047                                               asm, ".1q", ".1d", ".1d", []>;
5048     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5049                                               V128, V128, V128,
5050                                               asm#"2", ".1q", ".2d", ".2d", []>;
5051   }
5052
5053   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5054                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
5055       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5056 }
5057
5058 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5059                                  SDPatternOperator OpNode> {
5060   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5061                                                   V128, V64, V64,
5062                                                   asm, ".4s", ".4h", ".4h",
5063       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5064   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5065                                                   V128, V128, V128,
5066                                                   asm#"2", ".4s", ".8h", ".8h",
5067       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5068                                       (extract_high_v8i16 V128:$Rm)))]>;
5069   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5070                                                   V128, V64, V64,
5071                                                   asm, ".2d", ".2s", ".2s",
5072       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5073   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5074                                                   V128, V128, V128,
5075                                                   asm#"2", ".2d", ".4s", ".4s",
5076       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5077                                       (extract_high_v4i32 V128:$Rm)))]>;
5078 }
5079
5080 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5081                                   SDPatternOperator OpNode = null_frag> {
5082   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5083                                                   V128, V64, V64,
5084                                                   asm, ".8h", ".8b", ".8b",
5085       [(set (v8i16 V128:$Rd),
5086             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5087   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5088                                                  V128, V128, V128,
5089                                                  asm#"2", ".8h", ".16b", ".16b",
5090       [(set (v8i16 V128:$Rd),
5091             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5092                                 (extract_high_v16i8 V128:$Rm)))))]>;
5093   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5094                                                   V128, V64, V64,
5095                                                   asm, ".4s", ".4h", ".4h",
5096       [(set (v4i32 V128:$Rd),
5097             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5098   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5099                                                   V128, V128, V128,
5100                                                   asm#"2", ".4s", ".8h", ".8h",
5101       [(set (v4i32 V128:$Rd),
5102             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5103                                   (extract_high_v8i16 V128:$Rm)))))]>;
5104   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5105                                                   V128, V64, V64,
5106                                                   asm, ".2d", ".2s", ".2s",
5107       [(set (v2i64 V128:$Rd),
5108             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5109   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5110                                                   V128, V128, V128,
5111                                                   asm#"2", ".2d", ".4s", ".4s",
5112       [(set (v2i64 V128:$Rd),
5113             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5114                                  (extract_high_v4i32 V128:$Rm)))))]>;
5115 }
5116
5117 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5118                                           string asm,
5119                                           SDPatternOperator OpNode> {
5120   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5121                                                   V128, V64, V64,
5122                                                   asm, ".8h", ".8b", ".8b",
5123     [(set (v8i16 V128:$dst),
5124           (add (v8i16 V128:$Rd),
5125                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5126   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5127                                                  V128, V128, V128,
5128                                                  asm#"2", ".8h", ".16b", ".16b",
5129     [(set (v8i16 V128:$dst),
5130           (add (v8i16 V128:$Rd),
5131                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5132                                    (extract_high_v16i8 V128:$Rm))))))]>;
5133   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5134                                                   V128, V64, V64,
5135                                                   asm, ".4s", ".4h", ".4h",
5136     [(set (v4i32 V128:$dst),
5137           (add (v4i32 V128:$Rd),
5138                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5139   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5140                                                   V128, V128, V128,
5141                                                   asm#"2", ".4s", ".8h", ".8h",
5142     [(set (v4i32 V128:$dst),
5143           (add (v4i32 V128:$Rd),
5144                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5145                                     (extract_high_v8i16 V128:$Rm))))))]>;
5146   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5147                                                   V128, V64, V64,
5148                                                   asm, ".2d", ".2s", ".2s",
5149     [(set (v2i64 V128:$dst),
5150           (add (v2i64 V128:$Rd),
5151                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5152   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5153                                                   V128, V128, V128,
5154                                                   asm#"2", ".2d", ".4s", ".4s",
5155     [(set (v2i64 V128:$dst),
5156           (add (v2i64 V128:$Rd),
5157                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5158                                     (extract_high_v4i32 V128:$Rm))))))]>;
5159 }
5160
5161 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5162                                   SDPatternOperator OpNode = null_frag> {
5163   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5164                                                   V128, V64, V64,
5165                                                   asm, ".8h", ".8b", ".8b",
5166       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5167   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5168                                                  V128, V128, V128,
5169                                                  asm#"2", ".8h", ".16b", ".16b",
5170       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5171                                       (extract_high_v16i8 V128:$Rm)))]>;
5172   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5173                                                   V128, V64, V64,
5174                                                   asm, ".4s", ".4h", ".4h",
5175       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5176   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5177                                                   V128, V128, V128,
5178                                                   asm#"2", ".4s", ".8h", ".8h",
5179       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5180                                       (extract_high_v8i16 V128:$Rm)))]>;
5181   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5182                                                   V128, V64, V64,
5183                                                   asm, ".2d", ".2s", ".2s",
5184       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5185   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5186                                                   V128, V128, V128,
5187                                                   asm#"2", ".2d", ".4s", ".4s",
5188       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5189                                       (extract_high_v4i32 V128:$Rm)))]>;
5190 }
5191
5192 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5193                                       string asm,
5194                                       SDPatternOperator OpNode> {
5195   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5196                                                   V128, V64, V64,
5197                                                   asm, ".8h", ".8b", ".8b",
5198     [(set (v8i16 V128:$dst),
5199           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5200   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5201                                                  V128, V128, V128,
5202                                                  asm#"2", ".8h", ".16b", ".16b",
5203     [(set (v8i16 V128:$dst),
5204           (OpNode (v8i16 V128:$Rd),
5205                   (extract_high_v16i8 V128:$Rn),
5206                   (extract_high_v16i8 V128:$Rm)))]>;
5207   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5208                                                   V128, V64, V64,
5209                                                   asm, ".4s", ".4h", ".4h",
5210     [(set (v4i32 V128:$dst),
5211           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5212   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5213                                                   V128, V128, V128,
5214                                                   asm#"2", ".4s", ".8h", ".8h",
5215     [(set (v4i32 V128:$dst),
5216           (OpNode (v4i32 V128:$Rd),
5217                   (extract_high_v8i16 V128:$Rn),
5218                   (extract_high_v8i16 V128:$Rm)))]>;
5219   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5220                                                   V128, V64, V64,
5221                                                   asm, ".2d", ".2s", ".2s",
5222     [(set (v2i64 V128:$dst),
5223           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5224   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5225                                                   V128, V128, V128,
5226                                                   asm#"2", ".2d", ".4s", ".4s",
5227     [(set (v2i64 V128:$dst),
5228           (OpNode (v2i64 V128:$Rd),
5229                   (extract_high_v4i32 V128:$Rn),
5230                   (extract_high_v4i32 V128:$Rm)))]>;
5231 }
5232
5233 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5234                                            SDPatternOperator Accum> {
5235   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5236                                                   V128, V64, V64,
5237                                                   asm, ".4s", ".4h", ".4h",
5238     [(set (v4i32 V128:$dst),
5239           (Accum (v4i32 V128:$Rd),
5240                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5241                                                 (v4i16 V64:$Rm)))))]>;
5242   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5243                                                   V128, V128, V128,
5244                                                   asm#"2", ".4s", ".8h", ".8h",
5245     [(set (v4i32 V128:$dst),
5246           (Accum (v4i32 V128:$Rd),
5247                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5248                                             (extract_high_v8i16 V128:$Rm)))))]>;
5249   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5250                                                   V128, V64, V64,
5251                                                   asm, ".2d", ".2s", ".2s",
5252     [(set (v2i64 V128:$dst),
5253           (Accum (v2i64 V128:$Rd),
5254                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5255                                                 (v2i32 V64:$Rm)))))]>;
5256   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5257                                                   V128, V128, V128,
5258                                                   asm#"2", ".2d", ".4s", ".4s",
5259     [(set (v2i64 V128:$dst),
5260           (Accum (v2i64 V128:$Rd),
5261                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5262                                             (extract_high_v4i32 V128:$Rm)))))]>;
5263 }
5264
5265 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5266                                   SDPatternOperator OpNode> {
5267   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5268                                                   V128, V128, V64,
5269                                                   asm, ".8h", ".8h", ".8b",
5270        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5271   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5272                                                   V128, V128, V128,
5273                                                   asm#"2", ".8h", ".8h", ".16b",
5274        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5275                                        (extract_high_v16i8 V128:$Rm)))]>;
5276   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5277                                                   V128, V128, V64,
5278                                                   asm, ".4s", ".4s", ".4h",
5279        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5280   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5281                                                   V128, V128, V128,
5282                                                   asm#"2", ".4s", ".4s", ".8h",
5283        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5284                                        (extract_high_v8i16 V128:$Rm)))]>;
5285   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5286                                                   V128, V128, V64,
5287                                                   asm, ".2d", ".2d", ".2s",
5288        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5289   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5290                                                   V128, V128, V128,
5291                                                   asm#"2", ".2d", ".2d", ".4s",
5292        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5293                                        (extract_high_v4i32 V128:$Rm)))]>;
5294 }
5295
5296 //----------------------------------------------------------------------------
5297 // AdvSIMD bitwise extract from vector
5298 //----------------------------------------------------------------------------
5299
5300 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5301                              string asm, string kind>
5302   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5303       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5304       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5305       [(set (vty regtype:$Rd),
5306             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5307     Sched<[WriteV]> {
5308   bits<5> Rd;
5309   bits<5> Rn;
5310   bits<5> Rm;
5311   bits<4> imm;
5312   let Inst{31}    = 0;
5313   let Inst{30}    = size;
5314   let Inst{29-21} = 0b101110000;
5315   let Inst{20-16} = Rm;
5316   let Inst{15}    = 0;
5317   let Inst{14-11} = imm;
5318   let Inst{10}    = 0;
5319   let Inst{9-5}   = Rn;
5320   let Inst{4-0}   = Rd;
5321 }
5322
5323
5324 multiclass SIMDBitwiseExtract<string asm> {
5325   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5326     let imm{3} = 0;
5327   }
5328   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5329 }
5330
5331 //----------------------------------------------------------------------------
5332 // AdvSIMD zip vector
5333 //----------------------------------------------------------------------------
5334
5335 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5336                         string asm, string kind, SDNode OpNode, ValueType valty>
5337   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5338       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5339       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5340       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5341     Sched<[WriteV]> {
5342   bits<5> Rd;
5343   bits<5> Rn;
5344   bits<5> Rm;
5345   let Inst{31}    = 0;
5346   let Inst{30}    = size{0};
5347   let Inst{29-24} = 0b001110;
5348   let Inst{23-22} = size{2-1};
5349   let Inst{21}    = 0;
5350   let Inst{20-16} = Rm;
5351   let Inst{15}    = 0;
5352   let Inst{14-12} = opc;
5353   let Inst{11-10} = 0b10;
5354   let Inst{9-5}   = Rn;
5355   let Inst{4-0}   = Rd;
5356 }
5357
5358 multiclass SIMDZipVector<bits<3>opc, string asm,
5359                          SDNode OpNode> {
5360   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5361       asm, ".8b", OpNode, v8i8>;
5362   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5363       asm, ".16b", OpNode, v16i8>;
5364   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5365       asm, ".4h", OpNode, v4i16>;
5366   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5367       asm, ".8h", OpNode, v8i16>;
5368   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5369       asm, ".2s", OpNode, v2i32>;
5370   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5371       asm, ".4s", OpNode, v4i32>;
5372   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5373       asm, ".2d", OpNode, v2i64>;
5374
5375   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5376         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5377   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5378         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5379   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5380         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5381   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5382         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5383   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5384         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5385 }
5386
5387 //----------------------------------------------------------------------------
5388 // AdvSIMD three register scalar instructions
5389 //----------------------------------------------------------------------------
5390
5391 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5392 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5393                         RegisterClass regtype, string asm,
5394                         list<dag> pattern>
5395   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5396       "\t$Rd, $Rn, $Rm", "", pattern>,
5397     Sched<[WriteV]> {
5398   bits<5> Rd;
5399   bits<5> Rn;
5400   bits<5> Rm;
5401   let Inst{31-30} = 0b01;
5402   let Inst{29}    = U;
5403   let Inst{28-24} = 0b11110;
5404   let Inst{23-22} = size;
5405   let Inst{21}    = 1;
5406   let Inst{20-16} = Rm;
5407   let Inst{15-11} = opcode;
5408   let Inst{10}    = 1;
5409   let Inst{9-5}   = Rn;
5410   let Inst{4-0}   = Rd;
5411 }
5412
5413 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5414 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5415                         dag oops, dag iops, string asm,
5416             list<dag> pattern>
5417   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5418     Sched<[WriteV]> {
5419   bits<5> Rd;
5420   bits<5> Rn;
5421   bits<5> Rm;
5422   let Inst{31-30} = 0b01;
5423   let Inst{29}    = U;
5424   let Inst{28-24} = 0b11110;
5425   let Inst{23-22} = size;
5426   let Inst{21}    = R;
5427   let Inst{20-16} = Rm;
5428   let Inst{15-11} = opcode;
5429   let Inst{10}    = 1;
5430   let Inst{9-5}   = Rn;
5431   let Inst{4-0}   = Rd;
5432 }
5433
5434 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5435                             SDPatternOperator OpNode> {
5436   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5437     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5438 }
5439
5440 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5441                                SDPatternOperator OpNode> {
5442   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5443     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5444   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5445   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5446   def v1i8   : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5447
5448   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5449             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5450   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5451             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5452 }
5453
5454 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5455                              SDPatternOperator OpNode> {
5456   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5457                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5458   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5459 }
5460
5461 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5462                                  SDPatternOperator OpNode = null_frag> {
5463   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5464                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm), 
5465                                      asm, []>;
5466   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5467                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm), 
5468                                      asm, []>;
5469 }
5470
5471 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5472                              SDPatternOperator OpNode = null_frag> {
5473   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5474     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5475       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5476     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5477       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5478   }
5479
5480   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5481             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5482 }
5483
5484 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5485                                 SDPatternOperator OpNode = null_frag> {
5486   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5487     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5488       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5489     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5490       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5491   }
5492
5493   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5494             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5495 }
5496
5497 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5498               dag oops, dag iops, string asm, string cstr, list<dag> pat>
5499   : I<oops, iops, asm,
5500       "\t$Rd, $Rn, $Rm", cstr, pat>,
5501     Sched<[WriteV]> {
5502   bits<5> Rd;
5503   bits<5> Rn;
5504   bits<5> Rm;
5505   let Inst{31-30} = 0b01;
5506   let Inst{29}    = U;
5507   let Inst{28-24} = 0b11110;
5508   let Inst{23-22} = size;
5509   let Inst{21}    = 1;
5510   let Inst{20-16} = Rm;
5511   let Inst{15-11} = opcode;
5512   let Inst{10}    = 0;
5513   let Inst{9-5}   = Rn;
5514   let Inst{4-0}   = Rd;
5515 }
5516
5517 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5518 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5519                                   SDPatternOperator OpNode = null_frag> {
5520   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5521                                       (outs FPR32:$Rd),
5522                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5523   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5524                                       (outs FPR64:$Rd),
5525                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5526             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5527 }
5528
5529 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5530 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5531                                   SDPatternOperator OpNode = null_frag> {
5532   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5533                                       (outs FPR32:$dst),
5534                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5535                                       asm, "$Rd = $dst", []>;
5536   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5537                                       (outs FPR64:$dst),
5538                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5539                                       asm, "$Rd = $dst",
5540             [(set (i64 FPR64:$dst),
5541                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5542 }
5543
5544 //----------------------------------------------------------------------------
5545 // AdvSIMD two register scalar instructions
5546 //----------------------------------------------------------------------------
5547
5548 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5549 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5550                         RegisterClass regtype, RegisterClass regtype2,
5551                         string asm, list<dag> pat>
5552   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5553       "\t$Rd, $Rn", "", pat>,
5554     Sched<[WriteV]> {
5555   bits<5> Rd;
5556   bits<5> Rn;
5557   let Inst{31-30} = 0b01;
5558   let Inst{29}    = U;
5559   let Inst{28-24} = 0b11110;
5560   let Inst{23-22} = size;
5561   let Inst{21-17} = 0b10000;
5562   let Inst{16-12} = opcode;
5563   let Inst{11-10} = 0b10;
5564   let Inst{9-5}   = Rn;
5565   let Inst{4-0}   = Rd;
5566 }
5567
5568 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5569 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5570                         RegisterClass regtype, RegisterClass regtype2,
5571                         string asm, list<dag> pat>
5572   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5573       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5574     Sched<[WriteV]> {
5575   bits<5> Rd;
5576   bits<5> Rn;
5577   let Inst{31-30} = 0b01;
5578   let Inst{29}    = U;
5579   let Inst{28-24} = 0b11110;
5580   let Inst{23-22} = size;
5581   let Inst{21-17} = 0b10000;
5582   let Inst{16-12} = opcode;
5583   let Inst{11-10} = 0b10;
5584   let Inst{9-5}   = Rn;
5585   let Inst{4-0}   = Rd;
5586 }
5587
5588
5589 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5590 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5591                         RegisterClass regtype, string asm, string zero>
5592   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5593       "\t$Rd, $Rn, #" # zero, "", []>,
5594     Sched<[WriteV]> {
5595   bits<5> Rd;
5596   bits<5> Rn;
5597   let Inst{31-30} = 0b01;
5598   let Inst{29}    = U;
5599   let Inst{28-24} = 0b11110;
5600   let Inst{23-22} = size;
5601   let Inst{21-17} = 0b10000;
5602   let Inst{16-12} = opcode;
5603   let Inst{11-10} = 0b10;
5604   let Inst{9-5}   = Rn;
5605   let Inst{4-0}   = Rd;
5606 }
5607
5608 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5609   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5610      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5611     Sched<[WriteV]> {
5612   bits<5> Rd;
5613   bits<5> Rn;
5614   let Inst{31-17} = 0b011111100110000;
5615   let Inst{16-12} = opcode;
5616   let Inst{11-10} = 0b10;
5617   let Inst{9-5}   = Rn;
5618   let Inst{4-0}   = Rd;
5619 }
5620
5621 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5622                              SDPatternOperator OpNode> {
5623   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5624
5625   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5626             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5627 }
5628
5629 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
5630                               SDPatternOperator OpNode> {
5631   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5632   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5633
5634   def : InstAlias<asm # "\t$Rd, $Rn, #0",
5635                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5636   def : InstAlias<asm # "\t$Rd, $Rn, #0",
5637                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5638
5639   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5640             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5641 }
5642
5643 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5644                           SDPatternOperator OpNode = null_frag> {
5645   def v1i64       : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5646     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5647
5648   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5649             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5650 }
5651
5652 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
5653   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5654   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5655 }
5656
5657 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5658                               SDPatternOperator OpNode> {
5659   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5660                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5661   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5662                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5663 }
5664
5665 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5666                              SDPatternOperator OpNode = null_frag> {
5667   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5668     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5669            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5670     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5671            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5672     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5673     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5674   }
5675
5676   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5677             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5678 }
5679
5680 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5681                                  Intrinsic OpNode> {
5682   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5683     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5684         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5685     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5686         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5687     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5688     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5689   }
5690
5691   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5692             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5693 }
5694
5695
5696
5697 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5698 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5699                                  SDPatternOperator OpNode = null_frag> {
5700   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5701         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5702   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5703   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5704 }
5705
5706 //----------------------------------------------------------------------------
5707 // AdvSIMD scalar pairwise instructions
5708 //----------------------------------------------------------------------------
5709
5710 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5711 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5712                         RegisterOperand regtype, RegisterOperand vectype,
5713                         string asm, string kind>
5714   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5715       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5716     Sched<[WriteV]> {
5717   bits<5> Rd;
5718   bits<5> Rn;
5719   let Inst{31-30} = 0b01;
5720   let Inst{29}    = U;
5721   let Inst{28-24} = 0b11110;
5722   let Inst{23-22} = size;
5723   let Inst{21-17} = 0b11000;
5724   let Inst{16-12} = opcode;
5725   let Inst{11-10} = 0b10;
5726   let Inst{9-5}   = Rn;
5727   let Inst{4-0}   = Rd;
5728 }
5729
5730 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5731   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5732                                       asm, ".2d">;
5733 }
5734
5735 multiclass SIMDFPPairwiseScalar<bit U, bit S, bits<5> opc, string asm> {
5736   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5737                                       asm, ".2s">;
5738   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5739                                       asm, ".2d">;
5740 }
5741
5742 //----------------------------------------------------------------------------
5743 // AdvSIMD across lanes instructions
5744 //----------------------------------------------------------------------------
5745
5746 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5747 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5748                           RegisterClass regtype, RegisterOperand vectype,
5749                           string asm, string kind, list<dag> pattern>
5750   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5751       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5752     Sched<[WriteV]> {
5753   bits<5> Rd;
5754   bits<5> Rn;
5755   let Inst{31}    = 0;
5756   let Inst{30}    = Q;
5757   let Inst{29}    = U;
5758   let Inst{28-24} = 0b01110;
5759   let Inst{23-22} = size;
5760   let Inst{21-17} = 0b11000;
5761   let Inst{16-12} = opcode;
5762   let Inst{11-10} = 0b10;
5763   let Inst{9-5}   = Rn;
5764   let Inst{4-0}   = Rd;
5765 }
5766
5767 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5768                               string asm> {
5769   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5770                                    asm, ".8b", []>;
5771   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5772                                    asm, ".16b", []>;
5773   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5774                                    asm, ".4h", []>;
5775   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5776                                    asm, ".8h", []>;
5777   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5778                                    asm, ".4s", []>;
5779 }
5780
5781 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5782   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5783                                    asm, ".8b", []>;
5784   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5785                                    asm, ".16b", []>;
5786   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5787                                    asm, ".4h", []>;
5788   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5789                                    asm, ".8h", []>;
5790   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5791                                    asm, ".4s", []>;
5792 }
5793
5794 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5795                             Intrinsic intOp> {
5796   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5797                                    asm, ".4s",
5798         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5799 }
5800
5801 //----------------------------------------------------------------------------
5802 // AdvSIMD INS/DUP instructions
5803 //----------------------------------------------------------------------------
5804
5805 // FIXME: There has got to be a better way to factor these. ugh.
5806
5807 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5808                      string operands, string constraints, list<dag> pattern>
5809   : I<outs, ins, asm, operands, constraints, pattern>,
5810     Sched<[WriteV]> {
5811   bits<5> Rd;
5812   bits<5> Rn;
5813   let Inst{31} = 0;
5814   let Inst{30} = Q;
5815   let Inst{29} = op;
5816   let Inst{28-21} = 0b01110000;
5817   let Inst{15} = 0;
5818   let Inst{10} = 1;
5819   let Inst{9-5} = Rn;
5820   let Inst{4-0} = Rd;
5821 }
5822
5823 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5824                       RegisterOperand vecreg, RegisterClass regtype>
5825   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5826                    "{\t$Rd" # size # ", $Rn" #
5827                    "|" # size # "\t$Rd, $Rn}", "",
5828                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
5829   let Inst{20-16} = imm5;
5830   let Inst{14-11} = 0b0001;
5831 }
5832
5833 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5834                          ValueType vectype, ValueType insreg,
5835                          RegisterOperand vecreg, Operand idxtype,
5836                          ValueType elttype, SDNode OpNode>
5837   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5838                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5839                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5840                  [(set (vectype vecreg:$Rd),
5841                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5842   let Inst{14-11} = 0b0000;
5843 }
5844
5845 class SIMDDup64FromElement
5846   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5847                        VectorIndexD, i64, AArch64duplane64> {
5848   bits<1> idx;
5849   let Inst{20} = idx;
5850   let Inst{19-16} = 0b1000;
5851 }
5852
5853 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5854                            RegisterOperand vecreg>
5855   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5856                        VectorIndexS, i64, AArch64duplane32> {
5857   bits<2> idx;
5858   let Inst{20-19} = idx;
5859   let Inst{18-16} = 0b100;
5860 }
5861
5862 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5863                            RegisterOperand vecreg>
5864   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5865                        VectorIndexH, i64, AArch64duplane16> {
5866   bits<3> idx;
5867   let Inst{20-18} = idx;
5868   let Inst{17-16} = 0b10;
5869 }
5870
5871 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5872                           RegisterOperand vecreg>
5873   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5874                        VectorIndexB, i64, AArch64duplane8> {
5875   bits<4> idx;
5876   let Inst{20-17} = idx;
5877   let Inst{16} = 1;
5878 }
5879
5880 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5881                   Operand idxtype, string asm, list<dag> pattern>
5882   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5883                    "{\t$Rd, $Rn" # size # "$idx" #
5884                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5885   let Inst{14-11} = imm4;
5886 }
5887
5888 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5889                Operand idxtype>
5890   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5891 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5892                Operand idxtype>
5893   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5894       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5895
5896 class SIMDMovAlias<string asm, string size, Instruction inst,
5897                    RegisterClass regtype, Operand idxtype>
5898     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5899                     "|" # size # "\t$dst, $src$idx}",
5900                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5901
5902 multiclass SMov {
5903   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5904     bits<4> idx;
5905     let Inst{20-17} = idx;
5906     let Inst{16} = 1;
5907   }
5908   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5909     bits<4> idx;
5910     let Inst{20-17} = idx;
5911     let Inst{16} = 1;
5912   }
5913   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5914     bits<3> idx;
5915     let Inst{20-18} = idx;
5916     let Inst{17-16} = 0b10;
5917   }
5918   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5919     bits<3> idx;
5920     let Inst{20-18} = idx;
5921     let Inst{17-16} = 0b10;
5922   }
5923   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5924     bits<2> idx;
5925     let Inst{20-19} = idx;
5926     let Inst{18-16} = 0b100;
5927   }
5928 }
5929
5930 multiclass UMov {
5931   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5932     bits<4> idx;
5933     let Inst{20-17} = idx;
5934     let Inst{16} = 1;
5935   }
5936   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5937     bits<3> idx;
5938     let Inst{20-18} = idx;
5939     let Inst{17-16} = 0b10;
5940   }
5941   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5942     bits<2> idx;
5943     let Inst{20-19} = idx;
5944     let Inst{18-16} = 0b100;
5945   }
5946   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5947     bits<1> idx;
5948     let Inst{20} = idx;
5949     let Inst{19-16} = 0b1000;
5950   }
5951   def : SIMDMovAlias<"mov", ".s",
5952                      !cast<Instruction>(NAME#"vi32"),
5953                      GPR32, VectorIndexS>;
5954   def : SIMDMovAlias<"mov", ".d",
5955                      !cast<Instruction>(NAME#"vi64"),
5956                      GPR64, VectorIndexD>;
5957 }
5958
5959 class SIMDInsFromMain<string size, ValueType vectype,
5960                       RegisterClass regtype, Operand idxtype>
5961   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5962                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5963                    "{\t$Rd" # size # "$idx, $Rn" #
5964                    "|" # size # "\t$Rd$idx, $Rn}",
5965                    "$Rd = $dst",
5966             [(set V128:$dst,
5967               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5968   let Inst{14-11} = 0b0011;
5969 }
5970
5971 class SIMDInsFromElement<string size, ValueType vectype,
5972                          ValueType elttype, Operand idxtype>
5973   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5974                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5975                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5976                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
5977                    "$Rd = $dst",
5978          [(set V128:$dst,
5979                (vector_insert
5980                  (vectype V128:$Rd),
5981                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5982                  idxtype:$idx))]>;
5983
5984 class SIMDInsMainMovAlias<string size, Instruction inst,
5985                           RegisterClass regtype, Operand idxtype>
5986     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5987                         "|" # size #"\t$dst$idx, $src}",
5988                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5989 class SIMDInsElementMovAlias<string size, Instruction inst,
5990                              Operand idxtype>
5991     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5992                       # "|" # size #"\t$dst$idx, $src$idx2}",
5993                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5994
5995
5996 multiclass SIMDIns {
5997   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5998     bits<4> idx;
5999     let Inst{20-17} = idx;
6000     let Inst{16} = 1;
6001   }
6002   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6003     bits<3> idx;
6004     let Inst{20-18} = idx;
6005     let Inst{17-16} = 0b10;
6006   }
6007   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6008     bits<2> idx;
6009     let Inst{20-19} = idx;
6010     let Inst{18-16} = 0b100;
6011   }
6012   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6013     bits<1> idx;
6014     let Inst{20} = idx;
6015     let Inst{19-16} = 0b1000;
6016   }
6017
6018   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6019     bits<4> idx;
6020     bits<4> idx2;
6021     let Inst{20-17} = idx;
6022     let Inst{16} = 1;
6023     let Inst{14-11} = idx2;
6024   }
6025   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6026     bits<3> idx;
6027     bits<3> idx2;
6028     let Inst{20-18} = idx;
6029     let Inst{17-16} = 0b10;
6030     let Inst{14-12} = idx2;
6031     let Inst{11} = {?};
6032   }
6033   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6034     bits<2> idx;
6035     bits<2> idx2;
6036     let Inst{20-19} = idx;
6037     let Inst{18-16} = 0b100;
6038     let Inst{14-13} = idx2;
6039     let Inst{12-11} = {?,?};
6040   }
6041   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6042     bits<1> idx;
6043     bits<1> idx2;
6044     let Inst{20} = idx;
6045     let Inst{19-16} = 0b1000;
6046     let Inst{14} = idx2;
6047     let Inst{13-11} = {?,?,?};
6048   }
6049
6050   // For all forms of the INS instruction, the "mov" mnemonic is the
6051   // preferred alias. Why they didn't just call the instruction "mov" in
6052   // the first place is a very good question indeed...
6053   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6054                          GPR32, VectorIndexB>;
6055   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6056                          GPR32, VectorIndexH>;
6057   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6058                          GPR32, VectorIndexS>;
6059   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6060                          GPR64, VectorIndexD>;
6061
6062   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6063                          VectorIndexB>;
6064   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6065                          VectorIndexH>;
6066   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6067                          VectorIndexS>;
6068   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6069                          VectorIndexD>;
6070 }
6071
6072 //----------------------------------------------------------------------------
6073 // AdvSIMD TBL/TBX
6074 //----------------------------------------------------------------------------
6075
6076 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6077 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6078                           RegisterOperand listtype, string asm, string kind>
6079   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6080        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6081     Sched<[WriteV]> {
6082   bits<5> Vd;
6083   bits<5> Vn;
6084   bits<5> Vm;
6085   let Inst{31}    = 0;
6086   let Inst{30}    = Q;
6087   let Inst{29-21} = 0b001110000;
6088   let Inst{20-16} = Vm;
6089   let Inst{15}    = 0;
6090   let Inst{14-13} = len;
6091   let Inst{12}    = op;
6092   let Inst{11-10} = 0b00;
6093   let Inst{9-5}   = Vn;
6094   let Inst{4-0}   = Vd;
6095 }
6096
6097 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6098 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6099                           RegisterOperand listtype, string asm, string kind>
6100   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6101        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6102     Sched<[WriteV]> {
6103   bits<5> Vd;
6104   bits<5> Vn;
6105   bits<5> Vm;
6106   let Inst{31}    = 0;
6107   let Inst{30}    = Q;
6108   let Inst{29-21} = 0b001110000;
6109   let Inst{20-16} = Vm;
6110   let Inst{15}    = 0;
6111   let Inst{14-13} = len;
6112   let Inst{12}    = op;
6113   let Inst{11-10} = 0b00;
6114   let Inst{9-5}   = Vn;
6115   let Inst{4-0}   = Vd;
6116 }
6117
6118 class SIMDTableLookupAlias<string asm, Instruction inst,
6119                           RegisterOperand vectype, RegisterOperand listtype>
6120     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6121                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6122
6123 multiclass SIMDTableLookup<bit op, string asm> {
6124   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6125                                       asm, ".8b">;
6126   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6127                                       asm, ".8b">;
6128   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6129                                       asm, ".8b">;
6130   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6131                                       asm, ".8b">;
6132   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6133                                       asm, ".16b">;
6134   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6135                                       asm, ".16b">;
6136   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6137                                       asm, ".16b">;
6138   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6139                                       asm, ".16b">;
6140
6141   def : SIMDTableLookupAlias<asm # ".8b",
6142                          !cast<Instruction>(NAME#"v8i8One"),
6143                          V64, VecListOne128>;
6144   def : SIMDTableLookupAlias<asm # ".8b",
6145                          !cast<Instruction>(NAME#"v8i8Two"),
6146                          V64, VecListTwo128>;
6147   def : SIMDTableLookupAlias<asm # ".8b",
6148                          !cast<Instruction>(NAME#"v8i8Three"),
6149                          V64, VecListThree128>;
6150   def : SIMDTableLookupAlias<asm # ".8b",
6151                          !cast<Instruction>(NAME#"v8i8Four"),
6152                          V64, VecListFour128>;
6153   def : SIMDTableLookupAlias<asm # ".16b",
6154                          !cast<Instruction>(NAME#"v16i8One"),
6155                          V128, VecListOne128>;
6156   def : SIMDTableLookupAlias<asm # ".16b",
6157                          !cast<Instruction>(NAME#"v16i8Two"),
6158                          V128, VecListTwo128>;
6159   def : SIMDTableLookupAlias<asm # ".16b",
6160                          !cast<Instruction>(NAME#"v16i8Three"),
6161                          V128, VecListThree128>;
6162   def : SIMDTableLookupAlias<asm # ".16b",
6163                          !cast<Instruction>(NAME#"v16i8Four"),
6164                          V128, VecListFour128>;
6165 }
6166
6167 multiclass SIMDTableLookupTied<bit op, string asm> {
6168   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6169                                       asm, ".8b">;
6170   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6171                                       asm, ".8b">;
6172   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6173                                       asm, ".8b">;
6174   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6175                                       asm, ".8b">;
6176   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6177                                       asm, ".16b">;
6178   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6179                                       asm, ".16b">;
6180   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6181                                       asm, ".16b">;
6182   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6183                                       asm, ".16b">;
6184
6185   def : SIMDTableLookupAlias<asm # ".8b",
6186                          !cast<Instruction>(NAME#"v8i8One"),
6187                          V64, VecListOne128>;
6188   def : SIMDTableLookupAlias<asm # ".8b",
6189                          !cast<Instruction>(NAME#"v8i8Two"),
6190                          V64, VecListTwo128>;
6191   def : SIMDTableLookupAlias<asm # ".8b",
6192                          !cast<Instruction>(NAME#"v8i8Three"),
6193                          V64, VecListThree128>;
6194   def : SIMDTableLookupAlias<asm # ".8b",
6195                          !cast<Instruction>(NAME#"v8i8Four"),
6196                          V64, VecListFour128>;
6197   def : SIMDTableLookupAlias<asm # ".16b",
6198                          !cast<Instruction>(NAME#"v16i8One"),
6199                          V128, VecListOne128>;
6200   def : SIMDTableLookupAlias<asm # ".16b",
6201                          !cast<Instruction>(NAME#"v16i8Two"),
6202                          V128, VecListTwo128>;
6203   def : SIMDTableLookupAlias<asm # ".16b",
6204                          !cast<Instruction>(NAME#"v16i8Three"),
6205                          V128, VecListThree128>;
6206   def : SIMDTableLookupAlias<asm # ".16b",
6207                          !cast<Instruction>(NAME#"v16i8Four"),
6208                          V128, VecListFour128>;
6209 }
6210
6211
6212 //----------------------------------------------------------------------------
6213 // AdvSIMD scalar CPY
6214 //----------------------------------------------------------------------------
6215 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6216 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6217                         string kind, Operand idxtype>
6218   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6219        "{\t$dst, $src" # kind # "$idx" #
6220        "|\t$dst, $src$idx}", "", []>,
6221     Sched<[WriteV]> {
6222   bits<5> dst;
6223   bits<5> src;
6224   let Inst{31-21} = 0b01011110000;
6225   let Inst{15-10} = 0b000001;
6226   let Inst{9-5}   = src;
6227   let Inst{4-0}   = dst;
6228 }
6229
6230 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6231       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6232     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6233                     # "|\t$dst, $src$index}",
6234                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6235
6236
6237 multiclass SIMDScalarCPY<string asm> {
6238   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6239     bits<4> idx;
6240     let Inst{20-17} = idx;
6241     let Inst{16} = 1;
6242   }
6243   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6244     bits<3> idx;
6245     let Inst{20-18} = idx;
6246     let Inst{17-16} = 0b10;
6247   }
6248   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6249     bits<2> idx;
6250     let Inst{20-19} = idx;
6251     let Inst{18-16} = 0b100;
6252   }
6253   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6254     bits<1> idx;
6255     let Inst{20} = idx;
6256     let Inst{19-16} = 0b1000;
6257   }
6258
6259   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6260                                                           VectorIndexD:$idx)))),
6261             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6262
6263   // 'DUP' mnemonic aliases.
6264   def : SIMDScalarCPYAlias<"dup", ".b",
6265                            !cast<Instruction>(NAME#"i8"),
6266                            FPR8, V128, VectorIndexB>;
6267   def : SIMDScalarCPYAlias<"dup", ".h",
6268                            !cast<Instruction>(NAME#"i16"),
6269                            FPR16, V128, VectorIndexH>;
6270   def : SIMDScalarCPYAlias<"dup", ".s",
6271                            !cast<Instruction>(NAME#"i32"),
6272                            FPR32, V128, VectorIndexS>;
6273   def : SIMDScalarCPYAlias<"dup", ".d",
6274                            !cast<Instruction>(NAME#"i64"),
6275                            FPR64, V128, VectorIndexD>;
6276 }
6277
6278 //----------------------------------------------------------------------------
6279 // AdvSIMD modified immediate instructions
6280 //----------------------------------------------------------------------------
6281
6282 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
6283                           string asm, string op_string,
6284                           string cstr, list<dag> pattern>
6285   : I<oops, iops, asm, op_string, cstr, pattern>,
6286     Sched<[WriteV]> {
6287   bits<5> Rd;
6288   bits<8> imm8;
6289   let Inst{31}    = 0;
6290   let Inst{30}    = Q;
6291   let Inst{29}    = op;
6292   let Inst{28-19} = 0b0111100000;
6293   let Inst{18-16} = imm8{7-5};
6294   let Inst{11-10} = 0b01;
6295   let Inst{9-5}   = imm8{4-0};
6296   let Inst{4-0}   = Rd;
6297 }
6298
6299 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
6300                                 Operand immtype, dag opt_shift_iop,
6301                                 string opt_shift, string asm, string kind,
6302                                 list<dag> pattern>
6303   : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
6304                         !con((ins immtype:$imm8), opt_shift_iop), asm,
6305                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
6306                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6307                         "", pattern> {
6308   let DecoderMethod = "DecodeModImmInstruction";
6309 }
6310
6311 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6312                                 Operand immtype, dag opt_shift_iop,
6313                                 string opt_shift, string asm, string kind,
6314                                 list<dag> pattern>
6315   : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
6316                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6317                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6318                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6319                         "$Rd = $dst", pattern> {
6320   let DecoderMethod = "DecodeModImmTiedInstruction";
6321 }
6322
6323 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6324                                      RegisterOperand vectype, string asm,
6325                                      string kind, list<dag> pattern>
6326   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6327                               (ins logical_vec_shift:$shift),
6328                               "$shift", asm, kind, pattern> {
6329   bits<2> shift;
6330   let Inst{15}    = b15_b12{1};
6331   let Inst{14-13} = shift;
6332   let Inst{12}    = b15_b12{0};
6333 }
6334
6335 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6336                                      RegisterOperand vectype, string asm,
6337                                      string kind, list<dag> pattern>
6338   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6339                               (ins logical_vec_shift:$shift),
6340                               "$shift", asm, kind, pattern> {
6341   bits<2> shift;
6342   let Inst{15}    = b15_b12{1};
6343   let Inst{14-13} = shift;
6344   let Inst{12}    = b15_b12{0};
6345 }
6346
6347
6348 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6349                                          RegisterOperand vectype, string asm,
6350                                          string kind, list<dag> pattern>
6351   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6352                               (ins logical_vec_hw_shift:$shift),
6353                               "$shift", asm, kind, pattern> {
6354   bits<2> shift;
6355   let Inst{15} = b15_b12{1};
6356   let Inst{14} = 0;
6357   let Inst{13} = shift{0};
6358   let Inst{12} = b15_b12{0};
6359 }
6360
6361 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6362                                          RegisterOperand vectype, string asm,
6363                                          string kind, list<dag> pattern>
6364   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6365                               (ins logical_vec_hw_shift:$shift),
6366                               "$shift", asm, kind, pattern> {
6367   bits<2> shift;
6368   let Inst{15} = b15_b12{1};
6369   let Inst{14} = 0;
6370   let Inst{13} = shift{0};
6371   let Inst{12} = b15_b12{0};
6372 }
6373
6374 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6375                                       string asm> {
6376   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6377                                                  asm, ".4h", []>;
6378   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6379                                                  asm, ".8h", []>;
6380
6381   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6382                                              asm, ".2s", []>;
6383   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6384                                              asm, ".4s", []>;
6385 }
6386
6387 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6388                                       bits<2> w_cmode, string asm,
6389                                       SDNode OpNode> {
6390   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6391                                                  asm, ".4h",
6392              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6393                                              imm0_255:$imm8,
6394                                              (i32 imm:$shift)))]>;
6395   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6396                                                  asm, ".8h",
6397              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6398                                               imm0_255:$imm8,
6399                                               (i32 imm:$shift)))]>;
6400
6401   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6402                                              asm, ".2s",
6403              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6404                                              imm0_255:$imm8,
6405                                              (i32 imm:$shift)))]>;
6406   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6407                                              asm, ".4s",
6408              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6409                                               imm0_255:$imm8,
6410                                               (i32 imm:$shift)))]>;
6411 }
6412
6413 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6414                              RegisterOperand vectype, string asm,
6415                              string kind, list<dag> pattern>
6416   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6417                               (ins move_vec_shift:$shift),
6418                               "$shift", asm, kind, pattern> {
6419   bits<1> shift;
6420   let Inst{15-13} = cmode{3-1};
6421   let Inst{12}    = shift;
6422 }
6423
6424 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
6425                                    RegisterOperand vectype,
6426                                    Operand imm_type, string asm,
6427                                    string kind, list<dag> pattern>
6428   : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
6429                               asm, kind, pattern> {
6430   let Inst{15-12} = cmode;
6431 }
6432
6433 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6434                                    list<dag> pattern>
6435   : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6436                         "\t$Rd, $imm8", "", pattern> {
6437   let Inst{15-12} = cmode;
6438   let DecoderMethod = "DecodeModImmInstruction";
6439 }
6440
6441 //----------------------------------------------------------------------------
6442 // AdvSIMD indexed element
6443 //----------------------------------------------------------------------------
6444
6445 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6446 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6447                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6448                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6449                       string apple_kind, string dst_kind, string lhs_kind,
6450                       string rhs_kind, list<dag> pattern>
6451   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6452       asm,
6453       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6454       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6455     Sched<[WriteV]> {
6456   bits<5> Rd;
6457   bits<5> Rn;
6458   bits<5> Rm;
6459
6460   let Inst{31}    = 0;
6461   let Inst{30}    = Q;
6462   let Inst{29}    = U;
6463   let Inst{28}    = Scalar;
6464   let Inst{27-24} = 0b1111;
6465   let Inst{23-22} = size;
6466   // Bit 21 must be set by the derived class.
6467   let Inst{20-16} = Rm;
6468   let Inst{15-12} = opc;
6469   // Bit 11 must be set by the derived class.
6470   let Inst{10}    = 0;
6471   let Inst{9-5}   = Rn;
6472   let Inst{4-0}   = Rd;
6473 }
6474
6475 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6476 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6477                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6478                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6479                       string apple_kind, string dst_kind, string lhs_kind,
6480                       string rhs_kind, list<dag> pattern>
6481   : I<(outs dst_reg:$dst),
6482       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6483       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6484       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6485     Sched<[WriteV]> {
6486   bits<5> Rd;
6487   bits<5> Rn;
6488   bits<5> Rm;
6489
6490   let Inst{31}    = 0;
6491   let Inst{30}    = Q;
6492   let Inst{29}    = U;
6493   let Inst{28}    = Scalar;
6494   let Inst{27-24} = 0b1111;
6495   let Inst{23-22} = size;
6496   // Bit 21 must be set by the derived class.
6497   let Inst{20-16} = Rm;
6498   let Inst{15-12} = opc;
6499   // Bit 11 must be set by the derived class.
6500   let Inst{10}    = 0;
6501   let Inst{9-5}   = Rn;
6502   let Inst{4-0}   = Rd;
6503 }
6504
6505 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
6506                          SDPatternOperator OpNode> {
6507   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6508                                       V64, V64,
6509                                       V128, VectorIndexS,
6510                                       asm, ".2s", ".2s", ".2s", ".s",
6511     [(set (v2f32 V64:$Rd),
6512         (OpNode (v2f32 V64:$Rn),
6513          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6514     bits<2> idx;
6515     let Inst{11} = idx{1};
6516     let Inst{21} = idx{0};
6517   }
6518
6519   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6520                                       V128, V128,
6521                                       V128, VectorIndexS,
6522                                       asm, ".4s", ".4s", ".4s", ".s",
6523     [(set (v4f32 V128:$Rd),
6524         (OpNode (v4f32 V128:$Rn),
6525          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6526     bits<2> idx;
6527     let Inst{11} = idx{1};
6528     let Inst{21} = idx{0};
6529   }
6530
6531   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6532                                       V128, V128,
6533                                       V128, VectorIndexD,
6534                                       asm, ".2d", ".2d", ".2d", ".d",
6535     [(set (v2f64 V128:$Rd),
6536         (OpNode (v2f64 V128:$Rn),
6537          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6538     bits<1> idx;
6539     let Inst{11} = idx{0};
6540     let Inst{21} = 0;
6541   }
6542
6543   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6544                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6545                                       asm, ".s", "", "", ".s",
6546     [(set (f32 FPR32Op:$Rd),
6547           (OpNode (f32 FPR32Op:$Rn),
6548                   (f32 (vector_extract (v4f32 V128:$Rm),
6549                                        VectorIndexS:$idx))))]> {
6550     bits<2> idx;
6551     let Inst{11} = idx{1};
6552     let Inst{21} = idx{0};
6553   }
6554
6555   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6556                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6557                                       asm, ".d", "", "", ".d",
6558     [(set (f64 FPR64Op:$Rd),
6559           (OpNode (f64 FPR64Op:$Rn),
6560                   (f64 (vector_extract (v2f64 V128:$Rm),
6561                                        VectorIndexD:$idx))))]> {
6562     bits<1> idx;
6563     let Inst{11} = idx{0};
6564     let Inst{21} = 0;
6565   }
6566 }
6567
6568 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
6569   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6570   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6571                            (AArch64duplane32 (v4f32 V128:$Rm),
6572                                            VectorIndexS:$idx))),
6573             (!cast<Instruction>(INST # v2i32_indexed)
6574                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6575   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6576                            (AArch64dup (f32 FPR32Op:$Rm)))),
6577             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6578                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6579
6580
6581   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6582   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6583                            (AArch64duplane32 (v4f32 V128:$Rm),
6584                                            VectorIndexS:$idx))),
6585             (!cast<Instruction>(INST # "v4i32_indexed")
6586                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6587   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6588                            (AArch64dup (f32 FPR32Op:$Rm)))),
6589             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6590                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6591
6592   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6593   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6594                            (AArch64duplane64 (v2f64 V128:$Rm),
6595                                            VectorIndexD:$idx))),
6596             (!cast<Instruction>(INST # "v2i64_indexed")
6597                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6598   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6599                            (AArch64dup (f64 FPR64Op:$Rm)))),
6600             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6601                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6602
6603   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6604   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6605                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6606             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6607                 V128:$Rm, VectorIndexS:$idx)>;
6608   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6609                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6610             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6611                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6612
6613   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6614   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6615                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6616             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6617                 V128:$Rm, VectorIndexD:$idx)>;
6618 }
6619
6620 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
6621   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6622                                           V128, VectorIndexS,
6623                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6624     bits<2> idx;
6625     let Inst{11} = idx{1};
6626     let Inst{21} = idx{0};
6627   }
6628
6629   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6630                                       V128, V128,
6631                                       V128, VectorIndexS,
6632                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6633     bits<2> idx;
6634     let Inst{11} = idx{1};
6635     let Inst{21} = idx{0};
6636   }
6637
6638   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6639                                       V128, V128,
6640                                       V128, VectorIndexD,
6641                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6642     bits<1> idx;
6643     let Inst{11} = idx{0};
6644     let Inst{21} = 0;
6645   }
6646
6647
6648   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6649                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6650                                       asm, ".s", "", "", ".s", []> {
6651     bits<2> idx;
6652     let Inst{11} = idx{1};
6653     let Inst{21} = idx{0};
6654   }
6655
6656   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6657                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6658                                       asm, ".d", "", "", ".d", []> {
6659     bits<1> idx;
6660     let Inst{11} = idx{0};
6661     let Inst{21} = 0;
6662   }
6663 }
6664
6665 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6666                          SDPatternOperator OpNode> {
6667   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6668                                       V128_lo, VectorIndexH,
6669                                       asm, ".4h", ".4h", ".4h", ".h",
6670     [(set (v4i16 V64:$Rd),
6671         (OpNode (v4i16 V64:$Rn),
6672          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6673     bits<3> idx;
6674     let Inst{11} = idx{2};
6675     let Inst{21} = idx{1};
6676     let Inst{20} = idx{0};
6677   }
6678
6679   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6680                                       V128, V128,
6681                                       V128_lo, VectorIndexH,
6682                                       asm, ".8h", ".8h", ".8h", ".h",
6683     [(set (v8i16 V128:$Rd),
6684        (OpNode (v8i16 V128:$Rn),
6685          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6686     bits<3> idx;
6687     let Inst{11} = idx{2};
6688     let Inst{21} = idx{1};
6689     let Inst{20} = idx{0};
6690   }
6691
6692   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6693                                       V64, V64,
6694                                       V128, VectorIndexS,
6695                                       asm, ".2s", ".2s", ".2s",  ".s",
6696     [(set (v2i32 V64:$Rd),
6697        (OpNode (v2i32 V64:$Rn),
6698           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6699     bits<2> idx;
6700     let Inst{11} = idx{1};
6701     let Inst{21} = idx{0};
6702   }
6703
6704   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6705                                       V128, V128,
6706                                       V128, VectorIndexS,
6707                                       asm, ".4s", ".4s", ".4s", ".s",
6708     [(set (v4i32 V128:$Rd),
6709        (OpNode (v4i32 V128:$Rn),
6710           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6711     bits<2> idx;
6712     let Inst{11} = idx{1};
6713     let Inst{21} = idx{0};
6714   }
6715
6716   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6717                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6718                                       asm, ".h", "", "", ".h", []> {
6719     bits<3> idx;
6720     let Inst{11} = idx{2};
6721     let Inst{21} = idx{1};
6722     let Inst{20} = idx{0};
6723   }
6724
6725   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6726                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6727                                       asm, ".s", "", "", ".s",
6728       [(set (i32 FPR32Op:$Rd),
6729             (OpNode FPR32Op:$Rn,
6730                     (i32 (vector_extract (v4i32 V128:$Rm),
6731                                          VectorIndexS:$idx))))]> {
6732     bits<2> idx;
6733     let Inst{11} = idx{1};
6734     let Inst{21} = idx{0};
6735   }
6736 }
6737
6738 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6739                                SDPatternOperator OpNode> {
6740   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6741                                       V64, V64,
6742                                       V128_lo, VectorIndexH,
6743                                       asm, ".4h", ".4h", ".4h", ".h",
6744     [(set (v4i16 V64:$Rd),
6745         (OpNode (v4i16 V64:$Rn),
6746          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6747     bits<3> idx;
6748     let Inst{11} = idx{2};
6749     let Inst{21} = idx{1};
6750     let Inst{20} = idx{0};
6751   }
6752
6753   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6754                                       V128, V128,
6755                                       V128_lo, VectorIndexH,
6756                                       asm, ".8h", ".8h", ".8h", ".h",
6757     [(set (v8i16 V128:$Rd),
6758        (OpNode (v8i16 V128:$Rn),
6759          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6760     bits<3> idx;
6761     let Inst{11} = idx{2};
6762     let Inst{21} = idx{1};
6763     let Inst{20} = idx{0};
6764   }
6765
6766   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6767                                       V64, V64,
6768                                       V128, VectorIndexS,
6769                                       asm, ".2s", ".2s", ".2s", ".s",
6770     [(set (v2i32 V64:$Rd),
6771        (OpNode (v2i32 V64:$Rn),
6772           (v2i32 (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   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6779                                       V128, V128,
6780                                       V128, VectorIndexS,
6781                                       asm, ".4s", ".4s", ".4s", ".s",
6782     [(set (v4i32 V128:$Rd),
6783        (OpNode (v4i32 V128:$Rn),
6784           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6785     bits<2> idx;
6786     let Inst{11} = idx{1};
6787     let Inst{21} = idx{0};
6788   }
6789 }
6790
6791 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6792                                    SDPatternOperator OpNode> {
6793   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6794                                           V128_lo, VectorIndexH,
6795                                           asm, ".4h", ".4h", ".4h", ".h",
6796     [(set (v4i16 V64:$dst),
6797         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6798          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6799     bits<3> idx;
6800     let Inst{11} = idx{2};
6801     let Inst{21} = idx{1};
6802     let Inst{20} = idx{0};
6803   }
6804
6805   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6806                                       V128, V128,
6807                                       V128_lo, VectorIndexH,
6808                                       asm, ".8h", ".8h", ".8h", ".h",
6809     [(set (v8i16 V128:$dst),
6810        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6811          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6812     bits<3> idx;
6813     let Inst{11} = idx{2};
6814     let Inst{21} = idx{1};
6815     let Inst{20} = idx{0};
6816   }
6817
6818   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6819                                       V64, V64,
6820                                       V128, VectorIndexS,
6821                                       asm, ".2s", ".2s", ".2s", ".s",
6822     [(set (v2i32 V64:$dst),
6823        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6824           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6825     bits<2> idx;
6826     let Inst{11} = idx{1};
6827     let Inst{21} = idx{0};
6828   }
6829
6830   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6831                                       V128, V128,
6832                                       V128, VectorIndexS,
6833                                       asm, ".4s", ".4s", ".4s", ".s",
6834     [(set (v4i32 V128:$dst),
6835        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6836           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6837     bits<2> idx;
6838     let Inst{11} = idx{1};
6839     let Inst{21} = idx{0};
6840   }
6841 }
6842
6843 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6844                              SDPatternOperator OpNode> {
6845   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6846                                       V128, V64,
6847                                       V128_lo, VectorIndexH,
6848                                       asm, ".4s", ".4s", ".4h", ".h",
6849     [(set (v4i32 V128:$Rd),
6850         (OpNode (v4i16 V64:$Rn),
6851          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6852     bits<3> idx;
6853     let Inst{11} = idx{2};
6854     let Inst{21} = idx{1};
6855     let Inst{20} = idx{0};
6856   }
6857
6858   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6859                                       V128, V128,
6860                                       V128_lo, VectorIndexH,
6861                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6862     [(set (v4i32 V128:$Rd),
6863           (OpNode (extract_high_v8i16 V128:$Rn),
6864                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6865                                                       VectorIndexH:$idx))))]> {
6866
6867     bits<3> idx;
6868     let Inst{11} = idx{2};
6869     let Inst{21} = idx{1};
6870     let Inst{20} = idx{0};
6871   }
6872
6873   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6874                                       V128, V64,
6875                                       V128, VectorIndexS,
6876                                       asm, ".2d", ".2d", ".2s", ".s",
6877     [(set (v2i64 V128:$Rd),
6878         (OpNode (v2i32 V64:$Rn),
6879          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6880     bits<2> idx;
6881     let Inst{11} = idx{1};
6882     let Inst{21} = idx{0};
6883   }
6884
6885   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6886                                       V128, V128,
6887                                       V128, VectorIndexS,
6888                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6889     [(set (v2i64 V128:$Rd),
6890           (OpNode (extract_high_v4i32 V128:$Rn),
6891                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
6892                                                       VectorIndexS:$idx))))]> {
6893     bits<2> idx;
6894     let Inst{11} = idx{1};
6895     let Inst{21} = idx{0};
6896   }
6897
6898   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6899                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6900                                       asm, ".h", "", "", ".h", []> {
6901     bits<3> idx;
6902     let Inst{11} = idx{2};
6903     let Inst{21} = idx{1};
6904     let Inst{20} = idx{0};
6905   }
6906
6907   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6908                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6909                                       asm, ".s", "", "", ".s", []> {
6910     bits<2> idx;
6911     let Inst{11} = idx{1};
6912     let Inst{21} = idx{0};
6913   }
6914 }
6915
6916 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6917                                        SDPatternOperator Accum> {
6918   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6919                                       V128, V64,
6920                                       V128_lo, VectorIndexH,
6921                                       asm, ".4s", ".4s", ".4h", ".h",
6922     [(set (v4i32 V128:$dst),
6923           (Accum (v4i32 V128:$Rd),
6924                  (v4i32 (int_aarch64_neon_sqdmull
6925                              (v4i16 V64:$Rn),
6926                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6927                                                     VectorIndexH:$idx))))))]> {
6928     bits<3> idx;
6929     let Inst{11} = idx{2};
6930     let Inst{21} = idx{1};
6931     let Inst{20} = idx{0};
6932   }
6933
6934   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6935   // intermediate EXTRACT_SUBREG would be untyped.
6936   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6937                 (i32 (vector_extract (v4i32
6938                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6939                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6940                                                     VectorIndexH:$idx)))),
6941                          (i64 0))))),
6942             (EXTRACT_SUBREG
6943                 (!cast<Instruction>(NAME # v4i16_indexed)
6944                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6945                     V128_lo:$Rm, VectorIndexH:$idx),
6946                 ssub)>;
6947
6948   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6949                                       V128, V128,
6950                                       V128_lo, VectorIndexH,
6951                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6952     [(set (v4i32 V128:$dst),
6953           (Accum (v4i32 V128:$Rd),
6954                  (v4i32 (int_aarch64_neon_sqdmull
6955                             (extract_high_v8i16 V128:$Rn),
6956                             (extract_high_v8i16
6957                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6958                                                 VectorIndexH:$idx))))))]> {
6959     bits<3> idx;
6960     let Inst{11} = idx{2};
6961     let Inst{21} = idx{1};
6962     let Inst{20} = idx{0};
6963   }
6964
6965   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6966                                       V128, V64,
6967                                       V128, VectorIndexS,
6968                                       asm, ".2d", ".2d", ".2s", ".s",
6969     [(set (v2i64 V128:$dst),
6970         (Accum (v2i64 V128:$Rd),
6971                (v2i64 (int_aarch64_neon_sqdmull
6972                           (v2i32 V64:$Rn),
6973                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
6974                                                  VectorIndexS:$idx))))))]> {
6975     bits<2> idx;
6976     let Inst{11} = idx{1};
6977     let Inst{21} = idx{0};
6978   }
6979
6980   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6981                                       V128, V128,
6982                                       V128, VectorIndexS,
6983                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6984     [(set (v2i64 V128:$dst),
6985           (Accum (v2i64 V128:$Rd),
6986                  (v2i64 (int_aarch64_neon_sqdmull
6987                             (extract_high_v4i32 V128:$Rn),
6988                             (extract_high_v4i32
6989                                 (AArch64duplane32 (v4i32 V128:$Rm),
6990                                                 VectorIndexS:$idx))))))]> {
6991     bits<2> idx;
6992     let Inst{11} = idx{1};
6993     let Inst{21} = idx{0};
6994   }
6995
6996   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6997                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6998                                       asm, ".h", "", "", ".h", []> {
6999     bits<3> idx;
7000     let Inst{11} = idx{2};
7001     let Inst{21} = idx{1};
7002     let Inst{20} = idx{0};
7003   }
7004
7005
7006   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7007                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7008                                       asm, ".s", "", "", ".s",
7009     [(set (i64 FPR64Op:$dst),
7010           (Accum (i64 FPR64Op:$Rd),
7011                  (i64 (int_aarch64_neon_sqdmulls_scalar
7012                             (i32 FPR32Op:$Rn),
7013                             (i32 (vector_extract (v4i32 V128:$Rm),
7014                                                  VectorIndexS:$idx))))))]> {
7015
7016     bits<2> idx;
7017     let Inst{11} = idx{1};
7018     let Inst{21} = idx{0};
7019   }
7020 }
7021
7022 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
7023                                    SDPatternOperator OpNode> {
7024   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7025   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7026                                       V128, V64,
7027                                       V128_lo, VectorIndexH,
7028                                       asm, ".4s", ".4s", ".4h", ".h",
7029     [(set (v4i32 V128:$Rd),
7030         (OpNode (v4i16 V64:$Rn),
7031          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7032     bits<3> idx;
7033     let Inst{11} = idx{2};
7034     let Inst{21} = idx{1};
7035     let Inst{20} = idx{0};
7036   }
7037
7038   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7039                                       V128, V128,
7040                                       V128_lo, VectorIndexH,
7041                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7042     [(set (v4i32 V128:$Rd),
7043           (OpNode (extract_high_v8i16 V128:$Rn),
7044                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7045                                                       VectorIndexH:$idx))))]> {
7046
7047     bits<3> idx;
7048     let Inst{11} = idx{2};
7049     let Inst{21} = idx{1};
7050     let Inst{20} = idx{0};
7051   }
7052
7053   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7054                                       V128, V64,
7055                                       V128, VectorIndexS,
7056                                       asm, ".2d", ".2d", ".2s", ".s",
7057     [(set (v2i64 V128:$Rd),
7058         (OpNode (v2i32 V64:$Rn),
7059          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7060     bits<2> idx;
7061     let Inst{11} = idx{1};
7062     let Inst{21} = idx{0};
7063   }
7064
7065   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7066                                       V128, V128,
7067                                       V128, VectorIndexS,
7068                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7069     [(set (v2i64 V128:$Rd),
7070           (OpNode (extract_high_v4i32 V128:$Rn),
7071                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7072                                                       VectorIndexS:$idx))))]> {
7073     bits<2> idx;
7074     let Inst{11} = idx{1};
7075     let Inst{21} = idx{0};
7076   }
7077   }
7078 }
7079
7080 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7081                                        SDPatternOperator OpNode> {
7082   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7083   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7084                                       V128, V64,
7085                                       V128_lo, VectorIndexH,
7086                                       asm, ".4s", ".4s", ".4h", ".h",
7087     [(set (v4i32 V128:$dst),
7088         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7089          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7090     bits<3> idx;
7091     let Inst{11} = idx{2};
7092     let Inst{21} = idx{1};
7093     let Inst{20} = idx{0};
7094   }
7095
7096   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7097                                       V128, V128,
7098                                       V128_lo, VectorIndexH,
7099                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7100     [(set (v4i32 V128:$dst),
7101           (OpNode (v4i32 V128:$Rd),
7102                   (extract_high_v8i16 V128:$Rn),
7103                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7104                                                       VectorIndexH:$idx))))]> {
7105     bits<3> idx;
7106     let Inst{11} = idx{2};
7107     let Inst{21} = idx{1};
7108     let Inst{20} = idx{0};
7109   }
7110
7111   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7112                                       V128, V64,
7113                                       V128, VectorIndexS,
7114                                       asm, ".2d", ".2d", ".2s", ".s",
7115     [(set (v2i64 V128:$dst),
7116         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7117          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7118     bits<2> idx;
7119     let Inst{11} = idx{1};
7120     let Inst{21} = idx{0};
7121   }
7122
7123   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7124                                       V128, V128,
7125                                       V128, VectorIndexS,
7126                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7127     [(set (v2i64 V128:$dst),
7128           (OpNode (v2i64 V128:$Rd),
7129                   (extract_high_v4i32 V128:$Rn),
7130                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7131                                                       VectorIndexS:$idx))))]> {
7132     bits<2> idx;
7133     let Inst{11} = idx{1};
7134     let Inst{21} = idx{0};
7135   }
7136   }
7137 }
7138
7139 //----------------------------------------------------------------------------
7140 // AdvSIMD scalar shift by immediate
7141 //----------------------------------------------------------------------------
7142
7143 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7144 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7145                      RegisterClass regtype1, RegisterClass regtype2,
7146                      Operand immtype, string asm, list<dag> pattern>
7147   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7148       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7149     Sched<[WriteV]> {
7150   bits<5> Rd;
7151   bits<5> Rn;
7152   bits<7> imm;
7153   let Inst{31-30} = 0b01;
7154   let Inst{29}    = U;
7155   let Inst{28-23} = 0b111110;
7156   let Inst{22-16} = fixed_imm;
7157   let Inst{15-11} = opc;
7158   let Inst{10}    = 1;
7159   let Inst{9-5} = Rn;
7160   let Inst{4-0} = Rd;
7161 }
7162
7163 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7164 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7165                      RegisterClass regtype1, RegisterClass regtype2,
7166                      Operand immtype, string asm, list<dag> pattern>
7167   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7168       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7169     Sched<[WriteV]> {
7170   bits<5> Rd;
7171   bits<5> Rn;
7172   bits<7> imm;
7173   let Inst{31-30} = 0b01;
7174   let Inst{29}    = U;
7175   let Inst{28-23} = 0b111110;
7176   let Inst{22-16} = fixed_imm;
7177   let Inst{15-11} = opc;
7178   let Inst{10}    = 1;
7179   let Inst{9-5} = Rn;
7180   let Inst{4-0} = Rd;
7181 }
7182
7183
7184 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
7185   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7186                               FPR32, FPR32, vecshiftR32, asm, []> {
7187     let Inst{20-16} = imm{4-0};
7188   }
7189
7190   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7191                               FPR64, FPR64, vecshiftR64, asm, []> {
7192     let Inst{21-16} = imm{5-0};
7193   }
7194 }
7195
7196 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7197                              SDPatternOperator OpNode> {
7198   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7199                               FPR64, FPR64, vecshiftR64, asm,
7200   [(set (i64 FPR64:$Rd),
7201      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7202     let Inst{21-16} = imm{5-0};
7203   }
7204
7205   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7206             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7207 }
7208
7209 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7210                                  SDPatternOperator OpNode = null_frag> {
7211   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7212                               FPR64, FPR64, vecshiftR64, asm,
7213   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7214                                                    (i32 vecshiftR64:$imm)))]> {
7215     let Inst{21-16} = imm{5-0};
7216   }
7217
7218   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7219                            (i32 vecshiftR64:$imm))),
7220             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7221                                             vecshiftR64:$imm)>;
7222 }
7223
7224 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7225                              SDPatternOperator OpNode> {
7226   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7227                               FPR64, FPR64, vecshiftL64, asm,
7228     [(set (v1i64 FPR64:$Rd),
7229        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7230     let Inst{21-16} = imm{5-0};
7231   }
7232 }
7233
7234 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7235 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7236   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7237                               FPR64, FPR64, vecshiftL64, asm, []> {
7238     let Inst{21-16} = imm{5-0};
7239   }
7240 }
7241
7242 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7243 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7244                                SDPatternOperator OpNode = null_frag> {
7245   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7246                               FPR8, FPR16, vecshiftR8, asm, []> {
7247     let Inst{18-16} = imm{2-0};
7248   }
7249
7250   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7251                               FPR16, FPR32, vecshiftR16, asm, []> {
7252     let Inst{19-16} = imm{3-0};
7253   }
7254
7255   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7256                               FPR32, FPR64, vecshiftR32, asm,
7257     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7258     let Inst{20-16} = imm{4-0};
7259   }
7260 }
7261
7262 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7263                                 SDPatternOperator OpNode> {
7264   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7265                               FPR8, FPR8, vecshiftL8, asm, []> {
7266     let Inst{18-16} = imm{2-0};
7267   }
7268
7269   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7270                               FPR16, FPR16, vecshiftL16, asm, []> {
7271     let Inst{19-16} = imm{3-0};
7272   }
7273
7274   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7275                               FPR32, FPR32, vecshiftL32, asm,
7276     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7277     let Inst{20-16} = imm{4-0};
7278   }
7279
7280   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7281                               FPR64, FPR64, vecshiftL64, asm,
7282     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7283     let Inst{21-16} = imm{5-0};
7284   }
7285
7286   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7287             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7288 }
7289
7290 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7291   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7292                               FPR8, FPR8, vecshiftR8, asm, []> {
7293     let Inst{18-16} = imm{2-0};
7294   }
7295
7296   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7297                               FPR16, FPR16, vecshiftR16, asm, []> {
7298     let Inst{19-16} = imm{3-0};
7299   }
7300
7301   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7302                               FPR32, FPR32, vecshiftR32, asm, []> {
7303     let Inst{20-16} = imm{4-0};
7304   }
7305
7306   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7307                               FPR64, FPR64, vecshiftR64, asm, []> {
7308     let Inst{21-16} = imm{5-0};
7309   }
7310 }
7311
7312 //----------------------------------------------------------------------------
7313 // AdvSIMD vector x indexed element
7314 //----------------------------------------------------------------------------
7315
7316 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7317 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7318                      RegisterOperand dst_reg, RegisterOperand src_reg,
7319                      Operand immtype,
7320                      string asm, string dst_kind, string src_kind,
7321                      list<dag> pattern>
7322   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7323       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7324            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7325     Sched<[WriteV]> {
7326   bits<5> Rd;
7327   bits<5> Rn;
7328   let Inst{31}    = 0;
7329   let Inst{30}    = Q;
7330   let Inst{29}    = U;
7331   let Inst{28-23} = 0b011110;
7332   let Inst{22-16} = fixed_imm;
7333   let Inst{15-11} = opc;
7334   let Inst{10}    = 1;
7335   let Inst{9-5}   = Rn;
7336   let Inst{4-0}   = Rd;
7337 }
7338
7339 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7340 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7341                      RegisterOperand vectype1, RegisterOperand vectype2,
7342                      Operand immtype,
7343                      string asm, string dst_kind, string src_kind,
7344                      list<dag> pattern>
7345   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7346       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7347            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7348     Sched<[WriteV]> {
7349   bits<5> Rd;
7350   bits<5> Rn;
7351   let Inst{31}    = 0;
7352   let Inst{30}    = Q;
7353   let Inst{29}    = U;
7354   let Inst{28-23} = 0b011110;
7355   let Inst{22-16} = fixed_imm;
7356   let Inst{15-11} = opc;
7357   let Inst{10}    = 1;
7358   let Inst{9-5}   = Rn;
7359   let Inst{4-0}   = Rd;
7360 }
7361
7362 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7363                               Intrinsic OpNode> {
7364   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7365                                   V64, V64, vecshiftR32,
7366                                   asm, ".2s", ".2s",
7367       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
7368     bits<5> imm;
7369     let Inst{20-16} = imm;
7370   }
7371
7372   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7373                                   V128, V128, vecshiftR32,
7374                                   asm, ".4s", ".4s",
7375       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7376     bits<5> imm;
7377     let Inst{20-16} = imm;
7378   }
7379
7380   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7381                                   V128, V128, vecshiftR64,
7382                                   asm, ".2d", ".2d",
7383       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7384     bits<6> imm;
7385     let Inst{21-16} = imm;
7386   }
7387 }
7388
7389 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
7390                                   Intrinsic OpNode> {
7391   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7392                                   V64, V64, vecshiftR32,
7393                                   asm, ".2s", ".2s",
7394       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7395     bits<5> imm;
7396     let Inst{20-16} = imm;
7397   }
7398
7399   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7400                                   V128, V128, vecshiftR32,
7401                                   asm, ".4s", ".4s",
7402       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7403     bits<5> imm;
7404     let Inst{20-16} = imm;
7405   }
7406
7407   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7408                                   V128, V128, vecshiftR64,
7409                                   asm, ".2d", ".2d",
7410       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7411     bits<6> imm;
7412     let Inst{21-16} = imm;
7413   }
7414 }
7415
7416 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7417                                      SDPatternOperator OpNode> {
7418   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7419                                   V64, V128, vecshiftR16Narrow,
7420                                   asm, ".8b", ".8h",
7421       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7422     bits<3> imm;
7423     let Inst{18-16} = imm;
7424   }
7425
7426   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7427                                   V128, V128, vecshiftR16Narrow,
7428                                   asm#"2", ".16b", ".8h", []> {
7429     bits<3> imm;
7430     let Inst{18-16} = imm;
7431     let hasSideEffects = 0;
7432   }
7433
7434   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7435                                   V64, V128, vecshiftR32Narrow,
7436                                   asm, ".4h", ".4s",
7437       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7438     bits<4> imm;
7439     let Inst{19-16} = imm;
7440   }
7441
7442   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7443                                   V128, V128, vecshiftR32Narrow,
7444                                   asm#"2", ".8h", ".4s", []> {
7445     bits<4> imm;
7446     let Inst{19-16} = imm;
7447     let hasSideEffects = 0;
7448   }
7449
7450   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7451                                   V64, V128, vecshiftR64Narrow,
7452                                   asm, ".2s", ".2d",
7453       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7454     bits<5> imm;
7455     let Inst{20-16} = imm;
7456   }
7457
7458   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7459                                   V128, V128, vecshiftR64Narrow,
7460                                   asm#"2", ".4s", ".2d", []> {
7461     bits<5> imm;
7462     let Inst{20-16} = imm;
7463     let hasSideEffects = 0;
7464   }
7465
7466   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7467   // themselves, so put them here instead.
7468
7469   // Patterns involving what's effectively an insert high and a normal
7470   // intrinsic, represented by CONCAT_VECTORS.
7471   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7472                                                    vecshiftR16Narrow:$imm)),
7473             (!cast<Instruction>(NAME # "v16i8_shift")
7474                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7475                 V128:$Rn, vecshiftR16Narrow:$imm)>;
7476   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7477                                                      vecshiftR32Narrow:$imm)),
7478             (!cast<Instruction>(NAME # "v8i16_shift")
7479                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7480                 V128:$Rn, vecshiftR32Narrow:$imm)>;
7481   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7482                                                      vecshiftR64Narrow:$imm)),
7483             (!cast<Instruction>(NAME # "v4i32_shift")
7484                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7485                 V128:$Rn, vecshiftR64Narrow:$imm)>;
7486 }
7487
7488 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7489                                 SDPatternOperator OpNode> {
7490   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7491                                   V64, V64, vecshiftL8,
7492                                   asm, ".8b", ".8b",
7493                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7494                        (i32 vecshiftL8:$imm)))]> {
7495     bits<3> imm;
7496     let Inst{18-16} = imm;
7497   }
7498
7499   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7500                                   V128, V128, vecshiftL8,
7501                                   asm, ".16b", ".16b",
7502              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7503                    (i32 vecshiftL8:$imm)))]> {
7504     bits<3> imm;
7505     let Inst{18-16} = imm;
7506   }
7507
7508   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7509                                   V64, V64, vecshiftL16,
7510                                   asm, ".4h", ".4h",
7511               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7512                     (i32 vecshiftL16:$imm)))]> {
7513     bits<4> imm;
7514     let Inst{19-16} = imm;
7515   }
7516
7517   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7518                                   V128, V128, vecshiftL16,
7519                                   asm, ".8h", ".8h",
7520             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7521                   (i32 vecshiftL16:$imm)))]> {
7522     bits<4> imm;
7523     let Inst{19-16} = imm;
7524   }
7525
7526   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7527                                   V64, V64, vecshiftL32,
7528                                   asm, ".2s", ".2s",
7529               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7530                     (i32 vecshiftL32:$imm)))]> {
7531     bits<5> imm;
7532     let Inst{20-16} = imm;
7533   }
7534
7535   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7536                                   V128, V128, vecshiftL32,
7537                                   asm, ".4s", ".4s",
7538             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7539                   (i32 vecshiftL32:$imm)))]> {
7540     bits<5> imm;
7541     let Inst{20-16} = imm;
7542   }
7543
7544   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7545                                   V128, V128, vecshiftL64,
7546                                   asm, ".2d", ".2d",
7547             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7548                   (i32 vecshiftL64:$imm)))]> {
7549     bits<6> imm;
7550     let Inst{21-16} = imm;
7551   }
7552 }
7553
7554 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7555                                 SDPatternOperator OpNode> {
7556   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7557                                   V64, V64, vecshiftR8,
7558                                   asm, ".8b", ".8b",
7559                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7560                        (i32 vecshiftR8:$imm)))]> {
7561     bits<3> imm;
7562     let Inst{18-16} = imm;
7563   }
7564
7565   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7566                                   V128, V128, vecshiftR8,
7567                                   asm, ".16b", ".16b",
7568              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7569                    (i32 vecshiftR8:$imm)))]> {
7570     bits<3> imm;
7571     let Inst{18-16} = imm;
7572   }
7573
7574   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7575                                   V64, V64, vecshiftR16,
7576                                   asm, ".4h", ".4h",
7577               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7578                     (i32 vecshiftR16:$imm)))]> {
7579     bits<4> imm;
7580     let Inst{19-16} = imm;
7581   }
7582
7583   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7584                                   V128, V128, vecshiftR16,
7585                                   asm, ".8h", ".8h",
7586             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7587                   (i32 vecshiftR16:$imm)))]> {
7588     bits<4> imm;
7589     let Inst{19-16} = imm;
7590   }
7591
7592   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7593                                   V64, V64, vecshiftR32,
7594                                   asm, ".2s", ".2s",
7595               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7596                     (i32 vecshiftR32:$imm)))]> {
7597     bits<5> imm;
7598     let Inst{20-16} = imm;
7599   }
7600
7601   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7602                                   V128, V128, vecshiftR32,
7603                                   asm, ".4s", ".4s",
7604             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7605                   (i32 vecshiftR32:$imm)))]> {
7606     bits<5> imm;
7607     let Inst{20-16} = imm;
7608   }
7609
7610   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7611                                   V128, V128, vecshiftR64,
7612                                   asm, ".2d", ".2d",
7613             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7614                   (i32 vecshiftR64:$imm)))]> {
7615     bits<6> imm;
7616     let Inst{21-16} = imm;
7617   }
7618 }
7619
7620 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7621 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7622                                     SDPatternOperator OpNode = null_frag> {
7623   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7624                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
7625                  [(set (v8i8 V64:$dst),
7626                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7627                            (i32 vecshiftR8:$imm)))]> {
7628     bits<3> imm;
7629     let Inst{18-16} = imm;
7630   }
7631
7632   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7633                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
7634              [(set (v16i8 V128:$dst),
7635                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7636                        (i32 vecshiftR8:$imm)))]> {
7637     bits<3> imm;
7638     let Inst{18-16} = imm;
7639   }
7640
7641   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7642                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
7643               [(set (v4i16 V64:$dst),
7644                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7645                         (i32 vecshiftR16:$imm)))]> {
7646     bits<4> imm;
7647     let Inst{19-16} = imm;
7648   }
7649
7650   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7651                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
7652             [(set (v8i16 V128:$dst),
7653               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7654                       (i32 vecshiftR16:$imm)))]> {
7655     bits<4> imm;
7656     let Inst{19-16} = imm;
7657   }
7658
7659   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7660                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
7661               [(set (v2i32 V64:$dst),
7662                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7663                         (i32 vecshiftR32:$imm)))]> {
7664     bits<5> imm;
7665     let Inst{20-16} = imm;
7666   }
7667
7668   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7669                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
7670             [(set (v4i32 V128:$dst),
7671               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7672                       (i32 vecshiftR32:$imm)))]> {
7673     bits<5> imm;
7674     let Inst{20-16} = imm;
7675   }
7676
7677   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7678                                   V128, V128, vecshiftR64,
7679                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7680               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7681                       (i32 vecshiftR64:$imm)))]> {
7682     bits<6> imm;
7683     let Inst{21-16} = imm;
7684   }
7685 }
7686
7687 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7688                                     SDPatternOperator OpNode = null_frag> {
7689   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7690                                   V64, V64, vecshiftL8,
7691                                   asm, ".8b", ".8b",
7692                     [(set (v8i8 V64:$dst),
7693                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7694                                   (i32 vecshiftL8:$imm)))]> {
7695     bits<3> imm;
7696     let Inst{18-16} = imm;
7697   }
7698
7699   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7700                                   V128, V128, vecshiftL8,
7701                                   asm, ".16b", ".16b",
7702                     [(set (v16i8 V128:$dst),
7703                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7704                                   (i32 vecshiftL8:$imm)))]> {
7705     bits<3> imm;
7706     let Inst{18-16} = imm;
7707   }
7708
7709   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7710                                   V64, V64, vecshiftL16,
7711                                   asm, ".4h", ".4h",
7712                     [(set (v4i16 V64:$dst),
7713                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7714                                    (i32 vecshiftL16:$imm)))]> {
7715     bits<4> imm;
7716     let Inst{19-16} = imm;
7717   }
7718
7719   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7720                                   V128, V128, vecshiftL16,
7721                                   asm, ".8h", ".8h",
7722                     [(set (v8i16 V128:$dst),
7723                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7724                                   (i32 vecshiftL16:$imm)))]> {
7725     bits<4> imm;
7726     let Inst{19-16} = imm;
7727   }
7728
7729   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7730                                   V64, V64, vecshiftL32,
7731                                   asm, ".2s", ".2s",
7732                     [(set (v2i32 V64:$dst),
7733                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7734                                   (i32 vecshiftL32:$imm)))]> {
7735     bits<5> imm;
7736     let Inst{20-16} = imm;
7737   }
7738
7739   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7740                                   V128, V128, vecshiftL32,
7741                                   asm, ".4s", ".4s",
7742                     [(set (v4i32 V128:$dst),
7743                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7744                                   (i32 vecshiftL32:$imm)))]> {
7745     bits<5> imm;
7746     let Inst{20-16} = imm;
7747   }
7748
7749   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7750                                   V128, V128, vecshiftL64,
7751                                   asm, ".2d", ".2d",
7752                     [(set (v2i64 V128:$dst),
7753                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7754                                   (i32 vecshiftL64:$imm)))]> {
7755     bits<6> imm;
7756     let Inst{21-16} = imm;
7757   }
7758 }
7759
7760 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7761                                    SDPatternOperator OpNode> {
7762   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7763                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
7764       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7765     bits<3> imm;
7766     let Inst{18-16} = imm;
7767   }
7768
7769   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7770                                   V128, V128, vecshiftL8,
7771                                   asm#"2", ".8h", ".16b",
7772       [(set (v8i16 V128:$Rd),
7773             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7774     bits<3> imm;
7775     let Inst{18-16} = imm;
7776   }
7777
7778   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7779                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
7780       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7781     bits<4> imm;
7782     let Inst{19-16} = imm;
7783   }
7784
7785   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7786                                   V128, V128, vecshiftL16,
7787                                   asm#"2", ".4s", ".8h",
7788       [(set (v4i32 V128:$Rd),
7789             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7790
7791     bits<4> imm;
7792     let Inst{19-16} = imm;
7793   }
7794
7795   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7796                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
7797       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7798     bits<5> imm;
7799     let Inst{20-16} = imm;
7800   }
7801
7802   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7803                                   V128, V128, vecshiftL32,
7804                                   asm#"2", ".2d", ".4s",
7805       [(set (v2i64 V128:$Rd),
7806             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7807     bits<5> imm;
7808     let Inst{20-16} = imm;
7809   }
7810 }
7811
7812
7813 //---
7814 // Vector load/store
7815 //---
7816 // SIMD ldX/stX no-index memory references don't allow the optional
7817 // ", #0" constant and handle post-indexing explicitly, so we use
7818 // a more specialized parse method for them. Otherwise, it's the same as
7819 // the general GPR64sp handling.
7820
7821 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7822                    string asm, dag oops, dag iops, list<dag> pattern>
7823   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
7824   bits<5> Vt;
7825   bits<5> Rn;
7826   let Inst{31} = 0;
7827   let Inst{30} = Q;
7828   let Inst{29-23} = 0b0011000;
7829   let Inst{22} = L;
7830   let Inst{21-16} = 0b000000;
7831   let Inst{15-12} = opcode;
7832   let Inst{11-10} = size;
7833   let Inst{9-5} = Rn;
7834   let Inst{4-0} = Vt;
7835 }
7836
7837 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7838                        string asm, dag oops, dag iops>
7839   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
7840   bits<5> Vt;
7841   bits<5> Rn;
7842   bits<5> Xm;
7843   let Inst{31} = 0;
7844   let Inst{30} = Q;
7845   let Inst{29-23} = 0b0011001;
7846   let Inst{22} = L;
7847   let Inst{21} = 0;
7848   let Inst{20-16} = Xm;
7849   let Inst{15-12} = opcode;
7850   let Inst{11-10} = size;
7851   let Inst{9-5} = Rn;
7852   let Inst{4-0} = Vt;
7853 }
7854
7855 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7856 // register post-index addressing from the zero register.
7857 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7858                            int Offset, int Size> {
7859   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7860   //      "ld1\t$Vt, [$Rn], #16"
7861   // may get mapped to
7862   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
7863   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
7864                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7865                       GPR64sp:$Rn,
7866                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7867                       XZR), 1>;
7868
7869   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7870   //      "ld1.8b\t$Vt, [$Rn], #16"
7871   // may get mapped to
7872   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
7873   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
7874                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7875                       GPR64sp:$Rn,
7876                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7877                       XZR), 0>;
7878
7879   // E.g. "ld1.8b { v0, v1 }, [x1]"
7880   //      "ld1\t$Vt, [$Rn]"
7881   // may get mapped to
7882   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
7883   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
7884                   (!cast<Instruction>(NAME # Count # "v" # layout)
7885                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7886                       GPR64sp:$Rn), 0>;
7887
7888   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7889   //      "ld1\t$Vt, [$Rn], $Xm"
7890   // may get mapped to
7891   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
7892   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
7893                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7894                       GPR64sp:$Rn,
7895                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7896                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7897 }
7898
7899 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7900                        int Offset64, bits<4> opcode> {
7901   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7902     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7903                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7904                            (ins GPR64sp:$Rn), []>;
7905     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7906                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7907                            (ins GPR64sp:$Rn), []>;
7908     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7909                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7910                            (ins GPR64sp:$Rn), []>;
7911     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7912                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7913                            (ins GPR64sp:$Rn), []>;
7914     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7915                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7916                            (ins GPR64sp:$Rn), []>;
7917     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7918                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7919                            (ins GPR64sp:$Rn), []>;
7920     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7921                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7922                            (ins GPR64sp:$Rn), []>;
7923
7924
7925     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7926                        (outs GPR64sp:$wback,
7927                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
7928                        (ins GPR64sp:$Rn,
7929                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7930     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7931                        (outs GPR64sp:$wback,
7932                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
7933                        (ins GPR64sp:$Rn,
7934                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7935     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7936                        (outs GPR64sp:$wback,
7937                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
7938                        (ins GPR64sp:$Rn,
7939                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7940     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7941                        (outs GPR64sp:$wback,
7942                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
7943                        (ins GPR64sp:$Rn,
7944                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7945     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7946                        (outs GPR64sp:$wback,
7947                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
7948                        (ins GPR64sp:$Rn,
7949                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7950     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7951                        (outs GPR64sp:$wback,
7952                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
7953                        (ins GPR64sp:$Rn,
7954                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7955     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7956                        (outs GPR64sp:$wback,
7957                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
7958                        (ins GPR64sp:$Rn,
7959                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7960   }
7961
7962   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7963   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7964   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7965   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7966   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7967   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7968   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7969 }
7970
7971 // Only ld1/st1 has a v1d version.
7972 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7973                        int Offset64, bits<4> opcode> {
7974   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7975     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7976                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7977                                  GPR64sp:$Rn), []>;
7978     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7979                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7980                                 GPR64sp:$Rn), []>;
7981     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7982                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7983                                 GPR64sp:$Rn), []>;
7984     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7985                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7986                                 GPR64sp:$Rn), []>;
7987     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7988                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7989                                 GPR64sp:$Rn), []>;
7990     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7991                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7992                                 GPR64sp:$Rn), []>;
7993     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7994                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7995                                 GPR64sp:$Rn), []>;
7996
7997     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
7998                        (outs GPR64sp:$wback),
7999                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8000                             GPR64sp:$Rn,
8001                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8002     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
8003                        (outs GPR64sp:$wback),
8004                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8005                             GPR64sp:$Rn,
8006                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8007     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
8008                        (outs GPR64sp:$wback),
8009                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8010                             GPR64sp:$Rn,
8011                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8012     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
8013                        (outs GPR64sp:$wback),
8014                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8015                             GPR64sp:$Rn,
8016                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8017     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
8018                        (outs GPR64sp:$wback),
8019                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8020                             GPR64sp:$Rn,
8021                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8022     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
8023                        (outs GPR64sp:$wback),
8024                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8025                             GPR64sp:$Rn,
8026                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8027     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
8028                        (outs GPR64sp:$wback),
8029                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8030                             GPR64sp:$Rn,
8031                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8032   }
8033
8034   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8035   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8036   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8037   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8038   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8039   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8040   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8041 }
8042
8043 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
8044                        int Offset128, int Offset64, bits<4> opcode>
8045   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
8046
8047   // LD1 instructions have extra "1d" variants.
8048   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8049     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8050                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8051                            (ins GPR64sp:$Rn), []>;
8052
8053     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8054                        (outs GPR64sp:$wback,
8055                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
8056                        (ins GPR64sp:$Rn,
8057                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8058   }
8059
8060   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8061 }
8062
8063 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
8064                        int Offset128, int Offset64, bits<4> opcode>
8065   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
8066
8067   // ST1 instructions have extra "1d" variants.
8068   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8069     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8070                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8071                                 GPR64sp:$Rn), []>;
8072
8073     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8074                        (outs GPR64sp:$wback),
8075                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8076                             GPR64sp:$Rn,
8077                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8078   }
8079
8080   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8081 }
8082
8083 multiclass SIMDLd1Multiple<string asm> {
8084   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8085   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8086   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8087   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8088 }
8089
8090 multiclass SIMDSt1Multiple<string asm> {
8091   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8092   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8093   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8094   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8095 }
8096
8097 multiclass SIMDLd2Multiple<string asm> {
8098   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8099 }
8100
8101 multiclass SIMDSt2Multiple<string asm> {
8102   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8103 }
8104
8105 multiclass SIMDLd3Multiple<string asm> {
8106   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8107 }
8108
8109 multiclass SIMDSt3Multiple<string asm> {
8110   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8111 }
8112
8113 multiclass SIMDLd4Multiple<string asm> {
8114   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8115 }
8116
8117 multiclass SIMDSt4Multiple<string asm> {
8118   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8119 }
8120
8121 //---
8122 // AdvSIMD Load/store single-element
8123 //---
8124
8125 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8126                          string asm, string operands, string cst,
8127                          dag oops, dag iops, list<dag> pattern>
8128   : I<oops, iops, asm, operands, cst, pattern> {
8129   bits<5> Vt;
8130   bits<5> Rn;
8131   let Inst{31} = 0;
8132   let Inst{29-24} = 0b001101;
8133   let Inst{22} = L;
8134   let Inst{21} = R;
8135   let Inst{15-13} = opcode;
8136   let Inst{9-5} = Rn;
8137   let Inst{4-0} = Vt;
8138 }
8139
8140 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8141                          string asm, string operands, string cst,
8142                          dag oops, dag iops, list<dag> pattern>
8143   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8144   bits<5> Vt;
8145   bits<5> Rn;
8146   let Inst{31} = 0;
8147   let Inst{29-24} = 0b001101;
8148   let Inst{22} = L;
8149   let Inst{21} = R;
8150   let Inst{15-13} = opcode;
8151   let Inst{9-5} = Rn;
8152   let Inst{4-0} = Vt;
8153 }
8154
8155
8156 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8157 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8158                   Operand listtype>
8159   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8160                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
8161                        []> {
8162   let Inst{30} = Q;
8163   let Inst{23} = 0;
8164   let Inst{20-16} = 0b00000;
8165   let Inst{12} = S;
8166   let Inst{11-10} = size;
8167 }
8168 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8169 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8170                       string asm, Operand listtype, Operand GPR64pi>
8171   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8172                        "$Rn = $wback",
8173                        (outs GPR64sp:$wback, listtype:$Vt),
8174                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8175   bits<5> Xm;
8176   let Inst{30} = Q;
8177   let Inst{23} = 1;
8178   let Inst{20-16} = Xm;
8179   let Inst{12} = S;
8180   let Inst{11-10} = size;
8181 }
8182
8183 multiclass SIMDLdrAliases<string asm, string layout, string Count,
8184                           int Offset, int Size> {
8185   // E.g. "ld1r { v0.8b }, [x1], #1"
8186   //      "ld1r.8b\t$Vt, [$Rn], #1"
8187   // may get mapped to
8188   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8189   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8190                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8191                       GPR64sp:$Rn,
8192                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8193                       XZR), 1>;
8194
8195   // E.g. "ld1r.8b { v0 }, [x1], #1"
8196   //      "ld1r.8b\t$Vt, [$Rn], #1"
8197   // may get mapped to
8198   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8199   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8200                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8201                       GPR64sp:$Rn,
8202                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8203                       XZR), 0>;
8204
8205   // E.g. "ld1r.8b { v0 }, [x1]"
8206   //      "ld1r.8b\t$Vt, [$Rn]"
8207   // may get mapped to
8208   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8209   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8210                   (!cast<Instruction>(NAME # "v" # layout)
8211                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8212                       GPR64sp:$Rn), 0>;
8213
8214   // E.g. "ld1r.8b { v0 }, [x1], x2"
8215   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
8216   // may get mapped to
8217   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8218   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8219                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8220                       GPR64sp:$Rn,
8221                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8222                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8223 }
8224
8225 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8226   int Offset1, int Offset2, int Offset4, int Offset8> {
8227   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8228                         !cast<Operand>("VecList" # Count # "8b")>;
8229   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8230                         !cast<Operand>("VecList" # Count #"16b")>;
8231   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8232                         !cast<Operand>("VecList" # Count #"4h")>;
8233   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8234                         !cast<Operand>("VecList" # Count #"8h")>;
8235   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8236                         !cast<Operand>("VecList" # Count #"2s")>;
8237   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8238                         !cast<Operand>("VecList" # Count #"4s")>;
8239   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8240                         !cast<Operand>("VecList" # Count #"1d")>;
8241   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8242                         !cast<Operand>("VecList" # Count #"2d")>;
8243
8244   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8245                                  !cast<Operand>("VecList" # Count # "8b"),
8246                                  !cast<Operand>("GPR64pi" # Offset1)>;
8247   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8248                                  !cast<Operand>("VecList" # Count # "16b"),
8249                                  !cast<Operand>("GPR64pi" # Offset1)>;
8250   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8251                                  !cast<Operand>("VecList" # Count # "4h"),
8252                                  !cast<Operand>("GPR64pi" # Offset2)>;
8253   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8254                                  !cast<Operand>("VecList" # Count # "8h"),
8255                                  !cast<Operand>("GPR64pi" # Offset2)>;
8256   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8257                                  !cast<Operand>("VecList" # Count # "2s"),
8258                                  !cast<Operand>("GPR64pi" # Offset4)>;
8259   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8260                                  !cast<Operand>("VecList" # Count # "4s"),
8261                                  !cast<Operand>("GPR64pi" # Offset4)>;
8262   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8263                                  !cast<Operand>("VecList" # Count # "1d"),
8264                                  !cast<Operand>("GPR64pi" # Offset8)>;
8265   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8266                                  !cast<Operand>("VecList" # Count # "2d"),
8267                                  !cast<Operand>("GPR64pi" # Offset8)>;
8268
8269   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
8270   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8271   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
8272   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
8273   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
8274   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
8275   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
8276   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
8277 }
8278
8279 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8280                       dag oops, dag iops, list<dag> pattern>
8281   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8282                        pattern> {
8283   // idx encoded in Q:S:size fields.
8284   bits<4> idx;
8285   let Inst{30} = idx{3};
8286   let Inst{23} = 0;
8287   let Inst{20-16} = 0b00000;
8288   let Inst{12} = idx{2};
8289   let Inst{11-10} = idx{1-0};
8290 }
8291 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8292                       dag oops, dag iops, list<dag> pattern>
8293   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8294                            oops, iops, pattern> {
8295   // idx encoded in Q:S:size fields.
8296   bits<4> idx;
8297   let Inst{30} = idx{3};
8298   let Inst{23} = 0;
8299   let Inst{20-16} = 0b00000;
8300   let Inst{12} = idx{2};
8301   let Inst{11-10} = idx{1-0};
8302 }
8303 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8304                           dag oops, dag iops>
8305   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8306                        "$Rn = $wback", oops, iops, []> {
8307   // idx encoded in Q:S:size fields.
8308   bits<4> idx;
8309   bits<5> Xm;
8310   let Inst{30} = idx{3};
8311   let Inst{23} = 1;
8312   let Inst{20-16} = Xm;
8313   let Inst{12} = idx{2};
8314   let Inst{11-10} = idx{1-0};
8315 }
8316 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8317                           dag oops, dag iops>
8318   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8319                            "$Rn = $wback", oops, iops, []> {
8320   // idx encoded in Q:S:size fields.
8321   bits<4> idx;
8322   bits<5> Xm;
8323   let Inst{30} = idx{3};
8324   let Inst{23} = 1;
8325   let Inst{20-16} = Xm;
8326   let Inst{12} = idx{2};
8327   let Inst{11-10} = idx{1-0};
8328 }
8329
8330 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8331                       dag oops, dag iops, list<dag> pattern>
8332   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8333                        pattern> {
8334   // idx encoded in Q:S:size<1> fields.
8335   bits<3> idx;
8336   let Inst{30} = idx{2};
8337   let Inst{23} = 0;
8338   let Inst{20-16} = 0b00000;
8339   let Inst{12} = idx{1};
8340   let Inst{11} = idx{0};
8341   let Inst{10} = size;
8342 }
8343 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8344                       dag oops, dag iops, list<dag> pattern>
8345   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8346                            oops, iops, pattern> {
8347   // idx encoded in Q:S:size<1> fields.
8348   bits<3> idx;
8349   let Inst{30} = idx{2};
8350   let Inst{23} = 0;
8351   let Inst{20-16} = 0b00000;
8352   let Inst{12} = idx{1};
8353   let Inst{11} = idx{0};
8354   let Inst{10} = size;
8355 }
8356
8357 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8358                           dag oops, dag iops>
8359   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8360                        "$Rn = $wback", oops, iops, []> {
8361   // idx encoded in Q:S:size<1> fields.
8362   bits<3> idx;
8363   bits<5> Xm;
8364   let Inst{30} = idx{2};
8365   let Inst{23} = 1;
8366   let Inst{20-16} = Xm;
8367   let Inst{12} = idx{1};
8368   let Inst{11} = idx{0};
8369   let Inst{10} = size;
8370 }
8371 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8372                           dag oops, dag iops>
8373   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8374                            "$Rn = $wback", oops, iops, []> {
8375   // idx encoded in Q:S:size<1> fields.
8376   bits<3> idx;
8377   bits<5> Xm;
8378   let Inst{30} = idx{2};
8379   let Inst{23} = 1;
8380   let Inst{20-16} = Xm;
8381   let Inst{12} = idx{1};
8382   let Inst{11} = idx{0};
8383   let Inst{10} = size;
8384 }
8385 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8386                       dag oops, dag iops, list<dag> pattern>
8387   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8388                        pattern> {
8389   // idx encoded in Q:S fields.
8390   bits<2> idx;
8391   let Inst{30} = idx{1};
8392   let Inst{23} = 0;
8393   let Inst{20-16} = 0b00000;
8394   let Inst{12} = idx{0};
8395   let Inst{11-10} = size;
8396 }
8397 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8398                       dag oops, dag iops, list<dag> pattern>
8399   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8400                            oops, iops, pattern> {
8401   // idx encoded in Q:S fields.
8402   bits<2> idx;
8403   let Inst{30} = idx{1};
8404   let Inst{23} = 0;
8405   let Inst{20-16} = 0b00000;
8406   let Inst{12} = idx{0};
8407   let Inst{11-10} = size;
8408 }
8409 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8410                           string asm, dag oops, dag iops>
8411   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8412                        "$Rn = $wback", oops, iops, []> {
8413   // idx encoded in Q:S fields.
8414   bits<2> idx;
8415   bits<5> Xm;
8416   let Inst{30} = idx{1};
8417   let Inst{23} = 1;
8418   let Inst{20-16} = Xm;
8419   let Inst{12} = idx{0};
8420   let Inst{11-10} = size;
8421 }
8422 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8423                           string asm, dag oops, dag iops>
8424   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8425                            "$Rn = $wback", oops, iops, []> {
8426   // idx encoded in Q:S fields.
8427   bits<2> idx;
8428   bits<5> Xm;
8429   let Inst{30} = idx{1};
8430   let Inst{23} = 1;
8431   let Inst{20-16} = Xm;
8432   let Inst{12} = idx{0};
8433   let Inst{11-10} = size;
8434 }
8435 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8436                       dag oops, dag iops, list<dag> pattern>
8437   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8438                        pattern> {
8439   // idx encoded in Q field.
8440   bits<1> idx;
8441   let Inst{30} = idx;
8442   let Inst{23} = 0;
8443   let Inst{20-16} = 0b00000;
8444   let Inst{12} = 0;
8445   let Inst{11-10} = size;
8446 }
8447 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8448                       dag oops, dag iops, list<dag> pattern>
8449   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8450                            oops, iops, pattern> {
8451   // idx encoded in Q field.
8452   bits<1> idx;
8453   let Inst{30} = idx;
8454   let Inst{23} = 0;
8455   let Inst{20-16} = 0b00000;
8456   let Inst{12} = 0;
8457   let Inst{11-10} = size;
8458 }
8459 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8460                           string asm, dag oops, dag iops>
8461   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8462                        "$Rn = $wback", oops, iops, []> {
8463   // idx encoded in Q field.
8464   bits<1> idx;
8465   bits<5> Xm;
8466   let Inst{30} = idx;
8467   let Inst{23} = 1;
8468   let Inst{20-16} = Xm;
8469   let Inst{12} = 0;
8470   let Inst{11-10} = size;
8471 }
8472 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8473                           string asm, dag oops, dag iops>
8474   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8475                            "$Rn = $wback", oops, iops, []> {
8476   // idx encoded in Q field.
8477   bits<1> idx;
8478   bits<5> Xm;
8479   let Inst{30} = idx;
8480   let Inst{23} = 1;
8481   let Inst{20-16} = Xm;
8482   let Inst{12} = 0;
8483   let Inst{11-10} = size;
8484 }
8485
8486 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8487 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8488                          RegisterOperand listtype,
8489                          RegisterOperand GPR64pi> {
8490   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8491                            (outs listtype:$dst),
8492                            (ins listtype:$Vt, VectorIndexB:$idx,
8493                                 GPR64sp:$Rn), []>;
8494
8495   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8496                             (outs GPR64sp:$wback, listtype:$dst),
8497                             (ins listtype:$Vt, VectorIndexB:$idx,
8498                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8499 }
8500 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8501 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8502                          RegisterOperand listtype,
8503                          RegisterOperand GPR64pi> {
8504   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8505                             (outs listtype:$dst),
8506                             (ins listtype:$Vt, VectorIndexH:$idx,
8507                                  GPR64sp:$Rn), []>;
8508
8509   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8510                             (outs GPR64sp:$wback, listtype:$dst),
8511                             (ins listtype:$Vt, VectorIndexH:$idx,
8512                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8513 }
8514 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8515 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8516                          RegisterOperand listtype,
8517                          RegisterOperand GPR64pi> {
8518   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8519                             (outs listtype:$dst),
8520                             (ins listtype:$Vt, VectorIndexS:$idx,
8521                                  GPR64sp:$Rn), []>;
8522
8523   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8524                             (outs GPR64sp:$wback, listtype:$dst),
8525                             (ins listtype:$Vt, VectorIndexS:$idx,
8526                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8527 }
8528 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8529 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8530                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8531   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8532                             (outs listtype:$dst),
8533                             (ins listtype:$Vt, VectorIndexD:$idx,
8534                                  GPR64sp:$Rn), []>;
8535
8536   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8537                             (outs GPR64sp:$wback, listtype:$dst),
8538                             (ins listtype:$Vt, VectorIndexD:$idx,
8539                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8540 }
8541 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8542 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8543                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8544   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8545                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8546                                         GPR64sp:$Rn), []>;
8547
8548   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8549                                     (outs GPR64sp:$wback),
8550                                     (ins listtype:$Vt, VectorIndexB:$idx,
8551                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
8552 }
8553 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8554 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8555                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8556   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8557                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8558                                          GPR64sp:$Rn), []>;
8559
8560   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8561                             (outs GPR64sp:$wback),
8562                             (ins listtype:$Vt, VectorIndexH:$idx,
8563                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8564 }
8565 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8566 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8567                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8568   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8569                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8570                                          GPR64sp:$Rn), []>;
8571
8572   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8573                             (outs GPR64sp:$wback),
8574                             (ins listtype:$Vt, VectorIndexS:$idx,
8575                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8576 }
8577 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8578 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8579                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8580   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8581                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8582                                          GPR64sp:$Rn), []>;
8583
8584   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8585                             (outs GPR64sp:$wback),
8586                             (ins listtype:$Vt, VectorIndexD:$idx,
8587                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8588 }
8589
8590 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8591                                  string Count, int Offset, Operand idxtype> {
8592   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8593   //      "ld1\t$Vt, [$Rn], #1"
8594   // may get mapped to
8595   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8596   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8597                   (!cast<Instruction>(NAME # Type  # "_POST")
8598                       GPR64sp:$Rn,
8599                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8600                       idxtype:$idx, XZR), 1>;
8601
8602   // E.g. "ld1.8b { v0 }[0], [x1], #1"
8603   //      "ld1.8b\t$Vt, [$Rn], #1"
8604   // may get mapped to
8605   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8606   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
8607                   (!cast<Instruction>(NAME # Type # "_POST")
8608                       GPR64sp:$Rn,
8609                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8610                       idxtype:$idx, XZR), 0>;
8611
8612   // E.g. "ld1.8b { v0 }[0], [x1]"
8613   //      "ld1.8b\t$Vt, [$Rn]"
8614   // may get mapped to
8615   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8616   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
8617                       (!cast<Instruction>(NAME # Type)
8618                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8619                          idxtype:$idx, GPR64sp:$Rn), 0>;
8620
8621   // E.g. "ld1.8b { v0 }[0], [x1], x2"
8622   //      "ld1.8b\t$Vt, [$Rn], $Xm"
8623   // may get mapped to
8624   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8625   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
8626                       (!cast<Instruction>(NAME # Type # "_POST")
8627                          GPR64sp:$Rn,
8628                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8629                          idxtype:$idx,
8630                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8631 }
8632
8633 multiclass SIMDLdSt1SingleAliases<string asm> {
8634   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
8635   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8636   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8637   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8638 }
8639
8640 multiclass SIMDLdSt2SingleAliases<string asm> {
8641   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
8642   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
8643   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
8644   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8645 }
8646
8647 multiclass SIMDLdSt3SingleAliases<string asm> {
8648   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
8649   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
8650   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8651   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8652 }
8653
8654 multiclass SIMDLdSt4SingleAliases<string asm> {
8655   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
8656   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
8657   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8658   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8659 }
8660 } // end of 'let Predicates = [HasNEON]'
8661
8662 //----------------------------------------------------------------------------
8663 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
8664 //----------------------------------------------------------------------------
8665
8666 let Predicates = [HasNEON, HasV8_1a] in {
8667
8668 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
8669                                     RegisterOperand regtype, string asm, 
8670                                     string kind, list<dag> pattern>
8671   : BaseSIMDThreeSameVectorTied<Q, U, size, opcode, regtype, asm, kind, 
8672                                 pattern> {
8673   let Inst{21}=0;
8674 }
8675 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
8676                                              SDPatternOperator Accum> {
8677   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
8678     [(set (v4i16 V64:$dst),
8679           (Accum (v4i16 V64:$Rd),
8680                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
8681                                                    (v4i16 V64:$Rm)))))]>;         
8682   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
8683     [(set (v8i16 V128:$dst),
8684           (Accum (v8i16 V128:$Rd),
8685                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
8686                                                    (v8i16 V128:$Rm)))))]>;
8687   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
8688     [(set (v2i32 V64:$dst),
8689           (Accum (v2i32 V64:$Rd),
8690                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
8691                                                    (v2i32 V64:$Rm)))))]>;
8692   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
8693     [(set (v4i32 V128:$dst),
8694           (Accum (v4i32 V128:$Rd),
8695                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
8696                                                    (v4i32 V128:$Rm)))))]>;
8697 }
8698
8699 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
8700                                      SDPatternOperator Accum> {
8701   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8702                                           V64, V64, V128_lo, VectorIndexH,
8703                                           asm, ".4h", ".4h", ".4h", ".h",
8704     [(set (v4i16 V64:$dst),
8705           (Accum (v4i16 V64:$Rd),
8706                  (v4i16 (int_aarch64_neon_sqrdmulh
8707                           (v4i16 V64:$Rn),
8708                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8709                                                     VectorIndexH:$idx))))))]> {
8710     bits<3> idx;
8711     let Inst{11} = idx{2};
8712     let Inst{21} = idx{1};
8713     let Inst{20} = idx{0};
8714   }
8715
8716   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8717                                           V128, V128, V128_lo, VectorIndexH,
8718                                           asm, ".8h", ".8h", ".8h", ".h",
8719     [(set (v8i16 V128:$dst),
8720           (Accum (v8i16 V128:$Rd),
8721                  (v8i16 (int_aarch64_neon_sqrdmulh
8722                           (v8i16 V128:$Rn),
8723                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8724                                                    VectorIndexH:$idx))))))]> {
8725     bits<3> idx;
8726     let Inst{11} = idx{2};
8727     let Inst{21} = idx{1};
8728     let Inst{20} = idx{0};
8729   }
8730
8731   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8732                                           V64, V64, V128, VectorIndexS,
8733                                           asm, ".2s", ".2s", ".2s", ".s",
8734     [(set (v2i32 V64:$dst),
8735         (Accum (v2i32 V64:$Rd),
8736                (v2i32 (int_aarch64_neon_sqrdmulh
8737                         (v2i32 V64:$Rn),
8738                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8739                                                  VectorIndexS:$idx))))))]> {
8740     bits<2> idx;
8741     let Inst{11} = idx{1};
8742     let Inst{21} = idx{0};
8743   }
8744
8745   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but 
8746   // an intermediate EXTRACT_SUBREG would be untyped.
8747   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we 
8748   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
8749   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8750                        (i32 (vector_extract 
8751                                (v4i32 (insert_subvector
8752                                        (undef), 
8753                                         (v2i32 (int_aarch64_neon_sqrdmulh 
8754                                                  (v2i32 V64:$Rn),
8755                                                  (v2i32 (AArch64duplane32 
8756                                                           (v4i32 V128:$Rm),
8757                                                           VectorIndexS:$idx)))),
8758                                       (i32 0))),
8759                                (i64 0))))),
8760             (EXTRACT_SUBREG
8761                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
8762                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), 
8763                                                 FPR32Op:$Rd, 
8764                                                 ssub)), 
8765                           V64:$Rn,
8766                           V128:$Rm, 
8767                           VectorIndexS:$idx)),
8768                 ssub)>;
8769
8770   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8771                                           V128, V128, V128, VectorIndexS,
8772                                           asm, ".4s", ".4s", ".4s", ".s",
8773     [(set (v4i32 V128:$dst),
8774           (Accum (v4i32 V128:$Rd),
8775                  (v4i32 (int_aarch64_neon_sqrdmulh
8776                           (v4i32 V128:$Rn),
8777                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8778                                                    VectorIndexS:$idx))))))]> {
8779     bits<2> idx;
8780     let Inst{11} = idx{1};
8781     let Inst{21} = idx{0};
8782   }
8783
8784   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
8785   // an intermediate EXTRACT_SUBREG would be untyped.
8786   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8787                         (i32 (vector_extract 
8788                                (v4i32 (int_aarch64_neon_sqrdmulh 
8789                                         (v4i32 V128:$Rn),
8790                                         (v4i32 (AArch64duplane32 
8791                                                  (v4i32 V128:$Rm),
8792                                                  VectorIndexS:$idx)))),
8793                                (i64 0))))),
8794             (EXTRACT_SUBREG
8795                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
8796                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), 
8797                                                FPR32Op:$Rd, 
8798                                                ssub)), 
8799                          V128:$Rn,
8800                          V128:$Rm, 
8801                          VectorIndexS:$idx)),
8802                 ssub)>;
8803
8804   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8805                                         FPR16Op, FPR16Op, V128_lo,
8806                                         VectorIndexH, asm, ".h", "", "", ".h", 
8807                                         []> {
8808     bits<3> idx;
8809     let Inst{11} = idx{2};
8810     let Inst{21} = idx{1};
8811     let Inst{20} = idx{0};
8812   }
8813
8814   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8815                                         FPR32Op, FPR32Op, V128, VectorIndexS,
8816                                         asm, ".s", "", "", ".s",
8817     [(set (i32 FPR32Op:$dst),
8818           (Accum (i32 FPR32Op:$Rd),
8819                  (i32 (int_aarch64_neon_sqrdmulh
8820                         (i32 FPR32Op:$Rn),
8821                         (i32 (vector_extract (v4i32 V128:$Rm),
8822                                              VectorIndexS:$idx))))))]> {
8823     bits<2> idx;
8824     let Inst{11} = idx{1};
8825     let Inst{21} = idx{0};
8826   }
8827 }
8828 } // let Predicates = [HasNeon, HasV8_1a]
8829
8830 //----------------------------------------------------------------------------
8831 // Crypto extensions
8832 //----------------------------------------------------------------------------
8833
8834 let Predicates = [HasCrypto] in {
8835 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8836 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8837               list<dag> pat>
8838   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8839     Sched<[WriteV]>{
8840   bits<5> Rd;
8841   bits<5> Rn;
8842   let Inst{31-16} = 0b0100111000101000;
8843   let Inst{15-12} = opc;
8844   let Inst{11-10} = 0b10;
8845   let Inst{9-5}   = Rn;
8846   let Inst{4-0}   = Rd;
8847 }
8848
8849 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8850   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8851             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8852
8853 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8854   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8855             "$Rd = $dst",
8856             [(set (v16i8 V128:$dst),
8857                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8858
8859 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8860 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8861                      dag oops, dag iops, list<dag> pat>
8862   : I<oops, iops, asm,
8863       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8864       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8865     Sched<[WriteV]>{
8866   bits<5> Rd;
8867   bits<5> Rn;
8868   bits<5> Rm;
8869   let Inst{31-21} = 0b01011110000;
8870   let Inst{20-16} = Rm;
8871   let Inst{15}    = 0;
8872   let Inst{14-12} = opc;
8873   let Inst{11-10} = 0b00;
8874   let Inst{9-5}   = Rn;
8875   let Inst{4-0}   = Rd;
8876 }
8877
8878 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8879   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8880                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8881                    [(set (v4i32 FPR128:$dst),
8882                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8883                                  (v4i32 V128:$Rm)))]>;
8884
8885 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8886   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8887                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
8888                    [(set (v4i32 V128:$dst),
8889                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8890                                  (v4i32 V128:$Rm)))]>;
8891
8892 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8893   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8894                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8895                    [(set (v4i32 FPR128:$dst),
8896                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8897                                  (v4i32 V128:$Rm)))]>;
8898
8899 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8900 class SHA2OpInst<bits<4> opc, string asm, string kind,
8901                  string cstr, dag oops, dag iops,
8902                  list<dag> pat>
8903   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8904                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8905     Sched<[WriteV]>{
8906   bits<5> Rd;
8907   bits<5> Rn;
8908   let Inst{31-16} = 0b0101111000101000;
8909   let Inst{15-12} = opc;
8910   let Inst{11-10} = 0b10;
8911   let Inst{9-5}   = Rn;
8912   let Inst{4-0}   = Rd;
8913 }
8914
8915 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8916   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8917                (ins V128:$Rd, V128:$Rn),
8918                [(set (v4i32 V128:$dst),
8919                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8920
8921 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8922   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8923                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8924 } // end of 'let Predicates = [HasCrypto]'
8925
8926 //----------------------------------------------------------------------------
8927 // v8.1 atomic instructions extension:
8928 // * CAS
8929 // * CASP
8930 // * SWP
8931 // * LDOPregister<OP>, and aliases STOPregister<OP>
8932
8933 // Instruction encodings:
8934 //
8935 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
8936 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
8937 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
8938 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
8939 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
8940 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
8941
8942 // Instruction syntax:
8943 //
8944 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8945 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
8946 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
8947 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
8948 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8949 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
8950 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8951 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
8952 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
8953 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
8954
8955 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
8956 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
8957                       string cstr, list<dag> pattern>
8958       : I<oops, iops, asm, operands, cstr, pattern> {
8959   bits<2> Sz;
8960   bit NP;
8961   bit Acq;
8962   bit Rel;
8963   bits<5> Rs;
8964   bits<5> Rn;
8965   bits<5> Rt;
8966   let Inst{31-30} = Sz;
8967   let Inst{29-24} = 0b001000;
8968   let Inst{23} = NP;
8969   let Inst{22} = Acq;
8970   let Inst{21} = 0b1;
8971   let Inst{20-16} = Rs;
8972   let Inst{15} = Rel;
8973   let Inst{14-10} = 0b11111;
8974   let Inst{9-5} = Rn;
8975   let Inst{4-0} = Rt;
8976 }
8977
8978 class BaseCAS<string order, string size, RegisterClass RC>
8979       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8980                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
8981                         "$out = $Rs",[]> {
8982   let NP = 1;
8983 }
8984
8985 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
8986   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
8987   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
8988   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
8989   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
8990 }
8991
8992 class BaseCASP<string order, string size, RegisterOperand RC>
8993       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8994                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
8995                         "$out = $Rs",[]> {
8996   let NP = 0;
8997 }
8998
8999 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
9000   let Sz = 0b00, Acq = Acq, Rel = Rel in 
9001     def s : BaseCASP<order, "", WSeqPairClassOperand>;
9002   let Sz = 0b01, Acq = Acq, Rel = Rel in 
9003     def d : BaseCASP<order, "", XSeqPairClassOperand>;
9004 }
9005
9006 let Predicates = [HasV8_1a] in
9007 class BaseSWP<string order, string size, RegisterClass RC>
9008       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
9009           "\t$Rs, $Rt, [$Rn]","",[]> {
9010   bits<2> Sz;
9011   bit Acq;
9012   bit Rel;
9013   bits<5> Rs;
9014   bits<3> opc = 0b000;
9015   bits<5> Rn;
9016   bits<5> Rt;
9017   let Inst{31-30} = Sz;
9018   let Inst{29-24} = 0b111000;
9019   let Inst{23} = Acq;
9020   let Inst{22} = Rel;
9021   let Inst{21} = 0b1;
9022   let Inst{20-16} = Rs;
9023   let Inst{15} = 0b1;
9024   let Inst{14-12} = opc;
9025   let Inst{11-10} = 0b00;
9026   let Inst{9-5} = Rn;
9027   let Inst{4-0} = Rt;
9028 }
9029
9030 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
9031   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
9032   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
9033   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
9034   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
9035 }
9036
9037 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9038 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
9039       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
9040           "\t$Rs, $Rt, [$Rn]","",[]> {
9041   bits<2> Sz;
9042   bit Acq;
9043   bit Rel;
9044   bits<5> Rs;
9045   bits<3> opc;
9046   bits<5> Rn;
9047   bits<5> Rt;
9048   let Inst{31-30} = Sz;
9049   let Inst{29-24} = 0b111000;
9050   let Inst{23} = Acq;
9051   let Inst{22} = Rel;
9052   let Inst{21} = 0b1;
9053   let Inst{20-16} = Rs;
9054   let Inst{15} = 0b0;
9055   let Inst{14-12} = opc;
9056   let Inst{11-10} = 0b00;
9057   let Inst{9-5} = Rn;
9058   let Inst{4-0} = Rt;
9059 }
9060
9061 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel, 
9062                         string order> {
9063   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in 
9064     def b : BaseLDOPregister<op, order, "b", GPR32>;
9065   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in 
9066     def h : BaseLDOPregister<op, order, "h", GPR32>;
9067   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in 
9068     def s : BaseLDOPregister<op, order, "", GPR32>;
9069   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in 
9070     def d : BaseLDOPregister<op, order, "", GPR64>;
9071 }
9072
9073 let Predicates = [HasV8_1a] in
9074 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
9075                         Instruction inst> :
9076       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
9077
9078 multiclass STOPregister<string asm, string instr> {
9079   def : BaseSTOPregister<asm # "lb", GPR32, WZR, 
9080                     !cast<Instruction>(instr # "Lb")>;
9081   def : BaseSTOPregister<asm # "lh", GPR32, WZR, 
9082                     !cast<Instruction>(instr # "Lh")>;
9083   def : BaseSTOPregister<asm # "l",  GPR32, WZR, 
9084                     !cast<Instruction>(instr # "Ls")>;
9085   def : BaseSTOPregister<asm # "l",  GPR64, XZR, 
9086                     !cast<Instruction>(instr # "Ld")>;
9087   def : BaseSTOPregister<asm # "b",  GPR32, WZR, 
9088                     !cast<Instruction>(instr # "b")>;
9089   def : BaseSTOPregister<asm # "h",  GPR32, WZR, 
9090                     !cast<Instruction>(instr # "h")>;
9091   def : BaseSTOPregister<asm,        GPR32, WZR, 
9092                     !cast<Instruction>(instr # "s")>;
9093   def : BaseSTOPregister<asm,        GPR64, XZR, 
9094                     !cast<Instruction>(instr # "d")>;
9095 }
9096
9097 //----------------------------------------------------------------------------
9098 // Allow the size specifier tokens to be upper case, not just lower.
9099 def : TokenAlias<".8B", ".8b">;
9100 def : TokenAlias<".4H", ".4h">;
9101 def : TokenAlias<".2S", ".2s">;
9102 def : TokenAlias<".1D", ".1d">;
9103 def : TokenAlias<".16B", ".16b">;
9104 def : TokenAlias<".8H", ".8h">;
9105 def : TokenAlias<".4S", ".4s">;
9106 def : TokenAlias<".2D", ".2d">;
9107 def : TokenAlias<".1Q", ".1q">;
9108 def : TokenAlias<".B", ".b">;
9109 def : TokenAlias<".H", ".h">;
9110 def : TokenAlias<".S", ".s">;
9111 def : TokenAlias<".D", ".d">;
9112 def : TokenAlias<".Q", ".q">;