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