[AArch64] Fix problems in decoding generic MSR instructions
[oota-llvm.git] / lib / Target / AArch64 / AArch64InstrFormats.td
1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 //===----------------------------------------------------------------------===//
11 //  Describe AArch64 instructions format here
12 //
13
14 // Format specifies the encoding used by the instruction.  This is part of the
15 // ad-hoc solution used to emit machine instruction encodings by our machine
16 // code emitter.
17 class Format<bits<2> val> {
18   bits<2> Value = val;
19 }
20
21 def PseudoFrm   : Format<0>;
22 def NormalFrm   : Format<1>; // Do we need any others?
23
24 // AArch64 Instruction Format
25 class AArch64Inst<Format f, string cstr> : Instruction {
26   field bits<32> Inst; // Instruction encoding.
27   // Mask of bits that cause an encoding to be UNPREDICTABLE.
28   // If a bit is set, then if the corresponding bit in the
29   // target encoding differs from its value in the "Inst" field,
30   // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
31   field bits<32> Unpredictable = 0;
32   // SoftFail is the generic name for this field, but we alias it so
33   // as to make it more obvious what it means in ARM-land.
34   field bits<32> SoftFail = Unpredictable;
35   let Namespace   = "AArch64";
36   Format F        = f;
37   bits<2> Form    = F.Value;
38   let Pattern     = [];
39   let Constraints = cstr;
40 }
41
42 // Pseudo instructions (don't have encoding information)
43 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
44     : AArch64Inst<PseudoFrm, cstr> {
45   dag OutOperandList = oops;
46   dag InOperandList  = iops;
47   let Pattern        = pattern;
48   let isCodeGenOnly  = 1;
49 }
50
51 // Real instructions (have encoding information)
52 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
53   let Pattern = pattern;
54   let Size = 4;
55 }
56
57 // Normal instructions
58 class I<dag oops, dag iops, string asm, string operands, string cstr,
59         list<dag> pattern>
60     : EncodedI<cstr, pattern> {
61   dag OutOperandList = oops;
62   dag InOperandList  = iops;
63   let AsmString      = !strconcat(asm, operands);
64 }
65
66 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
67 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
68 class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
69
70 // Helper fragment for an extract of the high portion of a 128-bit vector.
71 def extract_high_v16i8 :
72    UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
73 def extract_high_v8i16 :
74    UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
75 def extract_high_v4i32 :
76    UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
77 def extract_high_v2i64 :
78    UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
79
80 //===----------------------------------------------------------------------===//
81 // Asm Operand Classes.
82 //
83
84 // Shifter operand for arithmetic shifted encodings.
85 def ShifterOperand : AsmOperandClass {
86   let Name = "Shifter";
87 }
88
89 // Shifter operand for mov immediate encodings.
90 def MovImm32ShifterOperand : AsmOperandClass {
91   let SuperClasses = [ShifterOperand];
92   let Name = "MovImm32Shifter";
93   let RenderMethod = "addShifterOperands";
94   let DiagnosticType = "InvalidMovImm32Shift";
95 }
96 def MovImm64ShifterOperand : AsmOperandClass {
97   let SuperClasses = [ShifterOperand];
98   let Name = "MovImm64Shifter";
99   let RenderMethod = "addShifterOperands";
100   let DiagnosticType = "InvalidMovImm64Shift";
101 }
102
103 // Shifter operand for arithmetic register shifted encodings.
104 class ArithmeticShifterOperand<int width> : AsmOperandClass {
105   let SuperClasses = [ShifterOperand];
106   let Name = "ArithmeticShifter" # width;
107   let PredicateMethod = "isArithmeticShifter<" # width # ">";
108   let RenderMethod = "addShifterOperands";
109   let DiagnosticType = "AddSubRegShift" # width;
110 }
111
112 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
113 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
114
115 // Shifter operand for logical register shifted encodings.
116 class LogicalShifterOperand<int width> : AsmOperandClass {
117   let SuperClasses = [ShifterOperand];
118   let Name = "LogicalShifter" # width;
119   let PredicateMethod = "isLogicalShifter<" # width # ">";
120   let RenderMethod = "addShifterOperands";
121   let DiagnosticType = "AddSubRegShift" # width;
122 }
123
124 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
125 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
126
127 // Shifter operand for logical vector 128/64-bit shifted encodings.
128 def LogicalVecShifterOperand : AsmOperandClass {
129   let SuperClasses = [ShifterOperand];
130   let Name = "LogicalVecShifter";
131   let RenderMethod = "addShifterOperands";
132 }
133 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
134   let SuperClasses = [LogicalVecShifterOperand];
135   let Name = "LogicalVecHalfWordShifter";
136   let RenderMethod = "addShifterOperands";
137 }
138
139 // The "MSL" shifter on the vector MOVI instruction.
140 def MoveVecShifterOperand : AsmOperandClass {
141   let SuperClasses = [ShifterOperand];
142   let Name = "MoveVecShifter";
143   let RenderMethod = "addShifterOperands";
144 }
145
146 // Extend operand for arithmetic encodings.
147 def ExtendOperand : AsmOperandClass {
148   let Name = "Extend";
149   let DiagnosticType = "AddSubRegExtendLarge";
150 }
151 def ExtendOperand64 : AsmOperandClass {
152   let SuperClasses = [ExtendOperand];
153   let Name = "Extend64";
154   let DiagnosticType = "AddSubRegExtendSmall";
155 }
156 // 'extend' that's a lsl of a 64-bit register.
157 def ExtendOperandLSL64 : AsmOperandClass {
158   let SuperClasses = [ExtendOperand];
159   let Name = "ExtendLSL64";
160   let RenderMethod = "addExtend64Operands";
161   let DiagnosticType = "AddSubRegExtendLarge";
162 }
163
164 // 8-bit floating-point immediate encodings.
165 def FPImmOperand : AsmOperandClass {
166   let Name = "FPImm";
167   let ParserMethod = "tryParseFPImm";
168   let DiagnosticType = "InvalidFPImm";
169 }
170
171 def CondCode : AsmOperandClass {
172   let Name = "CondCode";
173   let DiagnosticType = "InvalidCondCode";
174 }
175
176 // A 32-bit register pasrsed as 64-bit
177 def GPR32as64Operand : AsmOperandClass {
178   let Name = "GPR32as64";
179 }
180 def GPR32as64 : RegisterOperand<GPR32> {
181   let ParserMatchClass = GPR32as64Operand;
182 }
183
184 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
185 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
186 // are encoded as the eight bit value 'abcdefgh'.
187 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
188
189
190 //===----------------------------------------------------------------------===//
191 // Operand Definitions.
192 //
193
194 // ADR[P] instruction labels.
195 def AdrpOperand : AsmOperandClass {
196   let Name = "AdrpLabel";
197   let ParserMethod = "tryParseAdrpLabel";
198   let DiagnosticType = "InvalidLabel";
199 }
200 def adrplabel : Operand<i64> {
201   let EncoderMethod = "getAdrLabelOpValue";
202   let PrintMethod = "printAdrpLabel";
203   let ParserMatchClass = AdrpOperand;
204 }
205
206 def AdrOperand : AsmOperandClass {
207   let Name = "AdrLabel";
208   let ParserMethod = "tryParseAdrLabel";
209   let DiagnosticType = "InvalidLabel";
210 }
211 def adrlabel : Operand<i64> {
212   let EncoderMethod = "getAdrLabelOpValue";
213   let ParserMatchClass = AdrOperand;
214 }
215
216 // simm9 predicate - True if the immediate is in the range [-256, 255].
217 def SImm9Operand : AsmOperandClass {
218   let Name = "SImm9";
219   let DiagnosticType = "InvalidMemoryIndexedSImm9";
220 }
221 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
222   let ParserMatchClass = SImm9Operand;
223 }
224
225 // simm7sN predicate - True if the immediate is a multiple of N in the range
226 // [-64 * N, 63 * N].
227 class SImm7Scaled<int Scale> : AsmOperandClass {
228   let Name = "SImm7s" # Scale;
229   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm7";
230 }
231
232 def SImm7s4Operand : SImm7Scaled<4>;
233 def SImm7s8Operand : SImm7Scaled<8>;
234 def SImm7s16Operand : SImm7Scaled<16>;
235
236 def simm7s4 : Operand<i32> {
237   let ParserMatchClass = SImm7s4Operand;
238   let PrintMethod = "printImmScale<4>";
239 }
240
241 def simm7s8 : Operand<i32> {
242   let ParserMatchClass = SImm7s8Operand;
243   let PrintMethod = "printImmScale<8>";
244 }
245
246 def simm7s16 : Operand<i32> {
247   let ParserMatchClass = SImm7s16Operand;
248   let PrintMethod = "printImmScale<16>";
249 }
250
251 class AsmImmRange<int Low, int High> : AsmOperandClass {
252   let Name = "Imm" # Low # "_" # High;
253   let DiagnosticType = "InvalidImm" # Low # "_" # High;
254 }
255
256 def Imm1_8Operand : AsmImmRange<1, 8>;
257 def Imm1_16Operand : AsmImmRange<1, 16>;
258 def Imm1_32Operand : AsmImmRange<1, 32>;
259 def Imm1_64Operand : AsmImmRange<1, 64>;
260
261 def MovZSymbolG3AsmOperand : AsmOperandClass {
262   let Name = "MovZSymbolG3";
263   let RenderMethod = "addImmOperands";
264 }
265
266 def movz_symbol_g3 : Operand<i32> {
267   let ParserMatchClass = MovZSymbolG3AsmOperand;
268 }
269
270 def MovZSymbolG2AsmOperand : AsmOperandClass {
271   let Name = "MovZSymbolG2";
272   let RenderMethod = "addImmOperands";
273 }
274
275 def movz_symbol_g2 : Operand<i32> {
276   let ParserMatchClass = MovZSymbolG2AsmOperand;
277 }
278
279 def MovZSymbolG1AsmOperand : AsmOperandClass {
280   let Name = "MovZSymbolG1";
281   let RenderMethod = "addImmOperands";
282 }
283
284 def movz_symbol_g1 : Operand<i32> {
285   let ParserMatchClass = MovZSymbolG1AsmOperand;
286 }
287
288 def MovZSymbolG0AsmOperand : AsmOperandClass {
289   let Name = "MovZSymbolG0";
290   let RenderMethod = "addImmOperands";
291 }
292
293 def movz_symbol_g0 : Operand<i32> {
294   let ParserMatchClass = MovZSymbolG0AsmOperand;
295 }
296
297 def MovKSymbolG3AsmOperand : AsmOperandClass {
298   let Name = "MovKSymbolG3";
299   let RenderMethod = "addImmOperands";
300 }
301
302 def movk_symbol_g3 : Operand<i32> {
303   let ParserMatchClass = MovKSymbolG3AsmOperand;
304 }
305
306 def MovKSymbolG2AsmOperand : AsmOperandClass {
307   let Name = "MovKSymbolG2";
308   let RenderMethod = "addImmOperands";
309 }
310
311 def movk_symbol_g2 : Operand<i32> {
312   let ParserMatchClass = MovKSymbolG2AsmOperand;
313 }
314
315 def MovKSymbolG1AsmOperand : AsmOperandClass {
316   let Name = "MovKSymbolG1";
317   let RenderMethod = "addImmOperands";
318 }
319
320 def movk_symbol_g1 : Operand<i32> {
321   let ParserMatchClass = MovKSymbolG1AsmOperand;
322 }
323
324 def MovKSymbolG0AsmOperand : AsmOperandClass {
325   let Name = "MovKSymbolG0";
326   let RenderMethod = "addImmOperands";
327 }
328
329 def movk_symbol_g0 : Operand<i32> {
330   let ParserMatchClass = MovKSymbolG0AsmOperand;
331 }
332
333 class fixedpoint_i32<ValueType FloatVT>
334   : Operand<FloatVT>,
335     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
336   let EncoderMethod = "getFixedPointScaleOpValue";
337   let DecoderMethod = "DecodeFixedPointScaleImm32";
338   let ParserMatchClass = Imm1_32Operand;
339 }
340
341 class fixedpoint_i64<ValueType FloatVT>
342   : Operand<FloatVT>,
343     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
344   let EncoderMethod = "getFixedPointScaleOpValue";
345   let DecoderMethod = "DecodeFixedPointScaleImm64";
346   let ParserMatchClass = Imm1_64Operand;
347 }
348
349 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
350 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
351
352 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
353 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
354
355 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
356   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
357 }]> {
358   let EncoderMethod = "getVecShiftR8OpValue";
359   let DecoderMethod = "DecodeVecShiftR8Imm";
360   let ParserMatchClass = Imm1_8Operand;
361 }
362 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
363   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
364 }]> {
365   let EncoderMethod = "getVecShiftR16OpValue";
366   let DecoderMethod = "DecodeVecShiftR16Imm";
367   let ParserMatchClass = Imm1_16Operand;
368 }
369 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
370   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
371 }]> {
372   let EncoderMethod = "getVecShiftR16OpValue";
373   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
374   let ParserMatchClass = Imm1_8Operand;
375 }
376 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
377   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
378 }]> {
379   let EncoderMethod = "getVecShiftR32OpValue";
380   let DecoderMethod = "DecodeVecShiftR32Imm";
381   let ParserMatchClass = Imm1_32Operand;
382 }
383 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
384   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
385 }]> {
386   let EncoderMethod = "getVecShiftR32OpValue";
387   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
388   let ParserMatchClass = Imm1_16Operand;
389 }
390 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
391   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
392 }]> {
393   let EncoderMethod = "getVecShiftR64OpValue";
394   let DecoderMethod = "DecodeVecShiftR64Imm";
395   let ParserMatchClass = Imm1_64Operand;
396 }
397 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
398   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
399 }]> {
400   let EncoderMethod = "getVecShiftR64OpValue";
401   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
402   let ParserMatchClass = Imm1_32Operand;
403 }
404
405 def Imm0_7Operand : AsmImmRange<0, 7>;
406 def Imm0_15Operand : AsmImmRange<0, 15>;
407 def Imm0_31Operand : AsmImmRange<0, 31>;
408 def Imm0_63Operand : AsmImmRange<0, 63>;
409
410 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
411   return (((uint32_t)Imm) < 8);
412 }]> {
413   let EncoderMethod = "getVecShiftL8OpValue";
414   let DecoderMethod = "DecodeVecShiftL8Imm";
415   let ParserMatchClass = Imm0_7Operand;
416 }
417 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
418   return (((uint32_t)Imm) < 16);
419 }]> {
420   let EncoderMethod = "getVecShiftL16OpValue";
421   let DecoderMethod = "DecodeVecShiftL16Imm";
422   let ParserMatchClass = Imm0_15Operand;
423 }
424 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
425   return (((uint32_t)Imm) < 32);
426 }]> {
427   let EncoderMethod = "getVecShiftL32OpValue";
428   let DecoderMethod = "DecodeVecShiftL32Imm";
429   let ParserMatchClass = Imm0_31Operand;
430 }
431 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
432   return (((uint32_t)Imm) < 64);
433 }]> {
434   let EncoderMethod = "getVecShiftL64OpValue";
435   let DecoderMethod = "DecodeVecShiftL64Imm";
436   let ParserMatchClass = Imm0_63Operand;
437 }
438
439
440 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
441 // instructions for splatting repeating bit patterns across the immediate.
442 def logical_imm32_XFORM : SDNodeXForm<imm, [{
443   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
444   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
445 }]>;
446 def logical_imm64_XFORM : SDNodeXForm<imm, [{
447   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
448   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
449 }]>;
450
451 let DiagnosticType = "LogicalSecondSource" in {
452   def LogicalImm32Operand : AsmOperandClass {
453     let Name = "LogicalImm32";
454   }
455   def LogicalImm64Operand : AsmOperandClass {
456     let Name = "LogicalImm64";
457   }
458   def LogicalImm32NotOperand : AsmOperandClass {
459     let Name = "LogicalImm32Not";
460   }
461   def LogicalImm64NotOperand : AsmOperandClass {
462     let Name = "LogicalImm64Not";
463   }
464 }
465 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
466   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
467 }], logical_imm32_XFORM> {
468   let PrintMethod = "printLogicalImm32";
469   let ParserMatchClass = LogicalImm32Operand;
470 }
471 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
472   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
473 }], logical_imm64_XFORM> {
474   let PrintMethod = "printLogicalImm64";
475   let ParserMatchClass = LogicalImm64Operand;
476 }
477 def logical_imm32_not : Operand<i32> {
478   let ParserMatchClass = LogicalImm32NotOperand;
479 }
480 def logical_imm64_not : Operand<i64> {
481   let ParserMatchClass = LogicalImm64NotOperand;
482 }
483
484 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
485 def Imm0_65535Operand : AsmImmRange<0, 65535>;
486 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
487   return ((uint32_t)Imm) < 65536;
488 }]> {
489   let ParserMatchClass = Imm0_65535Operand;
490   let PrintMethod = "printHexImm";
491 }
492
493 // imm0_255 predicate - True if the immediate is in the range [0,255].
494 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
495 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
496   return ((uint32_t)Imm) < 256;
497 }]> {
498   let ParserMatchClass = Imm0_255Operand;
499   let PrintMethod = "printHexImm";
500 }
501
502 // imm0_127 predicate - True if the immediate is in the range [0,127]
503 def Imm0_127Operand : AsmImmRange<0, 127>;
504 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
505   return ((uint32_t)Imm) < 128;
506 }]> {
507   let ParserMatchClass = Imm0_127Operand;
508   let PrintMethod = "printHexImm";
509 }
510
511 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
512 // for all shift-amounts.
513
514 // imm0_63 predicate - True if the immediate is in the range [0,63]
515 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
516   return ((uint64_t)Imm) < 64;
517 }]> {
518   let ParserMatchClass = Imm0_63Operand;
519 }
520
521 // imm0_31 predicate - True if the immediate is in the range [0,31]
522 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
523   return ((uint64_t)Imm) < 32;
524 }]> {
525   let ParserMatchClass = Imm0_31Operand;
526 }
527
528 // imm0_15 predicate - True if the immediate is in the range [0,15]
529 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
530   return ((uint64_t)Imm) < 16;
531 }]> {
532   let ParserMatchClass = Imm0_15Operand;
533 }
534
535 // imm0_7 predicate - True if the immediate is in the range [0,7]
536 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
537   return ((uint64_t)Imm) < 8;
538 }]> {
539   let ParserMatchClass = Imm0_7Operand;
540 }
541
542 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
543 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
544   return ((uint32_t)Imm) < 16;
545 }]>;
546
547 // An arithmetic shifter operand:
548 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
549 //  {5-0} - imm6
550 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
551   let PrintMethod = "printShifter";
552   let ParserMatchClass = !cast<AsmOperandClass>(
553                          "ArithmeticShifterOperand" # width);
554 }
555
556 def arith_shift32 : arith_shift<i32, 32>;
557 def arith_shift64 : arith_shift<i64, 64>;
558
559 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
560     : Operand<Ty>,
561       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
562   let PrintMethod = "printShiftedRegister";
563   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
564 }
565
566 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
567 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
568
569 // An arithmetic shifter operand:
570 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
571 //  {5-0} - imm6
572 class logical_shift<int width> : Operand<i32> {
573   let PrintMethod = "printShifter";
574   let ParserMatchClass = !cast<AsmOperandClass>(
575                          "LogicalShifterOperand" # width);
576 }
577
578 def logical_shift32 : logical_shift<32>;
579 def logical_shift64 : logical_shift<64>;
580
581 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
582     : Operand<Ty>,
583       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
584   let PrintMethod = "printShiftedRegister";
585   let MIOperandInfo = (ops regclass, shiftop);
586 }
587
588 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
589 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
590
591 // A logical vector shifter operand:
592 //  {7-6} - shift type: 00 = lsl
593 //  {5-0} - imm6: #0, #8, #16, or #24
594 def logical_vec_shift : Operand<i32> {
595   let PrintMethod = "printShifter";
596   let EncoderMethod = "getVecShifterOpValue";
597   let ParserMatchClass = LogicalVecShifterOperand;
598 }
599
600 // A logical vector half-word shifter operand:
601 //  {7-6} - shift type: 00 = lsl
602 //  {5-0} - imm6: #0 or #8
603 def logical_vec_hw_shift : Operand<i32> {
604   let PrintMethod = "printShifter";
605   let EncoderMethod = "getVecShifterOpValue";
606   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
607 }
608
609 // A vector move shifter operand:
610 //  {0} - imm1: #8 or #16
611 def move_vec_shift : Operand<i32> {
612   let PrintMethod = "printShifter";
613   let EncoderMethod = "getMoveVecShifterOpValue";
614   let ParserMatchClass = MoveVecShifterOperand;
615 }
616
617 let DiagnosticType = "AddSubSecondSource" in {
618   def AddSubImmOperand : AsmOperandClass {
619     let Name = "AddSubImm";
620     let ParserMethod = "tryParseAddSubImm";
621   }
622   def AddSubImmNegOperand : AsmOperandClass {
623     let Name = "AddSubImmNeg";
624     let ParserMethod = "tryParseAddSubImm";
625   }
626 }
627 // An ADD/SUB immediate shifter operand:
628 //  second operand:
629 //  {7-6} - shift type: 00 = lsl
630 //  {5-0} - imm6: #0 or #12
631 class addsub_shifted_imm<ValueType Ty>
632     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
633   let PrintMethod = "printAddSubImm";
634   let EncoderMethod = "getAddSubImmOpValue";
635   let ParserMatchClass = AddSubImmOperand;
636   let MIOperandInfo = (ops i32imm, i32imm);
637 }
638
639 class addsub_shifted_imm_neg<ValueType Ty>
640     : Operand<Ty> {
641   let EncoderMethod = "getAddSubImmOpValue";
642   let ParserMatchClass = AddSubImmNegOperand;
643   let MIOperandInfo = (ops i32imm, i32imm);
644 }
645
646 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
647 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
648 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
649 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
650
651 class neg_addsub_shifted_imm<ValueType Ty>
652     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
653   let PrintMethod = "printAddSubImm";
654   let EncoderMethod = "getAddSubImmOpValue";
655   let ParserMatchClass = AddSubImmOperand;
656   let MIOperandInfo = (ops i32imm, i32imm);
657 }
658
659 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
660 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
661
662 // An extend operand:
663 //  {5-3} - extend type
664 //  {2-0} - imm3
665 def arith_extend : Operand<i32> {
666   let PrintMethod = "printArithExtend";
667   let ParserMatchClass = ExtendOperand;
668 }
669 def arith_extend64 : Operand<i32> {
670   let PrintMethod = "printArithExtend";
671   let ParserMatchClass = ExtendOperand64;
672 }
673
674 // 'extend' that's a lsl of a 64-bit register.
675 def arith_extendlsl64 : Operand<i32> {
676   let PrintMethod = "printArithExtend";
677   let ParserMatchClass = ExtendOperandLSL64;
678 }
679
680 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
681                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
682   let PrintMethod = "printExtendedRegister";
683   let MIOperandInfo = (ops GPR32, arith_extend);
684 }
685
686 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
687                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
688   let PrintMethod = "printExtendedRegister";
689   let MIOperandInfo = (ops GPR32, arith_extend64);
690 }
691
692 // Floating-point immediate.
693 def fpimm32 : Operand<f32>,
694               PatLeaf<(f32 fpimm), [{
695       return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
696     }], SDNodeXForm<fpimm, [{
697       APFloat InVal = N->getValueAPF();
698       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
699       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
700     }]>> {
701   let ParserMatchClass = FPImmOperand;
702   let PrintMethod = "printFPImmOperand";
703 }
704 def fpimm64 : Operand<f64>,
705               PatLeaf<(f64 fpimm), [{
706       return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
707     }], SDNodeXForm<fpimm, [{
708       APFloat InVal = N->getValueAPF();
709       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
710       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
711     }]>> {
712   let ParserMatchClass = FPImmOperand;
713   let PrintMethod = "printFPImmOperand";
714 }
715
716 def fpimm8 : Operand<i32> {
717   let ParserMatchClass = FPImmOperand;
718   let PrintMethod = "printFPImmOperand";
719 }
720
721 def fpimm0 : PatLeaf<(fpimm), [{
722   return N->isExactlyValue(+0.0);
723 }]>;
724
725 // Vector lane operands
726 class AsmVectorIndex<string Suffix> : AsmOperandClass {
727   let Name = "VectorIndex" # Suffix;
728   let DiagnosticType = "InvalidIndex" # Suffix;
729 }
730 def VectorIndex1Operand : AsmVectorIndex<"1">;
731 def VectorIndexBOperand : AsmVectorIndex<"B">;
732 def VectorIndexHOperand : AsmVectorIndex<"H">;
733 def VectorIndexSOperand : AsmVectorIndex<"S">;
734 def VectorIndexDOperand : AsmVectorIndex<"D">;
735
736 def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
737   return ((uint64_t)Imm) == 1;
738 }]> {
739   let ParserMatchClass = VectorIndex1Operand;
740   let PrintMethod = "printVectorIndex";
741   let MIOperandInfo = (ops i64imm);
742 }
743 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
744   return ((uint64_t)Imm) < 16;
745 }]> {
746   let ParserMatchClass = VectorIndexBOperand;
747   let PrintMethod = "printVectorIndex";
748   let MIOperandInfo = (ops i64imm);
749 }
750 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
751   return ((uint64_t)Imm) < 8;
752 }]> {
753   let ParserMatchClass = VectorIndexHOperand;
754   let PrintMethod = "printVectorIndex";
755   let MIOperandInfo = (ops i64imm);
756 }
757 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
758   return ((uint64_t)Imm) < 4;
759 }]> {
760   let ParserMatchClass = VectorIndexSOperand;
761   let PrintMethod = "printVectorIndex";
762   let MIOperandInfo = (ops i64imm);
763 }
764 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
765   return ((uint64_t)Imm) < 2;
766 }]> {
767   let ParserMatchClass = VectorIndexDOperand;
768   let PrintMethod = "printVectorIndex";
769   let MIOperandInfo = (ops i64imm);
770 }
771
772 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
773 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
774 // are encoded as the eight bit value 'abcdefgh'.
775 def simdimmtype10 : Operand<i32>,
776                     PatLeaf<(f64 fpimm), [{
777       return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
778                                                .bitcastToAPInt()
779                                                .getZExtValue());
780     }], SDNodeXForm<fpimm, [{
781       APFloat InVal = N->getValueAPF();
782       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
783                                                            .bitcastToAPInt()
784                                                            .getZExtValue());
785       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
786     }]>> {
787   let ParserMatchClass = SIMDImmType10Operand;
788   let PrintMethod = "printSIMDType10Operand";
789 }
790
791
792 //---
793 // System management
794 //---
795
796 // Base encoding for system instruction operands.
797 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
798 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
799                   list<dag> pattern = []>
800     : I<oops, iops, asm, operands, "", pattern> {
801   let Inst{31-22} = 0b1101010100;
802   let Inst{21}    = L;
803 }
804
805 // System instructions which do not have an Rt register.
806 class SimpleSystemI<bit L, dag iops, string asm, string operands,
807                     list<dag> pattern = []>
808     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
809   let Inst{4-0} = 0b11111;
810 }
811
812 // System instructions which have an Rt register.
813 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
814     : BaseSystemI<L, oops, iops, asm, operands>,
815       Sched<[WriteSys]> {
816   bits<5> Rt;
817   let Inst{4-0} = Rt;
818 }
819
820 // Hint instructions that take both a CRm and a 3-bit immediate.
821 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
822 // model patterns with sufficiently fine granularity
823 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
824   class HintI<string mnemonic>
825       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "",
826                       [(int_aarch64_hint imm0_127:$imm)]>,
827         Sched<[WriteHint]> {
828     bits <7> imm;
829     let Inst{20-12} = 0b000110010;
830     let Inst{11-5} = imm;
831   }
832
833 // System instructions taking a single literal operand which encodes into
834 // CRm. op2 differentiates the opcodes.
835 def BarrierAsmOperand : AsmOperandClass {
836   let Name = "Barrier";
837   let ParserMethod = "tryParseBarrierOperand";
838 }
839 def barrier_op : Operand<i32> {
840   let PrintMethod = "printBarrierOption";
841   let ParserMatchClass = BarrierAsmOperand;
842 }
843 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
844                  list<dag> pattern = []>
845     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
846       Sched<[WriteBarrier]> {
847   bits<4> CRm;
848   let Inst{20-12} = 0b000110011;
849   let Inst{11-8} = CRm;
850   let Inst{7-5} = opc;
851 }
852
853 // MRS/MSR system instructions. These have different operand classes because
854 // a different subset of registers can be accessed through each instruction.
855 def MRSSystemRegisterOperand : AsmOperandClass {
856   let Name = "MRSSystemRegister";
857   let ParserMethod = "tryParseSysReg";
858   let DiagnosticType = "MRS";
859 }
860 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
861 def mrs_sysreg_op : Operand<i32> {
862   let ParserMatchClass = MRSSystemRegisterOperand;
863   let DecoderMethod = "DecodeMRSSystemRegister";
864   let PrintMethod = "printMRSSystemRegister";
865 }
866
867 def MSRSystemRegisterOperand : AsmOperandClass {
868   let Name = "MSRSystemRegister";
869   let ParserMethod = "tryParseSysReg";
870   let DiagnosticType = "MSR";
871 }
872 def msr_sysreg_op : Operand<i32> {
873   let ParserMatchClass = MSRSystemRegisterOperand;
874   let DecoderMethod = "DecodeMSRSystemRegister";
875   let PrintMethod = "printMSRSystemRegister";
876 }
877
878 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
879                        "mrs", "\t$Rt, $systemreg"> {
880   bits<16> systemreg;
881   let Inst{20-5} = systemreg;
882 }
883
884 // FIXME: Some of these def NZCV, others don't. Best way to model that?
885 // Explicitly modeling each of the system register as a register class
886 // would do it, but feels like overkill at this point.
887 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
888                        "msr", "\t$systemreg, $Rt"> {
889   bits<16> systemreg;
890   let Inst{20-5} = systemreg;
891 }
892
893 def SystemPStateFieldOperand : AsmOperandClass {
894   let Name = "SystemPStateField";
895   let ParserMethod = "tryParseSysReg";
896 }
897 def pstatefield_op : Operand<i32> {
898   let ParserMatchClass = SystemPStateFieldOperand;
899   let PrintMethod = "printSystemPStateField";
900 }
901
902 let Defs = [NZCV] in
903 class MSRpstateI
904   : SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm),
905                   "msr", "\t$pstate_field, $imm">,
906     Sched<[WriteSys]> {
907   bits<6> pstatefield;
908   bits<4> imm;
909   let Inst{20-19} = 0b00;
910   let Inst{18-16} = pstatefield{5-3};
911   let Inst{15-12} = 0b0100;
912   let Inst{11-8} = imm;
913   let Inst{7-5} = pstatefield{2-0};
914
915   let DecoderMethod = "DecodeSystemPStateInstruction";
916   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
917   // Fail the decoder should attempt to decode the instruction as MSRI.
918   let hasCompleteDecoder = 0;
919 }
920
921 // SYS and SYSL generic system instructions.
922 def SysCRAsmOperand : AsmOperandClass {
923   let Name = "SysCR";
924   let ParserMethod = "tryParseSysCROperand";
925 }
926
927 def sys_cr_op : Operand<i32> {
928   let PrintMethod = "printSysCROperand";
929   let ParserMatchClass = SysCRAsmOperand;
930 }
931
932 class SystemXtI<bit L, string asm>
933   : RtSystemI<L, (outs),
934        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
935        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
936   bits<3> op1;
937   bits<4> Cn;
938   bits<4> Cm;
939   bits<3> op2;
940   let Inst{20-19} = 0b01;
941   let Inst{18-16} = op1;
942   let Inst{15-12} = Cn;
943   let Inst{11-8}  = Cm;
944   let Inst{7-5}   = op2;
945 }
946
947 class SystemLXtI<bit L, string asm>
948   : RtSystemI<L, (outs),
949        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
950        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
951   bits<3> op1;
952   bits<4> Cn;
953   bits<4> Cm;
954   bits<3> op2;
955   let Inst{20-19} = 0b01;
956   let Inst{18-16} = op1;
957   let Inst{15-12} = Cn;
958   let Inst{11-8}  = Cm;
959   let Inst{7-5}   = op2;
960 }
961
962
963 // Branch (register) instructions:
964 //
965 //  case opc of
966 //    0001 blr
967 //    0000 br
968 //    0101 dret
969 //    0100 eret
970 //    0010 ret
971 //    otherwise UNDEFINED
972 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
973                     string operands, list<dag> pattern>
974     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
975   let Inst{31-25} = 0b1101011;
976   let Inst{24-21} = opc;
977   let Inst{20-16} = 0b11111;
978   let Inst{15-10} = 0b000000;
979   let Inst{4-0}   = 0b00000;
980 }
981
982 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
983     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
984   bits<5> Rn;
985   let Inst{9-5} = Rn;
986 }
987
988 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
989 class SpecialReturn<bits<4> opc, string asm>
990     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
991   let Inst{9-5} = 0b11111;
992 }
993
994 //---
995 // Conditional branch instruction.
996 //---
997
998 // Condition code.
999 // 4-bit immediate. Pretty-printed as <cc>
1000 def ccode : Operand<i32> {
1001   let PrintMethod = "printCondCode";
1002   let ParserMatchClass = CondCode;
1003 }
1004 def inv_ccode : Operand<i32> {
1005   // AL and NV are invalid in the aliases which use inv_ccode
1006   let PrintMethod = "printInverseCondCode";
1007   let ParserMatchClass = CondCode;
1008   let MCOperandPredicate = [{
1009     return MCOp.isImm() &&
1010            MCOp.getImm() != AArch64CC::AL &&
1011            MCOp.getImm() != AArch64CC::NV;
1012   }];
1013 }
1014
1015 // Conditional branch target. 19-bit immediate. The low two bits of the target
1016 // offset are implied zero and so are not part of the immediate.
1017 def PCRelLabel19Operand : AsmOperandClass {
1018   let Name = "PCRelLabel19";
1019   let DiagnosticType = "InvalidLabel";
1020 }
1021 def am_brcond : Operand<OtherVT> {
1022   let EncoderMethod = "getCondBranchTargetOpValue";
1023   let DecoderMethod = "DecodePCRelLabel19";
1024   let PrintMethod = "printAlignedLabel";
1025   let ParserMatchClass = PCRelLabel19Operand;
1026 }
1027
1028 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1029                      "b", ".$cond\t$target", "",
1030                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1031                    Sched<[WriteBr]> {
1032   let isBranch = 1;
1033   let isTerminator = 1;
1034   let Uses = [NZCV];
1035
1036   bits<4> cond;
1037   bits<19> target;
1038   let Inst{31-24} = 0b01010100;
1039   let Inst{23-5} = target;
1040   let Inst{4} = 0;
1041   let Inst{3-0} = cond;
1042 }
1043
1044 //---
1045 // Compare-and-branch instructions.
1046 //---
1047 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1048     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1049          asm, "\t$Rt, $target", "",
1050          [(node regtype:$Rt, bb:$target)]>,
1051       Sched<[WriteBr]> {
1052   let isBranch = 1;
1053   let isTerminator = 1;
1054
1055   bits<5> Rt;
1056   bits<19> target;
1057   let Inst{30-25} = 0b011010;
1058   let Inst{24}    = op;
1059   let Inst{23-5}  = target;
1060   let Inst{4-0}   = Rt;
1061 }
1062
1063 multiclass CmpBranch<bit op, string asm, SDNode node> {
1064   def W : BaseCmpBranch<GPR32, op, asm, node> {
1065     let Inst{31} = 0;
1066   }
1067   def X : BaseCmpBranch<GPR64, op, asm, node> {
1068     let Inst{31} = 1;
1069   }
1070 }
1071
1072 //---
1073 // Test-bit-and-branch instructions.
1074 //---
1075 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1076 // the target offset are implied zero and so are not part of the immediate.
1077 def BranchTarget14Operand : AsmOperandClass {
1078   let Name = "BranchTarget14";
1079 }
1080 def am_tbrcond : Operand<OtherVT> {
1081   let EncoderMethod = "getTestBranchTargetOpValue";
1082   let PrintMethod = "printAlignedLabel";
1083   let ParserMatchClass = BranchTarget14Operand;
1084 }
1085
1086 // AsmOperand classes to emit (or not) special diagnostics
1087 def TBZImm0_31Operand : AsmOperandClass {
1088   let Name = "TBZImm0_31";
1089   let PredicateMethod = "isImm0_31";
1090   let RenderMethod = "addImm0_31Operands";
1091 }
1092 def TBZImm32_63Operand : AsmOperandClass {
1093   let Name = "Imm32_63";
1094   let DiagnosticType = "InvalidImm0_63";
1095 }
1096
1097 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1098   return (((uint32_t)Imm) < 32);
1099 }]> {
1100   let ParserMatchClass = matcher;
1101 }
1102
1103 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1104 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1105
1106 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1107   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1108 }]> {
1109   let ParserMatchClass = TBZImm32_63Operand;
1110 }
1111
1112 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1113                      bit op, string asm, SDNode node>
1114     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1115        asm, "\t$Rt, $bit_off, $target", "",
1116        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1117       Sched<[WriteBr]> {
1118   let isBranch = 1;
1119   let isTerminator = 1;
1120
1121   bits<5> Rt;
1122   bits<6> bit_off;
1123   bits<14> target;
1124
1125   let Inst{30-25} = 0b011011;
1126   let Inst{24}    = op;
1127   let Inst{23-19} = bit_off{4-0};
1128   let Inst{18-5}  = target;
1129   let Inst{4-0}   = Rt;
1130
1131   let DecoderMethod = "DecodeTestAndBranch";
1132 }
1133
1134 multiclass TestBranch<bit op, string asm, SDNode node> {
1135   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1136     let Inst{31} = 0;
1137   }
1138
1139   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1140     let Inst{31} = 1;
1141   }
1142
1143   // Alias X-reg with 0-31 imm to W-Reg.
1144   def : InstAlias<asm # "\t$Rd, $imm, $target",
1145                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1146                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1147   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1148             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1149             tbz_imm0_31_diag:$imm, bb:$target)>;
1150 }
1151
1152 //---
1153 // Unconditional branch (immediate) instructions.
1154 //---
1155 def BranchTarget26Operand : AsmOperandClass {
1156   let Name = "BranchTarget26";
1157   let DiagnosticType = "InvalidLabel";
1158 }
1159 def am_b_target : Operand<OtherVT> {
1160   let EncoderMethod = "getBranchTargetOpValue";
1161   let PrintMethod = "printAlignedLabel";
1162   let ParserMatchClass = BranchTarget26Operand;
1163 }
1164 def am_bl_target : Operand<i64> {
1165   let EncoderMethod = "getBranchTargetOpValue";
1166   let PrintMethod = "printAlignedLabel";
1167   let ParserMatchClass = BranchTarget26Operand;
1168 }
1169
1170 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1171     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1172   bits<26> addr;
1173   let Inst{31}    = op;
1174   let Inst{30-26} = 0b00101;
1175   let Inst{25-0}  = addr;
1176
1177   let DecoderMethod = "DecodeUnconditionalBranch";
1178 }
1179
1180 class BranchImm<bit op, string asm, list<dag> pattern>
1181     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1182 class CallImm<bit op, string asm, list<dag> pattern>
1183     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1184
1185 //---
1186 // Basic one-operand data processing instructions.
1187 //---
1188
1189 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1190 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1191                          SDPatternOperator node>
1192   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1193       [(set regtype:$Rd, (node regtype:$Rn))]>,
1194     Sched<[WriteI, ReadI]> {
1195   bits<5> Rd;
1196   bits<5> Rn;
1197
1198   let Inst{30-13} = 0b101101011000000000;
1199   let Inst{12-10} = opc;
1200   let Inst{9-5}   = Rn;
1201   let Inst{4-0}   = Rd;
1202 }
1203
1204 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1205 multiclass OneOperandData<bits<3> opc, string asm,
1206                           SDPatternOperator node = null_frag> {
1207   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1208     let Inst{31} = 0;
1209   }
1210
1211   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1212     let Inst{31} = 1;
1213   }
1214 }
1215
1216 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1217     : BaseOneOperandData<opc, GPR32, asm, node> {
1218   let Inst{31} = 0;
1219 }
1220
1221 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1222     : BaseOneOperandData<opc, GPR64, asm, node> {
1223   let Inst{31} = 1;
1224 }
1225
1226 //---
1227 // Basic two-operand data processing instructions.
1228 //---
1229 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1230                           list<dag> pattern>
1231     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1232         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1233       Sched<[WriteI, ReadI, ReadI]> {
1234   let Uses = [NZCV];
1235   bits<5> Rd;
1236   bits<5> Rn;
1237   bits<5> Rm;
1238   let Inst{30}    = isSub;
1239   let Inst{28-21} = 0b11010000;
1240   let Inst{20-16} = Rm;
1241   let Inst{15-10} = 0;
1242   let Inst{9-5}   = Rn;
1243   let Inst{4-0}   = Rd;
1244 }
1245
1246 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1247                       SDNode OpNode>
1248     : BaseBaseAddSubCarry<isSub, regtype, asm,
1249         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1250
1251 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1252                               SDNode OpNode>
1253     : BaseBaseAddSubCarry<isSub, regtype, asm,
1254         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1255          (implicit NZCV)]> {
1256   let Defs = [NZCV];
1257 }
1258
1259 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1260                        SDNode OpNode, SDNode OpNode_setflags> {
1261   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1262     let Inst{31} = 0;
1263     let Inst{29} = 0;
1264   }
1265   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1266     let Inst{31} = 1;
1267     let Inst{29} = 0;
1268   }
1269
1270   // Sets flags.
1271   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1272                                     OpNode_setflags> {
1273     let Inst{31} = 0;
1274     let Inst{29} = 1;
1275   }
1276   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1277                                     OpNode_setflags> {
1278     let Inst{31} = 1;
1279     let Inst{29} = 1;
1280   }
1281 }
1282
1283 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1284                      SDPatternOperator OpNode>
1285   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1286       asm, "\t$Rd, $Rn, $Rm", "",
1287       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1288   bits<5> Rd;
1289   bits<5> Rn;
1290   bits<5> Rm;
1291   let Inst{30-21} = 0b0011010110;
1292   let Inst{20-16} = Rm;
1293   let Inst{15-14} = 0b00;
1294   let Inst{13-10} = opc;
1295   let Inst{9-5}   = Rn;
1296   let Inst{4-0}   = Rd;
1297 }
1298
1299 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1300               SDPatternOperator OpNode>
1301     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1302   let Inst{10}    = isSigned;
1303 }
1304
1305 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1306   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1307            Sched<[WriteID32, ReadID, ReadID]> {
1308     let Inst{31} = 0;
1309   }
1310   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1311            Sched<[WriteID64, ReadID, ReadID]> {
1312     let Inst{31} = 1;
1313   }
1314 }
1315
1316 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1317                 SDPatternOperator OpNode = null_frag>
1318   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1319     Sched<[WriteIS, ReadI]> {
1320   let Inst{11-10} = shift_type;
1321 }
1322
1323 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1324   def Wr : BaseShift<shift_type, GPR32, asm> {
1325     let Inst{31} = 0;
1326   }
1327
1328   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1329     let Inst{31} = 1;
1330   }
1331
1332   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1333             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1334                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1335
1336   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1337             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1338
1339   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1340             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1341
1342   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1343             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1344 }
1345
1346 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1347     : InstAlias<asm#" $dst, $src1, $src2",
1348                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1349
1350 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1351                        RegisterClass addtype, string asm,
1352                        list<dag> pattern>
1353   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1354       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1355   bits<5> Rd;
1356   bits<5> Rn;
1357   bits<5> Rm;
1358   bits<5> Ra;
1359   let Inst{30-24} = 0b0011011;
1360   let Inst{23-21} = opc;
1361   let Inst{20-16} = Rm;
1362   let Inst{15}    = isSub;
1363   let Inst{14-10} = Ra;
1364   let Inst{9-5}   = Rn;
1365   let Inst{4-0}   = Rd;
1366 }
1367
1368 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1369   // MADD/MSUB generation is decided by MachineCombiner.cpp
1370   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1371       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1372       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1373     let Inst{31} = 0;
1374   }
1375
1376   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1377       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1378       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1379     let Inst{31} = 1;
1380   }
1381 }
1382
1383 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1384                    SDNode AccNode, SDNode ExtNode>
1385   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1386     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1387                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1388     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1389   let Inst{31} = 1;
1390 }
1391
1392 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1393   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1394       asm, "\t$Rd, $Rn, $Rm", "",
1395       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1396     Sched<[WriteIM64, ReadIM, ReadIM]> {
1397   bits<5> Rd;
1398   bits<5> Rn;
1399   bits<5> Rm;
1400   let Inst{31-24} = 0b10011011;
1401   let Inst{23-21} = opc;
1402   let Inst{20-16} = Rm;
1403   let Inst{15}    = 0;
1404   let Inst{9-5}   = Rn;
1405   let Inst{4-0}   = Rd;
1406
1407   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1408   // (i.e. all bits 1) but is ignored by the processor.
1409   let PostEncoderMethod = "fixMulHigh";
1410 }
1411
1412 class MulAccumWAlias<string asm, Instruction inst>
1413     : InstAlias<asm#" $dst, $src1, $src2",
1414                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1415 class MulAccumXAlias<string asm, Instruction inst>
1416     : InstAlias<asm#" $dst, $src1, $src2",
1417                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1418 class WideMulAccumAlias<string asm, Instruction inst>
1419     : InstAlias<asm#" $dst, $src1, $src2",
1420                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1421
1422 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1423               SDPatternOperator OpNode, string asm>
1424   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1425       asm, "\t$Rd, $Rn, $Rm", "",
1426       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1427     Sched<[WriteISReg, ReadI, ReadISReg]> {
1428   bits<5> Rd;
1429   bits<5> Rn;
1430   bits<5> Rm;
1431
1432   let Inst{31} = sf;
1433   let Inst{30-21} = 0b0011010110;
1434   let Inst{20-16} = Rm;
1435   let Inst{15-13} = 0b010;
1436   let Inst{12} = C;
1437   let Inst{11-10} = sz;
1438   let Inst{9-5} = Rn;
1439   let Inst{4-0} = Rd;
1440   let Predicates = [HasCRC];
1441 }
1442
1443 //---
1444 // Address generation.
1445 //---
1446
1447 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1448     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1449         pattern>,
1450       Sched<[WriteI]> {
1451   bits<5>  Xd;
1452   bits<21> label;
1453   let Inst{31}    = page;
1454   let Inst{30-29} = label{1-0};
1455   let Inst{28-24} = 0b10000;
1456   let Inst{23-5}  = label{20-2};
1457   let Inst{4-0}   = Xd;
1458
1459   let DecoderMethod = "DecodeAdrInstruction";
1460 }
1461
1462 //---
1463 // Move immediate.
1464 //---
1465
1466 def movimm32_imm : Operand<i32> {
1467   let ParserMatchClass = Imm0_65535Operand;
1468   let EncoderMethod = "getMoveWideImmOpValue";
1469   let PrintMethod = "printHexImm";
1470 }
1471 def movimm32_shift : Operand<i32> {
1472   let PrintMethod = "printShifter";
1473   let ParserMatchClass = MovImm32ShifterOperand;
1474 }
1475 def movimm64_shift : Operand<i32> {
1476   let PrintMethod = "printShifter";
1477   let ParserMatchClass = MovImm64ShifterOperand;
1478 }
1479
1480 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1481 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1482                         string asm>
1483   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1484        asm, "\t$Rd, $imm$shift", "", []>,
1485     Sched<[WriteImm]> {
1486   bits<5> Rd;
1487   bits<16> imm;
1488   bits<6> shift;
1489   let Inst{30-29} = opc;
1490   let Inst{28-23} = 0b100101;
1491   let Inst{22-21} = shift{5-4};
1492   let Inst{20-5}  = imm;
1493   let Inst{4-0}   = Rd;
1494
1495   let DecoderMethod = "DecodeMoveImmInstruction";
1496 }
1497
1498 multiclass MoveImmediate<bits<2> opc, string asm> {
1499   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1500     let Inst{31} = 0;
1501   }
1502
1503   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1504     let Inst{31} = 1;
1505   }
1506 }
1507
1508 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1509 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1510                           string asm>
1511   : I<(outs regtype:$Rd),
1512       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1513        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1514     Sched<[WriteI, ReadI]> {
1515   bits<5> Rd;
1516   bits<16> imm;
1517   bits<6> shift;
1518   let Inst{30-29} = opc;
1519   let Inst{28-23} = 0b100101;
1520   let Inst{22-21} = shift{5-4};
1521   let Inst{20-5}  = imm;
1522   let Inst{4-0}   = Rd;
1523
1524   let DecoderMethod = "DecodeMoveImmInstruction";
1525 }
1526
1527 multiclass InsertImmediate<bits<2> opc, string asm> {
1528   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1529     let Inst{31} = 0;
1530   }
1531
1532   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1533     let Inst{31} = 1;
1534   }
1535 }
1536
1537 //---
1538 // Add/Subtract
1539 //---
1540
1541 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1542                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1543                     string asm, SDPatternOperator OpNode>
1544     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1545         asm, "\t$Rd, $Rn, $imm", "",
1546         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1547       Sched<[WriteI, ReadI]>  {
1548   bits<5>  Rd;
1549   bits<5>  Rn;
1550   bits<14> imm;
1551   let Inst{30}    = isSub;
1552   let Inst{29}    = setFlags;
1553   let Inst{28-24} = 0b10001;
1554   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1555   let Inst{21-10} = imm{11-0};
1556   let Inst{9-5}   = Rn;
1557   let Inst{4-0}   = Rd;
1558   let DecoderMethod = "DecodeBaseAddSubImm";
1559 }
1560
1561 class BaseAddSubRegPseudo<RegisterClass regtype,
1562                           SDPatternOperator OpNode>
1563     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1564              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1565       Sched<[WriteI, ReadI, ReadI]>;
1566
1567 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1568                      arith_shifted_reg shifted_regtype, string asm,
1569                      SDPatternOperator OpNode>
1570     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1571         asm, "\t$Rd, $Rn, $Rm", "",
1572         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1573       Sched<[WriteISReg, ReadI, ReadISReg]> {
1574   // The operands are in order to match the 'addr' MI operands, so we
1575   // don't need an encoder method and by-name matching. Just use the default
1576   // in-order handling. Since we're using by-order, make sure the names
1577   // do not match.
1578   bits<5> dst;
1579   bits<5> src1;
1580   bits<5> src2;
1581   bits<8> shift;
1582   let Inst{30}    = isSub;
1583   let Inst{29}    = setFlags;
1584   let Inst{28-24} = 0b01011;
1585   let Inst{23-22} = shift{7-6};
1586   let Inst{21}    = 0;
1587   let Inst{20-16} = src2;
1588   let Inst{15-10} = shift{5-0};
1589   let Inst{9-5}   = src1;
1590   let Inst{4-0}   = dst;
1591
1592   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1593 }
1594
1595 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1596                      RegisterClass src1Regtype, Operand src2Regtype,
1597                      string asm, SDPatternOperator OpNode>
1598     : I<(outs dstRegtype:$R1),
1599         (ins src1Regtype:$R2, src2Regtype:$R3),
1600         asm, "\t$R1, $R2, $R3", "",
1601         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1602       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1603   bits<5> Rd;
1604   bits<5> Rn;
1605   bits<5> Rm;
1606   bits<6> ext;
1607   let Inst{30}    = isSub;
1608   let Inst{29}    = setFlags;
1609   let Inst{28-24} = 0b01011;
1610   let Inst{23-21} = 0b001;
1611   let Inst{20-16} = Rm;
1612   let Inst{15-13} = ext{5-3};
1613   let Inst{12-10} = ext{2-0};
1614   let Inst{9-5}   = Rn;
1615   let Inst{4-0}   = Rd;
1616
1617   let DecoderMethod = "DecodeAddSubERegInstruction";
1618 }
1619
1620 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1621 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1622                        RegisterClass src1Regtype, RegisterClass src2Regtype,
1623                        Operand ext_op, string asm>
1624     : I<(outs dstRegtype:$Rd),
1625         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1626         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1627       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1628   bits<5> Rd;
1629   bits<5> Rn;
1630   bits<5> Rm;
1631   bits<6> ext;
1632   let Inst{30}    = isSub;
1633   let Inst{29}    = setFlags;
1634   let Inst{28-24} = 0b01011;
1635   let Inst{23-21} = 0b001;
1636   let Inst{20-16} = Rm;
1637   let Inst{15}    = ext{5};
1638   let Inst{12-10} = ext{2-0};
1639   let Inst{9-5}   = Rn;
1640   let Inst{4-0}   = Rd;
1641
1642   let DecoderMethod = "DecodeAddSubERegInstruction";
1643 }
1644
1645 // Aliases for register+register add/subtract.
1646 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1647                      RegisterClass src1Regtype, RegisterClass src2Regtype,
1648                      int shiftExt>
1649     : InstAlias<asm#" $dst, $src1, $src2",
1650                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1651                       shiftExt)>;
1652
1653 multiclass AddSub<bit isSub, string mnemonic, string alias,
1654                   SDPatternOperator OpNode = null_frag> {
1655   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1656   // Add/Subtract immediate
1657   // Increase the weight of the immediate variant to try to match it before
1658   // the extended register variant.
1659   // We used to match the register variant before the immediate when the
1660   // register argument could be implicitly zero-extended.
1661   let AddedComplexity = 6 in
1662   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1663                            mnemonic, OpNode> {
1664     let Inst{31} = 0;
1665   }
1666   let AddedComplexity = 6 in
1667   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1668                            mnemonic, OpNode> {
1669     let Inst{31} = 1;
1670   }
1671
1672   // Add/Subtract register - Only used for CodeGen
1673   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1674   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1675
1676   // Add/Subtract shifted register
1677   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1678                            OpNode> {
1679     let Inst{31} = 0;
1680   }
1681   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1682                            OpNode> {
1683     let Inst{31} = 1;
1684   }
1685   }
1686
1687   // Add/Subtract extended register
1688   let AddedComplexity = 1, hasSideEffects = 0 in {
1689   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1690                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1691     let Inst{31} = 0;
1692   }
1693   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1694                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1695     let Inst{31} = 1;
1696   }
1697   }
1698
1699   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1700                                arith_extendlsl64, mnemonic> {
1701     // UXTX and SXTX only.
1702     let Inst{14-13} = 0b11;
1703     let Inst{31} = 1;
1704   }
1705
1706   // add Rd, Rb, -imm -> sub Rd, Rn, imm
1707   def : InstAlias<alias#" $Rd, $Rn, $imm",
1708                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
1709                       addsub_shifted_imm32_neg:$imm), 0>;
1710   def : InstAlias<alias#" $Rd, $Rn, $imm",
1711                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
1712                        addsub_shifted_imm64_neg:$imm), 0>;
1713
1714   // Register/register aliases with no shift when SP is not used.
1715   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1716                        GPR32, GPR32, GPR32, 0>;
1717   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1718                        GPR64, GPR64, GPR64, 0>;
1719
1720   // Register/register aliases with no shift when either the destination or
1721   // first source register is SP.
1722   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1723                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1724   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1725                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1726   def : AddSubRegAlias<mnemonic,
1727                        !cast<Instruction>(NAME#"Xrx64"),
1728                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1729   def : AddSubRegAlias<mnemonic,
1730                        !cast<Instruction>(NAME#"Xrx64"),
1731                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1732 }
1733
1734 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
1735                    string alias, string cmpAlias> {
1736   let isCompare = 1, Defs = [NZCV] in {
1737   // Add/Subtract immediate
1738   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1739                            mnemonic, OpNode> {
1740     let Inst{31} = 0;
1741   }
1742   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1743                            mnemonic, OpNode> {
1744     let Inst{31} = 1;
1745   }
1746
1747   // Add/Subtract register
1748   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1749   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1750
1751   // Add/Subtract shifted register
1752   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1753                            OpNode> {
1754     let Inst{31} = 0;
1755   }
1756   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1757                            OpNode> {
1758     let Inst{31} = 1;
1759   }
1760
1761   // Add/Subtract extended register
1762   let AddedComplexity = 1 in {
1763   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1764                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1765     let Inst{31} = 0;
1766   }
1767   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1768                            arith_extended_reg32<i64>, mnemonic, OpNode> {
1769     let Inst{31} = 1;
1770   }
1771   }
1772
1773   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1774                                arith_extendlsl64, mnemonic> {
1775     // UXTX and SXTX only.
1776     let Inst{14-13} = 0b11;
1777     let Inst{31} = 1;
1778   }
1779   } // Defs = [NZCV]
1780
1781   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
1782   def : InstAlias<alias#" $Rd, $Rn, $imm",
1783                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
1784                       addsub_shifted_imm32_neg:$imm), 0>;
1785   def : InstAlias<alias#" $Rd, $Rn, $imm",
1786                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
1787                        addsub_shifted_imm64_neg:$imm), 0>;
1788
1789   // Compare aliases
1790   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Wri")
1791                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1792   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Xri")
1793                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1794   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1795                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1796   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1797                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1798   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1799                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1800   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1801                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1802   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1803                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1804
1805   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
1806   def : InstAlias<cmpAlias#" $src, $imm", (!cast<Instruction>(NAME#"Wri")
1807                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
1808   def : InstAlias<cmpAlias#" $src, $imm", (!cast<Instruction>(NAME#"Xri")
1809                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
1810
1811   // Compare shorthands
1812   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1813                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1814   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1815                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1816   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1817                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1818   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1819                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1820
1821   // Register/register aliases with no shift when SP is not used.
1822   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1823                        GPR32, GPR32, GPR32, 0>;
1824   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1825                        GPR64, GPR64, GPR64, 0>;
1826
1827   // Register/register aliases with no shift when the first source register
1828   // is SP.
1829   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1830                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1831   def : AddSubRegAlias<mnemonic,
1832                        !cast<Instruction>(NAME#"Xrx64"),
1833                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1834 }
1835
1836 //---
1837 // Extract
1838 //---
1839 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1840                                       SDTCisPtrTy<3>]>;
1841 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1842
1843 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1844                      list<dag> patterns>
1845     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1846          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1847       Sched<[WriteExtr, ReadExtrHi]> {
1848   bits<5> Rd;
1849   bits<5> Rn;
1850   bits<5> Rm;
1851   bits<6> imm;
1852
1853   let Inst{30-23} = 0b00100111;
1854   let Inst{21}    = 0;
1855   let Inst{20-16} = Rm;
1856   let Inst{15-10} = imm;
1857   let Inst{9-5}   = Rn;
1858   let Inst{4-0}   = Rd;
1859 }
1860
1861 multiclass ExtractImm<string asm> {
1862   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1863                       [(set GPR32:$Rd,
1864                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1865     let Inst{31} = 0;
1866     let Inst{22} = 0;
1867     // imm<5> must be zero.
1868     let imm{5}   = 0;
1869   }
1870   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1871                       [(set GPR64:$Rd,
1872                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1873
1874     let Inst{31} = 1;
1875     let Inst{22} = 1;
1876   }
1877 }
1878
1879 //---
1880 // Bitfield
1881 //---
1882
1883 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1884 class BaseBitfieldImm<bits<2> opc,
1885                       RegisterClass regtype, Operand imm_type, string asm>
1886     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1887          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1888       Sched<[WriteIS, ReadI]> {
1889   bits<5> Rd;
1890   bits<5> Rn;
1891   bits<6> immr;
1892   bits<6> imms;
1893
1894   let Inst{30-29} = opc;
1895   let Inst{28-23} = 0b100110;
1896   let Inst{21-16} = immr;
1897   let Inst{15-10} = imms;
1898   let Inst{9-5}   = Rn;
1899   let Inst{4-0}   = Rd;
1900 }
1901
1902 multiclass BitfieldImm<bits<2> opc, string asm> {
1903   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1904     let Inst{31} = 0;
1905     let Inst{22} = 0;
1906     // imms<5> and immr<5> must be zero, else ReservedValue().
1907     let Inst{21} = 0;
1908     let Inst{15} = 0;
1909   }
1910   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1911     let Inst{31} = 1;
1912     let Inst{22} = 1;
1913   }
1914 }
1915
1916 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1917 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1918                       RegisterClass regtype, Operand imm_type, string asm>
1919     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1920                              imm_type:$imms),
1921          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1922       Sched<[WriteIS, ReadI]> {
1923   bits<5> Rd;
1924   bits<5> Rn;
1925   bits<6> immr;
1926   bits<6> imms;
1927
1928   let Inst{30-29} = opc;
1929   let Inst{28-23} = 0b100110;
1930   let Inst{21-16} = immr;
1931   let Inst{15-10} = imms;
1932   let Inst{9-5}   = Rn;
1933   let Inst{4-0}   = Rd;
1934 }
1935
1936 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1937   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1938     let Inst{31} = 0;
1939     let Inst{22} = 0;
1940     // imms<5> and immr<5> must be zero, else ReservedValue().
1941     let Inst{21} = 0;
1942     let Inst{15} = 0;
1943   }
1944   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1945     let Inst{31} = 1;
1946     let Inst{22} = 1;
1947   }
1948 }
1949
1950 //---
1951 // Logical
1952 //---
1953
1954 // Logical (immediate)
1955 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1956                      RegisterClass sregtype, Operand imm_type, string asm,
1957                      list<dag> pattern>
1958     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1959          asm, "\t$Rd, $Rn, $imm", "", pattern>,
1960       Sched<[WriteI, ReadI]> {
1961   bits<5>  Rd;
1962   bits<5>  Rn;
1963   bits<13> imm;
1964   let Inst{30-29} = opc;
1965   let Inst{28-23} = 0b100100;
1966   let Inst{22}    = imm{12};
1967   let Inst{21-16} = imm{11-6};
1968   let Inst{15-10} = imm{5-0};
1969   let Inst{9-5}   = Rn;
1970   let Inst{4-0}   = Rd;
1971
1972   let DecoderMethod = "DecodeLogicalImmInstruction";
1973 }
1974
1975 // Logical (shifted register)
1976 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1977                       logical_shifted_reg shifted_regtype, string asm,
1978                       list<dag> pattern>
1979     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1980         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1981       Sched<[WriteISReg, ReadI, ReadISReg]> {
1982   // The operands are in order to match the 'addr' MI operands, so we
1983   // don't need an encoder method and by-name matching. Just use the default
1984   // in-order handling. Since we're using by-order, make sure the names
1985   // do not match.
1986   bits<5> dst;
1987   bits<5> src1;
1988   bits<5> src2;
1989   bits<8> shift;
1990   let Inst{30-29} = opc;
1991   let Inst{28-24} = 0b01010;
1992   let Inst{23-22} = shift{7-6};
1993   let Inst{21}    = N;
1994   let Inst{20-16} = src2;
1995   let Inst{15-10} = shift{5-0};
1996   let Inst{9-5}   = src1;
1997   let Inst{4-0}   = dst;
1998
1999   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2000 }
2001
2002 // Aliases for register+register logical instructions.
2003 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2004     : InstAlias<asm#" $dst, $src1, $src2",
2005                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2006
2007 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2008                       string Alias> {
2009   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2010   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2011                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2012                                                logical_imm32:$imm))]> {
2013     let Inst{31} = 0;
2014     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2015   }
2016   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2017   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2018                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2019                                                logical_imm64:$imm))]> {
2020     let Inst{31} = 1;
2021   }
2022
2023   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2024                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2025                       logical_imm32_not:$imm), 0>;
2026   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2027                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2028                        logical_imm64_not:$imm), 0>;
2029 }
2030
2031 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2032                        string Alias> {
2033   let isCompare = 1, Defs = [NZCV] in {
2034   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2035       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2036     let Inst{31} = 0;
2037     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2038   }
2039   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2040       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2041     let Inst{31} = 1;
2042   }
2043   } // end Defs = [NZCV]
2044
2045   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2046                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2047                       logical_imm32_not:$imm), 0>;
2048   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2049                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2050                        logical_imm64_not:$imm), 0>;
2051 }
2052
2053 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2054     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2055              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2056       Sched<[WriteI, ReadI, ReadI]>;
2057
2058 // Split from LogicalImm as not all instructions have both.
2059 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2060                       SDPatternOperator OpNode> {
2061   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2062   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2063   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2064   }
2065
2066   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2067                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2068                                                  logical_shifted_reg32:$Rm))]> {
2069     let Inst{31} = 0;
2070   }
2071   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2072                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2073                                                  logical_shifted_reg64:$Rm))]> {
2074     let Inst{31} = 1;
2075   }
2076
2077   def : LogicalRegAlias<mnemonic,
2078                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2079   def : LogicalRegAlias<mnemonic,
2080                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2081 }
2082
2083 // Split from LogicalReg to allow setting NZCV Defs
2084 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2085                        SDPatternOperator OpNode = null_frag> {
2086   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2087   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2088   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2089
2090   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2091             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2092     let Inst{31} = 0;
2093   }
2094   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2095             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2096     let Inst{31} = 1;
2097   }
2098   } // Defs = [NZCV]
2099
2100   def : LogicalRegAlias<mnemonic,
2101                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2102   def : LogicalRegAlias<mnemonic,
2103                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2104 }
2105
2106 //---
2107 // Conditionally set flags
2108 //---
2109
2110 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2111 class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
2112     : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
2113          asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
2114       Sched<[WriteI, ReadI]> {
2115   let Uses = [NZCV];
2116   let Defs = [NZCV];
2117
2118   bits<5> Rn;
2119   bits<5> imm;
2120   bits<4> nzcv;
2121   bits<4> cond;
2122
2123   let Inst{30}    = op;
2124   let Inst{29-21} = 0b111010010;
2125   let Inst{20-16} = imm;
2126   let Inst{15-12} = cond;
2127   let Inst{11-10} = 0b10;
2128   let Inst{9-5}   = Rn;
2129   let Inst{4}     = 0b0;
2130   let Inst{3-0}   = nzcv;
2131 }
2132
2133 multiclass CondSetFlagsImm<bit op, string asm> {
2134   def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
2135     let Inst{31} = 0;
2136   }
2137   def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
2138     let Inst{31} = 1;
2139   }
2140 }
2141
2142 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2143 class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
2144     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
2145          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
2146       Sched<[WriteI, ReadI, ReadI]> {
2147   let Uses = [NZCV];
2148   let Defs = [NZCV];
2149
2150   bits<5> Rn;
2151   bits<5> Rm;
2152   bits<4> nzcv;
2153   bits<4> cond;
2154
2155   let Inst{30}    = op;
2156   let Inst{29-21} = 0b111010010;
2157   let Inst{20-16} = Rm;
2158   let Inst{15-12} = cond;
2159   let Inst{11-10} = 0b00;
2160   let Inst{9-5}   = Rn;
2161   let Inst{4}     = 0b0;
2162   let Inst{3-0}   = nzcv;
2163 }
2164
2165 multiclass CondSetFlagsReg<bit op, string asm> {
2166   def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
2167     let Inst{31} = 0;
2168   }
2169   def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
2170     let Inst{31} = 1;
2171   }
2172 }
2173
2174 //---
2175 // Conditional select
2176 //---
2177
2178 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2179     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2180          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2181          [(set regtype:$Rd,
2182                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2183       Sched<[WriteI, ReadI, ReadI]> {
2184   let Uses = [NZCV];
2185
2186   bits<5> Rd;
2187   bits<5> Rn;
2188   bits<5> Rm;
2189   bits<4> cond;
2190
2191   let Inst{30}    = op;
2192   let Inst{29-21} = 0b011010100;
2193   let Inst{20-16} = Rm;
2194   let Inst{15-12} = cond;
2195   let Inst{11-10} = op2;
2196   let Inst{9-5}   = Rn;
2197   let Inst{4-0}   = Rd;
2198 }
2199
2200 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2201   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2202     let Inst{31} = 0;
2203   }
2204   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2205     let Inst{31} = 1;
2206   }
2207 }
2208
2209 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2210                        PatFrag frag>
2211     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2212          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2213          [(set regtype:$Rd,
2214                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2215                (i32 imm:$cond), NZCV))]>,
2216       Sched<[WriteI, ReadI, ReadI]> {
2217   let Uses = [NZCV];
2218
2219   bits<5> Rd;
2220   bits<5> Rn;
2221   bits<5> Rm;
2222   bits<4> cond;
2223
2224   let Inst{30}    = op;
2225   let Inst{29-21} = 0b011010100;
2226   let Inst{20-16} = Rm;
2227   let Inst{15-12} = cond;
2228   let Inst{11-10} = op2;
2229   let Inst{9-5}   = Rn;
2230   let Inst{4-0}   = Rd;
2231 }
2232
2233 def inv_cond_XFORM : SDNodeXForm<imm, [{
2234   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2235   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2236                                    MVT::i32);
2237 }]>;
2238
2239 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2240   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2241     let Inst{31} = 0;
2242   }
2243   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2244     let Inst{31} = 1;
2245   }
2246
2247   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2248             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2249                                            (inv_cond_XFORM imm:$cond))>;
2250
2251   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2252             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2253                                            (inv_cond_XFORM imm:$cond))>;
2254 }
2255
2256 //---
2257 // Special Mask Value
2258 //---
2259 def maski8_or_more : Operand<i32>,
2260   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2261 }
2262 def maski16_or_more : Operand<i32>,
2263   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2264 }
2265
2266
2267 //---
2268 // Load/store
2269 //---
2270
2271 // (unsigned immediate)
2272 // Indexed for 8-bit registers. offset is in range [0,4095].
2273 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2274 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2275 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2276 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2277 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2278
2279 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2280   let Name = "UImm12Offset" # Scale;
2281   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2282   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2283   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2284 }
2285
2286 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2287 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2288 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2289 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2290 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2291
2292 class uimm12_scaled<int Scale> : Operand<i64> {
2293   let ParserMatchClass
2294    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2295   let EncoderMethod
2296    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2297   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2298 }
2299
2300 def uimm12s1 : uimm12_scaled<1>;
2301 def uimm12s2 : uimm12_scaled<2>;
2302 def uimm12s4 : uimm12_scaled<4>;
2303 def uimm12s8 : uimm12_scaled<8>;
2304 def uimm12s16 : uimm12_scaled<16>;
2305
2306 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2307                       string asm, list<dag> pattern>
2308     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2309   bits<5> Rt;
2310
2311   bits<5> Rn;
2312   bits<12> offset;
2313
2314   let Inst{31-30} = sz;
2315   let Inst{29-27} = 0b111;
2316   let Inst{26}    = V;
2317   let Inst{25-24} = 0b01;
2318   let Inst{23-22} = opc;
2319   let Inst{21-10} = offset;
2320   let Inst{9-5}   = Rn;
2321   let Inst{4-0}   = Rt;
2322
2323   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2324 }
2325
2326 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2327                   Operand indextype, string asm, list<dag> pattern> {
2328   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2329   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2330                            (ins GPR64sp:$Rn, indextype:$offset),
2331                            asm, pattern>,
2332            Sched<[WriteLD]>;
2333
2334   def : InstAlias<asm # " $Rt, [$Rn]",
2335                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2336 }
2337
2338 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2339              Operand indextype, string asm, list<dag> pattern> {
2340   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2341   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2342                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2343                            asm, pattern>,
2344            Sched<[WriteST]>;
2345
2346   def : InstAlias<asm # " $Rt, [$Rn]",
2347                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2348 }
2349
2350 def PrefetchOperand : AsmOperandClass {
2351   let Name = "Prefetch";
2352   let ParserMethod = "tryParsePrefetch";
2353 }
2354 def prfop : Operand<i32> {
2355   let PrintMethod = "printPrefetchOp";
2356   let ParserMatchClass = PrefetchOperand;
2357 }
2358
2359 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2360 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2361     : BaseLoadStoreUI<sz, V, opc,
2362                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2363                       asm, pat>,
2364       Sched<[WriteLD]>;
2365
2366 //---
2367 // Load literal
2368 //---
2369
2370 // Load literal address: 19-bit immediate. The low two bits of the target
2371 // offset are implied zero and so are not part of the immediate.
2372 def am_ldrlit : Operand<OtherVT> {
2373   let EncoderMethod = "getLoadLiteralOpValue";
2374   let DecoderMethod = "DecodePCRelLabel19";
2375   let PrintMethod = "printAlignedLabel";
2376   let ParserMatchClass = PCRelLabel19Operand;
2377 }
2378
2379 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2380 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2381     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2382         asm, "\t$Rt, $label", "", []>,
2383       Sched<[WriteLD]> {
2384   bits<5> Rt;
2385   bits<19> label;
2386   let Inst{31-30} = opc;
2387   let Inst{29-27} = 0b011;
2388   let Inst{26}    = V;
2389   let Inst{25-24} = 0b00;
2390   let Inst{23-5}  = label;
2391   let Inst{4-0}   = Rt;
2392 }
2393
2394 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2395 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2396     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2397         asm, "\t$Rt, $label", "", pat>,
2398       Sched<[WriteLD]> {
2399   bits<5> Rt;
2400   bits<19> label;
2401   let Inst{31-30} = opc;
2402   let Inst{29-27} = 0b011;
2403   let Inst{26}    = V;
2404   let Inst{25-24} = 0b00;
2405   let Inst{23-5}  = label;
2406   let Inst{4-0}   = Rt;
2407 }
2408
2409 //---
2410 // Load/store register offset
2411 //---
2412
2413 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2414 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2415 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2416 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2417 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2418
2419 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2420 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2421 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2422 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2423 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2424
2425 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2426   let Name = "Mem" # Reg # "Extend" # Width;
2427   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2428   let RenderMethod = "addMemExtendOperands";
2429   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2430 }
2431
2432 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2433   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2434   // the trivial shift.
2435   let RenderMethod = "addMemExtend8Operands";
2436 }
2437 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2438 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2439 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2440 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2441
2442 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2443   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2444   // the trivial shift.
2445   let RenderMethod = "addMemExtend8Operands";
2446 }
2447 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2448 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2449 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2450 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2451
2452 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2453         : Operand<i32> {
2454   let ParserMatchClass = ParserClass;
2455   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2456   let DecoderMethod = "DecodeMemExtend";
2457   let EncoderMethod = "getMemExtendOpValue";
2458   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2459 }
2460
2461 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2462 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2463 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2464 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2465 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2466
2467 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2468 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2469 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2470 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2471 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2472
2473 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2474                   Operand wextend, Operand xextend>  {
2475   // CodeGen-level pattern covering the entire addressing mode.
2476   ComplexPattern Wpat = windex;
2477   ComplexPattern Xpat = xindex;
2478
2479   // Asm-level Operand covering the valid "uxtw #3" style syntax.
2480   Operand Wext = wextend;
2481   Operand Xext = xextend;
2482 }
2483
2484 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2485 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2486 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2487 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2488 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2489                        ro_Xextend128>;
2490
2491 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2492                       string asm, dag ins, dag outs, list<dag> pat>
2493     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2494   bits<5> Rt;
2495   bits<5> Rn;
2496   bits<5> Rm;
2497   bits<2> extend;
2498   let Inst{31-30} = sz;
2499   let Inst{29-27} = 0b111;
2500   let Inst{26}    = V;
2501   let Inst{25-24} = 0b00;
2502   let Inst{23-22} = opc;
2503   let Inst{21}    = 1;
2504   let Inst{20-16} = Rm;
2505   let Inst{15}    = extend{1}; // sign extend Rm?
2506   let Inst{14}    = 1;
2507   let Inst{12}    = extend{0}; // do shift?
2508   let Inst{11-10} = 0b10;
2509   let Inst{9-5}   = Rn;
2510   let Inst{4-0}   = Rt;
2511 }
2512
2513 class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2514   : InstAlias<asm # " $Rt, [$Rn, $Rm]",
2515               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2516
2517 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2518                    string asm, ValueType Ty, SDPatternOperator loadop> {
2519   let AddedComplexity = 10 in
2520   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2521                  (outs regtype:$Rt),
2522                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2523                  [(set (Ty regtype:$Rt),
2524                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2525                                              ro_Wextend8:$extend)))]>,
2526            Sched<[WriteLDIdx, ReadAdrBase]> {
2527     let Inst{13} = 0b0;
2528   }
2529
2530   let AddedComplexity = 10 in
2531   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2532                  (outs regtype:$Rt),
2533                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2534                  [(set (Ty regtype:$Rt),
2535                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2536                                              ro_Xextend8:$extend)))]>,
2537            Sched<[WriteLDIdx, ReadAdrBase]> {
2538     let Inst{13} = 0b1;
2539   }
2540
2541   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2542 }
2543
2544 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2545                     string asm, ValueType Ty, SDPatternOperator storeop> {
2546   let AddedComplexity = 10 in
2547   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2548                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2549                  [(storeop (Ty regtype:$Rt),
2550                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2551                                          ro_Wextend8:$extend))]>,
2552             Sched<[WriteSTIdx, ReadAdrBase]> {
2553     let Inst{13} = 0b0;
2554   }
2555
2556   let AddedComplexity = 10 in
2557   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2558                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2559                  [(storeop (Ty regtype:$Rt),
2560                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2561                                          ro_Xextend8:$extend))]>,
2562             Sched<[WriteSTIdx, ReadAdrBase]> {
2563     let Inst{13} = 0b1;
2564   }
2565
2566   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2567 }
2568
2569 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2570                       string asm, dag ins, dag outs, list<dag> pat>
2571     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2572   bits<5> Rt;
2573   bits<5> Rn;
2574   bits<5> Rm;
2575   bits<2> extend;
2576   let Inst{31-30} = sz;
2577   let Inst{29-27} = 0b111;
2578   let Inst{26}    = V;
2579   let Inst{25-24} = 0b00;
2580   let Inst{23-22} = opc;
2581   let Inst{21}    = 1;
2582   let Inst{20-16} = Rm;
2583   let Inst{15}    = extend{1}; // sign extend Rm?
2584   let Inst{14}    = 1;
2585   let Inst{12}    = extend{0}; // do shift?
2586   let Inst{11-10} = 0b10;
2587   let Inst{9-5}   = Rn;
2588   let Inst{4-0}   = Rt;
2589 }
2590
2591 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2592                     string asm, ValueType Ty, SDPatternOperator loadop> {
2593   let AddedComplexity = 10 in
2594   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2595                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2596                  [(set (Ty regtype:$Rt),
2597                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2598                                               ro_Wextend16:$extend)))]>,
2599             Sched<[WriteLDIdx, ReadAdrBase]> {
2600     let Inst{13} = 0b0;
2601   }
2602
2603   let AddedComplexity = 10 in
2604   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2605                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2606                  [(set (Ty regtype:$Rt),
2607                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2608                                              ro_Xextend16:$extend)))]>,
2609             Sched<[WriteLDIdx, ReadAdrBase]> {
2610     let Inst{13} = 0b1;
2611   }
2612
2613   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2614 }
2615
2616 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2617                      string asm, ValueType Ty, SDPatternOperator storeop> {
2618   let AddedComplexity = 10 in
2619   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2620                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2621                 [(storeop (Ty regtype:$Rt),
2622                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2623                                          ro_Wextend16:$extend))]>,
2624            Sched<[WriteSTIdx, ReadAdrBase]> {
2625     let Inst{13} = 0b0;
2626   }
2627
2628   let AddedComplexity = 10 in
2629   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2630                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2631                 [(storeop (Ty regtype:$Rt),
2632                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2633                                          ro_Xextend16:$extend))]>,
2634            Sched<[WriteSTIdx, ReadAdrBase]> {
2635     let Inst{13} = 0b1;
2636   }
2637
2638   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2639 }
2640
2641 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2642                       string asm, dag ins, dag outs, list<dag> pat>
2643     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2644   bits<5> Rt;
2645   bits<5> Rn;
2646   bits<5> Rm;
2647   bits<2> extend;
2648   let Inst{31-30} = sz;
2649   let Inst{29-27} = 0b111;
2650   let Inst{26}    = V;
2651   let Inst{25-24} = 0b00;
2652   let Inst{23-22} = opc;
2653   let Inst{21}    = 1;
2654   let Inst{20-16} = Rm;
2655   let Inst{15}    = extend{1}; // sign extend Rm?
2656   let Inst{14}    = 1;
2657   let Inst{12}    = extend{0}; // do shift?
2658   let Inst{11-10} = 0b10;
2659   let Inst{9-5}   = Rn;
2660   let Inst{4-0}   = Rt;
2661 }
2662
2663 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2664                     string asm, ValueType Ty, SDPatternOperator loadop> {
2665   let AddedComplexity = 10 in
2666   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2667                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2668                  [(set (Ty regtype:$Rt),
2669                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2670                                               ro_Wextend32:$extend)))]>,
2671            Sched<[WriteLDIdx, ReadAdrBase]> {
2672     let Inst{13} = 0b0;
2673   }
2674
2675   let AddedComplexity = 10 in
2676   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2677                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2678                  [(set (Ty regtype:$Rt),
2679                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2680                                               ro_Xextend32:$extend)))]>,
2681            Sched<[WriteLDIdx, ReadAdrBase]> {
2682     let Inst{13} = 0b1;
2683   }
2684
2685   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2686 }
2687
2688 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2689                      string asm, ValueType Ty, SDPatternOperator storeop> {
2690   let AddedComplexity = 10 in
2691   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2692                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2693                 [(storeop (Ty regtype:$Rt),
2694                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2695                                          ro_Wextend32:$extend))]>,
2696             Sched<[WriteSTIdx, ReadAdrBase]> {
2697     let Inst{13} = 0b0;
2698   }
2699
2700   let AddedComplexity = 10 in
2701   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2702                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2703                 [(storeop (Ty regtype:$Rt),
2704                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2705                                         ro_Xextend32:$extend))]>,
2706             Sched<[WriteSTIdx, ReadAdrBase]> {
2707     let Inst{13} = 0b1;
2708   }
2709
2710   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2711 }
2712
2713 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2714                       string asm, dag ins, dag outs, list<dag> pat>
2715     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2716   bits<5> Rt;
2717   bits<5> Rn;
2718   bits<5> Rm;
2719   bits<2> extend;
2720   let Inst{31-30} = sz;
2721   let Inst{29-27} = 0b111;
2722   let Inst{26}    = V;
2723   let Inst{25-24} = 0b00;
2724   let Inst{23-22} = opc;
2725   let Inst{21}    = 1;
2726   let Inst{20-16} = Rm;
2727   let Inst{15}    = extend{1}; // sign extend Rm?
2728   let Inst{14}    = 1;
2729   let Inst{12}    = extend{0}; // do shift?
2730   let Inst{11-10} = 0b10;
2731   let Inst{9-5}   = Rn;
2732   let Inst{4-0}   = Rt;
2733 }
2734
2735 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2736                     string asm, ValueType Ty, SDPatternOperator loadop> {
2737   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2738   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2739                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2740                 [(set (Ty regtype:$Rt),
2741                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2742                                              ro_Wextend64:$extend)))]>,
2743            Sched<[WriteLDIdx, ReadAdrBase]> {
2744     let Inst{13} = 0b0;
2745   }
2746
2747   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2748   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2749                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2750                  [(set (Ty regtype:$Rt),
2751                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2752                                               ro_Xextend64:$extend)))]>,
2753            Sched<[WriteLDIdx, ReadAdrBase]> {
2754     let Inst{13} = 0b1;
2755   }
2756
2757   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2758 }
2759
2760 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2761                      string asm, ValueType Ty, SDPatternOperator storeop> {
2762   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2763   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2764                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2765                 [(storeop (Ty regtype:$Rt),
2766                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2767                                          ro_Wextend64:$extend))]>,
2768             Sched<[WriteSTIdx, ReadAdrBase]> {
2769     let Inst{13} = 0b0;
2770   }
2771
2772   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2773   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2774                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2775                 [(storeop (Ty regtype:$Rt),
2776                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2777                                          ro_Xextend64:$extend))]>,
2778             Sched<[WriteSTIdx, ReadAdrBase]> {
2779     let Inst{13} = 0b1;
2780   }
2781
2782   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2783 }
2784
2785 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2786                       string asm, dag ins, dag outs, list<dag> pat>
2787     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2788   bits<5> Rt;
2789   bits<5> Rn;
2790   bits<5> Rm;
2791   bits<2> extend;
2792   let Inst{31-30} = sz;
2793   let Inst{29-27} = 0b111;
2794   let Inst{26}    = V;
2795   let Inst{25-24} = 0b00;
2796   let Inst{23-22} = opc;
2797   let Inst{21}    = 1;
2798   let Inst{20-16} = Rm;
2799   let Inst{15}    = extend{1}; // sign extend Rm?
2800   let Inst{14}    = 1;
2801   let Inst{12}    = extend{0}; // do shift?
2802   let Inst{11-10} = 0b10;
2803   let Inst{9-5}   = Rn;
2804   let Inst{4-0}   = Rt;
2805 }
2806
2807 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2808                      string asm, ValueType Ty, SDPatternOperator loadop> {
2809   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2810   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2811                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2812                  [(set (Ty regtype:$Rt),
2813                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2814                                                ro_Wextend128:$extend)))]>,
2815             Sched<[WriteLDIdx, ReadAdrBase]> {
2816     let Inst{13} = 0b0;
2817   }
2818
2819   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2820   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2821                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2822                  [(set (Ty regtype:$Rt),
2823                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2824                                                ro_Xextend128:$extend)))]>,
2825             Sched<[WriteLDIdx, ReadAdrBase]> {
2826     let Inst{13} = 0b1;
2827   }
2828
2829   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2830 }
2831
2832 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2833                       string asm, ValueType Ty, SDPatternOperator storeop> {
2834   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2835   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2836                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2837                 [(storeop (Ty regtype:$Rt),
2838                           (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2839                                           ro_Wextend128:$extend))]>,
2840             Sched<[WriteSTIdx, ReadAdrBase]> {
2841     let Inst{13} = 0b0;
2842   }
2843
2844   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2845   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2846                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2847                 [(storeop (Ty regtype:$Rt),
2848                           (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2849                                           ro_Xextend128:$extend))]>,
2850             Sched<[WriteSTIdx, ReadAdrBase]> {
2851     let Inst{13} = 0b1;
2852   }
2853
2854   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2855 }
2856
2857 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2858 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2859                      string asm, list<dag> pat>
2860     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2861       Sched<[WriteLD]> {
2862   bits<5> Rt;
2863   bits<5> Rn;
2864   bits<5> Rm;
2865   bits<2> extend;
2866   let Inst{31-30} = sz;
2867   let Inst{29-27} = 0b111;
2868   let Inst{26}    = V;
2869   let Inst{25-24} = 0b00;
2870   let Inst{23-22} = opc;
2871   let Inst{21}    = 1;
2872   let Inst{20-16} = Rm;
2873   let Inst{15}    = extend{1}; // sign extend Rm?
2874   let Inst{14}    = 1;
2875   let Inst{12}    = extend{0}; // do shift?
2876   let Inst{11-10} = 0b10;
2877   let Inst{9-5}   = Rn;
2878   let Inst{4-0}   = Rt;
2879 }
2880
2881 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2882   def roW : BasePrefetchRO<sz, V, opc, (outs),
2883                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2884                 asm, [(AArch64Prefetch imm:$Rt,
2885                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2886                                                     ro_Wextend64:$extend))]> {
2887     let Inst{13} = 0b0;
2888   }
2889
2890   def roX : BasePrefetchRO<sz, V, opc, (outs),
2891                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2892                 asm,  [(AArch64Prefetch imm:$Rt,
2893                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2894                                                      ro_Xextend64:$extend))]> {
2895     let Inst{13} = 0b1;
2896   }
2897
2898   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2899                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2900                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2901 }
2902
2903 //---
2904 // Load/store unscaled immediate
2905 //---
2906
2907 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2908 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2909 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2910 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2911 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2912
2913 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2914                            string asm, list<dag> pattern>
2915     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2916   bits<5> Rt;
2917   bits<5> Rn;
2918   bits<9> offset;
2919   let Inst{31-30} = sz;
2920   let Inst{29-27} = 0b111;
2921   let Inst{26}    = V;
2922   let Inst{25-24} = 0b00;
2923   let Inst{23-22} = opc;
2924   let Inst{21}    = 0;
2925   let Inst{20-12} = offset;
2926   let Inst{11-10} = 0b00;
2927   let Inst{9-5}   = Rn;
2928   let Inst{4-0}   = Rt;
2929
2930   let DecoderMethod = "DecodeSignedLdStInstruction";
2931 }
2932
2933 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2934                    string asm, list<dag> pattern> {
2935   let AddedComplexity = 1 in // try this before LoadUI
2936   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2937                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
2938           Sched<[WriteLD]>;
2939
2940   def : InstAlias<asm # " $Rt, [$Rn]",
2941                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2942 }
2943
2944 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2945                          string asm, list<dag> pattern> {
2946   let AddedComplexity = 1 in // try this before StoreUI
2947   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
2948                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
2949                                asm, pattern>,
2950           Sched<[WriteST]>;
2951
2952   def : InstAlias<asm # " $Rt, [$Rn]",
2953                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2954 }
2955
2956 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
2957                             list<dag> pat> {
2958   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2959   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
2960                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
2961                                asm, pat>,
2962           Sched<[WriteLD]>;
2963
2964   def : InstAlias<asm # " $Rt, [$Rn]",
2965                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
2966 }
2967
2968 //---
2969 // Load/store unscaled immediate, unprivileged
2970 //---
2971
2972 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2973                                 dag oops, dag iops, string asm>
2974     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
2975   bits<5> Rt;
2976   bits<5> Rn;
2977   bits<9> offset;
2978   let Inst{31-30} = sz;
2979   let Inst{29-27} = 0b111;
2980   let Inst{26}    = V;
2981   let Inst{25-24} = 0b00;
2982   let Inst{23-22} = opc;
2983   let Inst{21}    = 0;
2984   let Inst{20-12} = offset;
2985   let Inst{11-10} = 0b10;
2986   let Inst{9-5}   = Rn;
2987   let Inst{4-0}   = Rt;
2988
2989   let DecoderMethod = "DecodeSignedLdStInstruction";
2990 }
2991
2992 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
2993                             RegisterClass regtype, string asm> {
2994   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
2995   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
2996                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
2997           Sched<[WriteLD]>;
2998
2999   def : InstAlias<asm # " $Rt, [$Rn]",
3000                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3001 }
3002
3003 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3004                              RegisterClass regtype, string asm> {
3005   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3006   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3007                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3008                                  asm>,
3009           Sched<[WriteST]>;
3010
3011   def : InstAlias<asm # " $Rt, [$Rn]",
3012                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3013 }
3014
3015 //---
3016 // Load/store pre-indexed
3017 //---
3018
3019 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3020                           string asm, string cstr, list<dag> pat>
3021     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3022   bits<5> Rt;
3023   bits<5> Rn;
3024   bits<9> offset;
3025   let Inst{31-30} = sz;
3026   let Inst{29-27} = 0b111;
3027   let Inst{26}    = V;
3028   let Inst{25-24} = 0;
3029   let Inst{23-22} = opc;
3030   let Inst{21}    = 0;
3031   let Inst{20-12} = offset;
3032   let Inst{11-10} = 0b11;
3033   let Inst{9-5}   = Rn;
3034   let Inst{4-0}   = Rt;
3035
3036   let DecoderMethod = "DecodeSignedLdStInstruction";
3037 }
3038
3039 let hasSideEffects = 0 in {
3040 let mayStore = 0, mayLoad = 1 in
3041 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3042              string asm>
3043     : BaseLoadStorePreIdx<sz, V, opc,
3044                      (outs GPR64sp:$wback, regtype:$Rt),
3045                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3046                      "$Rn = $wback,@earlyclobber $wback", []>,
3047       Sched<[WriteLD, WriteAdr]>;
3048
3049 let mayStore = 1, mayLoad = 0 in
3050 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3051                   string asm, SDPatternOperator storeop, ValueType Ty>
3052     : BaseLoadStorePreIdx<sz, V, opc,
3053                       (outs GPR64sp:$wback),
3054                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3055                       asm, "$Rn = $wback,@earlyclobber $wback",
3056       [(set GPR64sp:$wback,
3057             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3058       Sched<[WriteAdr, WriteST]>;
3059 } // hasSideEffects = 0
3060
3061 //---
3062 // Load/store post-indexed
3063 //---
3064
3065 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3066                           string asm, string cstr, list<dag> pat>
3067     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3068   bits<5> Rt;
3069   bits<5> Rn;
3070   bits<9> offset;
3071   let Inst{31-30} = sz;
3072   let Inst{29-27} = 0b111;
3073   let Inst{26}    = V;
3074   let Inst{25-24} = 0b00;
3075   let Inst{23-22} = opc;
3076   let Inst{21}    = 0b0;
3077   let Inst{20-12} = offset;
3078   let Inst{11-10} = 0b01;
3079   let Inst{9-5}   = Rn;
3080   let Inst{4-0}   = Rt;
3081
3082   let DecoderMethod = "DecodeSignedLdStInstruction";
3083 }
3084
3085 let hasSideEffects = 0 in {
3086 let mayStore = 0, mayLoad = 1 in
3087 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3088              string asm>
3089     : BaseLoadStorePostIdx<sz, V, opc,
3090                       (outs GPR64sp:$wback, regtype:$Rt),
3091                       (ins GPR64sp:$Rn, simm9:$offset),
3092                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3093       Sched<[WriteLD, WriteI]>;
3094
3095 let mayStore = 1, mayLoad = 0 in
3096 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3097                    string asm, SDPatternOperator storeop, ValueType Ty>
3098     : BaseLoadStorePostIdx<sz, V, opc,
3099                       (outs GPR64sp:$wback),
3100                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3101                        asm, "$Rn = $wback,@earlyclobber $wback",
3102       [(set GPR64sp:$wback,
3103             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3104     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3105 } // hasSideEffects = 0
3106
3107
3108 //---
3109 // Load/store pair
3110 //---
3111
3112 // (indexed, offset)
3113
3114 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3115                               string asm>
3116     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3117   bits<5> Rt;
3118   bits<5> Rt2;
3119   bits<5> Rn;
3120   bits<7> offset;
3121   let Inst{31-30} = opc;
3122   let Inst{29-27} = 0b101;
3123   let Inst{26}    = V;
3124   let Inst{25-23} = 0b010;
3125   let Inst{22}    = L;
3126   let Inst{21-15} = offset;
3127   let Inst{14-10} = Rt2;
3128   let Inst{9-5}   = Rn;
3129   let Inst{4-0}   = Rt;
3130
3131   let DecoderMethod = "DecodePairLdStInstruction";
3132 }
3133
3134 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3135                           Operand indextype, string asm> {
3136   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3137   def i : BaseLoadStorePairOffset<opc, V, 1,
3138                                   (outs regtype:$Rt, regtype:$Rt2),
3139                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3140           Sched<[WriteLD, WriteLDHi]>;
3141
3142   def : InstAlias<asm # " $Rt, $Rt2, [$Rn]",
3143                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3144                                                   GPR64sp:$Rn, 0)>;
3145 }
3146
3147
3148 multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3149                            Operand indextype, string asm> {
3150   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3151   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3152                                   (ins regtype:$Rt, regtype:$Rt2,
3153                                        GPR64sp:$Rn, indextype:$offset),
3154                                   asm>,
3155           Sched<[WriteSTP]>;
3156
3157   def : InstAlias<asm # " $Rt, $Rt2, [$Rn]",
3158                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3159                                                   GPR64sp:$Rn, 0)>;
3160 }
3161
3162 // (pre-indexed)
3163 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3164                               string asm>
3165     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3166   bits<5> Rt;
3167   bits<5> Rt2;
3168   bits<5> Rn;
3169   bits<7> offset;
3170   let Inst{31-30} = opc;
3171   let Inst{29-27} = 0b101;
3172   let Inst{26}    = V;
3173   let Inst{25-23} = 0b011;
3174   let Inst{22}    = L;
3175   let Inst{21-15} = offset;
3176   let Inst{14-10} = Rt2;
3177   let Inst{9-5}   = Rn;
3178   let Inst{4-0}   = Rt;
3179
3180   let DecoderMethod = "DecodePairLdStInstruction";
3181 }
3182
3183 let hasSideEffects = 0 in {
3184 let mayStore = 0, mayLoad = 1 in
3185 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3186                      Operand indextype, string asm>
3187     : BaseLoadStorePairPreIdx<opc, V, 1,
3188                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3189                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3190       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3191
3192 let mayStore = 1, mayLoad = 0 in
3193 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3194                       Operand indextype, string asm>
3195     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3196                              (ins regtype:$Rt, regtype:$Rt2,
3197                                   GPR64sp:$Rn, indextype:$offset),
3198                              asm>,
3199       Sched<[WriteAdr, WriteSTP]>;
3200 } // hasSideEffects = 0
3201
3202 // (post-indexed)
3203
3204 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3205                               string asm>
3206     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3207   bits<5> Rt;
3208   bits<5> Rt2;
3209   bits<5> Rn;
3210   bits<7> offset;
3211   let Inst{31-30} = opc;
3212   let Inst{29-27} = 0b101;
3213   let Inst{26}    = V;
3214   let Inst{25-23} = 0b001;
3215   let Inst{22}    = L;
3216   let Inst{21-15} = offset;
3217   let Inst{14-10} = Rt2;
3218   let Inst{9-5}   = Rn;
3219   let Inst{4-0}   = Rt;
3220
3221   let DecoderMethod = "DecodePairLdStInstruction";
3222 }
3223
3224 let hasSideEffects = 0 in {
3225 let mayStore = 0, mayLoad = 1 in
3226 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3227                       Operand idxtype, string asm>
3228     : BaseLoadStorePairPostIdx<opc, V, 1,
3229                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3230                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3231       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3232
3233 let mayStore = 1, mayLoad = 0 in
3234 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3235                        Operand idxtype, string asm>
3236     : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
3237                              (ins GPR64sp:$wback, regtype:$Rt, regtype:$Rt2,
3238                                   GPR64sp:$Rn, idxtype:$offset),
3239                              asm>,
3240       Sched<[WriteAdr, WriteSTP]>;
3241 } // hasSideEffects = 0
3242
3243 //  (no-allocate)
3244
3245 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3246                               string asm>
3247     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3248   bits<5> Rt;
3249   bits<5> Rt2;
3250   bits<5> Rn;
3251   bits<7> offset;
3252   let Inst{31-30} = opc;
3253   let Inst{29-27} = 0b101;
3254   let Inst{26}    = V;
3255   let Inst{25-23} = 0b000;
3256   let Inst{22}    = L;
3257   let Inst{21-15} = offset;
3258   let Inst{14-10} = Rt2;
3259   let Inst{9-5}   = Rn;
3260   let Inst{4-0}   = Rt;
3261
3262   let DecoderMethod = "DecodePairLdStInstruction";
3263 }
3264
3265 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3266                            Operand indextype, string asm> {
3267   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3268   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3269                                    (outs regtype:$Rt, regtype:$Rt2),
3270                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3271           Sched<[WriteLD, WriteLDHi]>;
3272
3273
3274   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3275                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3276                                                   GPR64sp:$Rn, 0)>;
3277 }
3278
3279 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3280                       Operand indextype, string asm> {
3281   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3282   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3283                                    (ins regtype:$Rt, regtype:$Rt2,
3284                                         GPR64sp:$Rn, indextype:$offset),
3285                                    asm>,
3286           Sched<[WriteSTP]>;
3287
3288   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3289                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3290                                                   GPR64sp:$Rn, 0)>;
3291 }
3292
3293 //---
3294 // Load/store exclusive
3295 //---
3296
3297 // True exclusive operations write to and/or read from the system's exclusive
3298 // monitors, which as far as a compiler is concerned can be modelled as a
3299 // random shared memory address. Hence LoadExclusive mayStore.
3300 //
3301 // Since these instructions have the undefined register bits set to 1 in
3302 // their canonical form, we need a post encoder method to set those bits
3303 // to 1 when encoding these instructions. We do this using the
3304 // fixLoadStoreExclusive function. This function has template parameters:
3305 //
3306 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3307 //
3308 // hasRs indicates that the instruction uses the Rs field, so we won't set
3309 // it to 1 (and the same for Rt2). We don't need template parameters for
3310 // the other register fields since Rt and Rn are always used.
3311 //
3312 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3313 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3314                              dag oops, dag iops, string asm, string operands>
3315     : I<oops, iops, asm, operands, "", []> {
3316   let Inst{31-30} = sz;
3317   let Inst{29-24} = 0b001000;
3318   let Inst{23}    = o2;
3319   let Inst{22}    = L;
3320   let Inst{21}    = o1;
3321   let Inst{15}    = o0;
3322
3323   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3324 }
3325
3326 // Neither Rs nor Rt2 operands.
3327 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3328                                dag oops, dag iops, string asm, string operands>
3329     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3330   bits<5> Rt;
3331   bits<5> Rn;
3332   let Inst{20-16} = 0b11111;
3333   let Unpredictable{20-16} = 0b11111;
3334   let Inst{14-10} = 0b11111;
3335   let Unpredictable{14-10} = 0b11111;
3336   let Inst{9-5} = Rn;
3337   let Inst{4-0} = Rt;
3338
3339   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3340 }
3341
3342 // Simple load acquires don't set the exclusive monitor
3343 let mayLoad = 1, mayStore = 0 in
3344 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3345                   RegisterClass regtype, string asm>
3346     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3347                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3348       Sched<[WriteLD]>;
3349
3350 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3351                     RegisterClass regtype, string asm>
3352     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3353                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3354       Sched<[WriteLD]>;
3355
3356 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3357                        RegisterClass regtype, string asm>
3358     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3359                              (outs regtype:$Rt, regtype:$Rt2),
3360                              (ins GPR64sp0:$Rn), asm,
3361                              "\t$Rt, $Rt2, [$Rn]">,
3362       Sched<[WriteLD, WriteLDHi]> {
3363   bits<5> Rt;
3364   bits<5> Rt2;
3365   bits<5> Rn;
3366   let Inst{14-10} = Rt2;
3367   let Inst{9-5} = Rn;
3368   let Inst{4-0} = Rt;
3369
3370   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3371 }
3372
3373 // Simple store release operations do not check the exclusive monitor.
3374 let mayLoad = 0, mayStore = 1 in
3375 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3376                    RegisterClass regtype, string asm>
3377     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3378                                (ins regtype:$Rt, GPR64sp0:$Rn),
3379                                asm, "\t$Rt, [$Rn]">,
3380       Sched<[WriteST]>;
3381
3382 let mayLoad = 1, mayStore = 1 in
3383 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3384                      RegisterClass regtype, string asm>
3385     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3386                              (ins regtype:$Rt, GPR64sp0:$Rn),
3387                              asm, "\t$Ws, $Rt, [$Rn]">,
3388       Sched<[WriteSTX]> {
3389   bits<5> Ws;
3390   bits<5> Rt;
3391   bits<5> Rn;
3392   let Inst{20-16} = Ws;
3393   let Inst{9-5} = Rn;
3394   let Inst{4-0} = Rt;
3395
3396   let Constraints = "@earlyclobber $Ws";
3397   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3398 }
3399
3400 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3401                          RegisterClass regtype, string asm>
3402     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3403                              (outs GPR32:$Ws),
3404                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3405                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3406       Sched<[WriteSTX]> {
3407   bits<5> Ws;
3408   bits<5> Rt;
3409   bits<5> Rt2;
3410   bits<5> Rn;
3411   let Inst{20-16} = Ws;
3412   let Inst{14-10} = Rt2;
3413   let Inst{9-5} = Rn;
3414   let Inst{4-0} = Rt;
3415
3416   let Constraints = "@earlyclobber $Ws";
3417 }
3418
3419 //---
3420 // Exception generation
3421 //---
3422
3423 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3424 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3425     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3426       Sched<[WriteSys]> {
3427   bits<16> imm;
3428   let Inst{31-24} = 0b11010100;
3429   let Inst{23-21} = op1;
3430   let Inst{20-5}  = imm;
3431   let Inst{4-2}   = 0b000;
3432   let Inst{1-0}   = ll;
3433 }
3434
3435 let Predicates = [HasFPARMv8] in {
3436
3437 //---
3438 // Floating point to integer conversion
3439 //---
3440
3441 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3442                       RegisterClass srcType, RegisterClass dstType,
3443                       string asm, list<dag> pattern>
3444     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3445          asm, "\t$Rd, $Rn", "", pattern>,
3446       Sched<[WriteFCvt]> {
3447   bits<5> Rd;
3448   bits<5> Rn;
3449   let Inst{30-29} = 0b00;
3450   let Inst{28-24} = 0b11110;
3451   let Inst{23-22} = type;
3452   let Inst{21}    = 1;
3453   let Inst{20-19} = rmode;
3454   let Inst{18-16} = opcode;
3455   let Inst{15-10} = 0;
3456   let Inst{9-5}   = Rn;
3457   let Inst{4-0}   = Rd;
3458 }
3459
3460 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3461 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3462                       RegisterClass srcType, RegisterClass dstType,
3463                       Operand immType, string asm, list<dag> pattern>
3464     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3465          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3466       Sched<[WriteFCvt]> {
3467   bits<5> Rd;
3468   bits<5> Rn;
3469   bits<6> scale;
3470   let Inst{30-29} = 0b00;
3471   let Inst{28-24} = 0b11110;
3472   let Inst{23-22} = type;
3473   let Inst{21}    = 0;
3474   let Inst{20-19} = rmode;
3475   let Inst{18-16} = opcode;
3476   let Inst{15-10} = scale;
3477   let Inst{9-5}   = Rn;
3478   let Inst{4-0}   = Rd;
3479 }
3480
3481 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3482            SDPatternOperator OpN> {
3483   // Unscaled single-precision to 32-bit
3484   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3485                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3486     let Inst{31} = 0; // 32-bit GPR flag
3487   }
3488
3489   // Unscaled single-precision to 64-bit
3490   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3491                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3492     let Inst{31} = 1; // 64-bit GPR flag
3493   }
3494
3495   // Unscaled double-precision to 32-bit
3496   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3497                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3498     let Inst{31} = 0; // 32-bit GPR flag
3499   }
3500
3501   // Unscaled double-precision to 64-bit
3502   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3503                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3504     let Inst{31} = 1; // 64-bit GPR flag
3505   }
3506 }
3507
3508 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3509                              SDPatternOperator OpN> {
3510   // Scaled single-precision to 32-bit
3511   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3512                               fixedpoint_f32_i32, asm,
3513               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3514                                           fixedpoint_f32_i32:$scale)))]> {
3515     let Inst{31} = 0; // 32-bit GPR flag
3516     let scale{5} = 1;
3517   }
3518
3519   // Scaled single-precision to 64-bit
3520   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3521                               fixedpoint_f32_i64, asm,
3522               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3523                                           fixedpoint_f32_i64:$scale)))]> {
3524     let Inst{31} = 1; // 64-bit GPR flag
3525   }
3526
3527   // Scaled double-precision to 32-bit
3528   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3529                               fixedpoint_f64_i32, asm,
3530               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3531                                           fixedpoint_f64_i32:$scale)))]> {
3532     let Inst{31} = 0; // 32-bit GPR flag
3533     let scale{5} = 1;
3534   }
3535
3536   // Scaled double-precision to 64-bit
3537   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3538                               fixedpoint_f64_i64, asm,
3539               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3540                                           fixedpoint_f64_i64:$scale)))]> {
3541     let Inst{31} = 1; // 64-bit GPR flag
3542   }
3543 }
3544
3545 //---
3546 // Integer to floating point conversion
3547 //---
3548
3549 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3550 class BaseIntegerToFP<bit isUnsigned,
3551                       RegisterClass srcType, RegisterClass dstType,
3552                       Operand immType, string asm, list<dag> pattern>
3553     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3554          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3555       Sched<[WriteFCvt]> {
3556   bits<5> Rd;
3557   bits<5> Rn;
3558   bits<6> scale;
3559   let Inst{30-23} = 0b00111100;
3560   let Inst{21-17} = 0b00001;
3561   let Inst{16}    = isUnsigned;
3562   let Inst{15-10} = scale;
3563   let Inst{9-5}   = Rn;
3564   let Inst{4-0}   = Rd;
3565 }
3566
3567 class BaseIntegerToFPUnscaled<bit isUnsigned,
3568                       RegisterClass srcType, RegisterClass dstType,
3569                       ValueType dvt, string asm, SDNode node>
3570     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3571          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3572       Sched<[WriteFCvt]> {
3573   bits<5> Rd;
3574   bits<5> Rn;
3575   bits<6> scale;
3576   let Inst{30-23} = 0b00111100;
3577   let Inst{21-17} = 0b10001;
3578   let Inst{16}    = isUnsigned;
3579   let Inst{15-10} = 0b000000;
3580   let Inst{9-5}   = Rn;
3581   let Inst{4-0}   = Rd;
3582 }
3583
3584 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3585   // Unscaled
3586   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3587     let Inst{31} = 0; // 32-bit GPR flag
3588     let Inst{22} = 0; // 32-bit FPR flag
3589   }
3590
3591   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3592     let Inst{31} = 0; // 32-bit GPR flag
3593     let Inst{22} = 1; // 64-bit FPR flag
3594   }
3595
3596   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3597     let Inst{31} = 1; // 64-bit GPR flag
3598     let Inst{22} = 0; // 32-bit FPR flag
3599   }
3600
3601   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3602     let Inst{31} = 1; // 64-bit GPR flag
3603     let Inst{22} = 1; // 64-bit FPR flag
3604   }
3605
3606   // Scaled
3607   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3608                              [(set FPR32:$Rd,
3609                                    (fdiv (node GPR32:$Rn),
3610                                          fixedpoint_f32_i32:$scale))]> {
3611     let Inst{31} = 0; // 32-bit GPR flag
3612     let Inst{22} = 0; // 32-bit FPR flag
3613     let scale{5} = 1;
3614   }
3615
3616   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3617                              [(set FPR64:$Rd,
3618                                    (fdiv (node GPR32:$Rn),
3619                                          fixedpoint_f64_i32:$scale))]> {
3620     let Inst{31} = 0; // 32-bit GPR flag
3621     let Inst{22} = 1; // 64-bit FPR flag
3622     let scale{5} = 1;
3623   }
3624
3625   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3626                              [(set FPR32:$Rd,
3627                                    (fdiv (node GPR64:$Rn),
3628                                          fixedpoint_f32_i64:$scale))]> {
3629     let Inst{31} = 1; // 64-bit GPR flag
3630     let Inst{22} = 0; // 32-bit FPR flag
3631   }
3632
3633   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3634                              [(set FPR64:$Rd,
3635                                    (fdiv (node GPR64:$Rn),
3636                                          fixedpoint_f64_i64:$scale))]> {
3637     let Inst{31} = 1; // 64-bit GPR flag
3638     let Inst{22} = 1; // 64-bit FPR flag
3639   }
3640 }
3641
3642 //---
3643 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3644 //---
3645
3646 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3647 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3648                       RegisterClass srcType, RegisterClass dstType,
3649                       string asm>
3650     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3651         // We use COPY_TO_REGCLASS for these bitconvert operations.
3652         // copyPhysReg() expands the resultant COPY instructions after
3653         // regalloc is done. This gives greater freedom for the allocator
3654         // and related passes (coalescing, copy propagation, et. al.) to
3655         // be more effective.
3656         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3657       Sched<[WriteFCopy]> {
3658   bits<5> Rd;
3659   bits<5> Rn;
3660   let Inst{30-23} = 0b00111100;
3661   let Inst{21}    = 1;
3662   let Inst{20-19} = rmode;
3663   let Inst{18-16} = opcode;
3664   let Inst{15-10} = 0b000000;
3665   let Inst{9-5}   = Rn;
3666   let Inst{4-0}   = Rd;
3667 }
3668
3669 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3670 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3671                      RegisterClass srcType, RegisterOperand dstType, string asm,
3672                      string kind>
3673     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3674         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3675       Sched<[WriteFCopy]> {
3676   bits<5> Rd;
3677   bits<5> Rn;
3678   let Inst{30-23} = 0b00111101;
3679   let Inst{21}    = 1;
3680   let Inst{20-19} = rmode;
3681   let Inst{18-16} = opcode;
3682   let Inst{15-10} = 0b000000;
3683   let Inst{9-5}   = Rn;
3684   let Inst{4-0}   = Rd;
3685
3686   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3687 }
3688
3689 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3690 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3691                      RegisterOperand srcType, RegisterClass dstType, string asm,
3692                      string kind>
3693     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3694         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3695       Sched<[WriteFCopy]> {
3696   bits<5> Rd;
3697   bits<5> Rn;
3698   let Inst{30-23} = 0b00111101;
3699   let Inst{21}    = 1;
3700   let Inst{20-19} = rmode;
3701   let Inst{18-16} = opcode;
3702   let Inst{15-10} = 0b000000;
3703   let Inst{9-5}   = Rn;
3704   let Inst{4-0}   = Rd;
3705
3706   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3707 }
3708
3709
3710
3711 multiclass UnscaledConversion<string asm> {
3712   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3713     let Inst{31} = 0; // 32-bit GPR flag
3714     let Inst{22} = 0; // 32-bit FPR flag
3715   }
3716
3717   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3718     let Inst{31} = 1; // 64-bit GPR flag
3719     let Inst{22} = 1; // 64-bit FPR flag
3720   }
3721
3722   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3723     let Inst{31} = 0; // 32-bit GPR flag
3724     let Inst{22} = 0; // 32-bit FPR flag
3725   }
3726
3727   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3728     let Inst{31} = 1; // 64-bit GPR flag
3729     let Inst{22} = 1; // 64-bit FPR flag
3730   }
3731
3732   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3733                                              asm, ".d"> {
3734     let Inst{31} = 1;
3735     let Inst{22} = 0;
3736   }
3737
3738   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3739                                                asm, ".d"> {
3740     let Inst{31} = 1;
3741     let Inst{22} = 0;
3742   }
3743 }
3744
3745 //---
3746 // Floating point conversion
3747 //---
3748
3749 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3750                        RegisterClass srcType, string asm, list<dag> pattern>
3751     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3752       Sched<[WriteFCvt]> {
3753   bits<5> Rd;
3754   bits<5> Rn;
3755   let Inst{31-24} = 0b00011110;
3756   let Inst{23-22} = type;
3757   let Inst{21-17} = 0b10001;
3758   let Inst{16-15} = opcode;
3759   let Inst{14-10} = 0b10000;
3760   let Inst{9-5}   = Rn;
3761   let Inst{4-0}   = Rd;
3762 }
3763
3764 multiclass FPConversion<string asm> {
3765   // Double-precision to Half-precision
3766   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3767                              [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3768
3769   // Double-precision to Single-precision
3770   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3771                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3772
3773   // Half-precision to Double-precision
3774   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3775                              [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3776
3777   // Half-precision to Single-precision
3778   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3779                              [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3780
3781   // Single-precision to Double-precision
3782   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3783                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3784
3785   // Single-precision to Half-precision
3786   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3787                              [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3788 }
3789
3790 //---
3791 // Single operand floating point data processing
3792 //---
3793
3794 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3795 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3796                               ValueType vt, string asm, SDPatternOperator node>
3797     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3798          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3799       Sched<[WriteF]> {
3800   bits<5> Rd;
3801   bits<5> Rn;
3802   let Inst{31-23} = 0b000111100;
3803   let Inst{21-19} = 0b100;
3804   let Inst{18-15} = opcode;
3805   let Inst{14-10} = 0b10000;
3806   let Inst{9-5}   = Rn;
3807   let Inst{4-0}   = Rd;
3808 }
3809
3810 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3811                                SDPatternOperator node = null_frag> {
3812   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3813     let Inst{22} = 0; // 32-bit size flag
3814   }
3815
3816   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3817     let Inst{22} = 1; // 64-bit size flag
3818   }
3819 }
3820
3821 //---
3822 // Two operand floating point data processing
3823 //---
3824
3825 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3826 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3827                            string asm, list<dag> pat>
3828     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3829          asm, "\t$Rd, $Rn, $Rm", "", pat>,
3830       Sched<[WriteF]> {
3831   bits<5> Rd;
3832   bits<5> Rn;
3833   bits<5> Rm;
3834   let Inst{31-23} = 0b000111100;
3835   let Inst{21}    = 1;
3836   let Inst{20-16} = Rm;
3837   let Inst{15-12} = opcode;
3838   let Inst{11-10} = 0b10;
3839   let Inst{9-5}   = Rn;
3840   let Inst{4-0}   = Rd;
3841 }
3842
3843 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3844                             SDPatternOperator node = null_frag> {
3845   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3846                          [(set (f32 FPR32:$Rd),
3847                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3848     let Inst{22} = 0; // 32-bit size flag
3849   }
3850
3851   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3852                          [(set (f64 FPR64:$Rd),
3853                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3854     let Inst{22} = 1; // 64-bit size flag
3855   }
3856 }
3857
3858 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3859   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3860                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3861     let Inst{22} = 0; // 32-bit size flag
3862   }
3863
3864   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3865                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3866     let Inst{22} = 1; // 64-bit size flag
3867   }
3868 }
3869
3870
3871 //---
3872 // Three operand floating point data processing
3873 //---
3874
3875 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3876                              RegisterClass regtype, string asm, list<dag> pat>
3877     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3878          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3879       Sched<[WriteFMul]> {
3880   bits<5> Rd;
3881   bits<5> Rn;
3882   bits<5> Rm;
3883   bits<5> Ra;
3884   let Inst{31-23} = 0b000111110;
3885   let Inst{21}    = isNegated;
3886   let Inst{20-16} = Rm;
3887   let Inst{15}    = isSub;
3888   let Inst{14-10} = Ra;
3889   let Inst{9-5}   = Rn;
3890   let Inst{4-0}   = Rd;
3891 }
3892
3893 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3894                               SDPatternOperator node> {
3895   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3896             [(set FPR32:$Rd,
3897                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3898     let Inst{22} = 0; // 32-bit size flag
3899   }
3900
3901   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3902             [(set FPR64:$Rd,
3903                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3904     let Inst{22} = 1; // 64-bit size flag
3905   }
3906 }
3907
3908 //---
3909 // Floating point data comparisons
3910 //---
3911
3912 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3913 class BaseOneOperandFPComparison<bit signalAllNans,
3914                                  RegisterClass regtype, string asm,
3915                                  list<dag> pat>
3916     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3917       Sched<[WriteFCmp]> {
3918   bits<5> Rn;
3919   let Inst{31-23} = 0b000111100;
3920   let Inst{21}    = 1;
3921
3922   let Inst{15-10} = 0b001000;
3923   let Inst{9-5}   = Rn;
3924   let Inst{4}     = signalAllNans;
3925   let Inst{3-0}   = 0b1000;
3926
3927   // Rm should be 0b00000 canonically, but we need to accept any value.
3928   let PostEncoderMethod = "fixOneOperandFPComparison";
3929 }
3930
3931 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3932 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3933                                 string asm, list<dag> pat>
3934     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3935       Sched<[WriteFCmp]> {
3936   bits<5> Rm;
3937   bits<5> Rn;
3938   let Inst{31-23} = 0b000111100;
3939   let Inst{21}    = 1;
3940   let Inst{20-16} = Rm;
3941   let Inst{15-10} = 0b001000;
3942   let Inst{9-5}   = Rn;
3943   let Inst{4}     = signalAllNans;
3944   let Inst{3-0}   = 0b0000;
3945 }
3946
3947 multiclass FPComparison<bit signalAllNans, string asm,
3948                         SDPatternOperator OpNode = null_frag> {
3949   let Defs = [NZCV] in {
3950   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3951       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
3952     let Inst{22} = 0;
3953   }
3954
3955   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3956       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
3957     let Inst{22} = 0;
3958   }
3959
3960   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3961       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
3962     let Inst{22} = 1;
3963   }
3964
3965   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3966       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
3967     let Inst{22} = 1;
3968   }
3969   } // Defs = [NZCV]
3970 }
3971
3972 //---
3973 // Floating point conditional comparisons
3974 //---
3975
3976 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3977 class BaseFPCondComparison<bit signalAllNans,
3978                               RegisterClass regtype, string asm>
3979     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3980          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3981       Sched<[WriteFCmp]> {
3982   bits<5> Rn;
3983   bits<5> Rm;
3984   bits<4> nzcv;
3985   bits<4> cond;
3986
3987   let Inst{31-23} = 0b000111100;
3988   let Inst{21}    = 1;
3989   let Inst{20-16} = Rm;
3990   let Inst{15-12} = cond;
3991   let Inst{11-10} = 0b01;
3992   let Inst{9-5}   = Rn;
3993   let Inst{4}     = signalAllNans;
3994   let Inst{3-0}   = nzcv;
3995 }
3996
3997 multiclass FPCondComparison<bit signalAllNans, string asm> {
3998   let Defs = [NZCV], Uses = [NZCV] in {
3999   def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
4000     let Inst{22} = 0;
4001   }
4002
4003   def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
4004     let Inst{22} = 1;
4005   }
4006   } // Defs = [NZCV], Uses = [NZCV]
4007 }
4008
4009 //---
4010 // Floating point conditional select
4011 //---
4012
4013 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4014     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4015          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4016          [(set regtype:$Rd,
4017                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4018                           (i32 imm:$cond), NZCV))]>,
4019       Sched<[WriteF]> {
4020   bits<5> Rd;
4021   bits<5> Rn;
4022   bits<5> Rm;
4023   bits<4> cond;
4024
4025   let Inst{31-23} = 0b000111100;
4026   let Inst{21}    = 1;
4027   let Inst{20-16} = Rm;
4028   let Inst{15-12} = cond;
4029   let Inst{11-10} = 0b11;
4030   let Inst{9-5}   = Rn;
4031   let Inst{4-0}   = Rd;
4032 }
4033
4034 multiclass FPCondSelect<string asm> {
4035   let Uses = [NZCV] in {
4036   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4037     let Inst{22} = 0;
4038   }
4039
4040   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4041     let Inst{22} = 1;
4042   }
4043   } // Uses = [NZCV]
4044 }
4045
4046 //---
4047 // Floating move immediate
4048 //---
4049
4050 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4051   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4052       [(set regtype:$Rd, fpimmtype:$imm)]>,
4053     Sched<[WriteFImm]> {
4054   bits<5> Rd;
4055   bits<8> imm;
4056   let Inst{31-23} = 0b000111100;
4057   let Inst{21}    = 1;
4058   let Inst{20-13} = imm;
4059   let Inst{12-5}  = 0b10000000;
4060   let Inst{4-0}   = Rd;
4061 }
4062
4063 multiclass FPMoveImmediate<string asm> {
4064   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4065     let Inst{22} = 0;
4066   }
4067
4068   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4069     let Inst{22} = 1;
4070   }
4071 }
4072 } // end of 'let Predicates = [HasFPARMv8]'
4073
4074 //----------------------------------------------------------------------------
4075 // AdvSIMD
4076 //----------------------------------------------------------------------------
4077
4078 let Predicates = [HasNEON] in {
4079
4080 //----------------------------------------------------------------------------
4081 // AdvSIMD three register vector instructions
4082 //----------------------------------------------------------------------------
4083
4084 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4085 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4086                         RegisterOperand regtype, string asm, string kind,
4087                         list<dag> pattern>
4088   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4089       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4090       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4091     Sched<[WriteV]> {
4092   bits<5> Rd;
4093   bits<5> Rn;
4094   bits<5> Rm;
4095   let Inst{31}    = 0;
4096   let Inst{30}    = Q;
4097   let Inst{29}    = U;
4098   let Inst{28-24} = 0b01110;
4099   let Inst{23-22} = size;
4100   let Inst{21}    = 1;
4101   let Inst{20-16} = Rm;
4102   let Inst{15-11} = opcode;
4103   let Inst{10}    = 1;
4104   let Inst{9-5}   = Rn;
4105   let Inst{4-0}   = Rd;
4106 }
4107
4108 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4109 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4110                         RegisterOperand regtype, string asm, string kind,
4111                         list<dag> pattern>
4112   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4113       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4114       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4115     Sched<[WriteV]> {
4116   bits<5> Rd;
4117   bits<5> Rn;
4118   bits<5> Rm;
4119   let Inst{31}    = 0;
4120   let Inst{30}    = Q;
4121   let Inst{29}    = U;
4122   let Inst{28-24} = 0b01110;
4123   let Inst{23-22} = size;
4124   let Inst{21}    = 1;
4125   let Inst{20-16} = Rm;
4126   let Inst{15-11} = opcode;
4127   let Inst{10}    = 1;
4128   let Inst{9-5}   = Rn;
4129   let Inst{4-0}   = Rd;
4130 }
4131
4132 // All operand sizes distinguished in the encoding.
4133 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4134                                SDPatternOperator OpNode> {
4135   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4136                                       asm, ".8b",
4137          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4138   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4139                                       asm, ".16b",
4140          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4141   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4142                                       asm, ".4h",
4143          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4144   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4145                                       asm, ".8h",
4146          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4147   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4148                                       asm, ".2s",
4149          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4150   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4151                                       asm, ".4s",
4152          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4153   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
4154                                       asm, ".2d",
4155          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4156 }
4157
4158 // As above, but D sized elements unsupported.
4159 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4160                                   SDPatternOperator OpNode> {
4161   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4162                                       asm, ".8b",
4163         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4164   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4165                                       asm, ".16b",
4166         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4167   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4168                                       asm, ".4h",
4169         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4170   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4171                                       asm, ".8h",
4172         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4173   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4174                                       asm, ".2s",
4175         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4176   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4177                                       asm, ".4s",
4178         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4179 }
4180
4181 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4182                                   SDPatternOperator OpNode> {
4183   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
4184                                       asm, ".8b",
4185       [(set (v8i8 V64:$dst),
4186             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4187   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
4188                                       asm, ".16b",
4189       [(set (v16i8 V128:$dst),
4190             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4191   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
4192                                       asm, ".4h",
4193       [(set (v4i16 V64:$dst),
4194             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4195   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
4196                                       asm, ".8h",
4197       [(set (v8i16 V128:$dst),
4198             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4199   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
4200                                       asm, ".2s",
4201       [(set (v2i32 V64:$dst),
4202             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4203   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
4204                                       asm, ".4s",
4205       [(set (v4i32 V128:$dst),
4206             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4207 }
4208
4209 // As above, but only B sized elements supported.
4210 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4211                                 SDPatternOperator OpNode> {
4212   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4213                                       asm, ".8b",
4214     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4215   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4216                                       asm, ".16b",
4217     [(set (v16i8 V128:$Rd),
4218           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4219 }
4220
4221 // As above, but only S and D sized floating point elements supported.
4222 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
4223                                  string asm, SDPatternOperator OpNode> {
4224   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4225                                       asm, ".2s",
4226         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4227   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4228                                       asm, ".4s",
4229         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4230   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4231                                       asm, ".2d",
4232         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4233 }
4234
4235 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
4236                                     string asm,
4237                                     SDPatternOperator OpNode> {
4238   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4239                                       asm, ".2s",
4240         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4241   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4242                                       asm, ".4s",
4243         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4244   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4245                                       asm, ".2d",
4246         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4247 }
4248
4249 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
4250                                  string asm, SDPatternOperator OpNode> {
4251   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
4252                                       asm, ".2s",
4253      [(set (v2f32 V64:$dst),
4254            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4255   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
4256                                       asm, ".4s",
4257      [(set (v4f32 V128:$dst),
4258            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4259   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
4260                                       asm, ".2d",
4261      [(set (v2f64 V128:$dst),
4262            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4263 }
4264
4265 // As above, but D and B sized elements unsupported.
4266 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4267                                 SDPatternOperator OpNode> {
4268   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4269                                       asm, ".4h",
4270         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4271   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4272                                       asm, ".8h",
4273         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4274   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4275                                       asm, ".2s",
4276         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4277   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4278                                       asm, ".4s",
4279         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4280 }
4281
4282 // Logical three vector ops share opcode bits, and only use B sized elements.
4283 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4284                                   SDPatternOperator OpNode = null_frag> {
4285   def v8i8  : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4286                                      asm, ".8b",
4287                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4288   def v16i8  : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4289                                      asm, ".16b",
4290                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4291
4292   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4293           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4294   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4295           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4296   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4297           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4298
4299   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4300       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4301   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4302       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4303   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4304       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4305 }
4306
4307 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4308                                   string asm, SDPatternOperator OpNode> {
4309   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4310                                      asm, ".8b",
4311              [(set (v8i8 V64:$dst),
4312                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4313   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4314                                      asm, ".16b",
4315              [(set (v16i8 V128:$dst),
4316                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4317                            (v16i8 V128:$Rm)))]>;
4318
4319   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4320                            (v4i16 V64:$RHS))),
4321           (!cast<Instruction>(NAME#"v8i8")
4322             V64:$LHS, V64:$MHS, V64:$RHS)>;
4323   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4324                            (v2i32 V64:$RHS))),
4325           (!cast<Instruction>(NAME#"v8i8")
4326             V64:$LHS, V64:$MHS, V64:$RHS)>;
4327   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4328                            (v1i64 V64:$RHS))),
4329           (!cast<Instruction>(NAME#"v8i8")
4330             V64:$LHS, V64:$MHS, V64:$RHS)>;
4331
4332   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4333                            (v8i16 V128:$RHS))),
4334       (!cast<Instruction>(NAME#"v16i8")
4335         V128:$LHS, V128:$MHS, V128:$RHS)>;
4336   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4337                            (v4i32 V128:$RHS))),
4338       (!cast<Instruction>(NAME#"v16i8")
4339         V128:$LHS, V128:$MHS, V128:$RHS)>;
4340   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4341                            (v2i64 V128:$RHS))),
4342       (!cast<Instruction>(NAME#"v16i8")
4343         V128:$LHS, V128:$MHS, V128:$RHS)>;
4344 }
4345
4346
4347 //----------------------------------------------------------------------------
4348 // AdvSIMD two register vector instructions.
4349 //----------------------------------------------------------------------------
4350
4351 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4352 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4353                         RegisterOperand regtype, string asm, string dstkind,
4354                         string srckind, list<dag> pattern>
4355   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4356       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4357       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4358     Sched<[WriteV]> {
4359   bits<5> Rd;
4360   bits<5> Rn;
4361   let Inst{31}    = 0;
4362   let Inst{30}    = Q;
4363   let Inst{29}    = U;
4364   let Inst{28-24} = 0b01110;
4365   let Inst{23-22} = size;
4366   let Inst{21-17} = 0b10000;
4367   let Inst{16-12} = opcode;
4368   let Inst{11-10} = 0b10;
4369   let Inst{9-5}   = Rn;
4370   let Inst{4-0}   = Rd;
4371 }
4372
4373 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4374 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4375                             RegisterOperand regtype, string asm, string dstkind,
4376                             string srckind, list<dag> pattern>
4377   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4378       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4379       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4380     Sched<[WriteV]> {
4381   bits<5> Rd;
4382   bits<5> Rn;
4383   let Inst{31}    = 0;
4384   let Inst{30}    = Q;
4385   let Inst{29}    = U;
4386   let Inst{28-24} = 0b01110;
4387   let Inst{23-22} = size;
4388   let Inst{21-17} = 0b10000;
4389   let Inst{16-12} = opcode;
4390   let Inst{11-10} = 0b10;
4391   let Inst{9-5}   = Rn;
4392   let Inst{4-0}   = Rd;
4393 }
4394
4395 // Supports B, H, and S element sizes.
4396 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4397                             SDPatternOperator OpNode> {
4398   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4399                                       asm, ".8b", ".8b",
4400                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4401   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4402                                       asm, ".16b", ".16b",
4403                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4404   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4405                                       asm, ".4h", ".4h",
4406                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4407   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4408                                       asm, ".8h", ".8h",
4409                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4410   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4411                                       asm, ".2s", ".2s",
4412                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4413   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4414                                       asm, ".4s", ".4s",
4415                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4416 }
4417
4418 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4419                             RegisterOperand regtype, string asm, string dstkind,
4420                             string srckind, string amount>
4421   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4422       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4423       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4424     Sched<[WriteV]> {
4425   bits<5> Rd;
4426   bits<5> Rn;
4427   let Inst{31}    = 0;
4428   let Inst{30}    = Q;
4429   let Inst{29-24} = 0b101110;
4430   let Inst{23-22} = size;
4431   let Inst{21-10} = 0b100001001110;
4432   let Inst{9-5}   = Rn;
4433   let Inst{4-0}   = Rd;
4434 }
4435
4436 multiclass SIMDVectorLShiftLongBySizeBHS {
4437   let hasSideEffects = 0 in {
4438   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4439                                              "shll", ".8h",  ".8b", "8">;
4440   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4441                                              "shll2", ".8h", ".16b", "8">;
4442   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4443                                              "shll", ".4s",  ".4h", "16">;
4444   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4445                                              "shll2", ".4s", ".8h", "16">;
4446   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4447                                              "shll", ".2d",  ".2s", "32">;
4448   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4449                                              "shll2", ".2d", ".4s", "32">;
4450   }
4451 }
4452
4453 // Supports all element sizes.
4454 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4455                              SDPatternOperator OpNode> {
4456   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4457                                       asm, ".4h", ".8b",
4458                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4459   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4460                                       asm, ".8h", ".16b",
4461                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4462   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4463                                       asm, ".2s", ".4h",
4464                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4465   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4466                                       asm, ".4s", ".8h",
4467                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4468   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4469                                       asm, ".1d", ".2s",
4470                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4471   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4472                                       asm, ".2d", ".4s",
4473                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4474 }
4475
4476 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4477                                  SDPatternOperator OpNode> {
4478   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4479                                           asm, ".4h", ".8b",
4480       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4481                                       (v8i8 V64:$Rn)))]>;
4482   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4483                                           asm, ".8h", ".16b",
4484       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4485                                       (v16i8 V128:$Rn)))]>;
4486   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4487                                           asm, ".2s", ".4h",
4488       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4489                                       (v4i16 V64:$Rn)))]>;
4490   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4491                                           asm, ".4s", ".8h",
4492       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4493                                       (v8i16 V128:$Rn)))]>;
4494   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4495                                           asm, ".1d", ".2s",
4496       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4497                                       (v2i32 V64:$Rn)))]>;
4498   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4499                                           asm, ".2d", ".4s",
4500       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4501                                       (v4i32 V128:$Rn)))]>;
4502 }
4503
4504 // Supports all element sizes, except 1xD.
4505 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4506                                   SDPatternOperator OpNode> {
4507   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4508                                     asm, ".8b", ".8b",
4509     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4510   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4511                                     asm, ".16b", ".16b",
4512     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4513   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4514                                     asm, ".4h", ".4h",
4515     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4516   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4517                                     asm, ".8h", ".8h",
4518     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4519   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4520                                     asm, ".2s", ".2s",
4521     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4522   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4523                                     asm, ".4s", ".4s",
4524     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4525   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4526                                     asm, ".2d", ".2d",
4527     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4528 }
4529
4530 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4531                              SDPatternOperator OpNode = null_frag> {
4532   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4533                                 asm, ".8b", ".8b",
4534     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4535   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4536                                 asm, ".16b", ".16b",
4537     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4538   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4539                                 asm, ".4h", ".4h",
4540     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4541   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4542                                 asm, ".8h", ".8h",
4543     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4544   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4545                                 asm, ".2s", ".2s",
4546     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4547   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4548                                 asm, ".4s", ".4s",
4549     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4550   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4551                                 asm, ".2d", ".2d",
4552     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4553 }
4554
4555
4556 // Supports only B element sizes.
4557 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4558                           SDPatternOperator OpNode> {
4559   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4560                                 asm, ".8b", ".8b",
4561                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4562   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4563                                 asm, ".16b", ".16b",
4564                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4565
4566 }
4567
4568 // Supports only B and H element sizes.
4569 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4570                                 SDPatternOperator OpNode> {
4571   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4572                                 asm, ".8b", ".8b",
4573                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4574   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4575                                 asm, ".16b", ".16b",
4576                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4577   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4578                                 asm, ".4h", ".4h",
4579                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4580   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4581                                 asm, ".8h", ".8h",
4582                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4583 }
4584
4585 // Supports only S and D element sizes, uses high bit of the size field
4586 // as an extra opcode bit.
4587 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4588                            SDPatternOperator OpNode> {
4589   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4590                                 asm, ".2s", ".2s",
4591                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4592   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4593                                 asm, ".4s", ".4s",
4594                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4595   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4596                                 asm, ".2d", ".2d",
4597                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4598 }
4599
4600 // Supports only S element size.
4601 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4602                            SDPatternOperator OpNode> {
4603   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4604                                 asm, ".2s", ".2s",
4605                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4606   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4607                                 asm, ".4s", ".4s",
4608                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4609 }
4610
4611
4612 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4613                            SDPatternOperator OpNode> {
4614   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4615                                 asm, ".2s", ".2s",
4616                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4617   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4618                                 asm, ".4s", ".4s",
4619                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4620   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4621                                 asm, ".2d", ".2d",
4622                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4623 }
4624
4625 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4626                            SDPatternOperator OpNode> {
4627   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4628                                 asm, ".2s", ".2s",
4629                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4630   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4631                                 asm, ".4s", ".4s",
4632                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4633   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4634                                 asm, ".2d", ".2d",
4635                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4636 }
4637
4638
4639 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4640                            RegisterOperand inreg, RegisterOperand outreg,
4641                            string asm, string outkind, string inkind,
4642                            list<dag> pattern>
4643   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4644       "{\t$Rd" # outkind # ", $Rn" # inkind #
4645       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4646     Sched<[WriteV]> {
4647   bits<5> Rd;
4648   bits<5> Rn;
4649   let Inst{31}    = 0;
4650   let Inst{30}    = Q;
4651   let Inst{29}    = U;
4652   let Inst{28-24} = 0b01110;
4653   let Inst{23-22} = size;
4654   let Inst{21-17} = 0b10000;
4655   let Inst{16-12} = opcode;
4656   let Inst{11-10} = 0b10;
4657   let Inst{9-5}   = Rn;
4658   let Inst{4-0}   = Rd;
4659 }
4660
4661 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4662                            RegisterOperand inreg, RegisterOperand outreg,
4663                            string asm, string outkind, string inkind,
4664                            list<dag> pattern>
4665   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4666       "{\t$Rd" # outkind # ", $Rn" # inkind #
4667       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4668     Sched<[WriteV]> {
4669   bits<5> Rd;
4670   bits<5> Rn;
4671   let Inst{31}    = 0;
4672   let Inst{30}    = Q;
4673   let Inst{29}    = U;
4674   let Inst{28-24} = 0b01110;
4675   let Inst{23-22} = size;
4676   let Inst{21-17} = 0b10000;
4677   let Inst{16-12} = opcode;
4678   let Inst{11-10} = 0b10;
4679   let Inst{9-5}   = Rn;
4680   let Inst{4-0}   = Rd;
4681 }
4682
4683 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4684                               SDPatternOperator OpNode> {
4685   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4686                                       asm, ".8b", ".8h",
4687         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4688   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4689                                       asm#"2", ".16b", ".8h", []>;
4690   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4691                                       asm, ".4h", ".4s",
4692         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4693   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4694                                       asm#"2", ".8h", ".4s", []>;
4695   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4696                                       asm, ".2s", ".2d",
4697         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4698   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4699                                       asm#"2", ".4s", ".2d", []>;
4700
4701   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4702             (!cast<Instruction>(NAME # "v16i8")
4703                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4704   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4705             (!cast<Instruction>(NAME # "v8i16")
4706                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4707   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4708             (!cast<Instruction>(NAME # "v4i32")
4709                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4710 }
4711
4712 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4713                            RegisterOperand regtype,
4714                            string asm, string kind, string zero,
4715                            ValueType dty, ValueType sty, SDNode OpNode>
4716   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4717       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4718       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4719       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4720     Sched<[WriteV]> {
4721   bits<5> Rd;
4722   bits<5> Rn;
4723   let Inst{31}    = 0;
4724   let Inst{30}    = Q;
4725   let Inst{29}    = U;
4726   let Inst{28-24} = 0b01110;
4727   let Inst{23-22} = size;
4728   let Inst{21-17} = 0b10000;
4729   let Inst{16-12} = opcode;
4730   let Inst{11-10} = 0b10;
4731   let Inst{9-5}   = Rn;
4732   let Inst{4-0}   = Rd;
4733 }
4734
4735 // Comparisons support all element sizes, except 1xD.
4736 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4737                             SDNode OpNode> {
4738   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4739                                      asm, ".8b", "0",
4740                                      v8i8, v8i8, OpNode>;
4741   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4742                                      asm, ".16b", "0",
4743                                      v16i8, v16i8, OpNode>;
4744   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4745                                      asm, ".4h", "0",
4746                                      v4i16, v4i16, OpNode>;
4747   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4748                                      asm, ".8h", "0",
4749                                      v8i16, v8i16, OpNode>;
4750   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4751                                      asm, ".2s", "0",
4752                                      v2i32, v2i32, OpNode>;
4753   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4754                                      asm, ".4s", "0",
4755                                      v4i32, v4i32, OpNode>;
4756   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4757                                      asm, ".2d", "0",
4758                                      v2i64, v2i64, OpNode>;
4759 }
4760
4761 // FP Comparisons support only S and D element sizes.
4762 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4763                               string asm, SDNode OpNode> {
4764
4765   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4766                                      asm, ".2s", "0.0",
4767                                      v2i32, v2f32, OpNode>;
4768   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4769                                      asm, ".4s", "0.0",
4770                                      v4i32, v4f32, OpNode>;
4771   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4772                                      asm, ".2d", "0.0",
4773                                      v2i64, v2f64, OpNode>;
4774
4775   def : InstAlias<asm # " $Vd.2s, $Vn.2s, #0",
4776                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4777   def : InstAlias<asm # " $Vd.4s, $Vn.4s, #0",
4778                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4779   def : InstAlias<asm # " $Vd.2d, $Vn.2d, #0",
4780                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4781   def : InstAlias<asm # ".2s $Vd, $Vn, #0",
4782                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4783   def : InstAlias<asm # ".4s $Vd, $Vn, #0",
4784                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4785   def : InstAlias<asm # ".2d $Vd, $Vn, #0",
4786                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4787 }
4788
4789 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4790 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4791                              RegisterOperand outtype, RegisterOperand intype,
4792                              string asm, string VdTy, string VnTy,
4793                              list<dag> pattern>
4794   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4795       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4796     Sched<[WriteV]> {
4797   bits<5> Rd;
4798   bits<5> Rn;
4799   let Inst{31}    = 0;
4800   let Inst{30}    = Q;
4801   let Inst{29}    = U;
4802   let Inst{28-24} = 0b01110;
4803   let Inst{23-22} = size;
4804   let Inst{21-17} = 0b10000;
4805   let Inst{16-12} = opcode;
4806   let Inst{11-10} = 0b10;
4807   let Inst{9-5}   = Rn;
4808   let Inst{4-0}   = Rd;
4809 }
4810
4811 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4812                              RegisterOperand outtype, RegisterOperand intype,
4813                              string asm, string VdTy, string VnTy,
4814                              list<dag> pattern>
4815   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4816       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4817     Sched<[WriteV]> {
4818   bits<5> Rd;
4819   bits<5> Rn;
4820   let Inst{31}    = 0;
4821   let Inst{30}    = Q;
4822   let Inst{29}    = U;
4823   let Inst{28-24} = 0b01110;
4824   let Inst{23-22} = size;
4825   let Inst{21-17} = 0b10000;
4826   let Inst{16-12} = opcode;
4827   let Inst{11-10} = 0b10;
4828   let Inst{9-5}   = Rn;
4829   let Inst{4-0}   = Rd;
4830 }
4831
4832 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4833   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4834                                     asm, ".4s", ".4h", []>;
4835   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4836                                     asm#"2", ".4s", ".8h", []>;
4837   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4838                                     asm, ".2d", ".2s", []>;
4839   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4840                                     asm#"2", ".2d", ".4s", []>;
4841 }
4842
4843 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4844   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4845                                     asm, ".4h", ".4s", []>;
4846   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4847                                     asm#"2", ".8h", ".4s", []>;
4848   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4849                                     asm, ".2s", ".2d", []>;
4850   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4851                                     asm#"2", ".4s", ".2d", []>;
4852 }
4853
4854 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4855                                      Intrinsic OpNode> {
4856   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4857                                      asm, ".2s", ".2d",
4858                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4859   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4860                                     asm#"2", ".4s", ".2d", []>;
4861
4862   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4863             (!cast<Instruction>(NAME # "v4f32")
4864                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4865 }
4866
4867 //----------------------------------------------------------------------------
4868 // AdvSIMD three register different-size vector instructions.
4869 //----------------------------------------------------------------------------
4870
4871 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4872 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4873                       RegisterOperand outtype, RegisterOperand intype1,
4874                       RegisterOperand intype2, string asm,
4875                       string outkind, string inkind1, string inkind2,
4876                       list<dag> pattern>
4877   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4878       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4879       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4880     Sched<[WriteV]> {
4881   bits<5> Rd;
4882   bits<5> Rn;
4883   bits<5> Rm;
4884   let Inst{31}    = 0;
4885   let Inst{30}    = size{0};
4886   let Inst{29}    = U;
4887   let Inst{28-24} = 0b01110;
4888   let Inst{23-22} = size{2-1};
4889   let Inst{21}    = 1;
4890   let Inst{20-16} = Rm;
4891   let Inst{15-12} = opcode;
4892   let Inst{11-10} = 0b00;
4893   let Inst{9-5}   = Rn;
4894   let Inst{4-0}   = Rd;
4895 }
4896
4897 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4898 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4899                       RegisterOperand outtype, RegisterOperand intype1,
4900                       RegisterOperand intype2, string asm,
4901                       string outkind, string inkind1, string inkind2,
4902                       list<dag> pattern>
4903   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4904       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4905       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4906     Sched<[WriteV]> {
4907   bits<5> Rd;
4908   bits<5> Rn;
4909   bits<5> Rm;
4910   let Inst{31}    = 0;
4911   let Inst{30}    = size{0};
4912   let Inst{29}    = U;
4913   let Inst{28-24} = 0b01110;
4914   let Inst{23-22} = size{2-1};
4915   let Inst{21}    = 1;
4916   let Inst{20-16} = Rm;
4917   let Inst{15-12} = opcode;
4918   let Inst{11-10} = 0b00;
4919   let Inst{9-5}   = Rn;
4920   let Inst{4-0}   = Rd;
4921 }
4922
4923 // FIXME: TableGen doesn't know how to deal with expanded types that also
4924 //        change the element count (in this case, placing the results in
4925 //        the high elements of the result register rather than the low
4926 //        elements). Until that's fixed, we can't code-gen those.
4927 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4928                                     Intrinsic IntOp> {
4929   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4930                                                   V64, V128, V128,
4931                                                   asm, ".8b", ".8h", ".8h",
4932      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4933   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4934                                                   V128, V128, V128,
4935                                                   asm#"2", ".16b", ".8h", ".8h",
4936      []>;
4937   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4938                                                   V64, V128, V128,
4939                                                   asm, ".4h", ".4s", ".4s",
4940      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4941   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4942                                                   V128, V128, V128,
4943                                                   asm#"2", ".8h", ".4s", ".4s",
4944      []>;
4945   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4946                                                   V64, V128, V128,
4947                                                   asm, ".2s", ".2d", ".2d",
4948      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4949   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4950                                                   V128, V128, V128,
4951                                                   asm#"2", ".4s", ".2d", ".2d",
4952      []>;
4953
4954
4955   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4956   // a version attached to an instruction.
4957   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4958                                                    (v8i16 V128:$Rm))),
4959             (!cast<Instruction>(NAME # "v8i16_v16i8")
4960                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4961                 V128:$Rn, V128:$Rm)>;
4962   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4963                                                     (v4i32 V128:$Rm))),
4964             (!cast<Instruction>(NAME # "v4i32_v8i16")
4965                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4966                 V128:$Rn, V128:$Rm)>;
4967   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4968                                                     (v2i64 V128:$Rm))),
4969             (!cast<Instruction>(NAME # "v2i64_v4i32")
4970                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4971                 V128:$Rn, V128:$Rm)>;
4972 }
4973
4974 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4975                                       Intrinsic IntOp> {
4976   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4977                                             V128, V64, V64,
4978                                             asm, ".8h", ".8b", ".8b",
4979       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4980   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4981                                             V128, V128, V128,
4982                                             asm#"2", ".8h", ".16b", ".16b", []>;
4983   let Predicates = [HasCrypto] in {
4984     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4985                                               V128, V64, V64,
4986                                               asm, ".1q", ".1d", ".1d", []>;
4987     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4988                                               V128, V128, V128,
4989                                               asm#"2", ".1q", ".2d", ".2d", []>;
4990   }
4991
4992   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4993                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
4994       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4995 }
4996
4997 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4998                                  SDPatternOperator OpNode> {
4999   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5000                                                   V128, V64, V64,
5001                                                   asm, ".4s", ".4h", ".4h",
5002       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5003   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5004                                                   V128, V128, V128,
5005                                                   asm#"2", ".4s", ".8h", ".8h",
5006       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5007                                       (extract_high_v8i16 V128:$Rm)))]>;
5008   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5009                                                   V128, V64, V64,
5010                                                   asm, ".2d", ".2s", ".2s",
5011       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5012   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5013                                                   V128, V128, V128,
5014                                                   asm#"2", ".2d", ".4s", ".4s",
5015       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5016                                       (extract_high_v4i32 V128:$Rm)))]>;
5017 }
5018
5019 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5020                                   SDPatternOperator OpNode = null_frag> {
5021   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5022                                                   V128, V64, V64,
5023                                                   asm, ".8h", ".8b", ".8b",
5024       [(set (v8i16 V128:$Rd),
5025             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5026   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5027                                                  V128, V128, V128,
5028                                                  asm#"2", ".8h", ".16b", ".16b",
5029       [(set (v8i16 V128:$Rd),
5030             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5031                                 (extract_high_v16i8 V128:$Rm)))))]>;
5032   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5033                                                   V128, V64, V64,
5034                                                   asm, ".4s", ".4h", ".4h",
5035       [(set (v4i32 V128:$Rd),
5036             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5037   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5038                                                   V128, V128, V128,
5039                                                   asm#"2", ".4s", ".8h", ".8h",
5040       [(set (v4i32 V128:$Rd),
5041             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5042                                   (extract_high_v8i16 V128:$Rm)))))]>;
5043   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5044                                                   V128, V64, V64,
5045                                                   asm, ".2d", ".2s", ".2s",
5046       [(set (v2i64 V128:$Rd),
5047             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5048   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5049                                                   V128, V128, V128,
5050                                                   asm#"2", ".2d", ".4s", ".4s",
5051       [(set (v2i64 V128:$Rd),
5052             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5053                                  (extract_high_v4i32 V128:$Rm)))))]>;
5054 }
5055
5056 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5057                                           string asm,
5058                                           SDPatternOperator OpNode> {
5059   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5060                                                   V128, V64, V64,
5061                                                   asm, ".8h", ".8b", ".8b",
5062     [(set (v8i16 V128:$dst),
5063           (add (v8i16 V128:$Rd),
5064                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5065   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5066                                                  V128, V128, V128,
5067                                                  asm#"2", ".8h", ".16b", ".16b",
5068     [(set (v8i16 V128:$dst),
5069           (add (v8i16 V128:$Rd),
5070                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5071                                    (extract_high_v16i8 V128:$Rm))))))]>;
5072   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5073                                                   V128, V64, V64,
5074                                                   asm, ".4s", ".4h", ".4h",
5075     [(set (v4i32 V128:$dst),
5076           (add (v4i32 V128:$Rd),
5077                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5078   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5079                                                   V128, V128, V128,
5080                                                   asm#"2", ".4s", ".8h", ".8h",
5081     [(set (v4i32 V128:$dst),
5082           (add (v4i32 V128:$Rd),
5083                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5084                                     (extract_high_v8i16 V128:$Rm))))))]>;
5085   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5086                                                   V128, V64, V64,
5087                                                   asm, ".2d", ".2s", ".2s",
5088     [(set (v2i64 V128:$dst),
5089           (add (v2i64 V128:$Rd),
5090                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5091   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5092                                                   V128, V128, V128,
5093                                                   asm#"2", ".2d", ".4s", ".4s",
5094     [(set (v2i64 V128:$dst),
5095           (add (v2i64 V128:$Rd),
5096                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5097                                     (extract_high_v4i32 V128:$Rm))))))]>;
5098 }
5099
5100 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5101                                   SDPatternOperator OpNode = null_frag> {
5102   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5103                                                   V128, V64, V64,
5104                                                   asm, ".8h", ".8b", ".8b",
5105       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5106   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5107                                                  V128, V128, V128,
5108                                                  asm#"2", ".8h", ".16b", ".16b",
5109       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5110                                       (extract_high_v16i8 V128:$Rm)))]>;
5111   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5112                                                   V128, V64, V64,
5113                                                   asm, ".4s", ".4h", ".4h",
5114       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5115   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5116                                                   V128, V128, V128,
5117                                                   asm#"2", ".4s", ".8h", ".8h",
5118       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5119                                       (extract_high_v8i16 V128:$Rm)))]>;
5120   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5121                                                   V128, V64, V64,
5122                                                   asm, ".2d", ".2s", ".2s",
5123       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5124   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5125                                                   V128, V128, V128,
5126                                                   asm#"2", ".2d", ".4s", ".4s",
5127       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5128                                       (extract_high_v4i32 V128:$Rm)))]>;
5129 }
5130
5131 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5132                                       string asm,
5133                                       SDPatternOperator OpNode> {
5134   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5135                                                   V128, V64, V64,
5136                                                   asm, ".8h", ".8b", ".8b",
5137     [(set (v8i16 V128:$dst),
5138           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5139   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5140                                                  V128, V128, V128,
5141                                                  asm#"2", ".8h", ".16b", ".16b",
5142     [(set (v8i16 V128:$dst),
5143           (OpNode (v8i16 V128:$Rd),
5144                   (extract_high_v16i8 V128:$Rn),
5145                   (extract_high_v16i8 V128:$Rm)))]>;
5146   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5147                                                   V128, V64, V64,
5148                                                   asm, ".4s", ".4h", ".4h",
5149     [(set (v4i32 V128:$dst),
5150           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5151   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5152                                                   V128, V128, V128,
5153                                                   asm#"2", ".4s", ".8h", ".8h",
5154     [(set (v4i32 V128:$dst),
5155           (OpNode (v4i32 V128:$Rd),
5156                   (extract_high_v8i16 V128:$Rn),
5157                   (extract_high_v8i16 V128:$Rm)))]>;
5158   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5159                                                   V128, V64, V64,
5160                                                   asm, ".2d", ".2s", ".2s",
5161     [(set (v2i64 V128:$dst),
5162           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5163   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5164                                                   V128, V128, V128,
5165                                                   asm#"2", ".2d", ".4s", ".4s",
5166     [(set (v2i64 V128:$dst),
5167           (OpNode (v2i64 V128:$Rd),
5168                   (extract_high_v4i32 V128:$Rn),
5169                   (extract_high_v4i32 V128:$Rm)))]>;
5170 }
5171
5172 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5173                                            SDPatternOperator Accum> {
5174   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5175                                                   V128, V64, V64,
5176                                                   asm, ".4s", ".4h", ".4h",
5177     [(set (v4i32 V128:$dst),
5178           (Accum (v4i32 V128:$Rd),
5179                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5180                                                 (v4i16 V64:$Rm)))))]>;
5181   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5182                                                   V128, V128, V128,
5183                                                   asm#"2", ".4s", ".8h", ".8h",
5184     [(set (v4i32 V128:$dst),
5185           (Accum (v4i32 V128:$Rd),
5186                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5187                                             (extract_high_v8i16 V128:$Rm)))))]>;
5188   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5189                                                   V128, V64, V64,
5190                                                   asm, ".2d", ".2s", ".2s",
5191     [(set (v2i64 V128:$dst),
5192           (Accum (v2i64 V128:$Rd),
5193                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5194                                                 (v2i32 V64:$Rm)))))]>;
5195   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5196                                                   V128, V128, V128,
5197                                                   asm#"2", ".2d", ".4s", ".4s",
5198     [(set (v2i64 V128:$dst),
5199           (Accum (v2i64 V128:$Rd),
5200                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5201                                             (extract_high_v4i32 V128:$Rm)))))]>;
5202 }
5203
5204 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5205                                   SDPatternOperator OpNode> {
5206   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5207                                                   V128, V128, V64,
5208                                                   asm, ".8h", ".8h", ".8b",
5209        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5210   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5211                                                   V128, V128, V128,
5212                                                   asm#"2", ".8h", ".8h", ".16b",
5213        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5214                                        (extract_high_v16i8 V128:$Rm)))]>;
5215   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5216                                                   V128, V128, V64,
5217                                                   asm, ".4s", ".4s", ".4h",
5218        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5219   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5220                                                   V128, V128, V128,
5221                                                   asm#"2", ".4s", ".4s", ".8h",
5222        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5223                                        (extract_high_v8i16 V128:$Rm)))]>;
5224   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5225                                                   V128, V128, V64,
5226                                                   asm, ".2d", ".2d", ".2s",
5227        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5228   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5229                                                   V128, V128, V128,
5230                                                   asm#"2", ".2d", ".2d", ".4s",
5231        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5232                                        (extract_high_v4i32 V128:$Rm)))]>;
5233 }
5234
5235 //----------------------------------------------------------------------------
5236 // AdvSIMD bitwise extract from vector
5237 //----------------------------------------------------------------------------
5238
5239 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5240                              string asm, string kind>
5241   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5242       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5243       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5244       [(set (vty regtype:$Rd),
5245             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5246     Sched<[WriteV]> {
5247   bits<5> Rd;
5248   bits<5> Rn;
5249   bits<5> Rm;
5250   bits<4> imm;
5251   let Inst{31}    = 0;
5252   let Inst{30}    = size;
5253   let Inst{29-21} = 0b101110000;
5254   let Inst{20-16} = Rm;
5255   let Inst{15}    = 0;
5256   let Inst{14-11} = imm;
5257   let Inst{10}    = 0;
5258   let Inst{9-5}   = Rn;
5259   let Inst{4-0}   = Rd;
5260 }
5261
5262
5263 multiclass SIMDBitwiseExtract<string asm> {
5264   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5265     let imm{3} = 0;
5266   }
5267   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5268 }
5269
5270 //----------------------------------------------------------------------------
5271 // AdvSIMD zip vector
5272 //----------------------------------------------------------------------------
5273
5274 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5275                         string asm, string kind, SDNode OpNode, ValueType valty>
5276   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5277       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5278       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5279       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5280     Sched<[WriteV]> {
5281   bits<5> Rd;
5282   bits<5> Rn;
5283   bits<5> Rm;
5284   let Inst{31}    = 0;
5285   let Inst{30}    = size{0};
5286   let Inst{29-24} = 0b001110;
5287   let Inst{23-22} = size{2-1};
5288   let Inst{21}    = 0;
5289   let Inst{20-16} = Rm;
5290   let Inst{15}    = 0;
5291   let Inst{14-12} = opc;
5292   let Inst{11-10} = 0b10;
5293   let Inst{9-5}   = Rn;
5294   let Inst{4-0}   = Rd;
5295 }
5296
5297 multiclass SIMDZipVector<bits<3>opc, string asm,
5298                          SDNode OpNode> {
5299   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5300       asm, ".8b", OpNode, v8i8>;
5301   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5302       asm, ".16b", OpNode, v16i8>;
5303   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5304       asm, ".4h", OpNode, v4i16>;
5305   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5306       asm, ".8h", OpNode, v8i16>;
5307   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5308       asm, ".2s", OpNode, v2i32>;
5309   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5310       asm, ".4s", OpNode, v4i32>;
5311   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5312       asm, ".2d", OpNode, v2i64>;
5313
5314   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5315         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5316   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5317         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5318   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5319         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5320   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5321         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5322   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5323         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5324 }
5325
5326 //----------------------------------------------------------------------------
5327 // AdvSIMD three register scalar instructions
5328 //----------------------------------------------------------------------------
5329
5330 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5331 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5332                         RegisterClass regtype, string asm,
5333                         list<dag> pattern>
5334   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5335       "\t$Rd, $Rn, $Rm", "", pattern>,
5336     Sched<[WriteV]> {
5337   bits<5> Rd;
5338   bits<5> Rn;
5339   bits<5> Rm;
5340   let Inst{31-30} = 0b01;
5341   let Inst{29}    = U;
5342   let Inst{28-24} = 0b11110;
5343   let Inst{23-22} = size;
5344   let Inst{21}    = 1;
5345   let Inst{20-16} = Rm;
5346   let Inst{15-11} = opcode;
5347   let Inst{10}    = 1;
5348   let Inst{9-5}   = Rn;
5349   let Inst{4-0}   = Rd;
5350 }
5351
5352 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5353 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5354                         dag oops, dag iops, string asm,
5355             list<dag> pattern>
5356   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5357     Sched<[WriteV]> {
5358   bits<5> Rd;
5359   bits<5> Rn;
5360   bits<5> Rm;
5361   let Inst{31-30} = 0b01;
5362   let Inst{29}    = U;
5363   let Inst{28-24} = 0b11110;
5364   let Inst{23-22} = size;
5365   let Inst{21}    = R;
5366   let Inst{20-16} = Rm;
5367   let Inst{15-11} = opcode;
5368   let Inst{10}    = 1;
5369   let Inst{9-5}   = Rn;
5370   let Inst{4-0}   = Rd;
5371 }
5372
5373 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5374                             SDPatternOperator OpNode> {
5375   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5376     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5377 }
5378
5379 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5380                                SDPatternOperator OpNode> {
5381   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5382     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5383   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5384   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5385   def v1i8   : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5386
5387   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5388             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5389   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5390             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5391 }
5392
5393 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5394                              SDPatternOperator OpNode> {
5395   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5396                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5397   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5398 }
5399
5400 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5401                                  SDPatternOperator OpNode = null_frag> {
5402   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5403                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm), 
5404                                      asm, []>;
5405   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5406                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm), 
5407                                      asm, []>;
5408 }
5409
5410 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5411                              SDPatternOperator OpNode = null_frag> {
5412   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5413     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5414       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5415     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5416       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5417   }
5418
5419   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5420             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5421 }
5422
5423 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5424                                 SDPatternOperator OpNode = null_frag> {
5425   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5426     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5427       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5428     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5429       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5430   }
5431
5432   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5433             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5434 }
5435
5436 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5437               dag oops, dag iops, string asm, string cstr, list<dag> pat>
5438   : I<oops, iops, asm,
5439       "\t$Rd, $Rn, $Rm", cstr, pat>,
5440     Sched<[WriteV]> {
5441   bits<5> Rd;
5442   bits<5> Rn;
5443   bits<5> Rm;
5444   let Inst{31-30} = 0b01;
5445   let Inst{29}    = U;
5446   let Inst{28-24} = 0b11110;
5447   let Inst{23-22} = size;
5448   let Inst{21}    = 1;
5449   let Inst{20-16} = Rm;
5450   let Inst{15-11} = opcode;
5451   let Inst{10}    = 0;
5452   let Inst{9-5}   = Rn;
5453   let Inst{4-0}   = Rd;
5454 }
5455
5456 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5457 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5458                                   SDPatternOperator OpNode = null_frag> {
5459   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5460                                       (outs FPR32:$Rd),
5461                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5462   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5463                                       (outs FPR64:$Rd),
5464                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5465             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5466 }
5467
5468 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5469 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5470                                   SDPatternOperator OpNode = null_frag> {
5471   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5472                                       (outs FPR32:$dst),
5473                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5474                                       asm, "$Rd = $dst", []>;
5475   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5476                                       (outs FPR64:$dst),
5477                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5478                                       asm, "$Rd = $dst",
5479             [(set (i64 FPR64:$dst),
5480                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5481 }
5482
5483 //----------------------------------------------------------------------------
5484 // AdvSIMD two register scalar instructions
5485 //----------------------------------------------------------------------------
5486
5487 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5488 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5489                         RegisterClass regtype, RegisterClass regtype2,
5490                         string asm, list<dag> pat>
5491   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5492       "\t$Rd, $Rn", "", pat>,
5493     Sched<[WriteV]> {
5494   bits<5> Rd;
5495   bits<5> Rn;
5496   let Inst{31-30} = 0b01;
5497   let Inst{29}    = U;
5498   let Inst{28-24} = 0b11110;
5499   let Inst{23-22} = size;
5500   let Inst{21-17} = 0b10000;
5501   let Inst{16-12} = opcode;
5502   let Inst{11-10} = 0b10;
5503   let Inst{9-5}   = Rn;
5504   let Inst{4-0}   = Rd;
5505 }
5506
5507 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5508 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5509                         RegisterClass regtype, RegisterClass regtype2,
5510                         string asm, list<dag> pat>
5511   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5512       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5513     Sched<[WriteV]> {
5514   bits<5> Rd;
5515   bits<5> Rn;
5516   let Inst{31-30} = 0b01;
5517   let Inst{29}    = U;
5518   let Inst{28-24} = 0b11110;
5519   let Inst{23-22} = size;
5520   let Inst{21-17} = 0b10000;
5521   let Inst{16-12} = opcode;
5522   let Inst{11-10} = 0b10;
5523   let Inst{9-5}   = Rn;
5524   let Inst{4-0}   = Rd;
5525 }
5526
5527
5528 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5529 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5530                         RegisterClass regtype, string asm, string zero>
5531   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5532       "\t$Rd, $Rn, #" # zero, "", []>,
5533     Sched<[WriteV]> {
5534   bits<5> Rd;
5535   bits<5> Rn;
5536   let Inst{31-30} = 0b01;
5537   let Inst{29}    = U;
5538   let Inst{28-24} = 0b11110;
5539   let Inst{23-22} = size;
5540   let Inst{21-17} = 0b10000;
5541   let Inst{16-12} = opcode;
5542   let Inst{11-10} = 0b10;
5543   let Inst{9-5}   = Rn;
5544   let Inst{4-0}   = Rd;
5545 }
5546
5547 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5548   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5549      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5550     Sched<[WriteV]> {
5551   bits<5> Rd;
5552   bits<5> Rn;
5553   let Inst{31-17} = 0b011111100110000;
5554   let Inst{16-12} = opcode;
5555   let Inst{11-10} = 0b10;
5556   let Inst{9-5}   = Rn;
5557   let Inst{4-0}   = Rd;
5558 }
5559
5560 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5561                              SDPatternOperator OpNode> {
5562   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5563
5564   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5565             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5566 }
5567
5568 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5569                               SDPatternOperator OpNode> {
5570   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5571   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5572
5573   def : InstAlias<asm # " $Rd, $Rn, #0",
5574                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5575   def : InstAlias<asm # " $Rd, $Rn, #0",
5576                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5577
5578   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5579             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5580 }
5581
5582 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5583                           SDPatternOperator OpNode = null_frag> {
5584   def v1i64       : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5585     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5586
5587   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5588             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5589 }
5590
5591 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5592   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5593   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5594 }
5595
5596 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5597                               SDPatternOperator OpNode> {
5598   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5599                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5600   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5601                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5602 }
5603
5604 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5605                              SDPatternOperator OpNode = null_frag> {
5606   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5607     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5608            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5609     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5610            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5611     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5612     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5613   }
5614
5615   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5616             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5617 }
5618
5619 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5620                                  Intrinsic OpNode> {
5621   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5622     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5623         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5624     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5625         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5626     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5627     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5628   }
5629
5630   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5631             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5632 }
5633
5634
5635
5636 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5637 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5638                                  SDPatternOperator OpNode = null_frag> {
5639   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5640         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5641   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5642   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5643 }
5644
5645 //----------------------------------------------------------------------------
5646 // AdvSIMD scalar pairwise instructions
5647 //----------------------------------------------------------------------------
5648
5649 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5650 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5651                         RegisterOperand regtype, RegisterOperand vectype,
5652                         string asm, string kind>
5653   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5654       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5655     Sched<[WriteV]> {
5656   bits<5> Rd;
5657   bits<5> Rn;
5658   let Inst{31-30} = 0b01;
5659   let Inst{29}    = U;
5660   let Inst{28-24} = 0b11110;
5661   let Inst{23-22} = size;
5662   let Inst{21-17} = 0b11000;
5663   let Inst{16-12} = opcode;
5664   let Inst{11-10} = 0b10;
5665   let Inst{9-5}   = Rn;
5666   let Inst{4-0}   = Rd;
5667 }
5668
5669 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5670   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5671                                       asm, ".2d">;
5672 }
5673
5674 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5675   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5676                                       asm, ".2s">;
5677   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5678                                       asm, ".2d">;
5679 }
5680
5681 //----------------------------------------------------------------------------
5682 // AdvSIMD across lanes instructions
5683 //----------------------------------------------------------------------------
5684
5685 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5686 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5687                           RegisterClass regtype, RegisterOperand vectype,
5688                           string asm, string kind, list<dag> pattern>
5689   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5690       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5691     Sched<[WriteV]> {
5692   bits<5> Rd;
5693   bits<5> Rn;
5694   let Inst{31}    = 0;
5695   let Inst{30}    = Q;
5696   let Inst{29}    = U;
5697   let Inst{28-24} = 0b01110;
5698   let Inst{23-22} = size;
5699   let Inst{21-17} = 0b11000;
5700   let Inst{16-12} = opcode;
5701   let Inst{11-10} = 0b10;
5702   let Inst{9-5}   = Rn;
5703   let Inst{4-0}   = Rd;
5704 }
5705
5706 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5707                               string asm> {
5708   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5709                                    asm, ".8b", []>;
5710   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5711                                    asm, ".16b", []>;
5712   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5713                                    asm, ".4h", []>;
5714   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5715                                    asm, ".8h", []>;
5716   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5717                                    asm, ".4s", []>;
5718 }
5719
5720 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5721   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5722                                    asm, ".8b", []>;
5723   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5724                                    asm, ".16b", []>;
5725   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5726                                    asm, ".4h", []>;
5727   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5728                                    asm, ".8h", []>;
5729   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5730                                    asm, ".4s", []>;
5731 }
5732
5733 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5734                             Intrinsic intOp> {
5735   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5736                                    asm, ".4s",
5737         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5738 }
5739
5740 //----------------------------------------------------------------------------
5741 // AdvSIMD INS/DUP instructions
5742 //----------------------------------------------------------------------------
5743
5744 // FIXME: There has got to be a better way to factor these. ugh.
5745
5746 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5747                      string operands, string constraints, list<dag> pattern>
5748   : I<outs, ins, asm, operands, constraints, pattern>,
5749     Sched<[WriteV]> {
5750   bits<5> Rd;
5751   bits<5> Rn;
5752   let Inst{31} = 0;
5753   let Inst{30} = Q;
5754   let Inst{29} = op;
5755   let Inst{28-21} = 0b01110000;
5756   let Inst{15} = 0;
5757   let Inst{10} = 1;
5758   let Inst{9-5} = Rn;
5759   let Inst{4-0} = Rd;
5760 }
5761
5762 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5763                       RegisterOperand vecreg, RegisterClass regtype>
5764   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5765                    "{\t$Rd" # size # ", $Rn" #
5766                    "|" # size # "\t$Rd, $Rn}", "",
5767                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
5768   let Inst{20-16} = imm5;
5769   let Inst{14-11} = 0b0001;
5770 }
5771
5772 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5773                          ValueType vectype, ValueType insreg,
5774                          RegisterOperand vecreg, Operand idxtype,
5775                          ValueType elttype, SDNode OpNode>
5776   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5777                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5778                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5779                  [(set (vectype vecreg:$Rd),
5780                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5781   let Inst{14-11} = 0b0000;
5782 }
5783
5784 class SIMDDup64FromElement
5785   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5786                        VectorIndexD, i64, AArch64duplane64> {
5787   bits<1> idx;
5788   let Inst{20} = idx;
5789   let Inst{19-16} = 0b1000;
5790 }
5791
5792 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5793                            RegisterOperand vecreg>
5794   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5795                        VectorIndexS, i64, AArch64duplane32> {
5796   bits<2> idx;
5797   let Inst{20-19} = idx;
5798   let Inst{18-16} = 0b100;
5799 }
5800
5801 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5802                            RegisterOperand vecreg>
5803   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5804                        VectorIndexH, i64, AArch64duplane16> {
5805   bits<3> idx;
5806   let Inst{20-18} = idx;
5807   let Inst{17-16} = 0b10;
5808 }
5809
5810 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5811                           RegisterOperand vecreg>
5812   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5813                        VectorIndexB, i64, AArch64duplane8> {
5814   bits<4> idx;
5815   let Inst{20-17} = idx;
5816   let Inst{16} = 1;
5817 }
5818
5819 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5820                   Operand idxtype, string asm, list<dag> pattern>
5821   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5822                    "{\t$Rd, $Rn" # size # "$idx" #
5823                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5824   let Inst{14-11} = imm4;
5825 }
5826
5827 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5828                Operand idxtype>
5829   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5830 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5831                Operand idxtype>
5832   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5833       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5834
5835 class SIMDMovAlias<string asm, string size, Instruction inst,
5836                    RegisterClass regtype, Operand idxtype>
5837     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5838                     "|" # size # "\t$dst, $src$idx}",
5839                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5840
5841 multiclass SMov {
5842   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5843     bits<4> idx;
5844     let Inst{20-17} = idx;
5845     let Inst{16} = 1;
5846   }
5847   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5848     bits<4> idx;
5849     let Inst{20-17} = idx;
5850     let Inst{16} = 1;
5851   }
5852   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5853     bits<3> idx;
5854     let Inst{20-18} = idx;
5855     let Inst{17-16} = 0b10;
5856   }
5857   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5858     bits<3> idx;
5859     let Inst{20-18} = idx;
5860     let Inst{17-16} = 0b10;
5861   }
5862   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5863     bits<2> idx;
5864     let Inst{20-19} = idx;
5865     let Inst{18-16} = 0b100;
5866   }
5867 }
5868
5869 multiclass UMov {
5870   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5871     bits<4> idx;
5872     let Inst{20-17} = idx;
5873     let Inst{16} = 1;
5874   }
5875   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5876     bits<3> idx;
5877     let Inst{20-18} = idx;
5878     let Inst{17-16} = 0b10;
5879   }
5880   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5881     bits<2> idx;
5882     let Inst{20-19} = idx;
5883     let Inst{18-16} = 0b100;
5884   }
5885   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5886     bits<1> idx;
5887     let Inst{20} = idx;
5888     let Inst{19-16} = 0b1000;
5889   }
5890   def : SIMDMovAlias<"mov", ".s",
5891                      !cast<Instruction>(NAME#"vi32"),
5892                      GPR32, VectorIndexS>;
5893   def : SIMDMovAlias<"mov", ".d",
5894                      !cast<Instruction>(NAME#"vi64"),
5895                      GPR64, VectorIndexD>;
5896 }
5897
5898 class SIMDInsFromMain<string size, ValueType vectype,
5899                       RegisterClass regtype, Operand idxtype>
5900   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5901                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5902                    "{\t$Rd" # size # "$idx, $Rn" #
5903                    "|" # size # "\t$Rd$idx, $Rn}",
5904                    "$Rd = $dst",
5905             [(set V128:$dst,
5906               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5907   let Inst{14-11} = 0b0011;
5908 }
5909
5910 class SIMDInsFromElement<string size, ValueType vectype,
5911                          ValueType elttype, Operand idxtype>
5912   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5913                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5914                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5915                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
5916                    "$Rd = $dst",
5917          [(set V128:$dst,
5918                (vector_insert
5919                  (vectype V128:$Rd),
5920                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5921                  idxtype:$idx))]>;
5922
5923 class SIMDInsMainMovAlias<string size, Instruction inst,
5924                           RegisterClass regtype, Operand idxtype>
5925     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5926                         "|" # size #"\t$dst$idx, $src}",
5927                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5928 class SIMDInsElementMovAlias<string size, Instruction inst,
5929                              Operand idxtype>
5930     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5931                       # "|" # size #" $dst$idx, $src$idx2}",
5932                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5933
5934
5935 multiclass SIMDIns {
5936   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5937     bits<4> idx;
5938     let Inst{20-17} = idx;
5939     let Inst{16} = 1;
5940   }
5941   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5942     bits<3> idx;
5943     let Inst{20-18} = idx;
5944     let Inst{17-16} = 0b10;
5945   }
5946   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5947     bits<2> idx;
5948     let Inst{20-19} = idx;
5949     let Inst{18-16} = 0b100;
5950   }
5951   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5952     bits<1> idx;
5953     let Inst{20} = idx;
5954     let Inst{19-16} = 0b1000;
5955   }
5956
5957   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5958     bits<4> idx;
5959     bits<4> idx2;
5960     let Inst{20-17} = idx;
5961     let Inst{16} = 1;
5962     let Inst{14-11} = idx2;
5963   }
5964   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5965     bits<3> idx;
5966     bits<3> idx2;
5967     let Inst{20-18} = idx;
5968     let Inst{17-16} = 0b10;
5969     let Inst{14-12} = idx2;
5970     let Inst{11} = {?};
5971   }
5972   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5973     bits<2> idx;
5974     bits<2> idx2;
5975     let Inst{20-19} = idx;
5976     let Inst{18-16} = 0b100;
5977     let Inst{14-13} = idx2;
5978     let Inst{12-11} = {?,?};
5979   }
5980   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5981     bits<1> idx;
5982     bits<1> idx2;
5983     let Inst{20} = idx;
5984     let Inst{19-16} = 0b1000;
5985     let Inst{14} = idx2;
5986     let Inst{13-11} = {?,?,?};
5987   }
5988
5989   // For all forms of the INS instruction, the "mov" mnemonic is the
5990   // preferred alias. Why they didn't just call the instruction "mov" in
5991   // the first place is a very good question indeed...
5992   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5993                          GPR32, VectorIndexB>;
5994   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5995                          GPR32, VectorIndexH>;
5996   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5997                          GPR32, VectorIndexS>;
5998   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5999                          GPR64, VectorIndexD>;
6000
6001   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6002                          VectorIndexB>;
6003   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6004                          VectorIndexH>;
6005   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6006                          VectorIndexS>;
6007   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6008                          VectorIndexD>;
6009 }
6010
6011 //----------------------------------------------------------------------------
6012 // AdvSIMD TBL/TBX
6013 //----------------------------------------------------------------------------
6014
6015 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6016 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6017                           RegisterOperand listtype, string asm, string kind>
6018   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6019        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6020     Sched<[WriteV]> {
6021   bits<5> Vd;
6022   bits<5> Vn;
6023   bits<5> Vm;
6024   let Inst{31}    = 0;
6025   let Inst{30}    = Q;
6026   let Inst{29-21} = 0b001110000;
6027   let Inst{20-16} = Vm;
6028   let Inst{15}    = 0;
6029   let Inst{14-13} = len;
6030   let Inst{12}    = op;
6031   let Inst{11-10} = 0b00;
6032   let Inst{9-5}   = Vn;
6033   let Inst{4-0}   = Vd;
6034 }
6035
6036 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6037 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6038                           RegisterOperand listtype, string asm, string kind>
6039   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6040        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6041     Sched<[WriteV]> {
6042   bits<5> Vd;
6043   bits<5> Vn;
6044   bits<5> Vm;
6045   let Inst{31}    = 0;
6046   let Inst{30}    = Q;
6047   let Inst{29-21} = 0b001110000;
6048   let Inst{20-16} = Vm;
6049   let Inst{15}    = 0;
6050   let Inst{14-13} = len;
6051   let Inst{12}    = op;
6052   let Inst{11-10} = 0b00;
6053   let Inst{9-5}   = Vn;
6054   let Inst{4-0}   = Vd;
6055 }
6056
6057 class SIMDTableLookupAlias<string asm, Instruction inst,
6058                           RegisterOperand vectype, RegisterOperand listtype>
6059     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6060                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6061
6062 multiclass SIMDTableLookup<bit op, string asm> {
6063   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6064                                       asm, ".8b">;
6065   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6066                                       asm, ".8b">;
6067   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6068                                       asm, ".8b">;
6069   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6070                                       asm, ".8b">;
6071   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6072                                       asm, ".16b">;
6073   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6074                                       asm, ".16b">;
6075   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6076                                       asm, ".16b">;
6077   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6078                                       asm, ".16b">;
6079
6080   def : SIMDTableLookupAlias<asm # ".8b",
6081                          !cast<Instruction>(NAME#"v8i8One"),
6082                          V64, VecListOne128>;
6083   def : SIMDTableLookupAlias<asm # ".8b",
6084                          !cast<Instruction>(NAME#"v8i8Two"),
6085                          V64, VecListTwo128>;
6086   def : SIMDTableLookupAlias<asm # ".8b",
6087                          !cast<Instruction>(NAME#"v8i8Three"),
6088                          V64, VecListThree128>;
6089   def : SIMDTableLookupAlias<asm # ".8b",
6090                          !cast<Instruction>(NAME#"v8i8Four"),
6091                          V64, VecListFour128>;
6092   def : SIMDTableLookupAlias<asm # ".16b",
6093                          !cast<Instruction>(NAME#"v16i8One"),
6094                          V128, VecListOne128>;
6095   def : SIMDTableLookupAlias<asm # ".16b",
6096                          !cast<Instruction>(NAME#"v16i8Two"),
6097                          V128, VecListTwo128>;
6098   def : SIMDTableLookupAlias<asm # ".16b",
6099                          !cast<Instruction>(NAME#"v16i8Three"),
6100                          V128, VecListThree128>;
6101   def : SIMDTableLookupAlias<asm # ".16b",
6102                          !cast<Instruction>(NAME#"v16i8Four"),
6103                          V128, VecListFour128>;
6104 }
6105
6106 multiclass SIMDTableLookupTied<bit op, string asm> {
6107   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6108                                       asm, ".8b">;
6109   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6110                                       asm, ".8b">;
6111   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6112                                       asm, ".8b">;
6113   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6114                                       asm, ".8b">;
6115   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6116                                       asm, ".16b">;
6117   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6118                                       asm, ".16b">;
6119   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6120                                       asm, ".16b">;
6121   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6122                                       asm, ".16b">;
6123
6124   def : SIMDTableLookupAlias<asm # ".8b",
6125                          !cast<Instruction>(NAME#"v8i8One"),
6126                          V64, VecListOne128>;
6127   def : SIMDTableLookupAlias<asm # ".8b",
6128                          !cast<Instruction>(NAME#"v8i8Two"),
6129                          V64, VecListTwo128>;
6130   def : SIMDTableLookupAlias<asm # ".8b",
6131                          !cast<Instruction>(NAME#"v8i8Three"),
6132                          V64, VecListThree128>;
6133   def : SIMDTableLookupAlias<asm # ".8b",
6134                          !cast<Instruction>(NAME#"v8i8Four"),
6135                          V64, VecListFour128>;
6136   def : SIMDTableLookupAlias<asm # ".16b",
6137                          !cast<Instruction>(NAME#"v16i8One"),
6138                          V128, VecListOne128>;
6139   def : SIMDTableLookupAlias<asm # ".16b",
6140                          !cast<Instruction>(NAME#"v16i8Two"),
6141                          V128, VecListTwo128>;
6142   def : SIMDTableLookupAlias<asm # ".16b",
6143                          !cast<Instruction>(NAME#"v16i8Three"),
6144                          V128, VecListThree128>;
6145   def : SIMDTableLookupAlias<asm # ".16b",
6146                          !cast<Instruction>(NAME#"v16i8Four"),
6147                          V128, VecListFour128>;
6148 }
6149
6150
6151 //----------------------------------------------------------------------------
6152 // AdvSIMD scalar CPY
6153 //----------------------------------------------------------------------------
6154 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6155 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6156                         string kind, Operand idxtype>
6157   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6158        "{\t$dst, $src" # kind # "$idx" #
6159        "|\t$dst, $src$idx}", "", []>,
6160     Sched<[WriteV]> {
6161   bits<5> dst;
6162   bits<5> src;
6163   let Inst{31-21} = 0b01011110000;
6164   let Inst{15-10} = 0b000001;
6165   let Inst{9-5}   = src;
6166   let Inst{4-0}   = dst;
6167 }
6168
6169 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6170       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6171     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6172                     # "|\t$dst, $src$index}",
6173                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6174
6175
6176 multiclass SIMDScalarCPY<string asm> {
6177   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6178     bits<4> idx;
6179     let Inst{20-17} = idx;
6180     let Inst{16} = 1;
6181   }
6182   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6183     bits<3> idx;
6184     let Inst{20-18} = idx;
6185     let Inst{17-16} = 0b10;
6186   }
6187   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6188     bits<2> idx;
6189     let Inst{20-19} = idx;
6190     let Inst{18-16} = 0b100;
6191   }
6192   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6193     bits<1> idx;
6194     let Inst{20} = idx;
6195     let Inst{19-16} = 0b1000;
6196   }
6197
6198   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6199                                                           VectorIndexD:$idx)))),
6200             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6201
6202   // 'DUP' mnemonic aliases.
6203   def : SIMDScalarCPYAlias<"dup", ".b",
6204                            !cast<Instruction>(NAME#"i8"),
6205                            FPR8, V128, VectorIndexB>;
6206   def : SIMDScalarCPYAlias<"dup", ".h",
6207                            !cast<Instruction>(NAME#"i16"),
6208                            FPR16, V128, VectorIndexH>;
6209   def : SIMDScalarCPYAlias<"dup", ".s",
6210                            !cast<Instruction>(NAME#"i32"),
6211                            FPR32, V128, VectorIndexS>;
6212   def : SIMDScalarCPYAlias<"dup", ".d",
6213                            !cast<Instruction>(NAME#"i64"),
6214                            FPR64, V128, VectorIndexD>;
6215 }
6216
6217 //----------------------------------------------------------------------------
6218 // AdvSIMD modified immediate instructions
6219 //----------------------------------------------------------------------------
6220
6221 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
6222                           string asm, string op_string,
6223                           string cstr, list<dag> pattern>
6224   : I<oops, iops, asm, op_string, cstr, pattern>,
6225     Sched<[WriteV]> {
6226   bits<5> Rd;
6227   bits<8> imm8;
6228   let Inst{31}    = 0;
6229   let Inst{30}    = Q;
6230   let Inst{29}    = op;
6231   let Inst{28-19} = 0b0111100000;
6232   let Inst{18-16} = imm8{7-5};
6233   let Inst{11-10} = 0b01;
6234   let Inst{9-5}   = imm8{4-0};
6235   let Inst{4-0}   = Rd;
6236 }
6237
6238 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
6239                                 Operand immtype, dag opt_shift_iop,
6240                                 string opt_shift, string asm, string kind,
6241                                 list<dag> pattern>
6242   : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
6243                         !con((ins immtype:$imm8), opt_shift_iop), asm,
6244                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
6245                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6246                         "", pattern> {
6247   let DecoderMethod = "DecodeModImmInstruction";
6248 }
6249
6250 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6251                                 Operand immtype, dag opt_shift_iop,
6252                                 string opt_shift, string asm, string kind,
6253                                 list<dag> pattern>
6254   : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
6255                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6256                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6257                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6258                         "$Rd = $dst", pattern> {
6259   let DecoderMethod = "DecodeModImmTiedInstruction";
6260 }
6261
6262 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6263                                      RegisterOperand vectype, string asm,
6264                                      string kind, list<dag> pattern>
6265   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6266                               (ins logical_vec_shift:$shift),
6267                               "$shift", asm, kind, pattern> {
6268   bits<2> shift;
6269   let Inst{15}    = b15_b12{1};
6270   let Inst{14-13} = shift;
6271   let Inst{12}    = b15_b12{0};
6272 }
6273
6274 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6275                                      RegisterOperand vectype, string asm,
6276                                      string kind, list<dag> pattern>
6277   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6278                               (ins logical_vec_shift:$shift),
6279                               "$shift", asm, kind, pattern> {
6280   bits<2> shift;
6281   let Inst{15}    = b15_b12{1};
6282   let Inst{14-13} = shift;
6283   let Inst{12}    = b15_b12{0};
6284 }
6285
6286
6287 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6288                                          RegisterOperand vectype, string asm,
6289                                          string kind, list<dag> pattern>
6290   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6291                               (ins logical_vec_hw_shift:$shift),
6292                               "$shift", asm, kind, pattern> {
6293   bits<2> shift;
6294   let Inst{15} = b15_b12{1};
6295   let Inst{14} = 0;
6296   let Inst{13} = shift{0};
6297   let Inst{12} = b15_b12{0};
6298 }
6299
6300 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6301                                          RegisterOperand vectype, string asm,
6302                                          string kind, list<dag> pattern>
6303   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6304                               (ins logical_vec_hw_shift:$shift),
6305                               "$shift", asm, kind, pattern> {
6306   bits<2> shift;
6307   let Inst{15} = b15_b12{1};
6308   let Inst{14} = 0;
6309   let Inst{13} = shift{0};
6310   let Inst{12} = b15_b12{0};
6311 }
6312
6313 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6314                                       string asm> {
6315   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6316                                                  asm, ".4h", []>;
6317   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6318                                                  asm, ".8h", []>;
6319
6320   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6321                                              asm, ".2s", []>;
6322   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6323                                              asm, ".4s", []>;
6324 }
6325
6326 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6327                                       bits<2> w_cmode, string asm,
6328                                       SDNode OpNode> {
6329   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6330                                                  asm, ".4h",
6331              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6332                                              imm0_255:$imm8,
6333                                              (i32 imm:$shift)))]>;
6334   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6335                                                  asm, ".8h",
6336              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6337                                               imm0_255:$imm8,
6338                                               (i32 imm:$shift)))]>;
6339
6340   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6341                                              asm, ".2s",
6342              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6343                                              imm0_255:$imm8,
6344                                              (i32 imm:$shift)))]>;
6345   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6346                                              asm, ".4s",
6347              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6348                                               imm0_255:$imm8,
6349                                               (i32 imm:$shift)))]>;
6350 }
6351
6352 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6353                              RegisterOperand vectype, string asm,
6354                              string kind, list<dag> pattern>
6355   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6356                               (ins move_vec_shift:$shift),
6357                               "$shift", asm, kind, pattern> {
6358   bits<1> shift;
6359   let Inst{15-13} = cmode{3-1};
6360   let Inst{12}    = shift;
6361 }
6362
6363 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
6364                                    RegisterOperand vectype,
6365                                    Operand imm_type, string asm,
6366                                    string kind, list<dag> pattern>
6367   : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
6368                               asm, kind, pattern> {
6369   let Inst{15-12} = cmode;
6370 }
6371
6372 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6373                                    list<dag> pattern>
6374   : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6375                         "\t$Rd, $imm8", "", pattern> {
6376   let Inst{15-12} = cmode;
6377   let DecoderMethod = "DecodeModImmInstruction";
6378 }
6379
6380 //----------------------------------------------------------------------------
6381 // AdvSIMD indexed element
6382 //----------------------------------------------------------------------------
6383
6384 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6385 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6386                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6387                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6388                       string apple_kind, string dst_kind, string lhs_kind,
6389                       string rhs_kind, list<dag> pattern>
6390   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6391       asm,
6392       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6393       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6394     Sched<[WriteV]> {
6395   bits<5> Rd;
6396   bits<5> Rn;
6397   bits<5> Rm;
6398
6399   let Inst{31}    = 0;
6400   let Inst{30}    = Q;
6401   let Inst{29}    = U;
6402   let Inst{28}    = Scalar;
6403   let Inst{27-24} = 0b1111;
6404   let Inst{23-22} = size;
6405   // Bit 21 must be set by the derived class.
6406   let Inst{20-16} = Rm;
6407   let Inst{15-12} = opc;
6408   // Bit 11 must be set by the derived class.
6409   let Inst{10}    = 0;
6410   let Inst{9-5}   = Rn;
6411   let Inst{4-0}   = Rd;
6412 }
6413
6414 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6415 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6416                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6417                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6418                       string apple_kind, string dst_kind, string lhs_kind,
6419                       string rhs_kind, list<dag> pattern>
6420   : I<(outs dst_reg:$dst),
6421       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6422       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6423       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6424     Sched<[WriteV]> {
6425   bits<5> Rd;
6426   bits<5> Rn;
6427   bits<5> Rm;
6428
6429   let Inst{31}    = 0;
6430   let Inst{30}    = Q;
6431   let Inst{29}    = U;
6432   let Inst{28}    = Scalar;
6433   let Inst{27-24} = 0b1111;
6434   let Inst{23-22} = size;
6435   // Bit 21 must be set by the derived class.
6436   let Inst{20-16} = Rm;
6437   let Inst{15-12} = opc;
6438   // Bit 11 must be set by the derived class.
6439   let Inst{10}    = 0;
6440   let Inst{9-5}   = Rn;
6441   let Inst{4-0}   = Rd;
6442 }
6443
6444 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
6445                            SDPatternOperator OpNode> {
6446   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6447                                       V64, V64,
6448                                       V128, VectorIndexS,
6449                                       asm, ".2s", ".2s", ".2s", ".s",
6450     [(set (v2f32 V64:$Rd),
6451         (OpNode (v2f32 V64:$Rn),
6452          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6453     bits<2> idx;
6454     let Inst{11} = idx{1};
6455     let Inst{21} = idx{0};
6456   }
6457
6458   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6459                                       V128, V128,
6460                                       V128, VectorIndexS,
6461                                       asm, ".4s", ".4s", ".4s", ".s",
6462     [(set (v4f32 V128:$Rd),
6463         (OpNode (v4f32 V128:$Rn),
6464          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6465     bits<2> idx;
6466     let Inst{11} = idx{1};
6467     let Inst{21} = idx{0};
6468   }
6469
6470   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6471                                       V128, V128,
6472                                       V128, VectorIndexD,
6473                                       asm, ".2d", ".2d", ".2d", ".d",
6474     [(set (v2f64 V128:$Rd),
6475         (OpNode (v2f64 V128:$Rn),
6476          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6477     bits<1> idx;
6478     let Inst{11} = idx{0};
6479     let Inst{21} = 0;
6480   }
6481
6482   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6483                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6484                                       asm, ".s", "", "", ".s",
6485     [(set (f32 FPR32Op:$Rd),
6486           (OpNode (f32 FPR32Op:$Rn),
6487                   (f32 (vector_extract (v4f32 V128:$Rm),
6488                                        VectorIndexS:$idx))))]> {
6489     bits<2> idx;
6490     let Inst{11} = idx{1};
6491     let Inst{21} = idx{0};
6492   }
6493
6494   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6495                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6496                                       asm, ".d", "", "", ".d",
6497     [(set (f64 FPR64Op:$Rd),
6498           (OpNode (f64 FPR64Op:$Rn),
6499                   (f64 (vector_extract (v2f64 V128:$Rm),
6500                                        VectorIndexD:$idx))))]> {
6501     bits<1> idx;
6502     let Inst{11} = idx{0};
6503     let Inst{21} = 0;
6504   }
6505 }
6506
6507 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6508   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6509   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6510                            (AArch64duplane32 (v4f32 V128:$Rm),
6511                                            VectorIndexS:$idx))),
6512             (!cast<Instruction>(INST # v2i32_indexed)
6513                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6514   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6515                            (AArch64dup (f32 FPR32Op:$Rm)))),
6516             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6517                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6518
6519
6520   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6521   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6522                            (AArch64duplane32 (v4f32 V128:$Rm),
6523                                            VectorIndexS:$idx))),
6524             (!cast<Instruction>(INST # "v4i32_indexed")
6525                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6526   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6527                            (AArch64dup (f32 FPR32Op:$Rm)))),
6528             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6529                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6530
6531   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6532   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6533                            (AArch64duplane64 (v2f64 V128:$Rm),
6534                                            VectorIndexD:$idx))),
6535             (!cast<Instruction>(INST # "v2i64_indexed")
6536                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6537   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6538                            (AArch64dup (f64 FPR64Op:$Rm)))),
6539             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6540                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6541
6542   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6543   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6544                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6545             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6546                 V128:$Rm, VectorIndexS:$idx)>;
6547   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6548                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6549             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6550                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6551
6552   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6553   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6554                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6555             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6556                 V128:$Rm, VectorIndexD:$idx)>;
6557 }
6558
6559 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6560   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6561                                           V128, VectorIndexS,
6562                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6563     bits<2> idx;
6564     let Inst{11} = idx{1};
6565     let Inst{21} = idx{0};
6566   }
6567
6568   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6569                                       V128, V128,
6570                                       V128, VectorIndexS,
6571                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6572     bits<2> idx;
6573     let Inst{11} = idx{1};
6574     let Inst{21} = idx{0};
6575   }
6576
6577   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6578                                       V128, V128,
6579                                       V128, VectorIndexD,
6580                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6581     bits<1> idx;
6582     let Inst{11} = idx{0};
6583     let Inst{21} = 0;
6584   }
6585
6586
6587   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6588                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6589                                       asm, ".s", "", "", ".s", []> {
6590     bits<2> idx;
6591     let Inst{11} = idx{1};
6592     let Inst{21} = idx{0};
6593   }
6594
6595   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6596                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6597                                       asm, ".d", "", "", ".d", []> {
6598     bits<1> idx;
6599     let Inst{11} = idx{0};
6600     let Inst{21} = 0;
6601   }
6602 }
6603
6604 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6605                          SDPatternOperator OpNode> {
6606   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6607                                       V128_lo, VectorIndexH,
6608                                       asm, ".4h", ".4h", ".4h", ".h",
6609     [(set (v4i16 V64:$Rd),
6610         (OpNode (v4i16 V64:$Rn),
6611          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6612     bits<3> idx;
6613     let Inst{11} = idx{2};
6614     let Inst{21} = idx{1};
6615     let Inst{20} = idx{0};
6616   }
6617
6618   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6619                                       V128, V128,
6620                                       V128_lo, VectorIndexH,
6621                                       asm, ".8h", ".8h", ".8h", ".h",
6622     [(set (v8i16 V128:$Rd),
6623        (OpNode (v8i16 V128:$Rn),
6624          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6625     bits<3> idx;
6626     let Inst{11} = idx{2};
6627     let Inst{21} = idx{1};
6628     let Inst{20} = idx{0};
6629   }
6630
6631   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6632                                       V64, V64,
6633                                       V128, VectorIndexS,
6634                                       asm, ".2s", ".2s", ".2s",  ".s",
6635     [(set (v2i32 V64:$Rd),
6636        (OpNode (v2i32 V64:$Rn),
6637           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6638     bits<2> idx;
6639     let Inst{11} = idx{1};
6640     let Inst{21} = idx{0};
6641   }
6642
6643   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6644                                       V128, V128,
6645                                       V128, VectorIndexS,
6646                                       asm, ".4s", ".4s", ".4s", ".s",
6647     [(set (v4i32 V128:$Rd),
6648        (OpNode (v4i32 V128:$Rn),
6649           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6650     bits<2> idx;
6651     let Inst{11} = idx{1};
6652     let Inst{21} = idx{0};
6653   }
6654
6655   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6656                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6657                                       asm, ".h", "", "", ".h", []> {
6658     bits<3> idx;
6659     let Inst{11} = idx{2};
6660     let Inst{21} = idx{1};
6661     let Inst{20} = idx{0};
6662   }
6663
6664   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6665                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6666                                       asm, ".s", "", "", ".s",
6667       [(set (i32 FPR32Op:$Rd),
6668             (OpNode FPR32Op:$Rn,
6669                     (i32 (vector_extract (v4i32 V128:$Rm),
6670                                          VectorIndexS:$idx))))]> {
6671     bits<2> idx;
6672     let Inst{11} = idx{1};
6673     let Inst{21} = idx{0};
6674   }
6675 }
6676
6677 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6678                                SDPatternOperator OpNode> {
6679   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6680                                       V64, V64,
6681                                       V128_lo, VectorIndexH,
6682                                       asm, ".4h", ".4h", ".4h", ".h",
6683     [(set (v4i16 V64:$Rd),
6684         (OpNode (v4i16 V64:$Rn),
6685          (v4i16 (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 v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6693                                       V128, V128,
6694                                       V128_lo, VectorIndexH,
6695                                       asm, ".8h", ".8h", ".8h", ".h",
6696     [(set (v8i16 V128:$Rd),
6697        (OpNode (v8i16 V128:$Rn),
6698          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6699     bits<3> idx;
6700     let Inst{11} = idx{2};
6701     let Inst{21} = idx{1};
6702     let Inst{20} = idx{0};
6703   }
6704
6705   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6706                                       V64, V64,
6707                                       V128, VectorIndexS,
6708                                       asm, ".2s", ".2s", ".2s", ".s",
6709     [(set (v2i32 V64:$Rd),
6710        (OpNode (v2i32 V64:$Rn),
6711           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6712     bits<2> idx;
6713     let Inst{11} = idx{1};
6714     let Inst{21} = idx{0};
6715   }
6716
6717   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6718                                       V128, V128,
6719                                       V128, VectorIndexS,
6720                                       asm, ".4s", ".4s", ".4s", ".s",
6721     [(set (v4i32 V128:$Rd),
6722        (OpNode (v4i32 V128:$Rn),
6723           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6724     bits<2> idx;
6725     let Inst{11} = idx{1};
6726     let Inst{21} = idx{0};
6727   }
6728 }
6729
6730 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6731                                    SDPatternOperator OpNode> {
6732   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6733                                           V128_lo, VectorIndexH,
6734                                           asm, ".4h", ".4h", ".4h", ".h",
6735     [(set (v4i16 V64:$dst),
6736         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6737          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6738     bits<3> idx;
6739     let Inst{11} = idx{2};
6740     let Inst{21} = idx{1};
6741     let Inst{20} = idx{0};
6742   }
6743
6744   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6745                                       V128, V128,
6746                                       V128_lo, VectorIndexH,
6747                                       asm, ".8h", ".8h", ".8h", ".h",
6748     [(set (v8i16 V128:$dst),
6749        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6750          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6751     bits<3> idx;
6752     let Inst{11} = idx{2};
6753     let Inst{21} = idx{1};
6754     let Inst{20} = idx{0};
6755   }
6756
6757   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6758                                       V64, V64,
6759                                       V128, VectorIndexS,
6760                                       asm, ".2s", ".2s", ".2s", ".s",
6761     [(set (v2i32 V64:$dst),
6762        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6763           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6764     bits<2> idx;
6765     let Inst{11} = idx{1};
6766     let Inst{21} = idx{0};
6767   }
6768
6769   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6770                                       V128, V128,
6771                                       V128, VectorIndexS,
6772                                       asm, ".4s", ".4s", ".4s", ".s",
6773     [(set (v4i32 V128:$dst),
6774        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6775           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6776     bits<2> idx;
6777     let Inst{11} = idx{1};
6778     let Inst{21} = idx{0};
6779   }
6780 }
6781
6782 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6783                              SDPatternOperator OpNode> {
6784   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6785                                       V128, V64,
6786                                       V128_lo, VectorIndexH,
6787                                       asm, ".4s", ".4s", ".4h", ".h",
6788     [(set (v4i32 V128:$Rd),
6789         (OpNode (v4i16 V64:$Rn),
6790          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6791     bits<3> idx;
6792     let Inst{11} = idx{2};
6793     let Inst{21} = idx{1};
6794     let Inst{20} = idx{0};
6795   }
6796
6797   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6798                                       V128, V128,
6799                                       V128_lo, VectorIndexH,
6800                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6801     [(set (v4i32 V128:$Rd),
6802           (OpNode (extract_high_v8i16 V128:$Rn),
6803                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6804                                                       VectorIndexH:$idx))))]> {
6805
6806     bits<3> idx;
6807     let Inst{11} = idx{2};
6808     let Inst{21} = idx{1};
6809     let Inst{20} = idx{0};
6810   }
6811
6812   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6813                                       V128, V64,
6814                                       V128, VectorIndexS,
6815                                       asm, ".2d", ".2d", ".2s", ".s",
6816     [(set (v2i64 V128:$Rd),
6817         (OpNode (v2i32 V64:$Rn),
6818          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6819     bits<2> idx;
6820     let Inst{11} = idx{1};
6821     let Inst{21} = idx{0};
6822   }
6823
6824   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6825                                       V128, V128,
6826                                       V128, VectorIndexS,
6827                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6828     [(set (v2i64 V128:$Rd),
6829           (OpNode (extract_high_v4i32 V128:$Rn),
6830                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
6831                                                       VectorIndexS:$idx))))]> {
6832     bits<2> idx;
6833     let Inst{11} = idx{1};
6834     let Inst{21} = idx{0};
6835   }
6836
6837   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6838                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6839                                       asm, ".h", "", "", ".h", []> {
6840     bits<3> idx;
6841     let Inst{11} = idx{2};
6842     let Inst{21} = idx{1};
6843     let Inst{20} = idx{0};
6844   }
6845
6846   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6847                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6848                                       asm, ".s", "", "", ".s", []> {
6849     bits<2> idx;
6850     let Inst{11} = idx{1};
6851     let Inst{21} = idx{0};
6852   }
6853 }
6854
6855 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6856                                        SDPatternOperator Accum> {
6857   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6858                                       V128, V64,
6859                                       V128_lo, VectorIndexH,
6860                                       asm, ".4s", ".4s", ".4h", ".h",
6861     [(set (v4i32 V128:$dst),
6862           (Accum (v4i32 V128:$Rd),
6863                  (v4i32 (int_aarch64_neon_sqdmull
6864                              (v4i16 V64:$Rn),
6865                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6866                                                     VectorIndexH:$idx))))))]> {
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   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6874   // intermediate EXTRACT_SUBREG would be untyped.
6875   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6876                 (i32 (vector_extract (v4i32
6877                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6878                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6879                                                     VectorIndexH:$idx)))),
6880                          (i64 0))))),
6881             (EXTRACT_SUBREG
6882                 (!cast<Instruction>(NAME # v4i16_indexed)
6883                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6884                     V128_lo:$Rm, VectorIndexH:$idx),
6885                 ssub)>;
6886
6887   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6888                                       V128, V128,
6889                                       V128_lo, VectorIndexH,
6890                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6891     [(set (v4i32 V128:$dst),
6892           (Accum (v4i32 V128:$Rd),
6893                  (v4i32 (int_aarch64_neon_sqdmull
6894                             (extract_high_v8i16 V128:$Rn),
6895                             (extract_high_v8i16
6896                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6897                                                 VectorIndexH:$idx))))))]> {
6898     bits<3> idx;
6899     let Inst{11} = idx{2};
6900     let Inst{21} = idx{1};
6901     let Inst{20} = idx{0};
6902   }
6903
6904   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6905                                       V128, V64,
6906                                       V128, VectorIndexS,
6907                                       asm, ".2d", ".2d", ".2s", ".s",
6908     [(set (v2i64 V128:$dst),
6909         (Accum (v2i64 V128:$Rd),
6910                (v2i64 (int_aarch64_neon_sqdmull
6911                           (v2i32 V64:$Rn),
6912                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
6913                                                  VectorIndexS:$idx))))))]> {
6914     bits<2> idx;
6915     let Inst{11} = idx{1};
6916     let Inst{21} = idx{0};
6917   }
6918
6919   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6920                                       V128, V128,
6921                                       V128, VectorIndexS,
6922                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6923     [(set (v2i64 V128:$dst),
6924           (Accum (v2i64 V128:$Rd),
6925                  (v2i64 (int_aarch64_neon_sqdmull
6926                             (extract_high_v4i32 V128:$Rn),
6927                             (extract_high_v4i32
6928                                 (AArch64duplane32 (v4i32 V128:$Rm),
6929                                                 VectorIndexS:$idx))))))]> {
6930     bits<2> idx;
6931     let Inst{11} = idx{1};
6932     let Inst{21} = idx{0};
6933   }
6934
6935   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6936                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6937                                       asm, ".h", "", "", ".h", []> {
6938     bits<3> idx;
6939     let Inst{11} = idx{2};
6940     let Inst{21} = idx{1};
6941     let Inst{20} = idx{0};
6942   }
6943
6944
6945   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6946                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6947                                       asm, ".s", "", "", ".s",
6948     [(set (i64 FPR64Op:$dst),
6949           (Accum (i64 FPR64Op:$Rd),
6950                  (i64 (int_aarch64_neon_sqdmulls_scalar
6951                             (i32 FPR32Op:$Rn),
6952                             (i32 (vector_extract (v4i32 V128:$Rm),
6953                                                  VectorIndexS:$idx))))))]> {
6954
6955     bits<2> idx;
6956     let Inst{11} = idx{1};
6957     let Inst{21} = idx{0};
6958   }
6959 }
6960
6961 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6962                                    SDPatternOperator OpNode> {
6963   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6964   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6965                                       V128, V64,
6966                                       V128_lo, VectorIndexH,
6967                                       asm, ".4s", ".4s", ".4h", ".h",
6968     [(set (v4i32 V128:$Rd),
6969         (OpNode (v4i16 V64:$Rn),
6970          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6971     bits<3> idx;
6972     let Inst{11} = idx{2};
6973     let Inst{21} = idx{1};
6974     let Inst{20} = idx{0};
6975   }
6976
6977   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6978                                       V128, V128,
6979                                       V128_lo, VectorIndexH,
6980                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6981     [(set (v4i32 V128:$Rd),
6982           (OpNode (extract_high_v8i16 V128:$Rn),
6983                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6984                                                       VectorIndexH:$idx))))]> {
6985
6986     bits<3> idx;
6987     let Inst{11} = idx{2};
6988     let Inst{21} = idx{1};
6989     let Inst{20} = idx{0};
6990   }
6991
6992   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6993                                       V128, V64,
6994                                       V128, VectorIndexS,
6995                                       asm, ".2d", ".2d", ".2s", ".s",
6996     [(set (v2i64 V128:$Rd),
6997         (OpNode (v2i32 V64:$Rn),
6998          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6999     bits<2> idx;
7000     let Inst{11} = idx{1};
7001     let Inst{21} = idx{0};
7002   }
7003
7004   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7005                                       V128, V128,
7006                                       V128, VectorIndexS,
7007                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7008     [(set (v2i64 V128:$Rd),
7009           (OpNode (extract_high_v4i32 V128:$Rn),
7010                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7011                                                       VectorIndexS:$idx))))]> {
7012     bits<2> idx;
7013     let Inst{11} = idx{1};
7014     let Inst{21} = idx{0};
7015   }
7016   }
7017 }
7018
7019 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7020                                        SDPatternOperator OpNode> {
7021   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7022   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7023                                       V128, V64,
7024                                       V128_lo, VectorIndexH,
7025                                       asm, ".4s", ".4s", ".4h", ".h",
7026     [(set (v4i32 V128:$dst),
7027         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7028          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7029     bits<3> idx;
7030     let Inst{11} = idx{2};
7031     let Inst{21} = idx{1};
7032     let Inst{20} = idx{0};
7033   }
7034
7035   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7036                                       V128, V128,
7037                                       V128_lo, VectorIndexH,
7038                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7039     [(set (v4i32 V128:$dst),
7040           (OpNode (v4i32 V128:$Rd),
7041                   (extract_high_v8i16 V128:$Rn),
7042                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7043                                                       VectorIndexH:$idx))))]> {
7044     bits<3> idx;
7045     let Inst{11} = idx{2};
7046     let Inst{21} = idx{1};
7047     let Inst{20} = idx{0};
7048   }
7049
7050   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7051                                       V128, V64,
7052                                       V128, VectorIndexS,
7053                                       asm, ".2d", ".2d", ".2s", ".s",
7054     [(set (v2i64 V128:$dst),
7055         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7056          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7057     bits<2> idx;
7058     let Inst{11} = idx{1};
7059     let Inst{21} = idx{0};
7060   }
7061
7062   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7063                                       V128, V128,
7064                                       V128, VectorIndexS,
7065                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7066     [(set (v2i64 V128:$dst),
7067           (OpNode (v2i64 V128:$Rd),
7068                   (extract_high_v4i32 V128:$Rn),
7069                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7070                                                       VectorIndexS:$idx))))]> {
7071     bits<2> idx;
7072     let Inst{11} = idx{1};
7073     let Inst{21} = idx{0};
7074   }
7075   }
7076 }
7077
7078 //----------------------------------------------------------------------------
7079 // AdvSIMD scalar shift by immediate
7080 //----------------------------------------------------------------------------
7081
7082 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7083 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7084                      RegisterClass regtype1, RegisterClass regtype2,
7085                      Operand immtype, string asm, list<dag> pattern>
7086   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7087       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7088     Sched<[WriteV]> {
7089   bits<5> Rd;
7090   bits<5> Rn;
7091   bits<7> imm;
7092   let Inst{31-30} = 0b01;
7093   let Inst{29}    = U;
7094   let Inst{28-23} = 0b111110;
7095   let Inst{22-16} = fixed_imm;
7096   let Inst{15-11} = opc;
7097   let Inst{10}    = 1;
7098   let Inst{9-5} = Rn;
7099   let Inst{4-0} = Rd;
7100 }
7101
7102 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7103 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7104                      RegisterClass regtype1, RegisterClass regtype2,
7105                      Operand immtype, string asm, list<dag> pattern>
7106   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7107       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7108     Sched<[WriteV]> {
7109   bits<5> Rd;
7110   bits<5> Rn;
7111   bits<7> imm;
7112   let Inst{31-30} = 0b01;
7113   let Inst{29}    = U;
7114   let Inst{28-23} = 0b111110;
7115   let Inst{22-16} = fixed_imm;
7116   let Inst{15-11} = opc;
7117   let Inst{10}    = 1;
7118   let Inst{9-5} = Rn;
7119   let Inst{4-0} = Rd;
7120 }
7121
7122
7123 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
7124   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7125                               FPR32, FPR32, vecshiftR32, asm, []> {
7126     let Inst{20-16} = imm{4-0};
7127   }
7128
7129   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7130                               FPR64, FPR64, vecshiftR64, asm, []> {
7131     let Inst{21-16} = imm{5-0};
7132   }
7133 }
7134
7135 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7136                              SDPatternOperator OpNode> {
7137   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7138                               FPR64, FPR64, vecshiftR64, asm,
7139   [(set (i64 FPR64:$Rd),
7140      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7141     let Inst{21-16} = imm{5-0};
7142   }
7143
7144   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7145             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7146 }
7147
7148 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7149                                  SDPatternOperator OpNode = null_frag> {
7150   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7151                               FPR64, FPR64, vecshiftR64, asm,
7152   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7153                                                    (i32 vecshiftR64:$imm)))]> {
7154     let Inst{21-16} = imm{5-0};
7155   }
7156
7157   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7158                            (i32 vecshiftR64:$imm))),
7159             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7160                                             vecshiftR64:$imm)>;
7161 }
7162
7163 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7164                              SDPatternOperator OpNode> {
7165   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7166                               FPR64, FPR64, vecshiftL64, asm,
7167     [(set (v1i64 FPR64:$Rd),
7168        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7169     let Inst{21-16} = imm{5-0};
7170   }
7171 }
7172
7173 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7174 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7175   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7176                               FPR64, FPR64, vecshiftL64, asm, []> {
7177     let Inst{21-16} = imm{5-0};
7178   }
7179 }
7180
7181 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7182 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7183                                SDPatternOperator OpNode = null_frag> {
7184   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7185                               FPR8, FPR16, vecshiftR8, asm, []> {
7186     let Inst{18-16} = imm{2-0};
7187   }
7188
7189   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7190                               FPR16, FPR32, vecshiftR16, asm, []> {
7191     let Inst{19-16} = imm{3-0};
7192   }
7193
7194   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7195                               FPR32, FPR64, vecshiftR32, asm,
7196     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7197     let Inst{20-16} = imm{4-0};
7198   }
7199 }
7200
7201 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7202                                 SDPatternOperator OpNode> {
7203   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7204                               FPR8, FPR8, vecshiftL8, asm, []> {
7205     let Inst{18-16} = imm{2-0};
7206   }
7207
7208   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7209                               FPR16, FPR16, vecshiftL16, asm, []> {
7210     let Inst{19-16} = imm{3-0};
7211   }
7212
7213   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7214                               FPR32, FPR32, vecshiftL32, asm,
7215     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7216     let Inst{20-16} = imm{4-0};
7217   }
7218
7219   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7220                               FPR64, FPR64, vecshiftL64, asm,
7221     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7222     let Inst{21-16} = imm{5-0};
7223   }
7224
7225   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7226             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7227 }
7228
7229 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7230   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7231                               FPR8, FPR8, vecshiftR8, asm, []> {
7232     let Inst{18-16} = imm{2-0};
7233   }
7234
7235   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7236                               FPR16, FPR16, vecshiftR16, asm, []> {
7237     let Inst{19-16} = imm{3-0};
7238   }
7239
7240   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7241                               FPR32, FPR32, vecshiftR32, asm, []> {
7242     let Inst{20-16} = imm{4-0};
7243   }
7244
7245   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7246                               FPR64, FPR64, vecshiftR64, asm, []> {
7247     let Inst{21-16} = imm{5-0};
7248   }
7249 }
7250
7251 //----------------------------------------------------------------------------
7252 // AdvSIMD vector x indexed element
7253 //----------------------------------------------------------------------------
7254
7255 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7256 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7257                      RegisterOperand dst_reg, RegisterOperand src_reg,
7258                      Operand immtype,
7259                      string asm, string dst_kind, string src_kind,
7260                      list<dag> pattern>
7261   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7262       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7263            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7264     Sched<[WriteV]> {
7265   bits<5> Rd;
7266   bits<5> Rn;
7267   let Inst{31}    = 0;
7268   let Inst{30}    = Q;
7269   let Inst{29}    = U;
7270   let Inst{28-23} = 0b011110;
7271   let Inst{22-16} = fixed_imm;
7272   let Inst{15-11} = opc;
7273   let Inst{10}    = 1;
7274   let Inst{9-5}   = Rn;
7275   let Inst{4-0}   = Rd;
7276 }
7277
7278 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7279 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7280                      RegisterOperand vectype1, RegisterOperand vectype2,
7281                      Operand immtype,
7282                      string asm, string dst_kind, string src_kind,
7283                      list<dag> pattern>
7284   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7285       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7286            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7287     Sched<[WriteV]> {
7288   bits<5> Rd;
7289   bits<5> Rn;
7290   let Inst{31}    = 0;
7291   let Inst{30}    = Q;
7292   let Inst{29}    = U;
7293   let Inst{28-23} = 0b011110;
7294   let Inst{22-16} = fixed_imm;
7295   let Inst{15-11} = opc;
7296   let Inst{10}    = 1;
7297   let Inst{9-5}   = Rn;
7298   let Inst{4-0}   = Rd;
7299 }
7300
7301 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7302                               Intrinsic OpNode> {
7303   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7304                                   V64, V64, vecshiftR32,
7305                                   asm, ".2s", ".2s",
7306       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
7307     bits<5> imm;
7308     let Inst{20-16} = imm;
7309   }
7310
7311   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7312                                   V128, V128, vecshiftR32,
7313                                   asm, ".4s", ".4s",
7314       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7315     bits<5> imm;
7316     let Inst{20-16} = imm;
7317   }
7318
7319   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7320                                   V128, V128, vecshiftR64,
7321                                   asm, ".2d", ".2d",
7322       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7323     bits<6> imm;
7324     let Inst{21-16} = imm;
7325   }
7326 }
7327
7328 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
7329                                   Intrinsic OpNode> {
7330   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7331                                   V64, V64, vecshiftR32,
7332                                   asm, ".2s", ".2s",
7333       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7334     bits<5> imm;
7335     let Inst{20-16} = imm;
7336   }
7337
7338   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7339                                   V128, V128, vecshiftR32,
7340                                   asm, ".4s", ".4s",
7341       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7342     bits<5> imm;
7343     let Inst{20-16} = imm;
7344   }
7345
7346   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7347                                   V128, V128, vecshiftR64,
7348                                   asm, ".2d", ".2d",
7349       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7350     bits<6> imm;
7351     let Inst{21-16} = imm;
7352   }
7353 }
7354
7355 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7356                                      SDPatternOperator OpNode> {
7357   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7358                                   V64, V128, vecshiftR16Narrow,
7359                                   asm, ".8b", ".8h",
7360       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7361     bits<3> imm;
7362     let Inst{18-16} = imm;
7363   }
7364
7365   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7366                                   V128, V128, vecshiftR16Narrow,
7367                                   asm#"2", ".16b", ".8h", []> {
7368     bits<3> imm;
7369     let Inst{18-16} = imm;
7370     let hasSideEffects = 0;
7371   }
7372
7373   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7374                                   V64, V128, vecshiftR32Narrow,
7375                                   asm, ".4h", ".4s",
7376       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7377     bits<4> imm;
7378     let Inst{19-16} = imm;
7379   }
7380
7381   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7382                                   V128, V128, vecshiftR32Narrow,
7383                                   asm#"2", ".8h", ".4s", []> {
7384     bits<4> imm;
7385     let Inst{19-16} = imm;
7386     let hasSideEffects = 0;
7387   }
7388
7389   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7390                                   V64, V128, vecshiftR64Narrow,
7391                                   asm, ".2s", ".2d",
7392       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7393     bits<5> imm;
7394     let Inst{20-16} = imm;
7395   }
7396
7397   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7398                                   V128, V128, vecshiftR64Narrow,
7399                                   asm#"2", ".4s", ".2d", []> {
7400     bits<5> imm;
7401     let Inst{20-16} = imm;
7402     let hasSideEffects = 0;
7403   }
7404
7405   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7406   // themselves, so put them here instead.
7407
7408   // Patterns involving what's effectively an insert high and a normal
7409   // intrinsic, represented by CONCAT_VECTORS.
7410   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7411                                                    vecshiftR16Narrow:$imm)),
7412             (!cast<Instruction>(NAME # "v16i8_shift")
7413                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7414                 V128:$Rn, vecshiftR16Narrow:$imm)>;
7415   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7416                                                      vecshiftR32Narrow:$imm)),
7417             (!cast<Instruction>(NAME # "v8i16_shift")
7418                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7419                 V128:$Rn, vecshiftR32Narrow:$imm)>;
7420   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7421                                                      vecshiftR64Narrow:$imm)),
7422             (!cast<Instruction>(NAME # "v4i32_shift")
7423                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7424                 V128:$Rn, vecshiftR64Narrow:$imm)>;
7425 }
7426
7427 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7428                                 SDPatternOperator OpNode> {
7429   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7430                                   V64, V64, vecshiftL8,
7431                                   asm, ".8b", ".8b",
7432                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7433                        (i32 vecshiftL8:$imm)))]> {
7434     bits<3> imm;
7435     let Inst{18-16} = imm;
7436   }
7437
7438   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7439                                   V128, V128, vecshiftL8,
7440                                   asm, ".16b", ".16b",
7441              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7442                    (i32 vecshiftL8:$imm)))]> {
7443     bits<3> imm;
7444     let Inst{18-16} = imm;
7445   }
7446
7447   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7448                                   V64, V64, vecshiftL16,
7449                                   asm, ".4h", ".4h",
7450               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7451                     (i32 vecshiftL16:$imm)))]> {
7452     bits<4> imm;
7453     let Inst{19-16} = imm;
7454   }
7455
7456   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7457                                   V128, V128, vecshiftL16,
7458                                   asm, ".8h", ".8h",
7459             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7460                   (i32 vecshiftL16:$imm)))]> {
7461     bits<4> imm;
7462     let Inst{19-16} = imm;
7463   }
7464
7465   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7466                                   V64, V64, vecshiftL32,
7467                                   asm, ".2s", ".2s",
7468               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7469                     (i32 vecshiftL32:$imm)))]> {
7470     bits<5> imm;
7471     let Inst{20-16} = imm;
7472   }
7473
7474   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7475                                   V128, V128, vecshiftL32,
7476                                   asm, ".4s", ".4s",
7477             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7478                   (i32 vecshiftL32:$imm)))]> {
7479     bits<5> imm;
7480     let Inst{20-16} = imm;
7481   }
7482
7483   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7484                                   V128, V128, vecshiftL64,
7485                                   asm, ".2d", ".2d",
7486             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7487                   (i32 vecshiftL64:$imm)))]> {
7488     bits<6> imm;
7489     let Inst{21-16} = imm;
7490   }
7491 }
7492
7493 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7494                                 SDPatternOperator OpNode> {
7495   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7496                                   V64, V64, vecshiftR8,
7497                                   asm, ".8b", ".8b",
7498                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7499                        (i32 vecshiftR8:$imm)))]> {
7500     bits<3> imm;
7501     let Inst{18-16} = imm;
7502   }
7503
7504   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7505                                   V128, V128, vecshiftR8,
7506                                   asm, ".16b", ".16b",
7507              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7508                    (i32 vecshiftR8:$imm)))]> {
7509     bits<3> imm;
7510     let Inst{18-16} = imm;
7511   }
7512
7513   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7514                                   V64, V64, vecshiftR16,
7515                                   asm, ".4h", ".4h",
7516               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7517                     (i32 vecshiftR16:$imm)))]> {
7518     bits<4> imm;
7519     let Inst{19-16} = imm;
7520   }
7521
7522   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7523                                   V128, V128, vecshiftR16,
7524                                   asm, ".8h", ".8h",
7525             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7526                   (i32 vecshiftR16:$imm)))]> {
7527     bits<4> imm;
7528     let Inst{19-16} = imm;
7529   }
7530
7531   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7532                                   V64, V64, vecshiftR32,
7533                                   asm, ".2s", ".2s",
7534               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7535                     (i32 vecshiftR32:$imm)))]> {
7536     bits<5> imm;
7537     let Inst{20-16} = imm;
7538   }
7539
7540   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7541                                   V128, V128, vecshiftR32,
7542                                   asm, ".4s", ".4s",
7543             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7544                   (i32 vecshiftR32:$imm)))]> {
7545     bits<5> imm;
7546     let Inst{20-16} = imm;
7547   }
7548
7549   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7550                                   V128, V128, vecshiftR64,
7551                                   asm, ".2d", ".2d",
7552             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7553                   (i32 vecshiftR64:$imm)))]> {
7554     bits<6> imm;
7555     let Inst{21-16} = imm;
7556   }
7557 }
7558
7559 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7560 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7561                                     SDPatternOperator OpNode = null_frag> {
7562   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7563                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
7564                  [(set (v8i8 V64:$dst),
7565                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7566                            (i32 vecshiftR8:$imm)))]> {
7567     bits<3> imm;
7568     let Inst{18-16} = imm;
7569   }
7570
7571   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7572                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
7573              [(set (v16i8 V128:$dst),
7574                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7575                        (i32 vecshiftR8:$imm)))]> {
7576     bits<3> imm;
7577     let Inst{18-16} = imm;
7578   }
7579
7580   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7581                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
7582               [(set (v4i16 V64:$dst),
7583                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7584                         (i32 vecshiftR16:$imm)))]> {
7585     bits<4> imm;
7586     let Inst{19-16} = imm;
7587   }
7588
7589   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7590                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
7591             [(set (v8i16 V128:$dst),
7592               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7593                       (i32 vecshiftR16:$imm)))]> {
7594     bits<4> imm;
7595     let Inst{19-16} = imm;
7596   }
7597
7598   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7599                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
7600               [(set (v2i32 V64:$dst),
7601                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7602                         (i32 vecshiftR32:$imm)))]> {
7603     bits<5> imm;
7604     let Inst{20-16} = imm;
7605   }
7606
7607   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7608                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
7609             [(set (v4i32 V128:$dst),
7610               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7611                       (i32 vecshiftR32:$imm)))]> {
7612     bits<5> imm;
7613     let Inst{20-16} = imm;
7614   }
7615
7616   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7617                                   V128, V128, vecshiftR64,
7618                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7619               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7620                       (i32 vecshiftR64:$imm)))]> {
7621     bits<6> imm;
7622     let Inst{21-16} = imm;
7623   }
7624 }
7625
7626 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7627                                     SDPatternOperator OpNode = null_frag> {
7628   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7629                                   V64, V64, vecshiftL8,
7630                                   asm, ".8b", ".8b",
7631                     [(set (v8i8 V64:$dst),
7632                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7633                                   (i32 vecshiftL8:$imm)))]> {
7634     bits<3> imm;
7635     let Inst{18-16} = imm;
7636   }
7637
7638   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7639                                   V128, V128, vecshiftL8,
7640                                   asm, ".16b", ".16b",
7641                     [(set (v16i8 V128:$dst),
7642                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7643                                   (i32 vecshiftL8:$imm)))]> {
7644     bits<3> imm;
7645     let Inst{18-16} = imm;
7646   }
7647
7648   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7649                                   V64, V64, vecshiftL16,
7650                                   asm, ".4h", ".4h",
7651                     [(set (v4i16 V64:$dst),
7652                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7653                                    (i32 vecshiftL16:$imm)))]> {
7654     bits<4> imm;
7655     let Inst{19-16} = imm;
7656   }
7657
7658   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7659                                   V128, V128, vecshiftL16,
7660                                   asm, ".8h", ".8h",
7661                     [(set (v8i16 V128:$dst),
7662                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7663                                   (i32 vecshiftL16:$imm)))]> {
7664     bits<4> imm;
7665     let Inst{19-16} = imm;
7666   }
7667
7668   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7669                                   V64, V64, vecshiftL32,
7670                                   asm, ".2s", ".2s",
7671                     [(set (v2i32 V64:$dst),
7672                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7673                                   (i32 vecshiftL32:$imm)))]> {
7674     bits<5> imm;
7675     let Inst{20-16} = imm;
7676   }
7677
7678   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7679                                   V128, V128, vecshiftL32,
7680                                   asm, ".4s", ".4s",
7681                     [(set (v4i32 V128:$dst),
7682                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7683                                   (i32 vecshiftL32:$imm)))]> {
7684     bits<5> imm;
7685     let Inst{20-16} = imm;
7686   }
7687
7688   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7689                                   V128, V128, vecshiftL64,
7690                                   asm, ".2d", ".2d",
7691                     [(set (v2i64 V128:$dst),
7692                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7693                                   (i32 vecshiftL64:$imm)))]> {
7694     bits<6> imm;
7695     let Inst{21-16} = imm;
7696   }
7697 }
7698
7699 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7700                                    SDPatternOperator OpNode> {
7701   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7702                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
7703       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7704     bits<3> imm;
7705     let Inst{18-16} = imm;
7706   }
7707
7708   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7709                                   V128, V128, vecshiftL8,
7710                                   asm#"2", ".8h", ".16b",
7711       [(set (v8i16 V128:$Rd),
7712             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7713     bits<3> imm;
7714     let Inst{18-16} = imm;
7715   }
7716
7717   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7718                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
7719       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7720     bits<4> imm;
7721     let Inst{19-16} = imm;
7722   }
7723
7724   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7725                                   V128, V128, vecshiftL16,
7726                                   asm#"2", ".4s", ".8h",
7727       [(set (v4i32 V128:$Rd),
7728             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7729
7730     bits<4> imm;
7731     let Inst{19-16} = imm;
7732   }
7733
7734   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7735                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
7736       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7737     bits<5> imm;
7738     let Inst{20-16} = imm;
7739   }
7740
7741   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7742                                   V128, V128, vecshiftL32,
7743                                   asm#"2", ".2d", ".4s",
7744       [(set (v2i64 V128:$Rd),
7745             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7746     bits<5> imm;
7747     let Inst{20-16} = imm;
7748   }
7749 }
7750
7751
7752 //---
7753 // Vector load/store
7754 //---
7755 // SIMD ldX/stX no-index memory references don't allow the optional
7756 // ", #0" constant and handle post-indexing explicitly, so we use
7757 // a more specialized parse method for them. Otherwise, it's the same as
7758 // the general GPR64sp handling.
7759
7760 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7761                    string asm, dag oops, dag iops, list<dag> pattern>
7762   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
7763   bits<5> Vt;
7764   bits<5> Rn;
7765   let Inst{31} = 0;
7766   let Inst{30} = Q;
7767   let Inst{29-23} = 0b0011000;
7768   let Inst{22} = L;
7769   let Inst{21-16} = 0b000000;
7770   let Inst{15-12} = opcode;
7771   let Inst{11-10} = size;
7772   let Inst{9-5} = Rn;
7773   let Inst{4-0} = Vt;
7774 }
7775
7776 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7777                        string asm, dag oops, dag iops>
7778   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
7779   bits<5> Vt;
7780   bits<5> Rn;
7781   bits<5> Xm;
7782   let Inst{31} = 0;
7783   let Inst{30} = Q;
7784   let Inst{29-23} = 0b0011001;
7785   let Inst{22} = L;
7786   let Inst{21} = 0;
7787   let Inst{20-16} = Xm;
7788   let Inst{15-12} = opcode;
7789   let Inst{11-10} = size;
7790   let Inst{9-5} = Rn;
7791   let Inst{4-0} = Vt;
7792 }
7793
7794 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7795 // register post-index addressing from the zero register.
7796 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7797                            int Offset, int Size> {
7798   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7799   //      "ld1\t$Vt, [$Rn], #16"
7800   // may get mapped to
7801   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
7802   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
7803                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7804                       GPR64sp:$Rn,
7805                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7806                       XZR), 1>;
7807
7808   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7809   //      "ld1.8b\t$Vt, [$Rn], #16"
7810   // may get mapped to
7811   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
7812   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
7813                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7814                       GPR64sp:$Rn,
7815                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7816                       XZR), 0>;
7817
7818   // E.g. "ld1.8b { v0, v1 }, [x1]"
7819   //      "ld1\t$Vt, [$Rn]"
7820   // may get mapped to
7821   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
7822   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
7823                   (!cast<Instruction>(NAME # Count # "v" # layout)
7824                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7825                       GPR64sp:$Rn), 0>;
7826
7827   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7828   //      "ld1\t$Vt, [$Rn], $Xm"
7829   // may get mapped to
7830   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
7831   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
7832                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7833                       GPR64sp:$Rn,
7834                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7835                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7836 }
7837
7838 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7839                        int Offset64, bits<4> opcode> {
7840   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7841     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7842                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7843                            (ins GPR64sp:$Rn), []>;
7844     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7845                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7846                            (ins GPR64sp:$Rn), []>;
7847     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7848                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7849                            (ins GPR64sp:$Rn), []>;
7850     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7851                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7852                            (ins GPR64sp:$Rn), []>;
7853     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7854                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7855                            (ins GPR64sp:$Rn), []>;
7856     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7857                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7858                            (ins GPR64sp:$Rn), []>;
7859     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7860                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7861                            (ins GPR64sp:$Rn), []>;
7862
7863
7864     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7865                        (outs GPR64sp:$wback,
7866                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
7867                        (ins GPR64sp:$Rn,
7868                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7869     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7870                        (outs GPR64sp:$wback,
7871                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
7872                        (ins GPR64sp:$Rn,
7873                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7874     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7875                        (outs GPR64sp:$wback,
7876                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
7877                        (ins GPR64sp:$Rn,
7878                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7879     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7880                        (outs GPR64sp:$wback,
7881                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
7882                        (ins GPR64sp:$Rn,
7883                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7884     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7885                        (outs GPR64sp:$wback,
7886                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
7887                        (ins GPR64sp:$Rn,
7888                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7889     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7890                        (outs GPR64sp:$wback,
7891                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
7892                        (ins GPR64sp:$Rn,
7893                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7894     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7895                        (outs GPR64sp:$wback,
7896                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
7897                        (ins GPR64sp:$Rn,
7898                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7899   }
7900
7901   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7902   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7903   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7904   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7905   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7906   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7907   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7908 }
7909
7910 // Only ld1/st1 has a v1d version.
7911 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7912                        int Offset64, bits<4> opcode> {
7913   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7914     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7915                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7916                                  GPR64sp:$Rn), []>;
7917     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7918                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7919                                 GPR64sp:$Rn), []>;
7920     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7921                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7922                                 GPR64sp:$Rn), []>;
7923     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7924                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7925                                 GPR64sp:$Rn), []>;
7926     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7927                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7928                                 GPR64sp:$Rn), []>;
7929     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7930                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7931                                 GPR64sp:$Rn), []>;
7932     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7933                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7934                                 GPR64sp:$Rn), []>;
7935
7936     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
7937                        (outs GPR64sp:$wback),
7938                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7939                             GPR64sp:$Rn,
7940                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7941     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
7942                        (outs GPR64sp:$wback),
7943                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7944                             GPR64sp:$Rn,
7945                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7946     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
7947                        (outs GPR64sp:$wback),
7948                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7949                             GPR64sp:$Rn,
7950                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7951     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
7952                        (outs GPR64sp:$wback),
7953                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7954                             GPR64sp:$Rn,
7955                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7956     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
7957                        (outs GPR64sp:$wback),
7958                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7959                             GPR64sp:$Rn,
7960                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7961     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
7962                        (outs GPR64sp:$wback),
7963                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7964                             GPR64sp:$Rn,
7965                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7966     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
7967                        (outs GPR64sp:$wback),
7968                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7969                             GPR64sp:$Rn,
7970                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7971   }
7972
7973   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7974   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7975   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7976   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7977   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7978   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7979   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7980 }
7981
7982 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7983                        int Offset128, int Offset64, bits<4> opcode>
7984   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7985
7986   // LD1 instructions have extra "1d" variants.
7987   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7988     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7989                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7990                            (ins GPR64sp:$Rn), []>;
7991
7992     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7993                        (outs GPR64sp:$wback,
7994                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
7995                        (ins GPR64sp:$Rn,
7996                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7997   }
7998
7999   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8000 }
8001
8002 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
8003                        int Offset128, int Offset64, bits<4> opcode>
8004   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
8005
8006   // ST1 instructions have extra "1d" variants.
8007   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8008     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8009                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8010                                 GPR64sp:$Rn), []>;
8011
8012     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8013                        (outs GPR64sp:$wback),
8014                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8015                             GPR64sp:$Rn,
8016                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8017   }
8018
8019   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8020 }
8021
8022 multiclass SIMDLd1Multiple<string asm> {
8023   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8024   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8025   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8026   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8027 }
8028
8029 multiclass SIMDSt1Multiple<string asm> {
8030   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8031   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8032   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8033   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8034 }
8035
8036 multiclass SIMDLd2Multiple<string asm> {
8037   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8038 }
8039
8040 multiclass SIMDSt2Multiple<string asm> {
8041   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8042 }
8043
8044 multiclass SIMDLd3Multiple<string asm> {
8045   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8046 }
8047
8048 multiclass SIMDSt3Multiple<string asm> {
8049   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8050 }
8051
8052 multiclass SIMDLd4Multiple<string asm> {
8053   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8054 }
8055
8056 multiclass SIMDSt4Multiple<string asm> {
8057   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8058 }
8059
8060 //---
8061 // AdvSIMD Load/store single-element
8062 //---
8063
8064 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8065                          string asm, string operands, string cst,
8066                          dag oops, dag iops, list<dag> pattern>
8067   : I<oops, iops, asm, operands, cst, pattern> {
8068   bits<5> Vt;
8069   bits<5> Rn;
8070   let Inst{31} = 0;
8071   let Inst{29-24} = 0b001101;
8072   let Inst{22} = L;
8073   let Inst{21} = R;
8074   let Inst{15-13} = opcode;
8075   let Inst{9-5} = Rn;
8076   let Inst{4-0} = Vt;
8077 }
8078
8079 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8080                          string asm, string operands, string cst,
8081                          dag oops, dag iops, list<dag> pattern>
8082   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8083   bits<5> Vt;
8084   bits<5> Rn;
8085   let Inst{31} = 0;
8086   let Inst{29-24} = 0b001101;
8087   let Inst{22} = L;
8088   let Inst{21} = R;
8089   let Inst{15-13} = opcode;
8090   let Inst{9-5} = Rn;
8091   let Inst{4-0} = Vt;
8092 }
8093
8094
8095 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8096 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8097                   Operand listtype>
8098   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8099                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
8100                        []> {
8101   let Inst{30} = Q;
8102   let Inst{23} = 0;
8103   let Inst{20-16} = 0b00000;
8104   let Inst{12} = S;
8105   let Inst{11-10} = size;
8106 }
8107 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8108 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8109                       string asm, Operand listtype, Operand GPR64pi>
8110   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8111                        "$Rn = $wback",
8112                        (outs GPR64sp:$wback, listtype:$Vt),
8113                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8114   bits<5> Xm;
8115   let Inst{30} = Q;
8116   let Inst{23} = 1;
8117   let Inst{20-16} = Xm;
8118   let Inst{12} = S;
8119   let Inst{11-10} = size;
8120 }
8121
8122 multiclass SIMDLdrAliases<string asm, string layout, string Count,
8123                           int Offset, int Size> {
8124   // E.g. "ld1r { v0.8b }, [x1], #1"
8125   //      "ld1r.8b\t$Vt, [$Rn], #1"
8126   // may get mapped to
8127   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8128   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8129                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8130                       GPR64sp:$Rn,
8131                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8132                       XZR), 1>;
8133
8134   // E.g. "ld1r.8b { v0 }, [x1], #1"
8135   //      "ld1r.8b\t$Vt, [$Rn], #1"
8136   // may get mapped to
8137   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8138   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8139                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8140                       GPR64sp:$Rn,
8141                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8142                       XZR), 0>;
8143
8144   // E.g. "ld1r.8b { v0 }, [x1]"
8145   //      "ld1r.8b\t$Vt, [$Rn]"
8146   // may get mapped to
8147   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8148   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8149                   (!cast<Instruction>(NAME # "v" # layout)
8150                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8151                       GPR64sp:$Rn), 0>;
8152
8153   // E.g. "ld1r.8b { v0 }, [x1], x2"
8154   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
8155   // may get mapped to
8156   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8157   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8158                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8159                       GPR64sp:$Rn,
8160                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8161                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8162 }
8163
8164 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8165   int Offset1, int Offset2, int Offset4, int Offset8> {
8166   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8167                         !cast<Operand>("VecList" # Count # "8b")>;
8168   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8169                         !cast<Operand>("VecList" # Count #"16b")>;
8170   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8171                         !cast<Operand>("VecList" # Count #"4h")>;
8172   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8173                         !cast<Operand>("VecList" # Count #"8h")>;
8174   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8175                         !cast<Operand>("VecList" # Count #"2s")>;
8176   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8177                         !cast<Operand>("VecList" # Count #"4s")>;
8178   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8179                         !cast<Operand>("VecList" # Count #"1d")>;
8180   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8181                         !cast<Operand>("VecList" # Count #"2d")>;
8182
8183   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8184                                  !cast<Operand>("VecList" # Count # "8b"),
8185                                  !cast<Operand>("GPR64pi" # Offset1)>;
8186   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8187                                  !cast<Operand>("VecList" # Count # "16b"),
8188                                  !cast<Operand>("GPR64pi" # Offset1)>;
8189   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8190                                  !cast<Operand>("VecList" # Count # "4h"),
8191                                  !cast<Operand>("GPR64pi" # Offset2)>;
8192   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8193                                  !cast<Operand>("VecList" # Count # "8h"),
8194                                  !cast<Operand>("GPR64pi" # Offset2)>;
8195   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8196                                  !cast<Operand>("VecList" # Count # "2s"),
8197                                  !cast<Operand>("GPR64pi" # Offset4)>;
8198   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8199                                  !cast<Operand>("VecList" # Count # "4s"),
8200                                  !cast<Operand>("GPR64pi" # Offset4)>;
8201   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8202                                  !cast<Operand>("VecList" # Count # "1d"),
8203                                  !cast<Operand>("GPR64pi" # Offset8)>;
8204   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8205                                  !cast<Operand>("VecList" # Count # "2d"),
8206                                  !cast<Operand>("GPR64pi" # Offset8)>;
8207
8208   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
8209   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8210   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
8211   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
8212   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
8213   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
8214   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
8215   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
8216 }
8217
8218 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8219                       dag oops, dag iops, list<dag> pattern>
8220   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8221                        pattern> {
8222   // idx encoded in Q:S:size fields.
8223   bits<4> idx;
8224   let Inst{30} = idx{3};
8225   let Inst{23} = 0;
8226   let Inst{20-16} = 0b00000;
8227   let Inst{12} = idx{2};
8228   let Inst{11-10} = idx{1-0};
8229 }
8230 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8231                       dag oops, dag iops, list<dag> pattern>
8232   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8233                            oops, iops, pattern> {
8234   // idx encoded in Q:S:size fields.
8235   bits<4> idx;
8236   let Inst{30} = idx{3};
8237   let Inst{23} = 0;
8238   let Inst{20-16} = 0b00000;
8239   let Inst{12} = idx{2};
8240   let Inst{11-10} = idx{1-0};
8241 }
8242 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8243                           dag oops, dag iops>
8244   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8245                        "$Rn = $wback", oops, iops, []> {
8246   // idx encoded in Q:S:size fields.
8247   bits<4> idx;
8248   bits<5> Xm;
8249   let Inst{30} = idx{3};
8250   let Inst{23} = 1;
8251   let Inst{20-16} = Xm;
8252   let Inst{12} = idx{2};
8253   let Inst{11-10} = idx{1-0};
8254 }
8255 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8256                           dag oops, dag iops>
8257   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8258                            "$Rn = $wback", oops, iops, []> {
8259   // idx encoded in Q:S:size fields.
8260   bits<4> idx;
8261   bits<5> Xm;
8262   let Inst{30} = idx{3};
8263   let Inst{23} = 1;
8264   let Inst{20-16} = Xm;
8265   let Inst{12} = idx{2};
8266   let Inst{11-10} = idx{1-0};
8267 }
8268
8269 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8270                       dag oops, dag iops, list<dag> pattern>
8271   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8272                        pattern> {
8273   // idx encoded in Q:S:size<1> fields.
8274   bits<3> idx;
8275   let Inst{30} = idx{2};
8276   let Inst{23} = 0;
8277   let Inst{20-16} = 0b00000;
8278   let Inst{12} = idx{1};
8279   let Inst{11} = idx{0};
8280   let Inst{10} = size;
8281 }
8282 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8283                       dag oops, dag iops, list<dag> pattern>
8284   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8285                            oops, iops, pattern> {
8286   // idx encoded in Q:S:size<1> fields.
8287   bits<3> idx;
8288   let Inst{30} = idx{2};
8289   let Inst{23} = 0;
8290   let Inst{20-16} = 0b00000;
8291   let Inst{12} = idx{1};
8292   let Inst{11} = idx{0};
8293   let Inst{10} = size;
8294 }
8295
8296 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8297                           dag oops, dag iops>
8298   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8299                        "$Rn = $wback", oops, iops, []> {
8300   // idx encoded in Q:S:size<1> fields.
8301   bits<3> idx;
8302   bits<5> Xm;
8303   let Inst{30} = idx{2};
8304   let Inst{23} = 1;
8305   let Inst{20-16} = Xm;
8306   let Inst{12} = idx{1};
8307   let Inst{11} = idx{0};
8308   let Inst{10} = size;
8309 }
8310 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8311                           dag oops, dag iops>
8312   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8313                            "$Rn = $wback", oops, iops, []> {
8314   // idx encoded in Q:S:size<1> fields.
8315   bits<3> idx;
8316   bits<5> Xm;
8317   let Inst{30} = idx{2};
8318   let Inst{23} = 1;
8319   let Inst{20-16} = Xm;
8320   let Inst{12} = idx{1};
8321   let Inst{11} = idx{0};
8322   let Inst{10} = size;
8323 }
8324 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8325                       dag oops, dag iops, list<dag> pattern>
8326   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8327                        pattern> {
8328   // idx encoded in Q:S fields.
8329   bits<2> idx;
8330   let Inst{30} = idx{1};
8331   let Inst{23} = 0;
8332   let Inst{20-16} = 0b00000;
8333   let Inst{12} = idx{0};
8334   let Inst{11-10} = size;
8335 }
8336 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8337                       dag oops, dag iops, list<dag> pattern>
8338   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8339                            oops, iops, pattern> {
8340   // idx encoded in Q:S fields.
8341   bits<2> idx;
8342   let Inst{30} = idx{1};
8343   let Inst{23} = 0;
8344   let Inst{20-16} = 0b00000;
8345   let Inst{12} = idx{0};
8346   let Inst{11-10} = size;
8347 }
8348 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8349                           string asm, dag oops, dag iops>
8350   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8351                        "$Rn = $wback", oops, iops, []> {
8352   // idx encoded in Q:S fields.
8353   bits<2> idx;
8354   bits<5> Xm;
8355   let Inst{30} = idx{1};
8356   let Inst{23} = 1;
8357   let Inst{20-16} = Xm;
8358   let Inst{12} = idx{0};
8359   let Inst{11-10} = size;
8360 }
8361 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8362                           string asm, dag oops, dag iops>
8363   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8364                            "$Rn = $wback", oops, iops, []> {
8365   // idx encoded in Q:S fields.
8366   bits<2> idx;
8367   bits<5> Xm;
8368   let Inst{30} = idx{1};
8369   let Inst{23} = 1;
8370   let Inst{20-16} = Xm;
8371   let Inst{12} = idx{0};
8372   let Inst{11-10} = size;
8373 }
8374 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8375                       dag oops, dag iops, list<dag> pattern>
8376   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8377                        pattern> {
8378   // idx encoded in Q field.
8379   bits<1> idx;
8380   let Inst{30} = idx;
8381   let Inst{23} = 0;
8382   let Inst{20-16} = 0b00000;
8383   let Inst{12} = 0;
8384   let Inst{11-10} = size;
8385 }
8386 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8387                       dag oops, dag iops, list<dag> pattern>
8388   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8389                            oops, iops, pattern> {
8390   // idx encoded in Q field.
8391   bits<1> idx;
8392   let Inst{30} = idx;
8393   let Inst{23} = 0;
8394   let Inst{20-16} = 0b00000;
8395   let Inst{12} = 0;
8396   let Inst{11-10} = size;
8397 }
8398 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8399                           string asm, dag oops, dag iops>
8400   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8401                        "$Rn = $wback", oops, iops, []> {
8402   // idx encoded in Q field.
8403   bits<1> idx;
8404   bits<5> Xm;
8405   let Inst{30} = idx;
8406   let Inst{23} = 1;
8407   let Inst{20-16} = Xm;
8408   let Inst{12} = 0;
8409   let Inst{11-10} = size;
8410 }
8411 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8412                           string asm, dag oops, dag iops>
8413   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8414                            "$Rn = $wback", oops, iops, []> {
8415   // idx encoded in Q field.
8416   bits<1> idx;
8417   bits<5> Xm;
8418   let Inst{30} = idx;
8419   let Inst{23} = 1;
8420   let Inst{20-16} = Xm;
8421   let Inst{12} = 0;
8422   let Inst{11-10} = size;
8423 }
8424
8425 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8426 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8427                          RegisterOperand listtype,
8428                          RegisterOperand GPR64pi> {
8429   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8430                            (outs listtype:$dst),
8431                            (ins listtype:$Vt, VectorIndexB:$idx,
8432                                 GPR64sp:$Rn), []>;
8433
8434   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8435                             (outs GPR64sp:$wback, listtype:$dst),
8436                             (ins listtype:$Vt, VectorIndexB:$idx,
8437                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8438 }
8439 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8440 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8441                          RegisterOperand listtype,
8442                          RegisterOperand GPR64pi> {
8443   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8444                             (outs listtype:$dst),
8445                             (ins listtype:$Vt, VectorIndexH:$idx,
8446                                  GPR64sp:$Rn), []>;
8447
8448   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8449                             (outs GPR64sp:$wback, listtype:$dst),
8450                             (ins listtype:$Vt, VectorIndexH:$idx,
8451                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8452 }
8453 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8454 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8455                          RegisterOperand listtype,
8456                          RegisterOperand GPR64pi> {
8457   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8458                             (outs listtype:$dst),
8459                             (ins listtype:$Vt, VectorIndexS:$idx,
8460                                  GPR64sp:$Rn), []>;
8461
8462   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8463                             (outs GPR64sp:$wback, listtype:$dst),
8464                             (ins listtype:$Vt, VectorIndexS:$idx,
8465                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8466 }
8467 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8468 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8469                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8470   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8471                             (outs listtype:$dst),
8472                             (ins listtype:$Vt, VectorIndexD:$idx,
8473                                  GPR64sp:$Rn), []>;
8474
8475   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8476                             (outs GPR64sp:$wback, listtype:$dst),
8477                             (ins listtype:$Vt, VectorIndexD:$idx,
8478                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8479 }
8480 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8481 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8482                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8483   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8484                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8485                                         GPR64sp:$Rn), []>;
8486
8487   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8488                                     (outs GPR64sp:$wback),
8489                                     (ins listtype:$Vt, VectorIndexB:$idx,
8490                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
8491 }
8492 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8493 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8494                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8495   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8496                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8497                                          GPR64sp:$Rn), []>;
8498
8499   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8500                             (outs GPR64sp:$wback),
8501                             (ins listtype:$Vt, VectorIndexH:$idx,
8502                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8503 }
8504 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8505 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8506                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8507   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8508                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8509                                          GPR64sp:$Rn), []>;
8510
8511   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8512                             (outs GPR64sp:$wback),
8513                             (ins listtype:$Vt, VectorIndexS:$idx,
8514                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8515 }
8516 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8517 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8518                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8519   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8520                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8521                                          GPR64sp:$Rn), []>;
8522
8523   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8524                             (outs GPR64sp:$wback),
8525                             (ins listtype:$Vt, VectorIndexD:$idx,
8526                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8527 }
8528
8529 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8530                                  string Count, int Offset, Operand idxtype> {
8531   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8532   //      "ld1\t$Vt, [$Rn], #1"
8533   // may get mapped to
8534   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8535   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8536                   (!cast<Instruction>(NAME # Type  # "_POST")
8537                       GPR64sp:$Rn,
8538                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8539                       idxtype:$idx, XZR), 1>;
8540
8541   // E.g. "ld1.8b { v0 }[0], [x1], #1"
8542   //      "ld1.8b\t$Vt, [$Rn], #1"
8543   // may get mapped to
8544   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8545   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
8546                   (!cast<Instruction>(NAME # Type # "_POST")
8547                       GPR64sp:$Rn,
8548                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8549                       idxtype:$idx, XZR), 0>;
8550
8551   // E.g. "ld1.8b { v0 }[0], [x1]"
8552   //      "ld1.8b\t$Vt, [$Rn]"
8553   // may get mapped to
8554   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8555   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
8556                       (!cast<Instruction>(NAME # Type)
8557                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8558                          idxtype:$idx, GPR64sp:$Rn), 0>;
8559
8560   // E.g. "ld1.8b { v0 }[0], [x1], x2"
8561   //      "ld1.8b\t$Vt, [$Rn], $Xm"
8562   // may get mapped to
8563   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8564   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
8565                       (!cast<Instruction>(NAME # Type # "_POST")
8566                          GPR64sp:$Rn,
8567                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8568                          idxtype:$idx,
8569                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8570 }
8571
8572 multiclass SIMDLdSt1SingleAliases<string asm> {
8573   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
8574   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8575   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8576   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8577 }
8578
8579 multiclass SIMDLdSt2SingleAliases<string asm> {
8580   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
8581   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
8582   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
8583   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8584 }
8585
8586 multiclass SIMDLdSt3SingleAliases<string asm> {
8587   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
8588   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
8589   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8590   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8591 }
8592
8593 multiclass SIMDLdSt4SingleAliases<string asm> {
8594   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
8595   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
8596   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8597   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8598 }
8599 } // end of 'let Predicates = [HasNEON]'
8600
8601 //----------------------------------------------------------------------------
8602 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
8603 //----------------------------------------------------------------------------
8604
8605 let Predicates = [HasNEON, HasV8_1a] in {
8606
8607 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
8608                                     RegisterOperand regtype, string asm, 
8609                                     string kind, list<dag> pattern>
8610   : BaseSIMDThreeSameVectorTied<Q, U, size, opcode, regtype, asm, kind, 
8611                                 pattern> {
8612   let Inst{21}=0;
8613 }
8614 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
8615                                              SDPatternOperator Accum> {
8616   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
8617     [(set (v4i16 V64:$dst),
8618           (Accum (v4i16 V64:$Rd),
8619                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
8620                                                    (v4i16 V64:$Rm)))))]>;         
8621   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
8622     [(set (v8i16 V128:$dst),
8623           (Accum (v8i16 V128:$Rd),
8624                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
8625                                                    (v8i16 V128:$Rm)))))]>;
8626   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
8627     [(set (v2i32 V64:$dst),
8628           (Accum (v2i32 V64:$Rd),
8629                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
8630                                                    (v2i32 V64:$Rm)))))]>;
8631   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
8632     [(set (v4i32 V128:$dst),
8633           (Accum (v4i32 V128:$Rd),
8634                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
8635                                                    (v4i32 V128:$Rm)))))]>;
8636 }
8637
8638 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
8639                                      SDPatternOperator Accum> {
8640   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8641                                           V64, V64, V128_lo, VectorIndexH,
8642                                           asm, ".4h", ".4h", ".4h", ".h",
8643     [(set (v4i16 V64:$dst),
8644           (Accum (v4i16 V64:$Rd),
8645                  (v4i16 (int_aarch64_neon_sqrdmulh
8646                           (v4i16 V64:$Rn),
8647                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8648                                                     VectorIndexH:$idx))))))]> {
8649     bits<3> idx;
8650     let Inst{11} = idx{2};
8651     let Inst{21} = idx{1};
8652     let Inst{20} = idx{0};
8653   }
8654
8655   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8656                                           V128, V128, V128_lo, VectorIndexH,
8657                                           asm, ".8h", ".8h", ".8h", ".h",
8658     [(set (v8i16 V128:$dst),
8659           (Accum (v8i16 V128:$Rd),
8660                  (v8i16 (int_aarch64_neon_sqrdmulh
8661                           (v8i16 V128:$Rn),
8662                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8663                                                    VectorIndexH:$idx))))))]> {
8664     bits<3> idx;
8665     let Inst{11} = idx{2};
8666     let Inst{21} = idx{1};
8667     let Inst{20} = idx{0};
8668   }
8669
8670   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8671                                           V64, V64, V128, VectorIndexS,
8672                                           asm, ".2s", ".2s", ".2s", ".s",
8673     [(set (v2i32 V64:$dst),
8674         (Accum (v2i32 V64:$Rd),
8675                (v2i32 (int_aarch64_neon_sqrdmulh
8676                         (v2i32 V64:$Rn),
8677                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8678                                                  VectorIndexS:$idx))))))]> {
8679     bits<2> idx;
8680     let Inst{11} = idx{1};
8681     let Inst{21} = idx{0};
8682   }
8683
8684   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but 
8685   // an intermediate EXTRACT_SUBREG would be untyped.
8686   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we 
8687   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
8688   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8689                        (i32 (vector_extract 
8690                                (v4i32 (insert_subvector
8691                                        (undef), 
8692                                         (v2i32 (int_aarch64_neon_sqrdmulh 
8693                                                  (v2i32 V64:$Rn),
8694                                                  (v2i32 (AArch64duplane32 
8695                                                           (v4i32 V128:$Rm),
8696                                                           VectorIndexS:$idx)))),
8697                                       (i32 0))),
8698                                (i64 0))))),
8699             (EXTRACT_SUBREG
8700                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
8701                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), 
8702                                                 FPR32Op:$Rd, 
8703                                                 ssub)), 
8704                           V64:$Rn,
8705                           V128:$Rm, 
8706                           VectorIndexS:$idx)),
8707                 ssub)>;
8708
8709   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8710                                           V128, V128, V128, VectorIndexS,
8711                                           asm, ".4s", ".4s", ".4s", ".s",
8712     [(set (v4i32 V128:$dst),
8713           (Accum (v4i32 V128:$Rd),
8714                  (v4i32 (int_aarch64_neon_sqrdmulh
8715                           (v4i32 V128:$Rn),
8716                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8717                                                    VectorIndexS:$idx))))))]> {
8718     bits<2> idx;
8719     let Inst{11} = idx{1};
8720     let Inst{21} = idx{0};
8721   }
8722
8723   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
8724   // an intermediate EXTRACT_SUBREG would be untyped.
8725   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8726                         (i32 (vector_extract 
8727                                (v4i32 (int_aarch64_neon_sqrdmulh 
8728                                         (v4i32 V128:$Rn),
8729                                         (v4i32 (AArch64duplane32 
8730                                                  (v4i32 V128:$Rm),
8731                                                  VectorIndexS:$idx)))),
8732                                (i64 0))))),
8733             (EXTRACT_SUBREG
8734                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
8735                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), 
8736                                                FPR32Op:$Rd, 
8737                                                ssub)), 
8738                          V128:$Rn,
8739                          V128:$Rm, 
8740                          VectorIndexS:$idx)),
8741                 ssub)>;
8742
8743   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8744                                         FPR16Op, FPR16Op, V128_lo,
8745                                         VectorIndexH, asm, ".h", "", "", ".h", 
8746                                         []> {
8747     bits<3> idx;
8748     let Inst{11} = idx{2};
8749     let Inst{21} = idx{1};
8750     let Inst{20} = idx{0};
8751   }
8752
8753   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8754                                         FPR32Op, FPR32Op, V128, VectorIndexS,
8755                                         asm, ".s", "", "", ".s",
8756     [(set (i32 FPR32Op:$dst),
8757           (Accum (i32 FPR32Op:$Rd),
8758                  (i32 (int_aarch64_neon_sqrdmulh
8759                         (i32 FPR32Op:$Rn),
8760                         (i32 (vector_extract (v4i32 V128:$Rm),
8761                                              VectorIndexS:$idx))))))]> {
8762     bits<2> idx;
8763     let Inst{11} = idx{1};
8764     let Inst{21} = idx{0};
8765   }
8766 }
8767 } // let Predicates = [HasNeon, HasV8_1a]
8768
8769 //----------------------------------------------------------------------------
8770 // Crypto extensions
8771 //----------------------------------------------------------------------------
8772
8773 let Predicates = [HasCrypto] in {
8774 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8775 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8776               list<dag> pat>
8777   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8778     Sched<[WriteV]>{
8779   bits<5> Rd;
8780   bits<5> Rn;
8781   let Inst{31-16} = 0b0100111000101000;
8782   let Inst{15-12} = opc;
8783   let Inst{11-10} = 0b10;
8784   let Inst{9-5}   = Rn;
8785   let Inst{4-0}   = Rd;
8786 }
8787
8788 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8789   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8790             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8791
8792 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8793   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8794             "$Rd = $dst",
8795             [(set (v16i8 V128:$dst),
8796                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8797
8798 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8799 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8800                      dag oops, dag iops, list<dag> pat>
8801   : I<oops, iops, asm,
8802       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8803       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8804     Sched<[WriteV]>{
8805   bits<5> Rd;
8806   bits<5> Rn;
8807   bits<5> Rm;
8808   let Inst{31-21} = 0b01011110000;
8809   let Inst{20-16} = Rm;
8810   let Inst{15}    = 0;
8811   let Inst{14-12} = opc;
8812   let Inst{11-10} = 0b00;
8813   let Inst{9-5}   = Rn;
8814   let Inst{4-0}   = Rd;
8815 }
8816
8817 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8818   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8819                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8820                    [(set (v4i32 FPR128:$dst),
8821                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8822                                  (v4i32 V128:$Rm)))]>;
8823
8824 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8825   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8826                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
8827                    [(set (v4i32 V128:$dst),
8828                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8829                                  (v4i32 V128:$Rm)))]>;
8830
8831 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8832   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8833                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8834                    [(set (v4i32 FPR128:$dst),
8835                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8836                                  (v4i32 V128:$Rm)))]>;
8837
8838 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8839 class SHA2OpInst<bits<4> opc, string asm, string kind,
8840                  string cstr, dag oops, dag iops,
8841                  list<dag> pat>
8842   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8843                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8844     Sched<[WriteV]>{
8845   bits<5> Rd;
8846   bits<5> Rn;
8847   let Inst{31-16} = 0b0101111000101000;
8848   let Inst{15-12} = opc;
8849   let Inst{11-10} = 0b10;
8850   let Inst{9-5}   = Rn;
8851   let Inst{4-0}   = Rd;
8852 }
8853
8854 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8855   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8856                (ins V128:$Rd, V128:$Rn),
8857                [(set (v4i32 V128:$dst),
8858                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8859
8860 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8861   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8862                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8863 } // end of 'let Predicates = [HasCrypto]'
8864
8865 //----------------------------------------------------------------------------
8866 // v8.1 atomic instructions extension:
8867 // * CAS
8868 // * CASP
8869 // * SWP
8870 // * LDOPregister<OP>, and aliases STOPregister<OP>
8871
8872 // Instruction encodings:
8873 //
8874 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
8875 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
8876 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
8877 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
8878 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
8879 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
8880
8881 // Instruction syntax:
8882 //
8883 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8884 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
8885 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
8886 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
8887 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8888 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
8889 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8890 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
8891 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
8892 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
8893
8894 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
8895 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
8896                       string cstr, list<dag> pattern>
8897       : I<oops, iops, asm, operands, cstr, pattern> {
8898   bits<2> Sz;
8899   bit NP;
8900   bit Acq;
8901   bit Rel;
8902   bits<5> Rs;
8903   bits<5> Rn;
8904   bits<5> Rt;
8905   let Inst{31-30} = Sz;
8906   let Inst{29-24} = 0b001000;
8907   let Inst{23} = NP;
8908   let Inst{22} = Acq;
8909   let Inst{21} = 0b1;
8910   let Inst{20-16} = Rs;
8911   let Inst{15} = Rel;
8912   let Inst{14-10} = 0b11111;
8913   let Inst{9-5} = Rn;
8914   let Inst{4-0} = Rt;
8915 }
8916
8917 class BaseCAS<string order, string size, RegisterClass RC>
8918       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8919                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
8920                         "$out = $Rs",[]> {
8921   let NP = 1;
8922 }
8923
8924 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
8925   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
8926   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
8927   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
8928   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
8929 }
8930
8931 class BaseCASP<string order, string size, RegisterOperand RC>
8932       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8933                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
8934                         "$out = $Rs",[]> {
8935   let NP = 0;
8936 }
8937
8938 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
8939   let Sz = 0b00, Acq = Acq, Rel = Rel in 
8940     def s : BaseCASP<order, "", WSeqPairClassOperand>;
8941   let Sz = 0b01, Acq = Acq, Rel = Rel in 
8942     def d : BaseCASP<order, "", XSeqPairClassOperand>;
8943 }
8944
8945 let Predicates = [HasV8_1a] in
8946 class BaseSWP<string order, string size, RegisterClass RC>
8947       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
8948           "\t$Rs, $Rt, [$Rn]","",[]> {
8949   bits<2> Sz;
8950   bit Acq;
8951   bit Rel;
8952   bits<5> Rs;
8953   bits<3> opc = 0b000;
8954   bits<5> Rn;
8955   bits<5> Rt;
8956   let Inst{31-30} = Sz;
8957   let Inst{29-24} = 0b111000;
8958   let Inst{23} = Acq;
8959   let Inst{22} = Rel;
8960   let Inst{21} = 0b1;
8961   let Inst{20-16} = Rs;
8962   let Inst{15} = 0b1;
8963   let Inst{14-12} = opc;
8964   let Inst{11-10} = 0b00;
8965   let Inst{9-5} = Rn;
8966   let Inst{4-0} = Rt;
8967 }
8968
8969 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
8970   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
8971   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
8972   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
8973   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
8974 }
8975
8976 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
8977 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
8978       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
8979           "\t$Rs, $Rt, [$Rn]","",[]> {
8980   bits<2> Sz;
8981   bit Acq;
8982   bit Rel;
8983   bits<5> Rs;
8984   bits<3> opc;
8985   bits<5> Rn;
8986   bits<5> Rt;
8987   let Inst{31-30} = Sz;
8988   let Inst{29-24} = 0b111000;
8989   let Inst{23} = Acq;
8990   let Inst{22} = Rel;
8991   let Inst{21} = 0b1;
8992   let Inst{20-16} = Rs;
8993   let Inst{15} = 0b0;
8994   let Inst{14-12} = opc;
8995   let Inst{11-10} = 0b00;
8996   let Inst{9-5} = Rn;
8997   let Inst{4-0} = Rt;
8998 }
8999
9000 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel, 
9001                         string order> {
9002   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in 
9003     def b : BaseLDOPregister<op, order, "b", GPR32>;
9004   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in 
9005     def h : BaseLDOPregister<op, order, "h", GPR32>;
9006   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in 
9007     def s : BaseLDOPregister<op, order, "", GPR32>;
9008   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in 
9009     def d : BaseLDOPregister<op, order, "", GPR64>;
9010 }
9011
9012 let Predicates = [HasV8_1a] in
9013 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
9014                         Instruction inst> :
9015       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
9016
9017 multiclass STOPregister<string asm, string instr> {
9018   def : BaseSTOPregister<asm # "lb", GPR32, WZR, 
9019                     !cast<Instruction>(instr # "Lb")>;
9020   def : BaseSTOPregister<asm # "lh", GPR32, WZR, 
9021                     !cast<Instruction>(instr # "Lh")>;
9022   def : BaseSTOPregister<asm # "l",  GPR32, WZR, 
9023                     !cast<Instruction>(instr # "Ls")>;
9024   def : BaseSTOPregister<asm # "l",  GPR64, XZR, 
9025                     !cast<Instruction>(instr # "Ld")>;
9026   def : BaseSTOPregister<asm # "b",  GPR32, WZR, 
9027                     !cast<Instruction>(instr # "b")>;
9028   def : BaseSTOPregister<asm # "h",  GPR32, WZR, 
9029                     !cast<Instruction>(instr # "h")>;
9030   def : BaseSTOPregister<asm,        GPR32, WZR, 
9031                     !cast<Instruction>(instr # "s")>;
9032   def : BaseSTOPregister<asm,        GPR64, XZR, 
9033                     !cast<Instruction>(instr # "d")>;
9034 }
9035
9036 //----------------------------------------------------------------------------
9037 // Allow the size specifier tokens to be upper case, not just lower.
9038 def : TokenAlias<".8B", ".8b">;
9039 def : TokenAlias<".4H", ".4h">;
9040 def : TokenAlias<".2S", ".2s">;
9041 def : TokenAlias<".1D", ".1d">;
9042 def : TokenAlias<".16B", ".16b">;
9043 def : TokenAlias<".8H", ".8h">;
9044 def : TokenAlias<".4S", ".4s">;
9045 def : TokenAlias<".2D", ".2d">;
9046 def : TokenAlias<".1Q", ".1q">;
9047 def : TokenAlias<".B", ".b">;
9048 def : TokenAlias<".H", ".h">;
9049 def : TokenAlias<".S", ".s">;
9050 def : TokenAlias<".D", ".d">;
9051 def : TokenAlias<".Q", ".q">;