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