[ARM64] Add more simple diagnostics for immediate/shift ranges
[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 }
169
170 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
171 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
172 // are encoded as the eight bit value 'abcdefgh'.
173 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
174
175
176 //===----------------------------------------------------------------------===//
177 // Operand Definitions.
178 //
179
180 // ADR[P] instruction labels.
181 def AdrpOperand : AsmOperandClass {
182   let Name = "AdrpLabel";
183   let ParserMethod = "tryParseAdrpLabel";
184   let DiagnosticType = "InvalidLabel";
185 }
186 def adrplabel : Operand<i64> {
187   let EncoderMethod = "getAdrLabelOpValue";
188   let PrintMethod = "printAdrpLabel";
189   let ParserMatchClass = AdrpOperand;
190 }
191
192 def AdrOperand : AsmOperandClass {
193   let Name = "AdrLabel";
194   let ParserMethod = "tryParseAdrLabel";
195   let DiagnosticType = "InvalidLabel";
196 }
197 def adrlabel : Operand<i64> {
198   let EncoderMethod = "getAdrLabelOpValue";
199   let ParserMatchClass = AdrOperand;
200 }
201
202 // simm9 predicate - True if the immediate is in the range [-256, 255].
203 def SImm9Operand : AsmOperandClass {
204   let Name = "SImm9";
205   let DiagnosticType = "InvalidMemoryIndexedSImm9";
206 }
207 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
208   let ParserMatchClass = SImm9Operand;
209 }
210
211 // simm7s4 predicate - True if the immediate is a multiple of 4 in the range
212 // [-256, 252].
213 def SImm7s4Operand : AsmOperandClass {
214   let Name = "SImm7s4";
215   let DiagnosticType = "InvalidMemoryIndexed32SImm7";
216 }
217 def simm7s4 : Operand<i32> {
218   let ParserMatchClass = SImm7s4Operand;
219   let PrintMethod = "printImmScale<4>";
220 }
221
222 // simm7s8 predicate - True if the immediate is a multiple of 8 in the range
223 // [-512, 504].
224 def SImm7s8Operand : AsmOperandClass {
225   let Name = "SImm7s8";
226   let DiagnosticType = "InvalidMemoryIndexed64SImm7";
227 }
228 def simm7s8 : Operand<i32> {
229   let ParserMatchClass = SImm7s8Operand;
230   let PrintMethod = "printImmScale<8>";
231 }
232
233 // simm7s16 predicate - True if the immediate is a multiple of 16 in the range
234 // [-1024, 1008].
235 def SImm7s16Operand : AsmOperandClass {
236   let Name = "SImm7s16";
237   let DiagnosticType = "InvalidMemoryIndexed64SImm7";
238 }
239 def simm7s16 : Operand<i32> {
240   let ParserMatchClass = SImm7s16Operand;
241   let PrintMethod = "printImmScale<16>";
242 }
243
244 class AsmImmRange<int Low, int High> : AsmOperandClass {
245   let Name = "Imm" # Low # "_" # High;
246   let DiagnosticType = "InvalidImm" # Low # "_" # High;
247 }
248
249 def Imm1_8Operand : AsmImmRange<1, 8>;
250 def Imm1_16Operand : AsmImmRange<1, 16>;
251 def Imm1_32Operand : AsmImmRange<1, 32>;
252 def Imm1_64Operand : AsmImmRange<1, 64>;
253
254 def MovZSymbolG3AsmOperand : AsmOperandClass {
255   let Name = "MovZSymbolG3";
256   let RenderMethod = "addImmOperands";
257 }
258
259 def movz_symbol_g3 : Operand<i32> {
260   let ParserMatchClass = MovZSymbolG3AsmOperand;
261 }
262
263 def MovZSymbolG2AsmOperand : AsmOperandClass {
264   let Name = "MovZSymbolG2";
265   let RenderMethod = "addImmOperands";
266 }
267
268 def movz_symbol_g2 : Operand<i32> {
269   let ParserMatchClass = MovZSymbolG2AsmOperand;
270 }
271
272 def MovZSymbolG1AsmOperand : AsmOperandClass {
273   let Name = "MovZSymbolG1";
274   let RenderMethod = "addImmOperands";
275 }
276
277 def movz_symbol_g1 : Operand<i32> {
278   let ParserMatchClass = MovZSymbolG1AsmOperand;
279 }
280
281 def MovZSymbolG0AsmOperand : AsmOperandClass {
282   let Name = "MovZSymbolG0";
283   let RenderMethod = "addImmOperands";
284 }
285
286 def movz_symbol_g0 : Operand<i32> {
287   let ParserMatchClass = MovZSymbolG0AsmOperand;
288 }
289
290 def MovKSymbolG3AsmOperand : AsmOperandClass {
291   let Name = "MovKSymbolG3";
292   let RenderMethod = "addImmOperands";
293 }
294
295 def movk_symbol_g3 : Operand<i32> {
296   let ParserMatchClass = MovKSymbolG3AsmOperand;
297 }
298
299 def MovKSymbolG2AsmOperand : AsmOperandClass {
300   let Name = "MovKSymbolG2";
301   let RenderMethod = "addImmOperands";
302 }
303
304 def movk_symbol_g2 : Operand<i32> {
305   let ParserMatchClass = MovKSymbolG2AsmOperand;
306 }
307
308 def MovKSymbolG1AsmOperand : AsmOperandClass {
309   let Name = "MovKSymbolG1";
310   let RenderMethod = "addImmOperands";
311 }
312
313 def movk_symbol_g1 : Operand<i32> {
314   let ParserMatchClass = MovKSymbolG1AsmOperand;
315 }
316
317 def MovKSymbolG0AsmOperand : AsmOperandClass {
318   let Name = "MovKSymbolG0";
319   let RenderMethod = "addImmOperands";
320 }
321
322 def movk_symbol_g0 : Operand<i32> {
323   let ParserMatchClass = MovKSymbolG0AsmOperand;
324 }
325
326 class fixedpoint_i32<ValueType FloatVT>
327   : Operand<FloatVT>,
328     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
329   let EncoderMethod = "getFixedPointScaleOpValue";
330   let DecoderMethod = "DecodeFixedPointScaleImm32";
331   let ParserMatchClass = Imm1_32Operand;
332 }
333
334 class fixedpoint_i64<ValueType FloatVT>
335   : Operand<FloatVT>,
336     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
337   let EncoderMethod = "getFixedPointScaleOpValue";
338   let DecoderMethod = "DecodeFixedPointScaleImm64";
339   let ParserMatchClass = Imm1_64Operand;
340 }
341
342 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
343 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
344
345 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
346 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
347
348 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
349   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
350 }]> {
351   let EncoderMethod = "getVecShiftR8OpValue";
352   let DecoderMethod = "DecodeVecShiftR8Imm";
353   let ParserMatchClass = Imm1_8Operand;
354 }
355 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
356   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
357 }]> {
358   let EncoderMethod = "getVecShiftR16OpValue";
359   let DecoderMethod = "DecodeVecShiftR16Imm";
360   let ParserMatchClass = Imm1_16Operand;
361 }
362 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
363   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
364 }]> {
365   let EncoderMethod = "getVecShiftR16OpValue";
366   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
367   let ParserMatchClass = Imm1_8Operand;
368 }
369 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
370   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
371 }]> {
372   let EncoderMethod = "getVecShiftR32OpValue";
373   let DecoderMethod = "DecodeVecShiftR32Imm";
374   let ParserMatchClass = Imm1_32Operand;
375 }
376 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
377   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
378 }]> {
379   let EncoderMethod = "getVecShiftR32OpValue";
380   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
381   let ParserMatchClass = Imm1_16Operand;
382 }
383 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
384   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
385 }]> {
386   let EncoderMethod = "getVecShiftR64OpValue";
387   let DecoderMethod = "DecodeVecShiftR64Imm";
388   let ParserMatchClass = Imm1_64Operand;
389 }
390 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
391   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
392 }]> {
393   let EncoderMethod = "getVecShiftR64OpValue";
394   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
395   let ParserMatchClass = Imm1_32Operand;
396 }
397
398 def Imm0_7Operand : AsmImmRange<0, 7>;
399 def Imm0_15Operand : AsmImmRange<0, 15>;
400 def Imm0_31Operand : AsmImmRange<0, 31>;
401 def Imm0_63Operand : AsmImmRange<0, 63>;
402
403 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
404   return (((uint32_t)Imm) < 8);
405 }]> {
406   let EncoderMethod = "getVecShiftL8OpValue";
407   let DecoderMethod = "DecodeVecShiftL8Imm";
408   let ParserMatchClass = Imm0_7Operand;
409 }
410 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
411   return (((uint32_t)Imm) < 16);
412 }]> {
413   let EncoderMethod = "getVecShiftL16OpValue";
414   let DecoderMethod = "DecodeVecShiftL16Imm";
415   let ParserMatchClass = Imm0_15Operand;
416 }
417 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
418   return (((uint32_t)Imm) < 32);
419 }]> {
420   let EncoderMethod = "getVecShiftL32OpValue";
421   let DecoderMethod = "DecodeVecShiftL32Imm";
422   let ParserMatchClass = Imm0_31Operand;
423 }
424 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
425   return (((uint32_t)Imm) < 64);
426 }]> {
427   let EncoderMethod = "getVecShiftL64OpValue";
428   let DecoderMethod = "DecodeVecShiftL64Imm";
429   let ParserMatchClass = Imm0_63Operand;
430 }
431
432
433 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
434 // instructions for splatting repeating bit patterns across the immediate.
435 def logical_imm32_XFORM : SDNodeXForm<imm, [{
436   uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
437   return CurDAG->getTargetConstant(enc, MVT::i32);
438 }]>;
439 def logical_imm64_XFORM : SDNodeXForm<imm, [{
440   uint64_t enc = ARM64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
441   return CurDAG->getTargetConstant(enc, MVT::i32);
442 }]>;
443
444 def LogicalImm32Operand : AsmOperandClass {
445   let Name = "LogicalImm32";
446   let DiagnosticType = "LogicalSecondSource";
447 }
448 def LogicalImm64Operand : AsmOperandClass {
449   let Name = "LogicalImm64";
450   let DiagnosticType = "LogicalSecondSource";
451 }
452 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
453   return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 32);
454 }], logical_imm32_XFORM> {
455   let PrintMethod = "printLogicalImm32";
456   let ParserMatchClass = LogicalImm32Operand;
457 }
458 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
459   return ARM64_AM::isLogicalImmediate(N->getZExtValue(), 64);
460 }], logical_imm64_XFORM> {
461   let PrintMethod = "printLogicalImm64";
462   let ParserMatchClass = LogicalImm64Operand;
463 }
464
465 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
466 def Imm0_65535Operand : AsmImmRange<0, 65535>;
467 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
468   return ((uint32_t)Imm) < 65536;
469 }]> {
470   let ParserMatchClass = Imm0_65535Operand;
471   let PrintMethod = "printHexImm";
472 }
473
474 // imm0_255 predicate - True if the immediate is in the range [0,255].
475 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
476 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
477   return ((uint32_t)Imm) < 256;
478 }]> {
479   let ParserMatchClass = Imm0_255Operand;
480   let PrintMethod = "printHexImm";
481 }
482
483 // imm0_127 predicate - True if the immediate is in the range [0,127]
484 def Imm0_127Operand : AsmImmRange<0, 127>;
485 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
486   return ((uint32_t)Imm) < 128;
487 }]> {
488   let ParserMatchClass = Imm0_127Operand;
489   let PrintMethod = "printHexImm";
490 }
491
492 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
493 // for all shift-amounts.
494
495 // imm0_63 predicate - True if the immediate is in the range [0,63]
496 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
497   return ((uint64_t)Imm) < 64;
498 }]> {
499   let ParserMatchClass = Imm0_63Operand;
500 }
501
502 // imm0_31 predicate - True if the immediate is in the range [0,31]
503 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
504   return ((uint64_t)Imm) < 32;
505 }]> {
506   let ParserMatchClass = Imm0_31Operand;
507 }
508
509 // imm0_15 predicate - True if the immediate is in the range [0,15]
510 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
511   return ((uint64_t)Imm) < 16;
512 }]> {
513   let ParserMatchClass = Imm0_15Operand;
514 }
515
516 // imm0_7 predicate - True if the immediate is in the range [0,7]
517 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
518   return ((uint64_t)Imm) < 8;
519 }]> {
520   let ParserMatchClass = Imm0_7Operand;
521 }
522
523 // An arithmetic shifter operand:
524 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
525 //  {5-0} - imm6
526 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
527   let PrintMethod = "printShifter";
528   let ParserMatchClass = !cast<AsmOperandClass>(
529                          "ArithmeticShifterOperand" # width);
530 }
531
532 def arith_shift32 : arith_shift<i32, 32>;
533 def arith_shift64 : arith_shift<i64, 64>;
534
535 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
536     : Operand<Ty>,
537       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
538   let PrintMethod = "printShiftedRegister";
539   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
540 }
541
542 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
543 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
544
545 // An arithmetic shifter operand:
546 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
547 //  {5-0} - imm6
548 class logical_shift<int width> : Operand<i32> {
549   let PrintMethod = "printShifter";
550   let ParserMatchClass = !cast<AsmOperandClass>(
551                          "LogicalShifterOperand" # width);
552 }
553
554 def logical_shift32 : logical_shift<32>;
555 def logical_shift64 : logical_shift<64>;
556
557 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
558     : Operand<Ty>,
559       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
560   let PrintMethod = "printShiftedRegister";
561   let MIOperandInfo = (ops regclass, shiftop);
562 }
563
564 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
565 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
566
567 // A logical vector shifter operand:
568 //  {7-6} - shift type: 00 = lsl
569 //  {5-0} - imm6: #0, #8, #16, or #24
570 def logical_vec_shift : Operand<i32> {
571   let PrintMethod = "printShifter";
572   let EncoderMethod = "getVecShifterOpValue";
573   let ParserMatchClass = LogicalVecShifterOperand;
574 }
575
576 // A logical vector half-word shifter operand:
577 //  {7-6} - shift type: 00 = lsl
578 //  {5-0} - imm6: #0 or #8
579 def logical_vec_hw_shift : Operand<i32> {
580   let PrintMethod = "printShifter";
581   let EncoderMethod = "getVecShifterOpValue";
582   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
583 }
584
585 // A vector move shifter operand:
586 //  {0} - imm1: #8 or #16
587 def move_vec_shift : Operand<i32> {
588   let PrintMethod = "printShifter";
589   let EncoderMethod = "getMoveVecShifterOpValue";
590   let ParserMatchClass = MoveVecShifterOperand;
591 }
592
593 def AddSubImmOperand : AsmOperandClass {
594   let Name = "AddSubImm";
595   let ParserMethod = "tryParseAddSubImm";
596   let DiagnosticType = "AddSubSecondSource";
597 }
598 // An ADD/SUB immediate shifter operand:
599 //  second operand:
600 //  {7-6} - shift type: 00 = lsl
601 //  {5-0} - imm6: #0 or #12
602 class addsub_shifted_imm<ValueType Ty>
603     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
604   let PrintMethod = "printAddSubImm";
605   let EncoderMethod = "getAddSubImmOpValue";
606   let ParserMatchClass = AddSubImmOperand;
607   let MIOperandInfo = (ops i32imm, i32imm);
608 }
609
610 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
611 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
612
613 class neg_addsub_shifted_imm<ValueType Ty>
614     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
615   let PrintMethod = "printAddSubImm";
616   let EncoderMethod = "getAddSubImmOpValue";
617   let ParserMatchClass = AddSubImmOperand;
618   let MIOperandInfo = (ops i32imm, i32imm);
619 }
620
621 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
622 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
623
624 // An extend operand:
625 //  {5-3} - extend type
626 //  {2-0} - imm3
627 def arith_extend : Operand<i32> {
628   let PrintMethod = "printExtend";
629   let ParserMatchClass = ExtendOperand;
630 }
631 def arith_extend64 : Operand<i32> {
632   let PrintMethod = "printExtend";
633   let ParserMatchClass = ExtendOperand64;
634 }
635
636 // 'extend' that's a lsl of a 64-bit register.
637 def arith_extendlsl64 : Operand<i32> {
638   let PrintMethod = "printExtend";
639   let ParserMatchClass = ExtendOperandLSL64;
640 }
641
642 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
643                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
644   let PrintMethod = "printExtendedRegister";
645   let MIOperandInfo = (ops GPR32, arith_extend);
646 }
647
648 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
649                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
650   let PrintMethod = "printExtendedRegister";
651   let MIOperandInfo = (ops GPR32, arith_extend64);
652 }
653
654 // Floating-point immediate.
655 def fpimm32 : Operand<f32>,
656               PatLeaf<(f32 fpimm), [{
657       return ARM64_AM::getFP32Imm(N->getValueAPF()) != -1;
658     }], SDNodeXForm<fpimm, [{
659       APFloat InVal = N->getValueAPF();
660       uint32_t enc = ARM64_AM::getFP32Imm(InVal);
661       return CurDAG->getTargetConstant(enc, MVT::i32);
662     }]>> {
663   let ParserMatchClass = FPImmOperand;
664   let PrintMethod = "printFPImmOperand";
665 }
666 def fpimm64 : Operand<f64>,
667               PatLeaf<(f64 fpimm), [{
668       return ARM64_AM::getFP64Imm(N->getValueAPF()) != -1;
669     }], SDNodeXForm<fpimm, [{
670       APFloat InVal = N->getValueAPF();
671       uint32_t enc = ARM64_AM::getFP64Imm(InVal);
672       return CurDAG->getTargetConstant(enc, MVT::i32);
673     }]>> {
674   let ParserMatchClass = FPImmOperand;
675   let PrintMethod = "printFPImmOperand";
676 }
677
678 def fpimm8 : Operand<i32> {
679   let ParserMatchClass = FPImmOperand;
680   let PrintMethod = "printFPImmOperand";
681 }
682
683 def fpimm0 : PatLeaf<(fpimm), [{
684   return N->isExactlyValue(+0.0);
685 }]>;
686
687 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
688 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
689 // are encoded as the eight bit value 'abcdefgh'.
690 def simdimmtype10 : Operand<i32>,
691                     PatLeaf<(f64 fpimm), [{
692       return ARM64_AM::isAdvSIMDModImmType10(N->getValueAPF()
693                                                .bitcastToAPInt()
694                                                .getZExtValue());
695     }], SDNodeXForm<fpimm, [{
696       APFloat InVal = N->getValueAPF();
697       uint32_t enc = ARM64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
698                                                            .bitcastToAPInt()
699                                                            .getZExtValue());
700       return CurDAG->getTargetConstant(enc, MVT::i32);
701     }]>> {
702   let ParserMatchClass = SIMDImmType10Operand;
703   let PrintMethod = "printSIMDType10Operand";
704 }
705
706
707 //---
708 // System management
709 //---
710
711 // Base encoding for system instruction operands.
712 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
713 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands>
714     : I<oops, iops, asm, operands, "", []> {
715   let Inst{31-22} = 0b1101010100;
716   let Inst{21}    = L;
717 }
718
719 // System instructions which do not have an Rt register.
720 class SimpleSystemI<bit L, dag iops, string asm, string operands>
721     : BaseSystemI<L, (outs), iops, asm, operands> {
722   let Inst{4-0} = 0b11111;
723 }
724
725 // System instructions which have an Rt register.
726 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
727     : BaseSystemI<L, oops, iops, asm, operands>,
728       Sched<[WriteSys]> {
729   bits<5> Rt;
730   let Inst{4-0} = Rt;
731 }
732
733 // Hint instructions that take both a CRm and a 3-bit immediate.
734 class HintI<string mnemonic>
735     : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "">,
736       Sched<[WriteHint]> {
737   bits <7> imm;
738   let Inst{20-12} = 0b000110010;
739   let Inst{11-5} = imm;
740 }
741
742 // System instructions taking a single literal operand which encodes into
743 // CRm. op2 differentiates the opcodes.
744 def BarrierAsmOperand : AsmOperandClass {
745   let Name = "Barrier";
746   let ParserMethod = "tryParseBarrierOperand";
747 }
748 def barrier_op : Operand<i32> {
749   let PrintMethod = "printBarrierOption";
750   let ParserMatchClass = BarrierAsmOperand;
751 }
752 class CRmSystemI<Operand crmtype, bits<3> opc, string asm>
753     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm">,
754       Sched<[WriteBarrier]> {
755   bits<4> CRm;
756   let Inst{20-12} = 0b000110011;
757   let Inst{11-8} = CRm;
758   let Inst{7-5} = opc;
759 }
760
761 // MRS/MSR system instructions. These have different operand classes because
762 // a different subset of registers can be accessed through each instruction.
763 def MRSSystemRegisterOperand : AsmOperandClass {
764   let Name = "MRSSystemRegister";
765   let ParserMethod = "tryParseSysReg";
766   let DiagnosticType = "MRS";
767 }
768 // concatenation of 1, op0, op1, CRn, CRm, op2. 16-bit immediate.
769 def mrs_sysreg_op : Operand<i32> {
770   let ParserMatchClass = MRSSystemRegisterOperand;
771   let DecoderMethod = "DecodeMRSSystemRegister";
772   let PrintMethod = "printMRSSystemRegister";
773 }
774
775 def MSRSystemRegisterOperand : AsmOperandClass {
776   let Name = "MSRSystemRegister";
777   let ParserMethod = "tryParseSysReg";
778   let DiagnosticType = "MSR";
779 }
780 def msr_sysreg_op : Operand<i32> {
781   let ParserMatchClass = MSRSystemRegisterOperand;
782   let DecoderMethod = "DecodeMSRSystemRegister";
783   let PrintMethod = "printMSRSystemRegister";
784 }
785
786 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
787                        "mrs", "\t$Rt, $systemreg"> {
788   bits<15> systemreg;
789   let Inst{20} = 1;
790   let Inst{19-5} = systemreg;
791 }
792
793 // FIXME: Some of these def NZCV, others don't. Best way to model that?
794 // Explicitly modeling each of the system register as a register class
795 // would do it, but feels like overkill at this point.
796 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
797                        "msr", "\t$systemreg, $Rt"> {
798   bits<15> systemreg;
799   let Inst{20} = 1;
800   let Inst{19-5} = systemreg;
801 }
802
803 def SystemPStateFieldOperand : AsmOperandClass {
804   let Name = "SystemPStateField";
805   let ParserMethod = "tryParseSysReg";
806 }
807 def pstatefield_op : Operand<i32> {
808   let ParserMatchClass = SystemPStateFieldOperand;
809   let PrintMethod = "printSystemPStateField";
810 }
811
812 let Defs = [NZCV] in
813 class MSRpstateI
814   : SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm),
815                   "msr", "\t$pstate_field, $imm">,
816     Sched<[WriteSys]> {
817   bits<6> pstatefield;
818   bits<4> imm;
819   let Inst{20-19} = 0b00;
820   let Inst{18-16} = pstatefield{5-3};
821   let Inst{15-12} = 0b0100;
822   let Inst{11-8} = imm;
823   let Inst{7-5} = pstatefield{2-0};
824
825   let DecoderMethod = "DecodeSystemPStateInstruction";
826 }
827
828 // SYS and SYSL generic system instructions.
829 def SysCRAsmOperand : AsmOperandClass {
830   let Name = "SysCR";
831   let ParserMethod = "tryParseSysCROperand";
832 }
833
834 def sys_cr_op : Operand<i32> {
835   let PrintMethod = "printSysCROperand";
836   let ParserMatchClass = SysCRAsmOperand;
837 }
838
839 class SystemXtI<bit L, string asm>
840   : RtSystemI<L, (outs),
841        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
842        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
843   bits<3> op1;
844   bits<4> Cn;
845   bits<4> Cm;
846   bits<3> op2;
847   let Inst{20-19} = 0b01;
848   let Inst{18-16} = op1;
849   let Inst{15-12} = Cn;
850   let Inst{11-8}  = Cm;
851   let Inst{7-5}   = op2;
852 }
853
854 class SystemLXtI<bit L, string asm>
855   : RtSystemI<L, (outs),
856        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
857        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
858   bits<3> op1;
859   bits<4> Cn;
860   bits<4> Cm;
861   bits<3> op2;
862   let Inst{20-19} = 0b01;
863   let Inst{18-16} = op1;
864   let Inst{15-12} = Cn;
865   let Inst{11-8}  = Cm;
866   let Inst{7-5}   = op2;
867 }
868
869
870 // Branch (register) instructions:
871 //
872 //  case opc of
873 //    0001 blr
874 //    0000 br
875 //    0101 dret
876 //    0100 eret
877 //    0010 ret
878 //    otherwise UNDEFINED
879 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
880                     string operands, list<dag> pattern>
881     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
882   let Inst{31-25} = 0b1101011;
883   let Inst{24-21} = opc;
884   let Inst{20-16} = 0b11111;
885   let Inst{15-10} = 0b000000;
886   let Inst{4-0}   = 0b00000;
887 }
888
889 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
890     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
891   bits<5> Rn;
892   let Inst{9-5} = Rn;
893 }
894
895 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
896 class SpecialReturn<bits<4> opc, string asm>
897     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
898   let Inst{9-5} = 0b11111;
899 }
900
901 //---
902 // Conditional branch instruction.
903 //---
904 // Branch condition code.
905 // 4-bit immediate. Pretty-printed as .<cc>
906 def dotCcode : Operand<i32> {
907   let PrintMethod = "printDotCondCode";
908 }
909
910 // Conditional branch target. 19-bit immediate. The low two bits of the target
911 // offset are implied zero and so are not part of the immediate.
912 def PCRelLabel19Operand : AsmOperandClass {
913   let Name = "PCRelLabel19";
914   let DiagnosticType = "InvalidLabel";
915 }
916 def am_brcond : Operand<OtherVT> {
917   let EncoderMethod = "getCondBranchTargetOpValue";
918   let DecoderMethod = "DecodePCRelLabel19";
919   let PrintMethod = "printAlignedLabel";
920   let ParserMatchClass = PCRelLabel19Operand;
921 }
922
923 class BranchCond : I<(outs), (ins dotCcode:$cond, am_brcond:$target),
924                      "b", "$cond\t$target", "",
925                      [(ARM64brcond bb:$target, imm:$cond, NZCV)]>,
926                    Sched<[WriteBr]> {
927   let isBranch = 1;
928   let isTerminator = 1;
929   let Uses = [NZCV];
930
931   bits<4> cond;
932   bits<19> target;
933   let Inst{31-24} = 0b01010100;
934   let Inst{23-5} = target;
935   let Inst{4} = 0;
936   let Inst{3-0} = cond;
937 }
938
939 //---
940 // Compare-and-branch instructions.
941 //---
942 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
943     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
944          asm, "\t$Rt, $target", "",
945          [(node regtype:$Rt, bb:$target)]>,
946       Sched<[WriteBr]> {
947   let isBranch = 1;
948   let isTerminator = 1;
949
950   bits<5> Rt;
951   bits<19> target;
952   let Inst{30-25} = 0b011010;
953   let Inst{24}    = op;
954   let Inst{23-5}  = target;
955   let Inst{4-0}   = Rt;
956 }
957
958 multiclass CmpBranch<bit op, string asm, SDNode node> {
959   def W : BaseCmpBranch<GPR32, op, asm, node> {
960     let Inst{31} = 0;
961   }
962   def X : BaseCmpBranch<GPR64, op, asm, node> {
963     let Inst{31} = 1;
964   }
965 }
966
967 //---
968 // Test-bit-and-branch instructions.
969 //---
970 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
971 // the target offset are implied zero and so are not part of the immediate.
972 def BranchTarget14Operand : AsmOperandClass {
973   let Name = "BranchTarget14";
974 }
975 def am_tbrcond : Operand<OtherVT> {
976   let EncoderMethod = "getTestBranchTargetOpValue";
977   let PrintMethod = "printAlignedLabel";
978   let ParserMatchClass = BranchTarget14Operand;
979 }
980
981 class TestBranch<bit op, string asm, SDNode node>
982     : I<(outs), (ins GPR64:$Rt, imm0_63:$bit_off, am_tbrcond:$target),
983        asm, "\t$Rt, $bit_off, $target", "",
984        [(node GPR64:$Rt, imm0_63:$bit_off, bb:$target)]>,
985       Sched<[WriteBr]> {
986   let isBranch = 1;
987   let isTerminator = 1;
988
989   bits<5> Rt;
990   bits<6> bit_off;
991   bits<14> target;
992
993   let Inst{31}    = bit_off{5};
994   let Inst{30-25} = 0b011011;
995   let Inst{24}    = op;
996   let Inst{23-19} = bit_off{4-0};
997   let Inst{18-5}  = target;
998   let Inst{4-0}   = Rt;
999
1000   let DecoderMethod = "DecodeTestAndBranch";
1001 }
1002
1003 //---
1004 // Unconditional branch (immediate) instructions.
1005 //---
1006 def BranchTarget26Operand : AsmOperandClass {
1007   let Name = "BranchTarget26";
1008 }
1009 def am_b_target : Operand<OtherVT> {
1010   let EncoderMethod = "getBranchTargetOpValue";
1011   let PrintMethod = "printAlignedLabel";
1012   let ParserMatchClass = BranchTarget26Operand;
1013 }
1014 def am_bl_target : Operand<i64> {
1015   let EncoderMethod = "getBranchTargetOpValue";
1016   let PrintMethod = "printAlignedLabel";
1017   let ParserMatchClass = BranchTarget26Operand;
1018 }
1019
1020 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1021     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1022   bits<26> addr;
1023   let Inst{31}    = op;
1024   let Inst{30-26} = 0b00101;
1025   let Inst{25-0}  = addr;
1026
1027   let DecoderMethod = "DecodeUnconditionalBranch";
1028 }
1029
1030 class BranchImm<bit op, string asm, list<dag> pattern>
1031     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1032 class CallImm<bit op, string asm, list<dag> pattern>
1033     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1034
1035 //---
1036 // Basic one-operand data processing instructions.
1037 //---
1038
1039 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1040 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1041                          SDPatternOperator node>
1042   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1043       [(set regtype:$Rd, (node regtype:$Rn))]>,
1044     Sched<[WriteI]> {
1045   bits<5> Rd;
1046   bits<5> Rn;
1047
1048   let Inst{30-13} = 0b101101011000000000;
1049   let Inst{12-10} = opc;
1050   let Inst{9-5}   = Rn;
1051   let Inst{4-0}   = Rd;
1052 }
1053
1054 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1055 multiclass OneOperandData<bits<3> opc, string asm,
1056                           SDPatternOperator node = null_frag> {
1057   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1058     let Inst{31} = 0;
1059   }
1060
1061   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1062     let Inst{31} = 1;
1063   }
1064 }
1065
1066 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1067     : BaseOneOperandData<opc, GPR32, asm, node> {
1068   let Inst{31} = 0;
1069 }
1070
1071 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1072     : BaseOneOperandData<opc, GPR64, asm, node> {
1073   let Inst{31} = 1;
1074 }
1075
1076 //---
1077 // Basic two-operand data processing instructions.
1078 //---
1079 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1080                           list<dag> pattern>
1081     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1082         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1083       Sched<[WriteI]> {
1084   let Uses = [NZCV];
1085   bits<5> Rd;
1086   bits<5> Rn;
1087   bits<5> Rm;
1088   let Inst{30}    = isSub;
1089   let Inst{28-21} = 0b11010000;
1090   let Inst{20-16} = Rm;
1091   let Inst{15-10} = 0;
1092   let Inst{9-5}   = Rn;
1093   let Inst{4-0}   = Rd;
1094 }
1095
1096 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1097                       SDNode OpNode>
1098     : BaseBaseAddSubCarry<isSub, regtype, asm,
1099         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1100
1101 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1102                               SDNode OpNode>
1103     : BaseBaseAddSubCarry<isSub, regtype, asm,
1104         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1105          (implicit NZCV)]> {
1106   let Defs = [NZCV];
1107 }
1108
1109 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1110                        SDNode OpNode, SDNode OpNode_setflags> {
1111   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1112     let Inst{31} = 0;
1113     let Inst{29} = 0;
1114   }
1115   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1116     let Inst{31} = 1;
1117     let Inst{29} = 0;
1118   }
1119
1120   // Sets flags.
1121   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1122                                     OpNode_setflags> {
1123     let Inst{31} = 0;
1124     let Inst{29} = 1;
1125   }
1126   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1127                                     OpNode_setflags> {
1128     let Inst{31} = 1;
1129     let Inst{29} = 1;
1130   }
1131 }
1132
1133 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1134                      SDPatternOperator OpNode>
1135   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1136       asm, "\t$Rd, $Rn, $Rm", "",
1137       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1138   bits<5> Rd;
1139   bits<5> Rn;
1140   bits<5> Rm;
1141   let Inst{30-21} = 0b0011010110;
1142   let Inst{20-16} = Rm;
1143   let Inst{15-14} = 0b00;
1144   let Inst{13-10} = opc;
1145   let Inst{9-5}   = Rn;
1146   let Inst{4-0}   = Rd;
1147 }
1148
1149 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1150               SDPatternOperator OpNode>
1151     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1152   let Inst{10}    = isSigned;
1153 }
1154
1155 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1156   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1157            Sched<[WriteID32]> {
1158     let Inst{31} = 0;
1159   }
1160   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1161            Sched<[WriteID64]> {
1162     let Inst{31} = 1;
1163   }
1164 }
1165
1166 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1167                 SDPatternOperator OpNode = null_frag>
1168   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1169     Sched<[WriteIS]> {
1170   let Inst{11-10} = shift_type;
1171 }
1172
1173 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1174   def Wr : BaseShift<shift_type, GPR32, asm> {
1175     let Inst{31} = 0;
1176   }
1177
1178   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1179     let Inst{31} = 1;
1180   }
1181
1182   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1183             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1184                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1185
1186   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1187             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1188
1189   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1190             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1191
1192   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1193             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1194 }
1195
1196 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1197     : InstAlias<asm#" $dst, $src1, $src2",
1198                 (inst regtype:$dst, regtype:$src1, regtype:$src2)>;
1199
1200 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1201                        RegisterClass addtype, string asm,
1202                        list<dag> pattern>
1203   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1204       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1205   bits<5> Rd;
1206   bits<5> Rn;
1207   bits<5> Rm;
1208   bits<5> Ra;
1209   let Inst{30-24} = 0b0011011;
1210   let Inst{23-21} = opc;
1211   let Inst{20-16} = Rm;
1212   let Inst{15}    = isSub;
1213   let Inst{14-10} = Ra;
1214   let Inst{9-5}   = Rn;
1215   let Inst{4-0}   = Rd;
1216 }
1217
1218 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1219   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1220       [(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))]>,
1221       Sched<[WriteIM32]> {
1222     let Inst{31} = 0;
1223   }
1224
1225   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1226       [(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))]>,
1227       Sched<[WriteIM64]> {
1228     let Inst{31} = 1;
1229   }
1230 }
1231
1232 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1233                    SDNode AccNode, SDNode ExtNode>
1234   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1235     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1236                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1237     Sched<[WriteIM32]> {
1238   let Inst{31} = 1;
1239 }
1240
1241 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1242   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1243       asm, "\t$Rd, $Rn, $Rm", "",
1244       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1245     Sched<[WriteIM64]> {
1246   bits<5> Rd;
1247   bits<5> Rn;
1248   bits<5> Rm;
1249   let Inst{31-24} = 0b10011011;
1250   let Inst{23-21} = opc;
1251   let Inst{20-16} = Rm;
1252   let Inst{15}    = 0;
1253   let Inst{9-5}   = Rn;
1254   let Inst{4-0}   = Rd;
1255
1256   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1257   // (i.e. all bits 1) but is ignored by the processor.
1258   let PostEncoderMethod = "fixMulHigh";
1259 }
1260
1261 class MulAccumWAlias<string asm, Instruction inst>
1262     : InstAlias<asm#" $dst, $src1, $src2",
1263                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1264 class MulAccumXAlias<string asm, Instruction inst>
1265     : InstAlias<asm#" $dst, $src1, $src2",
1266                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1267 class WideMulAccumAlias<string asm, Instruction inst>
1268     : InstAlias<asm#" $dst, $src1, $src2",
1269                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1270
1271 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1272               SDPatternOperator OpNode, string asm>
1273   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1274       asm, "\t$Rd, $Rn, $Rm", "",
1275       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1276     Sched<[WriteISReg]> {
1277   bits<5> Rd;
1278   bits<5> Rn;
1279   bits<5> Rm;
1280
1281   let Inst{31} = sf;
1282   let Inst{30-21} = 0b0011010110;
1283   let Inst{20-16} = Rm;
1284   let Inst{15-13} = 0b010;
1285   let Inst{12} = C;
1286   let Inst{11-10} = sz;
1287   let Inst{9-5} = Rn;
1288   let Inst{4-0} = Rd;
1289   let Predicates = [HasCRC];
1290 }
1291
1292 //---
1293 // Address generation.
1294 //---
1295
1296 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1297     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1298         pattern>,
1299       Sched<[WriteI]> {
1300   bits<5>  Xd;
1301   bits<21> label;
1302   let Inst{31}    = page;
1303   let Inst{30-29} = label{1-0};
1304   let Inst{28-24} = 0b10000;
1305   let Inst{23-5}  = label{20-2};
1306   let Inst{4-0}   = Xd;
1307
1308   let DecoderMethod = "DecodeAdrInstruction";
1309 }
1310
1311 //---
1312 // Move immediate.
1313 //---
1314
1315 def movimm32_imm : Operand<i32> {
1316   let ParserMatchClass = Imm0_65535Operand;
1317   let EncoderMethod = "getMoveWideImmOpValue";
1318   let PrintMethod = "printHexImm";
1319 }
1320 def movimm32_shift : Operand<i32> {
1321   let PrintMethod = "printShifter";
1322   let ParserMatchClass = MovImm32ShifterOperand;
1323 }
1324 def movimm64_shift : Operand<i32> {
1325   let PrintMethod = "printShifter";
1326   let ParserMatchClass = MovImm64ShifterOperand;
1327 }
1328
1329 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1330 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1331                         string asm>
1332   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1333        asm, "\t$Rd, $imm$shift", "", []>,
1334     Sched<[WriteImm]> {
1335   bits<5> Rd;
1336   bits<16> imm;
1337   bits<6> shift;
1338   let Inst{30-29} = opc;
1339   let Inst{28-23} = 0b100101;
1340   let Inst{22-21} = shift{5-4};
1341   let Inst{20-5}  = imm;
1342   let Inst{4-0}   = Rd;
1343
1344   let DecoderMethod = "DecodeMoveImmInstruction";
1345 }
1346
1347 multiclass MoveImmediate<bits<2> opc, string asm> {
1348   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1349     let Inst{31} = 0;
1350   }
1351
1352   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1353     let Inst{31} = 1;
1354   }
1355 }
1356
1357 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1358 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1359                           string asm>
1360   : I<(outs regtype:$Rd),
1361       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1362        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1363     Sched<[WriteI]> {
1364   bits<5> Rd;
1365   bits<16> imm;
1366   bits<6> shift;
1367   let Inst{30-29} = opc;
1368   let Inst{28-23} = 0b100101;
1369   let Inst{22-21} = shift{5-4};
1370   let Inst{20-5}  = imm;
1371   let Inst{4-0}   = Rd;
1372
1373   let DecoderMethod = "DecodeMoveImmInstruction";
1374 }
1375
1376 multiclass InsertImmediate<bits<2> opc, string asm> {
1377   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1378     let Inst{31} = 0;
1379   }
1380
1381   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1382     let Inst{31} = 1;
1383   }
1384 }
1385
1386 //---
1387 // Add/Subtract
1388 //---
1389
1390 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1391                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1392                     string asm, SDPatternOperator OpNode>
1393     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1394         asm, "\t$Rd, $Rn, $imm", "",
1395         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1396       Sched<[WriteI]>  {
1397   bits<5>  Rd;
1398   bits<5>  Rn;
1399   bits<14> imm;
1400   let Inst{30}    = isSub;
1401   let Inst{29}    = setFlags;
1402   let Inst{28-24} = 0b10001;
1403   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1404   let Inst{21-10} = imm{11-0};
1405   let Inst{9-5}   = Rn;
1406   let Inst{4-0}   = Rd;
1407   let DecoderMethod = "DecodeBaseAddSubImm";
1408 }
1409
1410 class BaseAddSubRegPseudo<RegisterClass regtype,
1411                           SDPatternOperator OpNode>
1412     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1413              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1414       Sched<[WriteI]>;
1415
1416 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1417                      arith_shifted_reg shifted_regtype, string asm,
1418                      SDPatternOperator OpNode>
1419     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1420         asm, "\t$Rd, $Rn, $Rm", "",
1421         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1422       Sched<[WriteISReg]> {
1423   // The operands are in order to match the 'addr' MI operands, so we
1424   // don't need an encoder method and by-name matching. Just use the default
1425   // in-order handling. Since we're using by-order, make sure the names
1426   // do not match.
1427   bits<5> dst;
1428   bits<5> src1;
1429   bits<5> src2;
1430   bits<8> shift;
1431   let Inst{30}    = isSub;
1432   let Inst{29}    = setFlags;
1433   let Inst{28-24} = 0b01011;
1434   let Inst{23-22} = shift{7-6};
1435   let Inst{21}    = 0;
1436   let Inst{20-16} = src2;
1437   let Inst{15-10} = shift{5-0};
1438   let Inst{9-5}   = src1;
1439   let Inst{4-0}   = dst;
1440
1441   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1442 }
1443
1444 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1445                      RegisterClass src1Regtype, Operand src2Regtype,
1446                      string asm, SDPatternOperator OpNode>
1447     : I<(outs dstRegtype:$R1),
1448         (ins src1Regtype:$R2, src2Regtype:$R3),
1449         asm, "\t$R1, $R2, $R3", "",
1450         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1451       Sched<[WriteIEReg]> {
1452   bits<5> Rd;
1453   bits<5> Rn;
1454   bits<5> Rm;
1455   bits<6> ext;
1456   let Inst{30}    = isSub;
1457   let Inst{29}    = setFlags;
1458   let Inst{28-24} = 0b01011;
1459   let Inst{23-21} = 0b001;
1460   let Inst{20-16} = Rm;
1461   let Inst{15-13} = ext{5-3};
1462   let Inst{12-10} = ext{2-0};
1463   let Inst{9-5}   = Rn;
1464   let Inst{4-0}   = Rd;
1465
1466   let DecoderMethod = "DecodeAddSubERegInstruction";
1467 }
1468
1469 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1470 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1471                        RegisterClass src1Regtype, RegisterClass src2Regtype,
1472                        Operand ext_op, string asm>
1473     : I<(outs dstRegtype:$Rd),
1474         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1475         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1476       Sched<[WriteIEReg]> {
1477   bits<5> Rd;
1478   bits<5> Rn;
1479   bits<5> Rm;
1480   bits<6> ext;
1481   let Inst{30}    = isSub;
1482   let Inst{29}    = setFlags;
1483   let Inst{28-24} = 0b01011;
1484   let Inst{23-21} = 0b001;
1485   let Inst{20-16} = Rm;
1486   let Inst{15}    = ext{5};
1487   let Inst{12-10} = ext{2-0};
1488   let Inst{9-5}   = Rn;
1489   let Inst{4-0}   = Rd;
1490
1491   let DecoderMethod = "DecodeAddSubERegInstruction";
1492 }
1493
1494 // Aliases for register+register add/subtract.
1495 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1496                      RegisterClass src1Regtype, RegisterClass src2Regtype,
1497                      int shiftExt>
1498     : InstAlias<asm#" $dst, $src1, $src2",
1499                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1500                       shiftExt)>;
1501
1502 multiclass AddSub<bit isSub, string mnemonic,
1503                   SDPatternOperator OpNode = null_frag> {
1504   let hasSideEffects = 0 in {
1505   // Add/Subtract immediate
1506   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1507                            mnemonic, OpNode> {
1508     let Inst{31} = 0;
1509   }
1510   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1511                            mnemonic, OpNode> {
1512     let Inst{31} = 1;
1513   }
1514
1515   // Add/Subtract register - Only used for CodeGen
1516   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1517   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1518
1519   // Add/Subtract shifted register
1520   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1521                            OpNode> {
1522     let Inst{31} = 0;
1523   }
1524   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1525                            OpNode> {
1526     let Inst{31} = 1;
1527   }
1528   }
1529
1530   // Add/Subtract extended register
1531   let AddedComplexity = 1, hasSideEffects = 0 in {
1532   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1533                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1534     let Inst{31} = 0;
1535   }
1536   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1537                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1538     let Inst{31} = 1;
1539   }
1540   }
1541
1542   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1543                                arith_extendlsl64, mnemonic> {
1544     // UXTX and SXTX only.
1545     let Inst{14-13} = 0b11;
1546     let Inst{31} = 1;
1547   }
1548
1549   // Register/register aliases with no shift when SP is not used.
1550   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1551                        GPR32, GPR32, GPR32, 0>;
1552   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1553                        GPR64, GPR64, GPR64, 0>;
1554
1555   // Register/register aliases with no shift when either the destination or
1556   // first source register is SP.  This relies on the shifted register aliases
1557   // above matching first in the case when SP is not used.
1558   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1559                        GPR32sp, GPR32sp, GPR32, 16>; // UXTW #0
1560   def : AddSubRegAlias<mnemonic,
1561                        !cast<Instruction>(NAME#"Xrx64"),
1562                        GPR64sp, GPR64sp, GPR64, 24>; // UXTX #0
1563 }
1564
1565 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp> {
1566   let isCompare = 1, Defs = [NZCV] in {
1567   // Add/Subtract immediate
1568   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1569                            mnemonic, OpNode> {
1570     let Inst{31} = 0;
1571   }
1572   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1573                            mnemonic, OpNode> {
1574     let Inst{31} = 1;
1575   }
1576
1577   // Add/Subtract register
1578   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1579   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1580
1581   // Add/Subtract shifted register
1582   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1583                            OpNode> {
1584     let Inst{31} = 0;
1585   }
1586   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1587                            OpNode> {
1588     let Inst{31} = 1;
1589   }
1590
1591   // Add/Subtract extended register
1592   let AddedComplexity = 1 in {
1593   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1594                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1595     let Inst{31} = 0;
1596   }
1597   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1598                            arith_extended_reg32<i64>, mnemonic, OpNode> {
1599     let Inst{31} = 1;
1600   }
1601   }
1602
1603   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1604                                arith_extendlsl64, mnemonic> {
1605     // UXTX and SXTX only.
1606     let Inst{14-13} = 0b11;
1607     let Inst{31} = 1;
1608   }
1609   } // Defs = [NZCV]
1610
1611   // Compare aliases
1612   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Wri")
1613                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm)>;
1614   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Xri")
1615                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm)>;
1616   def : InstAlias<cmp#" $src1, $src2, $sh", (!cast<Instruction>(NAME#"Wrx")
1617                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh)>;
1618   def : InstAlias<cmp#" $src1, $src2, $sh", (!cast<Instruction>(NAME#"Xrx")
1619                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh)>;
1620   def : InstAlias<cmp#" $src1, $src2, $sh", (!cast<Instruction>(NAME#"Xrx64")
1621                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh)>;
1622   def : InstAlias<cmp#" $src1, $src2, $sh", (!cast<Instruction>(NAME#"Wrs")
1623                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh)>;
1624   def : InstAlias<cmp#" $src1, $src2, $sh", (!cast<Instruction>(NAME#"Xrs")
1625                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh)>;
1626
1627   // Compare shorthands
1628   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1629                   WZR, GPR32:$src1, GPR32:$src2, 0)>;
1630   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1631                   XZR, GPR64:$src1, GPR64:$src2, 0)>;
1632
1633   // Register/register aliases with no shift when SP is not used.
1634   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1635                        GPR32, GPR32, GPR32, 0>;
1636   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1637                        GPR64, GPR64, GPR64, 0>;
1638
1639   // Register/register aliases with no shift when the first source register
1640   // is SP.  This relies on the shifted register aliases above matching first
1641   // in the case when SP is not used.
1642   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1643                        GPR32, GPR32sp, GPR32, 16>; // UXTW #0
1644   def : AddSubRegAlias<mnemonic,
1645                        !cast<Instruction>(NAME#"Xrx64"),
1646                        GPR64, GPR64sp, GPR64, 24>; // UXTX #0
1647 }
1648
1649 //---
1650 // Extract
1651 //---
1652 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1653                                       SDTCisPtrTy<3>]>;
1654 def ARM64Extr : SDNode<"ARM64ISD::EXTR", SDTA64EXTR>;
1655
1656 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1657                      list<dag> patterns>
1658     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1659          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1660       Sched<[WriteExtr, ReadExtrHi]> {
1661   bits<5> Rd;
1662   bits<5> Rn;
1663   bits<5> Rm;
1664   bits<6> imm;
1665
1666   let Inst{30-23} = 0b00100111;
1667   let Inst{21}    = 0;
1668   let Inst{20-16} = Rm;
1669   let Inst{15-10} = imm;
1670   let Inst{9-5}   = Rn;
1671   let Inst{4-0}   = Rd;
1672 }
1673
1674 multiclass ExtractImm<string asm> {
1675   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1676                       [(set GPR32:$Rd,
1677                         (ARM64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1678     let Inst{31} = 0;
1679     let Inst{22} = 0;
1680     // imm<5> must be zero.
1681     let imm{5}   = 0;
1682   }
1683   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1684                       [(set GPR64:$Rd,
1685                         (ARM64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1686
1687     let Inst{31} = 1;
1688     let Inst{22} = 1;
1689   }
1690 }
1691
1692 //---
1693 // Bitfield
1694 //---
1695
1696 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1697 class BaseBitfieldImm<bits<2> opc,
1698                       RegisterClass regtype, Operand imm_type, string asm>
1699     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1700          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1701       Sched<[WriteIS]> {
1702   bits<5> Rd;
1703   bits<5> Rn;
1704   bits<6> immr;
1705   bits<6> imms;
1706
1707   let Inst{30-29} = opc;
1708   let Inst{28-23} = 0b100110;
1709   let Inst{21-16} = immr;
1710   let Inst{15-10} = imms;
1711   let Inst{9-5}   = Rn;
1712   let Inst{4-0}   = Rd;
1713 }
1714
1715 multiclass BitfieldImm<bits<2> opc, string asm> {
1716   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1717     let Inst{31} = 0;
1718     let Inst{22} = 0;
1719     // imms<5> and immr<5> must be zero, else ReservedValue().
1720     let Inst{21} = 0;
1721     let Inst{15} = 0;
1722   }
1723   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1724     let Inst{31} = 1;
1725     let Inst{22} = 1;
1726   }
1727 }
1728
1729 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1730 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1731                       RegisterClass regtype, Operand imm_type, string asm>
1732     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1733                              imm_type:$imms),
1734          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1735       Sched<[WriteIS]> {
1736   bits<5> Rd;
1737   bits<5> Rn;
1738   bits<6> immr;
1739   bits<6> imms;
1740
1741   let Inst{30-29} = opc;
1742   let Inst{28-23} = 0b100110;
1743   let Inst{21-16} = immr;
1744   let Inst{15-10} = imms;
1745   let Inst{9-5}   = Rn;
1746   let Inst{4-0}   = Rd;
1747 }
1748
1749 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1750   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1751     let Inst{31} = 0;
1752     let Inst{22} = 0;
1753     // imms<5> and immr<5> must be zero, else ReservedValue().
1754     let Inst{21} = 0;
1755     let Inst{15} = 0;
1756   }
1757   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1758     let Inst{31} = 1;
1759     let Inst{22} = 1;
1760   }
1761 }
1762
1763 //---
1764 // Logical
1765 //---
1766
1767 // Logical (immediate)
1768 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1769                      RegisterClass sregtype, Operand imm_type, string asm,
1770                      list<dag> pattern>
1771     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1772          asm, "\t$Rd, $Rn, $imm", "", pattern>,
1773       Sched<[WriteI]> {
1774   bits<5>  Rd;
1775   bits<5>  Rn;
1776   bits<13> imm;
1777   let Inst{30-29} = opc;
1778   let Inst{28-23} = 0b100100;
1779   let Inst{22}    = imm{12};
1780   let Inst{21-16} = imm{11-6};
1781   let Inst{15-10} = imm{5-0};
1782   let Inst{9-5}   = Rn;
1783   let Inst{4-0}   = Rd;
1784
1785   let DecoderMethod = "DecodeLogicalImmInstruction";
1786 }
1787
1788 // Logical (shifted register)
1789 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1790                       logical_shifted_reg shifted_regtype, string asm,
1791                       list<dag> pattern>
1792     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1793         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1794       Sched<[WriteISReg]> {
1795   // The operands are in order to match the 'addr' MI operands, so we
1796   // don't need an encoder method and by-name matching. Just use the default
1797   // in-order handling. Since we're using by-order, make sure the names
1798   // do not match.
1799   bits<5> dst;
1800   bits<5> src1;
1801   bits<5> src2;
1802   bits<8> shift;
1803   let Inst{30-29} = opc;
1804   let Inst{28-24} = 0b01010;
1805   let Inst{23-22} = shift{7-6};
1806   let Inst{21}    = N;
1807   let Inst{20-16} = src2;
1808   let Inst{15-10} = shift{5-0};
1809   let Inst{9-5}   = src1;
1810   let Inst{4-0}   = dst;
1811
1812   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1813 }
1814
1815 // Aliases for register+register logical instructions.
1816 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1817     : InstAlias<asm#" $dst, $src1, $src2",
1818                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1819
1820 let AddedComplexity = 6 in
1821 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
1822   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1823                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1824                                                logical_imm32:$imm))]> {
1825     let Inst{31} = 0;
1826     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1827   }
1828   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1829                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1830                                                logical_imm64:$imm))]> {
1831     let Inst{31} = 1;
1832   }
1833 }
1834
1835 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
1836   let isCompare = 1, Defs = [NZCV] in {
1837   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
1838       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
1839     let Inst{31} = 0;
1840     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1841   }
1842   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
1843       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
1844     let Inst{31} = 1;
1845   }
1846   } // end Defs = [NZCV]
1847 }
1848
1849 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
1850     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1851              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1852       Sched<[WriteI]>;
1853
1854 // Split from LogicalImm as not all instructions have both.
1855 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
1856                       SDPatternOperator OpNode> {
1857   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1858   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1859
1860   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1861                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
1862                                                  logical_shifted_reg32:$Rm))]> {
1863     let Inst{31} = 0;
1864   }
1865   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1866                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
1867                                                  logical_shifted_reg64:$Rm))]> {
1868     let Inst{31} = 1;
1869   }
1870
1871   def : LogicalRegAlias<mnemonic,
1872                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
1873   def : LogicalRegAlias<mnemonic,
1874                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
1875 }
1876
1877 // Split from LogicalReg to allow setting NZCV Defs
1878 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
1879                        SDPatternOperator OpNode = null_frag> {
1880   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
1881   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1882   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1883
1884   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1885             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
1886     let Inst{31} = 0;
1887   }
1888   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1889             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
1890     let Inst{31} = 1;
1891   }
1892   } // Defs = [NZCV]
1893
1894   def : LogicalRegAlias<mnemonic,
1895                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
1896   def : LogicalRegAlias<mnemonic,
1897                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
1898 }
1899
1900 //---
1901 // Conditionally set flags
1902 //---
1903
1904 // Condition code.
1905 // 4-bit immediate. Pretty-printed as <cc>
1906 def ccode : Operand<i32> {
1907   let PrintMethod = "printCondCode";
1908 }
1909
1910 def inv_ccode : Operand<i32> {
1911   let PrintMethod = "printInverseCondCode";
1912 }
1913
1914 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1915 class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
1916     : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
1917          asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
1918       Sched<[WriteI]> {
1919   let Uses = [NZCV];
1920   let Defs = [NZCV];
1921
1922   bits<5> Rn;
1923   bits<5> imm;
1924   bits<4> nzcv;
1925   bits<4> cond;
1926
1927   let Inst{30}    = op;
1928   let Inst{29-21} = 0b111010010;
1929   let Inst{20-16} = imm;
1930   let Inst{15-12} = cond;
1931   let Inst{11-10} = 0b10;
1932   let Inst{9-5}   = Rn;
1933   let Inst{4}     = 0b0;
1934   let Inst{3-0}   = nzcv;
1935 }
1936
1937 multiclass CondSetFlagsImm<bit op, string asm> {
1938   def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
1939     let Inst{31} = 0;
1940   }
1941   def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
1942     let Inst{31} = 1;
1943   }
1944 }
1945
1946 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1947 class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
1948     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
1949          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
1950       Sched<[WriteI]> {
1951   let Uses = [NZCV];
1952   let Defs = [NZCV];
1953
1954   bits<5> Rn;
1955   bits<5> Rm;
1956   bits<4> nzcv;
1957   bits<4> cond;
1958
1959   let Inst{30}    = op;
1960   let Inst{29-21} = 0b111010010;
1961   let Inst{20-16} = Rm;
1962   let Inst{15-12} = cond;
1963   let Inst{11-10} = 0b00;
1964   let Inst{9-5}   = Rn;
1965   let Inst{4}     = 0b0;
1966   let Inst{3-0}   = nzcv;
1967 }
1968
1969 multiclass CondSetFlagsReg<bit op, string asm> {
1970   def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
1971     let Inst{31} = 0;
1972   }
1973   def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
1974     let Inst{31} = 1;
1975   }
1976 }
1977
1978 //---
1979 // Conditional select
1980 //---
1981
1982 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
1983     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1984          asm, "\t$Rd, $Rn, $Rm, $cond", "",
1985          [(set regtype:$Rd,
1986                (ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
1987       Sched<[WriteI]> {
1988   let Uses = [NZCV];
1989
1990   bits<5> Rd;
1991   bits<5> Rn;
1992   bits<5> Rm;
1993   bits<4> cond;
1994
1995   let Inst{30}    = op;
1996   let Inst{29-21} = 0b011010100;
1997   let Inst{20-16} = Rm;
1998   let Inst{15-12} = cond;
1999   let Inst{11-10} = op2;
2000   let Inst{9-5}   = Rn;
2001   let Inst{4-0}   = Rd;
2002 }
2003
2004 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2005   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2006     let Inst{31} = 0;
2007   }
2008   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2009     let Inst{31} = 1;
2010   }
2011 }
2012
2013 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2014                        PatFrag frag>
2015     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2016          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2017          [(set regtype:$Rd,
2018                (ARM64csel regtype:$Rn, (frag regtype:$Rm),
2019                (i32 imm:$cond), NZCV))]>,
2020       Sched<[WriteI]> {
2021   let Uses = [NZCV];
2022
2023   bits<5> Rd;
2024   bits<5> Rn;
2025   bits<5> Rm;
2026   bits<4> cond;
2027
2028   let Inst{30}    = op;
2029   let Inst{29-21} = 0b011010100;
2030   let Inst{20-16} = Rm;
2031   let Inst{15-12} = cond;
2032   let Inst{11-10} = op2;
2033   let Inst{9-5}   = Rn;
2034   let Inst{4-0}   = Rd;
2035 }
2036
2037 def inv_cond_XFORM : SDNodeXForm<imm, [{
2038   ARM64CC::CondCode CC = static_cast<ARM64CC::CondCode>(N->getZExtValue());
2039   return CurDAG->getTargetConstant(ARM64CC::getInvertedCondCode(CC), MVT::i32);
2040 }]>;
2041
2042 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2043   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2044     let Inst{31} = 0;
2045   }
2046   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2047     let Inst{31} = 1;
2048   }
2049
2050   def : Pat<(ARM64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2051             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2052                                            (inv_cond_XFORM imm:$cond))>;
2053
2054   def : Pat<(ARM64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2055             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2056                                            (inv_cond_XFORM imm:$cond))>;
2057 }
2058
2059 //---
2060 // Special Mask Value
2061 //---
2062 def maski8_or_more : Operand<i32>,
2063   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2064 }
2065 def maski16_or_more : Operand<i32>,
2066   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2067 }
2068
2069
2070 //---
2071 // Load/store
2072 //---
2073
2074 // (unsigned immediate)
2075 // Indexed for 8-bit registers. offset is in range [0,4095].
2076 def MemoryIndexed8Operand : AsmOperandClass {
2077   let Name = "MemoryIndexed8";
2078   let DiagnosticType = "InvalidMemoryIndexed8";
2079 }
2080 def am_indexed8 : Operand<i64>,
2081                   ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []> {
2082   let PrintMethod = "printAMIndexed<8>";
2083   let EncoderMethod
2084       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale1>";
2085   let ParserMatchClass = MemoryIndexed8Operand;
2086   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2087 }
2088
2089 // Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190],
2090 // stored as immval/2 (the 12-bit literal that encodes directly into the insn).
2091 def MemoryIndexed16Operand : AsmOperandClass {
2092   let Name = "MemoryIndexed16";
2093   let DiagnosticType = "InvalidMemoryIndexed16";
2094 }
2095 def am_indexed16 : Operand<i64>,
2096                    ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []> {
2097   let PrintMethod = "printAMIndexed<16>";
2098   let EncoderMethod
2099       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale2>";
2100   let ParserMatchClass = MemoryIndexed16Operand;
2101   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2102 }
2103
2104 // Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380],
2105 // stored as immval/4 (the 12-bit literal that encodes directly into the insn).
2106 def MemoryIndexed32Operand : AsmOperandClass {
2107   let Name = "MemoryIndexed32";
2108   let DiagnosticType = "InvalidMemoryIndexed32";
2109 }
2110 def am_indexed32 : Operand<i64>,
2111                    ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []> {
2112   let PrintMethod = "printAMIndexed<32>";
2113   let EncoderMethod
2114       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale4>";
2115   let ParserMatchClass = MemoryIndexed32Operand;
2116   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2117 }
2118
2119 // Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760],
2120 // stored as immval/8 (the 12-bit literal that encodes directly into the insn).
2121 def MemoryIndexed64Operand : AsmOperandClass {
2122   let Name = "MemoryIndexed64";
2123   let DiagnosticType = "InvalidMemoryIndexed64";
2124 }
2125 def am_indexed64 : Operand<i64>,
2126                    ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []> {
2127   let PrintMethod = "printAMIndexed<64>";
2128   let EncoderMethod
2129       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale8>";
2130   let ParserMatchClass = MemoryIndexed64Operand;
2131   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2132 }
2133
2134 // Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520],
2135 // stored as immval/16 (the 12-bit literal that encodes directly into the insn).
2136 def MemoryIndexed128Operand : AsmOperandClass {
2137   let Name = "MemoryIndexed128";
2138   let DiagnosticType = "InvalidMemoryIndexed128";
2139 }
2140 def am_indexed128 : Operand<i64>,
2141                    ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []> {
2142   let PrintMethod = "printAMIndexed<128>";
2143   let EncoderMethod
2144       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale16>";
2145   let ParserMatchClass = MemoryIndexed128Operand;
2146   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2147 }
2148
2149 // No offset.
2150 def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; }
2151 def am_noindex : Operand<i64>,
2152                  ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
2153   let PrintMethod = "printAMNoIndex";
2154   let ParserMatchClass = MemoryNoIndexOperand;
2155   let MIOperandInfo = (ops GPR64sp:$base);
2156 }
2157
2158 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2159                       string asm, list<dag> pattern>
2160     : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2161   bits<5> dst;
2162
2163   bits<17> addr;
2164   bits<5> base = addr{4-0};
2165   bits<12> offset = addr{16-5};
2166
2167   let Inst{31-30} = sz;
2168   let Inst{29-27} = 0b111;
2169   let Inst{26}    = V;
2170   let Inst{25-24} = 0b01;
2171   let Inst{23-22} = opc;
2172   let Inst{21-10} = offset;
2173   let Inst{9-5}   = base;
2174   let Inst{4-0}   = dst;
2175
2176   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2177 }
2178
2179 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2180 class LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2181              Operand indextype, string asm, list<dag> pattern>
2182     : BaseLoadStoreUI<sz, V, opc,
2183                       (outs regtype:$Rt), (ins indextype:$addr), asm, pattern>,
2184       Sched<[WriteLD]>;
2185
2186 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2187 class StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2188              Operand indextype, string asm, list<dag> pattern>
2189     : BaseLoadStoreUI<sz, V, opc,
2190                       (outs), (ins regtype:$Rt, indextype:$addr), asm, pattern>,
2191       Sched<[WriteST]>;
2192
2193 def PrefetchOperand : AsmOperandClass {
2194   let Name = "Prefetch";
2195   let ParserMethod = "tryParsePrefetch";
2196 }
2197 def prfop : Operand<i32> {
2198   let PrintMethod = "printPrefetchOp";
2199   let ParserMatchClass = PrefetchOperand;
2200 }
2201
2202 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2203 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2204     : BaseLoadStoreUI<sz, V, opc,
2205                       (outs), (ins prfop:$Rt, am_indexed64:$addr), asm, pat>,
2206       Sched<[WriteLD]>;
2207
2208 //---
2209 // Load literal
2210 //---
2211
2212 // Load literal address: 19-bit immediate. The low two bits of the target
2213 // offset are implied zero and so are not part of the immediate.
2214 def am_ldrlit : Operand<OtherVT> {
2215   let EncoderMethod = "getLoadLiteralOpValue";
2216   let DecoderMethod = "DecodePCRelLabel19";
2217   let PrintMethod = "printAlignedLabel";
2218   let ParserMatchClass = PCRelLabel19Operand;
2219 }
2220
2221 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2222 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2223     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2224         asm, "\t$Rt, $label", "", []>,
2225       Sched<[WriteLD]> {
2226   bits<5> Rt;
2227   bits<19> label;
2228   let Inst{31-30} = opc;
2229   let Inst{29-27} = 0b011;
2230   let Inst{26}    = V;
2231   let Inst{25-24} = 0b00;
2232   let Inst{23-5}  = label;
2233   let Inst{4-0}   = Rt;
2234 }
2235
2236 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2237 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2238     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2239         asm, "\t$Rt, $label", "", pat>,
2240       Sched<[WriteLD]> {
2241   bits<5> Rt;
2242   bits<19> label;
2243   let Inst{31-30} = opc;
2244   let Inst{29-27} = 0b011;
2245   let Inst{26}    = V;
2246   let Inst{25-24} = 0b00;
2247   let Inst{23-5}  = label;
2248   let Inst{4-0}   = Rt;
2249 }
2250
2251 //---
2252 // Load/store register offset
2253 //---
2254
2255 class MemROAsmOperand<int sz> : AsmOperandClass {
2256   let Name = "MemoryRegisterOffset"#sz;
2257   let DiagnosticType = "InvalidMemoryIndexed";
2258 }
2259
2260 def MemROAsmOperand8 : MemROAsmOperand<8>;
2261 def MemROAsmOperand16 : MemROAsmOperand<16>;
2262 def MemROAsmOperand32 : MemROAsmOperand<32>;
2263 def MemROAsmOperand64 : MemROAsmOperand<64>;
2264 def MemROAsmOperand128 : MemROAsmOperand<128>;
2265
2266 class ro_indexed<int sz> : Operand<i64> { // ComplexPattern<...>
2267   let PrintMethod = "printMemoryRegOffset<" # sz # ">";
2268   let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend);
2269 }
2270
2271 def ro_indexed8 : ro_indexed<8>, ComplexPattern<i64, 3, "SelectAddrModeRO8", []> {
2272   let ParserMatchClass = MemROAsmOperand8;
2273 }
2274
2275 def ro_indexed16 : ro_indexed<16>, ComplexPattern<i64, 3, "SelectAddrModeRO16", []> {
2276   let ParserMatchClass = MemROAsmOperand16;
2277 }
2278
2279 def ro_indexed32 : ro_indexed<32>, ComplexPattern<i64, 3, "SelectAddrModeRO32", []> {
2280   let ParserMatchClass = MemROAsmOperand32;
2281 }
2282
2283 def ro_indexed64 : ro_indexed<64>, ComplexPattern<i64, 3, "SelectAddrModeRO64", []> {
2284   let ParserMatchClass = MemROAsmOperand64;
2285 }
2286
2287 def ro_indexed128 : ro_indexed<128>, ComplexPattern<i64, 3, "SelectAddrModeRO128", []> {
2288   let ParserMatchClass = MemROAsmOperand128;
2289 }
2290
2291 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2292                       string asm, dag ins, dag outs, list<dag> pat>
2293     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2294   // The operands are in order to match the 'addr' MI operands, so we
2295   // don't need an encoder method and by-name matching. Just use the default
2296   // in-order handling. Since we're using by-order, make sure the names
2297   // do not match.
2298   bits<5> dst;
2299   bits<5> base;
2300   bits<5> offset;
2301   bits<4> extend;
2302   let Inst{31-30} = sz;
2303   let Inst{29-27} = 0b111;
2304   let Inst{26}    = V;
2305   let Inst{25-24} = 0b00;
2306   let Inst{23-22} = opc;
2307   let Inst{21}    = 1;
2308   let Inst{20-16} = offset;
2309   let Inst{15-13} = extend{3-1};
2310
2311   let Inst{12}    = extend{0};
2312   let Inst{11-10} = 0b10;
2313   let Inst{9-5}   = base;
2314   let Inst{4-0}   = dst;
2315
2316   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2317 }
2318
2319 class Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2320              string asm, list<dag> pat>
2321   : LoadStore8RO<sz, V, opc, regtype, asm,
2322                  (outs regtype:$Rt), (ins ro_indexed8:$addr), pat>,
2323     Sched<[WriteLDIdx, ReadAdrBase]>;
2324
2325 class Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2326              string asm, list<dag> pat>
2327   : LoadStore8RO<sz, V, opc, regtype, asm,
2328                  (outs), (ins regtype:$Rt, ro_indexed8:$addr), pat>,
2329     Sched<[WriteSTIdx, ReadAdrBase]>;
2330
2331 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2332                       string asm, dag ins, dag outs, list<dag> pat>
2333     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2334   // The operands are in order to match the 'addr' MI operands, so we
2335   // don't need an encoder method and by-name matching. Just use the default
2336   // in-order handling. Since we're using by-order, make sure the names
2337   // do not match.
2338   bits<5> dst;
2339   bits<5> base;
2340   bits<5> offset;
2341   bits<4> extend;
2342   let Inst{31-30} = sz;
2343   let Inst{29-27} = 0b111;
2344   let Inst{26}    = V;
2345   let Inst{25-24} = 0b00;
2346   let Inst{23-22} = opc;
2347   let Inst{21}    = 1;
2348   let Inst{20-16} = offset;
2349   let Inst{15-13} = extend{3-1};
2350
2351   let Inst{12}    = extend{0};
2352   let Inst{11-10} = 0b10;
2353   let Inst{9-5}   = base;
2354   let Inst{4-0}   = dst;
2355
2356   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2357 }
2358
2359 class Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2360              string asm, list<dag> pat>
2361   : LoadStore16RO<sz, V, opc, regtype, asm,
2362                  (outs regtype:$Rt), (ins ro_indexed16:$addr), pat>,
2363     Sched<[WriteLDIdx, ReadAdrBase]>;
2364
2365 class Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2366              string asm, list<dag> pat>
2367   : LoadStore16RO<sz, V, opc, regtype, asm,
2368                  (outs), (ins regtype:$Rt, ro_indexed16:$addr), pat>,
2369     Sched<[WriteSTIdx, ReadAdrBase]>;
2370
2371 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2372                       string asm, dag ins, dag outs, list<dag> pat>
2373     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2374   // The operands are in order to match the 'addr' MI operands, so we
2375   // don't need an encoder method and by-name matching. Just use the default
2376   // in-order handling. Since we're using by-order, make sure the names
2377   // do not match.
2378   bits<5> dst;
2379   bits<5> base;
2380   bits<5> offset;
2381   bits<4> extend;
2382   let Inst{31-30} = sz;
2383   let Inst{29-27} = 0b111;
2384   let Inst{26}    = V;
2385   let Inst{25-24} = 0b00;
2386   let Inst{23-22} = opc;
2387   let Inst{21}    = 1;
2388   let Inst{20-16} = offset;
2389   let Inst{15-13} = extend{3-1};
2390
2391   let Inst{12}    = extend{0};
2392   let Inst{11-10} = 0b10;
2393   let Inst{9-5}   = base;
2394   let Inst{4-0}   = dst;
2395
2396   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2397 }
2398
2399 class Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2400              string asm, list<dag> pat>
2401   : LoadStore32RO<sz, V, opc, regtype, asm,
2402                  (outs regtype:$Rt), (ins ro_indexed32:$addr), pat>,
2403     Sched<[WriteLDIdx, ReadAdrBase]>;
2404
2405 class Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2406              string asm, list<dag> pat>
2407   : LoadStore32RO<sz, V, opc, regtype, asm,
2408                  (outs), (ins regtype:$Rt, ro_indexed32:$addr), pat>,
2409     Sched<[WriteSTIdx, ReadAdrBase]>;
2410
2411 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2412                       string asm, dag ins, dag outs, list<dag> pat>
2413     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2414   // The operands are in order to match the 'addr' MI operands, so we
2415   // don't need an encoder method and by-name matching. Just use the default
2416   // in-order handling. Since we're using by-order, make sure the names
2417   // do not match.
2418   bits<5> dst;
2419   bits<5> base;
2420   bits<5> offset;
2421   bits<4> extend;
2422   let Inst{31-30} = sz;
2423   let Inst{29-27} = 0b111;
2424   let Inst{26}    = V;
2425   let Inst{25-24} = 0b00;
2426   let Inst{23-22} = opc;
2427   let Inst{21}    = 1;
2428   let Inst{20-16} = offset;
2429   let Inst{15-13} = extend{3-1};
2430
2431   let Inst{12}    = extend{0};
2432   let Inst{11-10} = 0b10;
2433   let Inst{9-5}   = base;
2434   let Inst{4-0}   = dst;
2435
2436   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2437 }
2438
2439 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2440 class Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2441              string asm, list<dag> pat>
2442   : LoadStore64RO<sz, V, opc, regtype, asm,
2443                  (outs regtype:$Rt), (ins ro_indexed64:$addr), pat>,
2444     Sched<[WriteLDIdx, ReadAdrBase]>;
2445
2446 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2447 class Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2448              string asm, list<dag> pat>
2449   : LoadStore64RO<sz, V, opc, regtype, asm,
2450                  (outs), (ins regtype:$Rt, ro_indexed64:$addr), pat>,
2451     Sched<[WriteSTIdx, ReadAdrBase]>;
2452
2453
2454 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2455                       string asm, dag ins, dag outs, list<dag> pat>
2456     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2457   // The operands are in order to match the 'addr' MI operands, so we
2458   // don't need an encoder method and by-name matching. Just use the default
2459   // in-order handling. Since we're using by-order, make sure the names
2460   // do not match.
2461   bits<5> dst;
2462   bits<5> base;
2463   bits<5> offset;
2464   bits<4> extend;
2465   let Inst{31-30} = sz;
2466   let Inst{29-27} = 0b111;
2467   let Inst{26}    = V;
2468   let Inst{25-24} = 0b00;
2469   let Inst{23-22} = opc;
2470   let Inst{21}    = 1;
2471   let Inst{20-16} = offset;
2472   let Inst{15-13} = extend{3-1};
2473
2474   let Inst{12}    = extend{0};
2475   let Inst{11-10} = 0b10;
2476   let Inst{9-5}   = base;
2477   let Inst{4-0}   = dst;
2478
2479   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2480 }
2481
2482 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2483 class Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2484              string asm, list<dag> pat>
2485   : LoadStore128RO<sz, V, opc, regtype, asm,
2486                  (outs regtype:$Rt), (ins ro_indexed128:$addr), pat>,
2487     Sched<[WriteLDIdx, ReadAdrBase]>;
2488
2489 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2490 class Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2491              string asm, list<dag> pat>
2492   : LoadStore128RO<sz, V, opc, regtype, asm,
2493                  (outs), (ins regtype:$Rt, ro_indexed128:$addr), pat>,
2494     Sched<[WriteSTIdx, ReadAdrBase]>;
2495
2496 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2497 class PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2498     : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm,
2499          "\t$Rt, $addr", "", pat>,
2500       Sched<[WriteLD]> {
2501   // The operands are in order to match the 'addr' MI operands, so we
2502   // don't need an encoder method and by-name matching. Just use the default
2503   // in-order handling. Since we're using by-order, make sure the names
2504   // do not match.
2505   bits<5> dst;
2506   bits<5> base;
2507   bits<5> offset;
2508   bits<4> extend;
2509   let Inst{31-30} = sz;
2510   let Inst{29-27} = 0b111;
2511   let Inst{26}    = V;
2512   let Inst{25-24} = 0b00;
2513   let Inst{23-22} = opc;
2514   let Inst{21}    = 1;
2515   let Inst{20-16} = offset;
2516   let Inst{15-13} = extend{3-1};
2517
2518   let Inst{12}    = extend{0};
2519   let Inst{11-10} = 0b10;
2520   let Inst{9-5}   = base;
2521   let Inst{4-0}   = dst;
2522
2523   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2524 }
2525
2526 //---
2527 // Load/store unscaled immediate
2528 //---
2529
2530 def MemoryUnscaledOperand : AsmOperandClass {
2531   let Name = "MemoryUnscaled";
2532   let DiagnosticType = "InvalidMemoryIndexedSImm9";
2533 }
2534 class am_unscaled_operand : Operand<i64> {
2535   let PrintMethod = "printAMIndexed<8>";
2536   let ParserMatchClass = MemoryUnscaledOperand;
2537   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2538 }
2539 class am_unscaled_wb_operand : Operand<i64> {
2540   let PrintMethod = "printAMIndexedWB<8>";
2541   let ParserMatchClass = MemoryUnscaledOperand;
2542   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2543 }
2544 def am_unscaled   : am_unscaled_operand;
2545 def am_unscaled_wb: am_unscaled_wb_operand;
2546 def am_unscaled8  : am_unscaled_operand,
2547                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2548 def am_unscaled16 : am_unscaled_operand,
2549                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2550 def am_unscaled32 : am_unscaled_operand,
2551                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2552 def am_unscaled64 : am_unscaled_operand,
2553                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2554 def am_unscaled128 : am_unscaled_operand,
2555                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2556
2557 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2558                            string asm, list<dag> pattern>
2559     : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2560   // The operands are in order to match the 'addr' MI operands, so we
2561   // don't need an encoder method and by-name matching. Just use the default
2562   // in-order handling. Since we're using by-order, make sure the names
2563   // do not match.
2564   bits<5> dst;
2565   bits<5> base;
2566   bits<9> offset;
2567   let Inst{31-30} = sz;
2568   let Inst{29-27} = 0b111;
2569   let Inst{26}    = V;
2570   let Inst{25-24} = 0b00;
2571   let Inst{23-22} = opc;
2572   let Inst{21}    = 0;
2573   let Inst{20-12} = offset;
2574   let Inst{11-10} = 0b00;
2575   let Inst{9-5}   = base;
2576   let Inst{4-0}   = dst;
2577
2578   let DecoderMethod = "DecodeSignedLdStInstruction";
2579 }
2580
2581 let AddedComplexity = 1 in // try this before LoadUI
2582 class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2583                    Operand amtype, string asm, list<dag> pattern>
2584     : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2585                            (ins amtype:$addr), asm, pattern>,
2586       Sched<[WriteLD]>;
2587
2588 let AddedComplexity = 1 in // try this before StoreUI
2589 class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2590                     Operand amtype, string asm, list<dag> pattern>
2591     : BaseLoadStoreUnscale<sz, V, opc, (outs),
2592                            (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2593       Sched<[WriteST]>;
2594
2595 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2596 class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2597     : BaseLoadStoreUnscale<sz, V, opc, (outs),
2598                            (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2599       Sched<[WriteLD]>;
2600
2601 //---
2602 // Load/store unscaled immediate, unprivileged
2603 //---
2604
2605 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2606                                 dag oops, dag iops, string asm>
2607     : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2608   // The operands are in order to match the 'addr' MI operands, so we
2609   // don't need an encoder method and by-name matching. Just use the default
2610   // in-order handling. Since we're using by-order, make sure the names
2611   // do not match.
2612   bits<5> dst;
2613   bits<5> base;
2614   bits<9> offset;
2615   let Inst{31-30} = sz;
2616   let Inst{29-27} = 0b111;
2617   let Inst{26}    = V;
2618   let Inst{25-24} = 0b00;
2619   let Inst{23-22} = opc;
2620   let Inst{21}    = 0;
2621   let Inst{20-12} = offset;
2622   let Inst{11-10} = 0b10;
2623   let Inst{9-5}   = base;
2624   let Inst{4-0}   = dst;
2625
2626   let DecoderMethod = "DecodeSignedLdStInstruction";
2627 }
2628
2629 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2630 class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2631                    string asm>
2632     : BaseLoadStoreUnprivileged<sz, V, opc,
2633                       (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2634       Sched<[WriteLD]>;
2635 }
2636
2637 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2638 class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2639                     string asm>
2640     : BaseLoadStoreUnprivileged<sz, V, opc,
2641                       (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2642       Sched<[WriteST]>;
2643 }
2644
2645 //---
2646 // Load/store pre-indexed
2647 //---
2648
2649 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2650                           string asm, string cstr>
2651     : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2652   // The operands are in order to match the 'addr' MI operands, so we
2653   // don't need an encoder method and by-name matching. Just use the default
2654   // in-order handling.
2655   bits<5> dst;
2656   bits<5> base;
2657   bits<9> offset;
2658   let Inst{31-30} = sz;
2659   let Inst{29-27} = 0b111;
2660   let Inst{26}    = V;
2661   let Inst{25-24} = 0;
2662   let Inst{23-22} = opc;
2663   let Inst{21}    = 0;
2664   let Inst{20-12} = offset;
2665   let Inst{11-10} = 0b11;
2666   let Inst{9-5}   = base;
2667   let Inst{4-0}   = dst;
2668
2669   let DecoderMethod = "DecodeSignedLdStInstruction";
2670 }
2671
2672 let hasSideEffects = 0 in {
2673 let mayStore = 0, mayLoad = 1 in
2674 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2675 //        we need the complex addressing mode for the memory reference, but
2676 //        we also need the write-back specified as a tied operand to the
2677 //        base register. That combination does not play nicely with
2678 //        the asm matcher and friends.
2679 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2680              string asm>
2681     : BaseLoadStorePreIdx<sz, V, opc,
2682                      (outs regtype:$Rt/*, GPR64sp:$wback*/),
2683                      (ins am_unscaled_wb:$addr), asm, ""/*"$addr.base = $wback"*/>,
2684       Sched<[WriteLD, WriteAdr]>;
2685
2686 let mayStore = 1, mayLoad = 0 in
2687 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2688              string asm>
2689     : BaseLoadStorePreIdx<sz, V, opc,
2690                       (outs/* GPR64sp:$wback*/),
2691                       (ins regtype:$Rt, am_unscaled_wb:$addr),
2692                        asm, ""/*"$addr.base = $wback"*/>,
2693       Sched<[WriteAdr, WriteST]>;
2694 } // hasSideEffects = 0
2695
2696 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2697 // logic finally gets smart enough to strip off tied operands that are just
2698 // for isel convenience, we can get rid of these pseudos and just reference
2699 // the real instructions directly.
2700 //
2701 // Ironically, also because of the writeback operands, we can't put the
2702 // matcher pattern directly on the instruction, but need to define it
2703 // separately.
2704 //
2705 // Loads aren't matched with patterns here at all, but rather in C++
2706 // custom lowering.
2707 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2708 class LoadPreIdxPseudo<RegisterClass regtype>
2709     : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2710              (ins am_noindex:$addr, simm9:$offset), [],
2711               "$addr.base = $wback,@earlyclobber $wback">,
2712       Sched<[WriteLD, WriteAdr]>;
2713 class LoadPostIdxPseudo<RegisterClass regtype>
2714     : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2715              (ins am_noindex:$addr, simm9:$offset), [],
2716               "$addr.base = $wback,@earlyclobber $wback">,
2717       Sched<[WriteLD, WriteI]>;
2718 }
2719 multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2720                              SDPatternOperator OpNode> {
2721   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2722   def _isel: Pseudo<(outs GPR64sp:$wback),
2723                     (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2724                     "$addr.base = $wback,@earlyclobber $wback">,
2725       Sched<[WriteAdr, WriteST]>;
2726
2727   def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2728             (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2729                                             simm9:$offset)>;
2730 }
2731
2732 //---
2733 // Load/store post-indexed
2734 //---
2735
2736 // (pre-index) load/stores.
2737 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2738                           string asm, string cstr>
2739     : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2740   // The operands are in order to match the 'addr' MI operands, so we
2741   // don't need an encoder method and by-name matching. Just use the default
2742   // in-order handling.
2743   bits<5> dst;
2744   bits<5> base;
2745   bits<9> offset;
2746   let Inst{31-30} = sz;
2747   let Inst{29-27} = 0b111;
2748   let Inst{26}    = V;
2749   let Inst{25-24} = 0b00;
2750   let Inst{23-22} = opc;
2751   let Inst{21}    = 0b0;
2752   let Inst{20-12} = offset;
2753   let Inst{11-10} = 0b01;
2754   let Inst{9-5}   = base;
2755   let Inst{4-0}   = dst;
2756
2757   let DecoderMethod = "DecodeSignedLdStInstruction";
2758 }
2759
2760 let hasSideEffects = 0 in {
2761 let mayStore = 0, mayLoad = 1 in
2762 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2763 //        we need the complex addressing mode for the memory reference, but
2764 //        we also need the write-back specified as a tied operand to the
2765 //        base register. That combination does not play nicely with
2766 //        the asm matcher and friends.
2767 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2768              string asm>
2769     : BaseLoadStorePostIdx<sz, V, opc,
2770                       (outs regtype:$Rt/*, GPR64sp:$wback*/),
2771                       (ins am_noindex:$addr, simm9:$idx),
2772                       asm, ""/*"$addr.base = $wback"*/>,
2773       Sched<[WriteLD, WriteI]>;
2774
2775 let mayStore = 1, mayLoad = 0 in
2776 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2777              string asm>
2778     : BaseLoadStorePostIdx<sz, V, opc,
2779                       (outs/* GPR64sp:$wback*/),
2780                       (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2781                        asm, ""/*"$addr.base = $wback"*/>,
2782     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2783 } // hasSideEffects = 0
2784
2785 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2786 // logic finally gets smart enough to strip off tied operands that are just
2787 // for isel convenience, we can get rid of these pseudos and just reference
2788 // the real instructions directly.
2789 //
2790 // Ironically, also because of the writeback operands, we can't put the
2791 // matcher pattern directly on the instruction, but need to define it
2792 // separately.
2793 multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2794                               SDPatternOperator OpNode, Instruction Insn> {
2795   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2796   def _isel: Pseudo<(outs GPR64sp:$wback),
2797                     (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2798                     "$addr.base = $wback,@earlyclobber $wback">,
2799       PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2800       Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2801
2802   def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2803             (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2804                                             simm9:$idx)>;
2805 }
2806
2807 //---
2808 // Load/store pair
2809 //---
2810
2811 // (indexed, offset)
2812
2813 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2814                               string asm>
2815     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2816   // The operands are in order to match the 'addr' MI operands, so we
2817   // don't need an encoder method and by-name matching. Just use the default
2818   // in-order handling. Since we're using by-order, make sure the names
2819   // do not match.
2820   bits<5> dst;
2821   bits<5> dst2;
2822   bits<5> base;
2823   bits<7> offset;
2824   let Inst{31-30} = opc;
2825   let Inst{29-27} = 0b101;
2826   let Inst{26}    = V;
2827   let Inst{25-23} = 0b010;
2828   let Inst{22}    = L;
2829   let Inst{21-15} = offset;
2830   let Inst{14-10} = dst2;
2831   let Inst{9-5}   = base;
2832   let Inst{4-0}   = dst;
2833
2834   let DecoderMethod = "DecodePairLdStInstruction";
2835 }
2836
2837 let hasSideEffects = 0 in {
2838 let mayStore = 0, mayLoad = 1 in
2839 class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2840                      Operand indextype, string asm>
2841     : BaseLoadStorePairOffset<opc, V, 1,
2842                               (outs regtype:$Rt, regtype:$Rt2),
2843                               (ins indextype:$addr), asm>,
2844       Sched<[WriteLD, WriteLDHi]>;
2845
2846 let mayLoad = 0, mayStore = 1 in
2847 class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2848                       Operand indextype, string asm>
2849     : BaseLoadStorePairOffset<opc, V, 0, (outs),
2850                              (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2851                              asm>,
2852       Sched<[WriteSTP]>;
2853 } // hasSideEffects = 0
2854
2855 // (pre-indexed)
2856
2857 def MemoryIndexed32SImm7 : AsmOperandClass {
2858   let Name = "MemoryIndexed32SImm7";
2859   let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2860 }
2861 def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2862   let PrintMethod = "printAMIndexed<32>";
2863   let ParserMatchClass = MemoryIndexed32SImm7;
2864   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2865 }
2866 def am_indexed32simm7_wb : Operand<i32> { // ComplexPattern<...>
2867   let PrintMethod = "printAMIndexedWB<32>";
2868   let ParserMatchClass = MemoryIndexed32SImm7;
2869   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2870 }
2871
2872 def MemoryIndexed64SImm7 : AsmOperandClass {
2873   let Name = "MemoryIndexed64SImm7";
2874   let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2875 }
2876 def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2877   let PrintMethod = "printAMIndexed<64>";
2878   let ParserMatchClass = MemoryIndexed64SImm7;
2879   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2880 }
2881 def am_indexed64simm7_wb : Operand<i32> { // ComplexPattern<...>
2882   let PrintMethod = "printAMIndexedWB<64>";
2883   let ParserMatchClass = MemoryIndexed64SImm7;
2884   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2885 }
2886
2887 def MemoryIndexed128SImm7 : AsmOperandClass {
2888   let Name = "MemoryIndexed128SImm7";
2889   let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2890 }
2891 def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2892   let PrintMethod = "printAMIndexed<128>";
2893   let ParserMatchClass = MemoryIndexed128SImm7;
2894   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2895 }
2896 def am_indexed128simm7_wb : Operand<i32> { // ComplexPattern<...>
2897   let PrintMethod = "printAMIndexedWB<128>";
2898   let ParserMatchClass = MemoryIndexed128SImm7;
2899   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2900 }
2901
2902 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2903                               string asm>
2904     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2905   // The operands are in order to match the 'addr' MI operands, so we
2906   // don't need an encoder method and by-name matching. Just use the default
2907   // in-order handling. Since we're using by-order, make sure the names
2908   // do not match.
2909   bits<5> dst;
2910   bits<5> dst2;
2911   bits<5> base;
2912   bits<7> offset;
2913   let Inst{31-30} = opc;
2914   let Inst{29-27} = 0b101;
2915   let Inst{26}    = V;
2916   let Inst{25-23} = 0b011;
2917   let Inst{22}    = L;
2918   let Inst{21-15} = offset;
2919   let Inst{14-10} = dst2;
2920   let Inst{9-5}   = base;
2921   let Inst{4-0}   = dst;
2922
2923   let DecoderMethod = "DecodePairLdStInstruction";
2924 }
2925
2926 let hasSideEffects = 0 in {
2927 let mayStore = 0, mayLoad = 1 in
2928 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2929                      Operand addrmode, string asm>
2930     : BaseLoadStorePairPreIdx<opc, V, 1,
2931                               (outs regtype:$Rt, regtype:$Rt2),
2932                               (ins addrmode:$addr), asm>,
2933       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2934
2935 let mayStore = 1, mayLoad = 0 in
2936 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2937                       Operand addrmode, string asm>
2938     : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2939                              (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2940                              asm>,
2941       Sched<[WriteAdr, WriteSTP]>;
2942 } // hasSideEffects = 0
2943
2944 // (post-indexed)
2945
2946 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2947                               string asm>
2948     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2949   // The operands are in order to match the 'addr' MI operands, so we
2950   // don't need an encoder method and by-name matching. Just use the default
2951   // in-order handling. Since we're using by-order, make sure the names
2952   // do not match.
2953   bits<5> dst;
2954   bits<5> dst2;
2955   bits<5> base;
2956   bits<7> offset;
2957   let Inst{31-30} = opc;
2958   let Inst{29-27} = 0b101;
2959   let Inst{26}    = V;
2960   let Inst{25-23} = 0b001;
2961   let Inst{22}    = L;
2962   let Inst{21-15} = offset;
2963   let Inst{14-10} = dst2;
2964   let Inst{9-5}   = base;
2965   let Inst{4-0}   = dst;
2966
2967   let DecoderMethod = "DecodePairLdStInstruction";
2968 }
2969
2970 let hasSideEffects = 0 in {
2971 let mayStore = 0, mayLoad = 1 in
2972 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2973                       Operand idxtype, string asm>
2974     : BaseLoadStorePairPostIdx<opc, V, 1,
2975                               (outs regtype:$Rt, regtype:$Rt2),
2976                               (ins am_noindex:$addr, idxtype:$idx), asm>,
2977       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2978
2979 let mayStore = 1, mayLoad = 0 in
2980 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2981                        Operand idxtype, string asm>
2982     : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2983                              (ins regtype:$Rt, regtype:$Rt2,
2984                                   am_noindex:$addr, idxtype:$idx),
2985                              asm>,
2986       Sched<[WriteAdr, WriteSTP]>;
2987 } // hasSideEffects = 0
2988
2989 //  (no-allocate)
2990
2991 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2992                               string asm>
2993     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2994   // The operands are in order to match the 'addr' MI operands, so we
2995   // don't need an encoder method and by-name matching. Just use the default
2996   // in-order handling. Since we're using by-order, make sure the names
2997   // do not match.
2998   bits<5> dst;
2999   bits<5> dst2;
3000   bits<5> base;
3001   bits<7> offset;
3002   let Inst{31-30} = opc;
3003   let Inst{29-27} = 0b101;
3004   let Inst{26}    = V;
3005   let Inst{25-23} = 0b000;
3006   let Inst{22}    = L;
3007   let Inst{21-15} = offset;
3008   let Inst{14-10} = dst2;
3009   let Inst{9-5}   = base;
3010   let Inst{4-0}   = dst;
3011
3012   let DecoderMethod = "DecodePairLdStInstruction";
3013 }
3014
3015 let hasSideEffects = 0 in {
3016 let mayStore = 0, mayLoad = 1 in
3017 class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3018                      Operand indextype, string asm>
3019     : BaseLoadStorePairNoAlloc<opc, V, 1,
3020                               (outs regtype:$Rt, regtype:$Rt2),
3021                               (ins indextype:$addr), asm>,
3022       Sched<[WriteLD, WriteLDHi]>;
3023
3024 let mayStore = 1, mayLoad = 0 in
3025 class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3026                       Operand indextype, string asm>
3027     : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3028                              (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
3029                              asm>,
3030       Sched<[WriteSTP]>;
3031 } // hasSideEffects = 0
3032
3033 //---
3034 // Load/store exclusive
3035 //---
3036
3037 // True exclusive operations write to and/or read from the system's exclusive
3038 // monitors, which as far as a compiler is concerned can be modelled as a
3039 // random shared memory address. Hence LoadExclusive mayStore.
3040 //
3041 // Since these instructions have the undefined register bits set to 1 in
3042 // their canonical form, we need a post encoder method to set those bits
3043 // to 1 when encoding these instructions. We do this using the
3044 // fixLoadStoreExclusive function. This function has template parameters:
3045 //
3046 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3047 //
3048 // hasRs indicates that the instruction uses the Rs field, so we won't set
3049 // it to 1 (and the same for Rt2). We don't need template parameters for
3050 // the other register fields since Rt and Rn are always used.
3051 //
3052 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3053 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3054                              dag oops, dag iops, string asm, string operands>
3055     : I<oops, iops, asm, operands, "", []> {
3056   let Inst{31-30} = sz;
3057   let Inst{29-24} = 0b001000;
3058   let Inst{23}    = o2;
3059   let Inst{22}    = L;
3060   let Inst{21}    = o1;
3061   let Inst{15}    = o0;
3062
3063   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3064 }
3065
3066 // Neither Rs nor Rt2 operands.
3067 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3068                                dag oops, dag iops, string asm, string operands>
3069     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3070   bits<5> reg;
3071   bits<5> base;
3072   let Inst{9-5} = base;
3073   let Inst{4-0} = reg;
3074
3075   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3076 }
3077
3078 // Simple load acquires don't set the exclusive monitor
3079 let mayLoad = 1, mayStore = 0 in
3080 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3081                   RegisterClass regtype, string asm>
3082     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3083                                (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
3084       Sched<[WriteLD]>;
3085
3086 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3087                     RegisterClass regtype, string asm>
3088     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3089                                (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
3090       Sched<[WriteLD]>;
3091
3092 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3093                        RegisterClass regtype, string asm>
3094     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3095                              (outs regtype:$Rt, regtype:$Rt2),
3096                              (ins am_noindex:$addr), asm,
3097                              "\t$Rt, $Rt2, $addr">,
3098       Sched<[WriteLD, WriteLDHi]> {
3099   bits<5> dst1;
3100   bits<5> dst2;
3101   bits<5> base;
3102   let Inst{14-10} = dst2;
3103   let Inst{9-5} = base;
3104   let Inst{4-0} = dst1;
3105
3106   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3107 }
3108
3109 // Simple store release operations do not check the exclusive monitor.
3110 let mayLoad = 0, mayStore = 1 in
3111 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3112                    RegisterClass regtype, string asm>
3113     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3114                                (ins regtype:$Rt, am_noindex:$addr),
3115                                asm, "\t$Rt, $addr">,
3116       Sched<[WriteST]>;
3117
3118 let mayLoad = 1, mayStore = 1 in
3119 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3120                      RegisterClass regtype, string asm>
3121     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3122                              (ins regtype:$Rt, am_noindex:$addr),
3123                              asm, "\t$Ws, $Rt, $addr">,
3124       Sched<[WriteSTX]> {
3125   bits<5> status;
3126   bits<5> reg;
3127   bits<5> base;
3128   let Inst{20-16} = status;
3129   let Inst{9-5} = base;
3130   let Inst{4-0} = reg;
3131
3132   let Constraints = "@earlyclobber $Ws";
3133   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3134 }
3135
3136 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3137                          RegisterClass regtype, string asm>
3138     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3139                              (outs GPR32:$Ws),
3140                              (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
3141                               asm, "\t$Ws, $Rt, $Rt2, $addr">,
3142       Sched<[WriteSTX]> {
3143   bits<5> status;
3144   bits<5> dst1;
3145   bits<5> dst2;
3146   bits<5> base;
3147   let Inst{20-16} = status;
3148   let Inst{14-10} = dst2;
3149   let Inst{9-5} = base;
3150   let Inst{4-0} = dst1;
3151
3152   let Constraints = "@earlyclobber $Ws";
3153 }
3154
3155 //---
3156 // Exception generation
3157 //---
3158
3159 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3160 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3161     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3162       Sched<[WriteSys]> {
3163   bits<16> imm;
3164   let Inst{31-24} = 0b11010100;
3165   let Inst{23-21} = op1;
3166   let Inst{20-5}  = imm;
3167   let Inst{4-2}   = 0b000;
3168   let Inst{1-0}   = ll;
3169 }
3170
3171 let Predicates = [HasFPARMv8] in {
3172
3173 //---
3174 // Floating point to integer conversion
3175 //---
3176
3177 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3178                       RegisterClass srcType, RegisterClass dstType,
3179                       string asm, list<dag> pattern>
3180     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3181          asm, "\t$Rd, $Rn", "", pattern>,
3182       Sched<[WriteFCvt]> {
3183   bits<5> Rd;
3184   bits<5> Rn;
3185   let Inst{30-29} = 0b00;
3186   let Inst{28-24} = 0b11110;
3187   let Inst{23-22} = type;
3188   let Inst{21}    = 1;
3189   let Inst{20-19} = rmode;
3190   let Inst{18-16} = opcode;
3191   let Inst{15-10} = 0;
3192   let Inst{9-5}   = Rn;
3193   let Inst{4-0}   = Rd;
3194 }
3195
3196 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3197 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3198                       RegisterClass srcType, RegisterClass dstType,
3199                       Operand immType, string asm, list<dag> pattern>
3200     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3201          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3202       Sched<[WriteFCvt]> {
3203   bits<5> Rd;
3204   bits<5> Rn;
3205   bits<6> scale;
3206   let Inst{30-29} = 0b00;
3207   let Inst{28-24} = 0b11110;
3208   let Inst{23-22} = type;
3209   let Inst{21}    = 0;
3210   let Inst{20-19} = rmode;
3211   let Inst{18-16} = opcode;
3212   let Inst{15-10} = scale;
3213   let Inst{9-5}   = Rn;
3214   let Inst{4-0}   = Rd;
3215 }
3216
3217 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3218            SDPatternOperator OpN> {
3219   // Unscaled single-precision to 32-bit
3220   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3221                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3222     let Inst{31} = 0; // 32-bit GPR flag
3223   }
3224
3225   // Unscaled single-precision to 64-bit
3226   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3227                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3228     let Inst{31} = 1; // 64-bit GPR flag
3229   }
3230
3231   // Unscaled double-precision to 32-bit
3232   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3233                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3234     let Inst{31} = 0; // 32-bit GPR flag
3235   }
3236
3237   // Unscaled double-precision to 64-bit
3238   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3239                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3240     let Inst{31} = 1; // 64-bit GPR flag
3241   }
3242 }
3243
3244 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3245                              SDPatternOperator OpN> {
3246   // Scaled single-precision to 32-bit
3247   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3248                               fixedpoint_f32_i32, asm,
3249               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3250                                           fixedpoint_f32_i32:$scale)))]> {
3251     let Inst{31} = 0; // 32-bit GPR flag
3252     let scale{5} = 1;
3253   }
3254
3255   // Scaled single-precision to 64-bit
3256   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3257                               fixedpoint_f32_i64, asm,
3258               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3259                                           fixedpoint_f32_i64:$scale)))]> {
3260     let Inst{31} = 1; // 64-bit GPR flag
3261   }
3262
3263   // Scaled double-precision to 32-bit
3264   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3265                               fixedpoint_f64_i32, asm,
3266               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3267                                           fixedpoint_f64_i32:$scale)))]> {
3268     let Inst{31} = 0; // 32-bit GPR flag
3269     let scale{5} = 1;
3270   }
3271
3272   // Scaled double-precision to 64-bit
3273   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3274                               fixedpoint_f64_i64, asm,
3275               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3276                                           fixedpoint_f64_i64:$scale)))]> {
3277     let Inst{31} = 1; // 64-bit GPR flag
3278   }
3279 }
3280
3281 //---
3282 // Integer to floating point conversion
3283 //---
3284
3285 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3286 class BaseIntegerToFP<bit isUnsigned,
3287                       RegisterClass srcType, RegisterClass dstType,
3288                       Operand immType, string asm, list<dag> pattern>
3289     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3290          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3291       Sched<[WriteFCvt]> {
3292   bits<5> Rd;
3293   bits<5> Rn;
3294   bits<6> scale;
3295   let Inst{30-23} = 0b00111100;
3296   let Inst{21-17} = 0b00001;
3297   let Inst{16}    = isUnsigned;
3298   let Inst{15-10} = scale;
3299   let Inst{9-5}   = Rn;
3300   let Inst{4-0}   = Rd;
3301 }
3302
3303 class BaseIntegerToFPUnscaled<bit isUnsigned,
3304                       RegisterClass srcType, RegisterClass dstType,
3305                       ValueType dvt, string asm, SDNode node>
3306     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3307          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3308       Sched<[WriteFCvt]> {
3309   bits<5> Rd;
3310   bits<5> Rn;
3311   bits<6> scale;
3312   let Inst{30-23} = 0b00111100;
3313   let Inst{21-17} = 0b10001;
3314   let Inst{16}    = isUnsigned;
3315   let Inst{15-10} = 0b000000;
3316   let Inst{9-5}   = Rn;
3317   let Inst{4-0}   = Rd;
3318 }
3319
3320 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3321   // Unscaled
3322   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3323     let Inst{31} = 0; // 32-bit GPR flag
3324     let Inst{22} = 0; // 32-bit FPR flag
3325   }
3326
3327   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3328     let Inst{31} = 0; // 32-bit GPR flag
3329     let Inst{22} = 1; // 64-bit FPR flag
3330   }
3331
3332   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3333     let Inst{31} = 1; // 64-bit GPR flag
3334     let Inst{22} = 0; // 32-bit FPR flag
3335   }
3336
3337   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3338     let Inst{31} = 1; // 64-bit GPR flag
3339     let Inst{22} = 1; // 64-bit FPR flag
3340   }
3341
3342   // Scaled
3343   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3344                              [(set FPR32:$Rd,
3345                                    (fdiv (node GPR32:$Rn),
3346                                          fixedpoint_f32_i32:$scale))]> {
3347     let Inst{31} = 0; // 32-bit GPR flag
3348     let Inst{22} = 0; // 32-bit FPR flag
3349     let scale{5} = 1;
3350   }
3351
3352   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3353                              [(set FPR64:$Rd,
3354                                    (fdiv (node GPR32:$Rn),
3355                                          fixedpoint_f64_i32:$scale))]> {
3356     let Inst{31} = 0; // 32-bit GPR flag
3357     let Inst{22} = 1; // 64-bit FPR flag
3358     let scale{5} = 1;
3359   }
3360
3361   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3362                              [(set FPR32:$Rd,
3363                                    (fdiv (node GPR64:$Rn),
3364                                          fixedpoint_f32_i64:$scale))]> {
3365     let Inst{31} = 1; // 64-bit GPR flag
3366     let Inst{22} = 0; // 32-bit FPR flag
3367   }
3368
3369   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3370                              [(set FPR64:$Rd,
3371                                    (fdiv (node GPR64:$Rn),
3372                                          fixedpoint_f64_i64:$scale))]> {
3373     let Inst{31} = 1; // 64-bit GPR flag
3374     let Inst{22} = 1; // 64-bit FPR flag
3375   }
3376 }
3377
3378 //---
3379 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3380 //---
3381
3382 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3383 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3384                       RegisterClass srcType, RegisterClass dstType,
3385                       string asm>
3386     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3387         // We use COPY_TO_REGCLASS for these bitconvert operations.
3388         // copyPhysReg() expands the resultant COPY instructions after
3389         // regalloc is done. This gives greater freedom for the allocator
3390         // and related passes (coalescing, copy propagation, et. al.) to
3391         // be more effective.
3392         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3393       Sched<[WriteFCopy]> {
3394   bits<5> Rd;
3395   bits<5> Rn;
3396   let Inst{30-23} = 0b00111100;
3397   let Inst{21}    = 1;
3398   let Inst{20-19} = rmode;
3399   let Inst{18-16} = opcode;
3400   let Inst{15-10} = 0b000000;
3401   let Inst{9-5}   = Rn;
3402   let Inst{4-0}   = Rd;
3403 }
3404
3405 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3406 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3407                      RegisterClass srcType, RegisterOperand dstType, string asm,
3408                      string kind>
3409     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3410         "{\t$Rd"#kind#"[1], $Rn|"#kind#"\t$Rd[1], $Rn}", "", []>,
3411       Sched<[WriteFCopy]> {
3412   bits<5> Rd;
3413   bits<5> Rn;
3414   let Inst{30-23} = 0b00111101;
3415   let Inst{21}    = 1;
3416   let Inst{20-19} = rmode;
3417   let Inst{18-16} = opcode;
3418   let Inst{15-10} = 0b000000;
3419   let Inst{9-5}   = Rn;
3420   let Inst{4-0}   = Rd;
3421 }
3422
3423 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3424 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3425                      RegisterOperand srcType, RegisterClass dstType, string asm,
3426                      string kind>
3427     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm,
3428         "{\t$Rd, $Rn"#kind#"[1]|"#kind#"\t$Rd, $Rn[1]}", "", []>,
3429       Sched<[WriteFCopy]> {
3430   bits<5> Rd;
3431   bits<5> Rn;
3432   let Inst{30-23} = 0b00111101;
3433   let Inst{21}    = 1;
3434   let Inst{20-19} = rmode;
3435   let Inst{18-16} = opcode;
3436   let Inst{15-10} = 0b000000;
3437   let Inst{9-5}   = Rn;
3438   let Inst{4-0}   = Rd;
3439 }
3440
3441
3442
3443 multiclass UnscaledConversion<string asm> {
3444   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3445     let Inst{31} = 0; // 32-bit GPR flag
3446     let Inst{22} = 0; // 32-bit FPR flag
3447   }
3448
3449   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3450     let Inst{31} = 1; // 64-bit GPR flag
3451     let Inst{22} = 1; // 64-bit FPR flag
3452   }
3453
3454   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3455     let Inst{31} = 0; // 32-bit GPR flag
3456     let Inst{22} = 0; // 32-bit FPR flag
3457   }
3458
3459   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3460     let Inst{31} = 1; // 64-bit GPR flag
3461     let Inst{22} = 1; // 64-bit FPR flag
3462   }
3463
3464   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3465                                              asm, ".d"> {
3466     let Inst{31} = 1;
3467     let Inst{22} = 0;
3468   }
3469
3470   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3471                                                asm, ".d"> {
3472     let Inst{31} = 1;
3473     let Inst{22} = 0;
3474   }
3475 }
3476
3477 //---
3478 // Floating point conversion
3479 //---
3480
3481 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3482                        RegisterClass srcType, string asm, list<dag> pattern>
3483     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3484       Sched<[WriteFCvt]> {
3485   bits<5> Rd;
3486   bits<5> Rn;
3487   let Inst{31-24} = 0b00011110;
3488   let Inst{23-22} = type;
3489   let Inst{21-17} = 0b10001;
3490   let Inst{16-15} = opcode;
3491   let Inst{14-10} = 0b10000;
3492   let Inst{9-5}   = Rn;
3493   let Inst{4-0}   = Rd;
3494 }
3495
3496 multiclass FPConversion<string asm> {
3497   // Double-precision to Half-precision
3498   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3499                              [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3500
3501   // Double-precision to Single-precision
3502   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3503                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3504
3505   // Half-precision to Double-precision
3506   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3507                              [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3508
3509   // Half-precision to Single-precision
3510   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3511                              [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3512
3513   // Single-precision to Double-precision
3514   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3515                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3516
3517   // Single-precision to Half-precision
3518   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3519                              [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3520 }
3521
3522 //---
3523 // Single operand floating point data processing
3524 //---
3525
3526 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3527 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3528                               ValueType vt, string asm, SDPatternOperator node>
3529     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3530          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3531       Sched<[WriteF]> {
3532   bits<5> Rd;
3533   bits<5> Rn;
3534   let Inst{31-23} = 0b000111100;
3535   let Inst{21-19} = 0b100;
3536   let Inst{18-15} = opcode;
3537   let Inst{14-10} = 0b10000;
3538   let Inst{9-5}   = Rn;
3539   let Inst{4-0}   = Rd;
3540 }
3541
3542 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3543                                SDPatternOperator node = null_frag> {
3544   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3545     let Inst{22} = 0; // 32-bit size flag
3546   }
3547
3548   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3549     let Inst{22} = 1; // 64-bit size flag
3550   }
3551 }
3552
3553 //---
3554 // Two operand floating point data processing
3555 //---
3556
3557 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3558 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3559                            string asm, list<dag> pat>
3560     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3561          asm, "\t$Rd, $Rn, $Rm", "", pat>,
3562       Sched<[WriteF]> {
3563   bits<5> Rd;
3564   bits<5> Rn;
3565   bits<5> Rm;
3566   let Inst{31-23} = 0b000111100;
3567   let Inst{21}    = 1;
3568   let Inst{20-16} = Rm;
3569   let Inst{15-12} = opcode;
3570   let Inst{11-10} = 0b10;
3571   let Inst{9-5}   = Rn;
3572   let Inst{4-0}   = Rd;
3573 }
3574
3575 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3576                             SDPatternOperator node = null_frag> {
3577   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3578                          [(set (f32 FPR32:$Rd),
3579                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3580     let Inst{22} = 0; // 32-bit size flag
3581   }
3582
3583   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3584                          [(set (f64 FPR64:$Rd),
3585                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3586     let Inst{22} = 1; // 64-bit size flag
3587   }
3588 }
3589
3590 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3591   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3592                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3593     let Inst{22} = 0; // 32-bit size flag
3594   }
3595
3596   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3597                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3598     let Inst{22} = 1; // 64-bit size flag
3599   }
3600 }
3601
3602
3603 //---
3604 // Three operand floating point data processing
3605 //---
3606
3607 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3608                              RegisterClass regtype, string asm, list<dag> pat>
3609     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3610          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3611       Sched<[WriteFMul]> {
3612   bits<5> Rd;
3613   bits<5> Rn;
3614   bits<5> Rm;
3615   bits<5> Ra;
3616   let Inst{31-23} = 0b000111110;
3617   let Inst{21}    = isNegated;
3618   let Inst{20-16} = Rm;
3619   let Inst{15}    = isSub;
3620   let Inst{14-10} = Ra;
3621   let Inst{9-5}   = Rn;
3622   let Inst{4-0}   = Rd;
3623 }
3624
3625 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3626                               SDPatternOperator node> {
3627   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3628             [(set FPR32:$Rd,
3629                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3630     let Inst{22} = 0; // 32-bit size flag
3631   }
3632
3633   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3634             [(set FPR64:$Rd,
3635                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3636     let Inst{22} = 1; // 64-bit size flag
3637   }
3638 }
3639
3640 //---
3641 // Floating point data comparisons
3642 //---
3643
3644 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3645 class BaseOneOperandFPComparison<bit signalAllNans,
3646                                  RegisterClass regtype, string asm,
3647                                  list<dag> pat>
3648     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3649       Sched<[WriteFCmp]> {
3650   bits<5> Rn;
3651   let Inst{31-23} = 0b000111100;
3652   let Inst{21}    = 1;
3653
3654   let Inst{15-10} = 0b001000;
3655   let Inst{9-5}   = Rn;
3656   let Inst{4}     = signalAllNans;
3657   let Inst{3-0}   = 0b1000;
3658
3659   // Rm should be 0b00000 canonically, but we need to accept any value.
3660   let PostEncoderMethod = "fixOneOperandFPComparison";
3661 }
3662
3663 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3664 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3665                                 string asm, list<dag> pat>
3666     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3667       Sched<[WriteFCmp]> {
3668   bits<5> Rm;
3669   bits<5> Rn;
3670   let Inst{31-23} = 0b000111100;
3671   let Inst{21}    = 1;
3672   let Inst{20-16} = Rm;
3673   let Inst{15-10} = 0b001000;
3674   let Inst{9-5}   = Rn;
3675   let Inst{4}     = signalAllNans;
3676   let Inst{3-0}   = 0b0000;
3677 }
3678
3679 multiclass FPComparison<bit signalAllNans, string asm,
3680                         SDPatternOperator OpNode = null_frag> {
3681   let Defs = [NZCV] in {
3682   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3683       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
3684     let Inst{22} = 0;
3685   }
3686
3687   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3688       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
3689     let Inst{22} = 0;
3690   }
3691
3692   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3693       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
3694     let Inst{22} = 1;
3695   }
3696
3697   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3698       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
3699     let Inst{22} = 1;
3700   }
3701   } // Defs = [NZCV]
3702 }
3703
3704 //---
3705 // Floating point conditional comparisons
3706 //---
3707
3708 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3709 class BaseFPCondComparison<bit signalAllNans,
3710                               RegisterClass regtype, string asm>
3711     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3712          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3713       Sched<[WriteFCmp]> {
3714   bits<5> Rn;
3715   bits<5> Rm;
3716   bits<4> nzcv;
3717   bits<4> cond;
3718
3719   let Inst{31-23} = 0b000111100;
3720   let Inst{21}    = 1;
3721   let Inst{20-16} = Rm;
3722   let Inst{15-12} = cond;
3723   let Inst{11-10} = 0b01;
3724   let Inst{9-5}   = Rn;
3725   let Inst{4}     = signalAllNans;
3726   let Inst{3-0}   = nzcv;
3727 }
3728
3729 multiclass FPCondComparison<bit signalAllNans, string asm> {
3730   let Defs = [NZCV], Uses = [NZCV] in {
3731   def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3732     let Inst{22} = 0;
3733   }
3734
3735   def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3736     let Inst{22} = 1;
3737   }
3738   } // Defs = [NZCV], Uses = [NZCV]
3739 }
3740
3741 //---
3742 // Floating point conditional select
3743 //---
3744
3745 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3746     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3747          asm, "\t$Rd, $Rn, $Rm, $cond", "",
3748          [(set regtype:$Rd,
3749                (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3750                           (i32 imm:$cond), NZCV))]>,
3751       Sched<[WriteF]> {
3752   bits<5> Rd;
3753   bits<5> Rn;
3754   bits<5> Rm;
3755   bits<4> cond;
3756
3757   let Inst{31-23} = 0b000111100;
3758   let Inst{21}    = 1;
3759   let Inst{20-16} = Rm;
3760   let Inst{15-12} = cond;
3761   let Inst{11-10} = 0b11;
3762   let Inst{9-5}   = Rn;
3763   let Inst{4-0}   = Rd;
3764 }
3765
3766 multiclass FPCondSelect<string asm> {
3767   let Uses = [NZCV] in {
3768   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3769     let Inst{22} = 0;
3770   }
3771
3772   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3773     let Inst{22} = 1;
3774   }
3775   } // Uses = [NZCV]
3776 }
3777
3778 //---
3779 // Floating move immediate
3780 //---
3781
3782 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3783   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3784       [(set regtype:$Rd, fpimmtype:$imm)]>,
3785     Sched<[WriteFImm]> {
3786   bits<5> Rd;
3787   bits<8> imm;
3788   let Inst{31-23} = 0b000111100;
3789   let Inst{21}    = 1;
3790   let Inst{20-13} = imm;
3791   let Inst{12-5}  = 0b10000000;
3792   let Inst{4-0}   = Rd;
3793 }
3794
3795 multiclass FPMoveImmediate<string asm> {
3796   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3797     let Inst{22} = 0;
3798   }
3799
3800   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3801     let Inst{22} = 1;
3802   }
3803 }
3804 } // end of 'let Predicates = [HasFPARMv8]'
3805
3806 //----------------------------------------------------------------------------
3807 // AdvSIMD
3808 //----------------------------------------------------------------------------
3809
3810 class AsmVectorIndex<string Suffix> : AsmOperandClass {
3811   let Name = "VectorIndex" # Suffix;
3812   let DiagnosticType = "InvalidIndex" # Suffix;
3813 }
3814 def VectorIndexBOperand : AsmVectorIndex<"B">;
3815 def VectorIndexHOperand : AsmVectorIndex<"H">;
3816 def VectorIndexSOperand : AsmVectorIndex<"S">;
3817 def VectorIndexDOperand : AsmVectorIndex<"D">;
3818
3819 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3820   return ((uint64_t)Imm) < 16;
3821 }]> {
3822   let ParserMatchClass = VectorIndexBOperand;
3823   let PrintMethod = "printVectorIndex";
3824   let MIOperandInfo = (ops i64imm);
3825 }
3826 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3827   return ((uint64_t)Imm) < 8;
3828 }]> {
3829   let ParserMatchClass = VectorIndexHOperand;
3830   let PrintMethod = "printVectorIndex";
3831   let MIOperandInfo = (ops i64imm);
3832 }
3833 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3834   return ((uint64_t)Imm) < 4;
3835 }]> {
3836   let ParserMatchClass = VectorIndexSOperand;
3837   let PrintMethod = "printVectorIndex";
3838   let MIOperandInfo = (ops i64imm);
3839 }
3840 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3841   return ((uint64_t)Imm) < 2;
3842 }]> {
3843   let ParserMatchClass = VectorIndexDOperand;
3844   let PrintMethod = "printVectorIndex";
3845   let MIOperandInfo = (ops i64imm);
3846 }
3847
3848 def MemorySIMDNoIndexOperand : AsmOperandClass {
3849   let Name = "MemorySIMDNoIndex";
3850   let ParserMethod = "tryParseNoIndexMemory";
3851 }
3852 def am_simdnoindex : Operand<i64>,
3853                      ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
3854   let PrintMethod = "printAMNoIndex";
3855   let ParserMatchClass = MemorySIMDNoIndexOperand;
3856   let MIOperandInfo = (ops GPR64sp:$base);
3857   let DecoderMethod = "DecodeGPR64spRegisterClass";
3858 }
3859
3860 let Predicates = [HasNEON] in {
3861
3862 //----------------------------------------------------------------------------
3863 // AdvSIMD three register vector instructions
3864 //----------------------------------------------------------------------------
3865
3866 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3867 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3868                         RegisterOperand regtype, string asm, string kind,
3869                         list<dag> pattern>
3870   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3871       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3872       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3873     Sched<[WriteV]> {
3874   bits<5> Rd;
3875   bits<5> Rn;
3876   bits<5> Rm;
3877   let Inst{31}    = 0;
3878   let Inst{30}    = Q;
3879   let Inst{29}    = U;
3880   let Inst{28-24} = 0b01110;
3881   let Inst{23-22} = size;
3882   let Inst{21}    = 1;
3883   let Inst{20-16} = Rm;
3884   let Inst{15-11} = opcode;
3885   let Inst{10}    = 1;
3886   let Inst{9-5}   = Rn;
3887   let Inst{4-0}   = Rd;
3888 }
3889
3890 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3891 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3892                         RegisterOperand regtype, string asm, string kind,
3893                         list<dag> pattern>
3894   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3895       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3896       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3897     Sched<[WriteV]> {
3898   bits<5> Rd;
3899   bits<5> Rn;
3900   bits<5> Rm;
3901   let Inst{31}    = 0;
3902   let Inst{30}    = Q;
3903   let Inst{29}    = U;
3904   let Inst{28-24} = 0b01110;
3905   let Inst{23-22} = size;
3906   let Inst{21}    = 1;
3907   let Inst{20-16} = Rm;
3908   let Inst{15-11} = opcode;
3909   let Inst{10}    = 1;
3910   let Inst{9-5}   = Rn;
3911   let Inst{4-0}   = Rd;
3912 }
3913
3914 // All operand sizes distinguished in the encoding.
3915 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3916                                SDPatternOperator OpNode> {
3917   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3918                                       asm, ".8b",
3919          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3920   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3921                                       asm, ".16b",
3922          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3923   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3924                                       asm, ".4h",
3925          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3926   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3927                                       asm, ".8h",
3928          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3929   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3930                                       asm, ".2s",
3931          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3932   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3933                                       asm, ".4s",
3934          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3935   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3936                                       asm, ".2d",
3937          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3938 }
3939
3940 // As above, but D sized elements unsupported.
3941 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3942                                   SDPatternOperator OpNode> {
3943   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3944                                       asm, ".8b",
3945         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3946   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3947                                       asm, ".16b",
3948         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3949   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3950                                       asm, ".4h",
3951         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3952   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3953                                       asm, ".8h",
3954         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3955   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3956                                       asm, ".2s",
3957         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3958   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3959                                       asm, ".4s",
3960         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3961 }
3962
3963 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3964                                   SDPatternOperator OpNode> {
3965   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3966                                       asm, ".8b",
3967       [(set (v8i8 V64:$dst),
3968             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3969   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3970                                       asm, ".16b",
3971       [(set (v16i8 V128:$dst),
3972             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3973   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3974                                       asm, ".4h",
3975       [(set (v4i16 V64:$dst),
3976             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3977   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3978                                       asm, ".8h",
3979       [(set (v8i16 V128:$dst),
3980             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3981   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3982                                       asm, ".2s",
3983       [(set (v2i32 V64:$dst),
3984             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3985   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3986                                       asm, ".4s",
3987       [(set (v4i32 V128:$dst),
3988             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3989 }
3990
3991 // As above, but only B sized elements supported.
3992 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3993                                 SDPatternOperator OpNode> {
3994   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3995                                       asm, ".8b",
3996     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3997   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3998                                       asm, ".16b",
3999     [(set (v16i8 V128:$Rd),
4000           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4001 }
4002
4003 // As above, but only S and D sized floating point elements supported.
4004 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
4005                                  string asm, SDPatternOperator OpNode> {
4006   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4007                                       asm, ".2s",
4008         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4009   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4010                                       asm, ".4s",
4011         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4012   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4013                                       asm, ".2d",
4014         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4015 }
4016
4017 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
4018                                     string asm,
4019                                     SDPatternOperator OpNode> {
4020   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4021                                       asm, ".2s",
4022         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4023   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4024                                       asm, ".4s",
4025         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4026   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4027                                       asm, ".2d",
4028         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4029 }
4030
4031 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
4032                                  string asm, SDPatternOperator OpNode> {
4033   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
4034                                       asm, ".2s",
4035      [(set (v2f32 V64:$dst),
4036            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4037   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
4038                                       asm, ".4s",
4039      [(set (v4f32 V128:$dst),
4040            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4041   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
4042                                       asm, ".2d",
4043      [(set (v2f64 V128:$dst),
4044            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4045 }
4046
4047 // As above, but D and B sized elements unsupported.
4048 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4049                                 SDPatternOperator OpNode> {
4050   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4051                                       asm, ".4h",
4052         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4053   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4054                                       asm, ".8h",
4055         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4056   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4057                                       asm, ".2s",
4058         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4059   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4060                                       asm, ".4s",
4061         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4062 }
4063
4064 // Logical three vector ops share opcode bits, and only use B sized elements.
4065 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4066                                   SDPatternOperator OpNode = null_frag> {
4067   def v8i8  : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4068                                      asm, ".8b",
4069                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4070   def v16i8  : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4071                                      asm, ".16b",
4072                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4073
4074   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4075           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4076   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4077           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4078   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4079           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4080
4081   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4082       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4083   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4084       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4085   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4086       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4087 }
4088
4089 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4090                                   string asm, SDPatternOperator OpNode> {
4091   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4092                                      asm, ".8b",
4093              [(set (v8i8 V64:$dst),
4094                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4095   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4096                                      asm, ".16b",
4097              [(set (v16i8 V128:$dst),
4098                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4099                            (v16i8 V128:$Rm)))]>;
4100
4101   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4102                            (v4i16 V64:$RHS))),
4103           (!cast<Instruction>(NAME#"v8i8")
4104             V64:$LHS, V64:$MHS, V64:$RHS)>;
4105   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4106                            (v2i32 V64:$RHS))),
4107           (!cast<Instruction>(NAME#"v8i8")
4108             V64:$LHS, V64:$MHS, V64:$RHS)>;
4109   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4110                            (v1i64 V64:$RHS))),
4111           (!cast<Instruction>(NAME#"v8i8")
4112             V64:$LHS, V64:$MHS, V64:$RHS)>;
4113
4114   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4115                            (v8i16 V128:$RHS))),
4116       (!cast<Instruction>(NAME#"v16i8")
4117         V128:$LHS, V128:$MHS, V128:$RHS)>;
4118   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4119                            (v4i32 V128:$RHS))),
4120       (!cast<Instruction>(NAME#"v16i8")
4121         V128:$LHS, V128:$MHS, V128:$RHS)>;
4122   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4123                            (v2i64 V128:$RHS))),
4124       (!cast<Instruction>(NAME#"v16i8")
4125         V128:$LHS, V128:$MHS, V128:$RHS)>;
4126 }
4127
4128
4129 //----------------------------------------------------------------------------
4130 // AdvSIMD two register vector instructions.
4131 //----------------------------------------------------------------------------
4132
4133 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4134 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4135                         RegisterOperand regtype, string asm, string dstkind,
4136                         string srckind, list<dag> pattern>
4137   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4138       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4139       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4140     Sched<[WriteV]> {
4141   bits<5> Rd;
4142   bits<5> Rn;
4143   let Inst{31}    = 0;
4144   let Inst{30}    = Q;
4145   let Inst{29}    = U;
4146   let Inst{28-24} = 0b01110;
4147   let Inst{23-22} = size;
4148   let Inst{21-17} = 0b10000;
4149   let Inst{16-12} = opcode;
4150   let Inst{11-10} = 0b10;
4151   let Inst{9-5}   = Rn;
4152   let Inst{4-0}   = Rd;
4153 }
4154
4155 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4156 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4157                             RegisterOperand regtype, string asm, string dstkind,
4158                             string srckind, list<dag> pattern>
4159   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4160       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4161       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4162     Sched<[WriteV]> {
4163   bits<5> Rd;
4164   bits<5> Rn;
4165   let Inst{31}    = 0;
4166   let Inst{30}    = Q;
4167   let Inst{29}    = U;
4168   let Inst{28-24} = 0b01110;
4169   let Inst{23-22} = size;
4170   let Inst{21-17} = 0b10000;
4171   let Inst{16-12} = opcode;
4172   let Inst{11-10} = 0b10;
4173   let Inst{9-5}   = Rn;
4174   let Inst{4-0}   = Rd;
4175 }
4176
4177 // Supports B, H, and S element sizes.
4178 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4179                             SDPatternOperator OpNode> {
4180   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4181                                       asm, ".8b", ".8b",
4182                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4183   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4184                                       asm, ".16b", ".16b",
4185                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4186   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4187                                       asm, ".4h", ".4h",
4188                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4189   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4190                                       asm, ".8h", ".8h",
4191                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4192   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4193                                       asm, ".2s", ".2s",
4194                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4195   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4196                                       asm, ".4s", ".4s",
4197                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4198 }
4199
4200 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4201                             RegisterOperand regtype, string asm, string dstkind,
4202                             string srckind, string amount>
4203   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4204       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4205       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4206     Sched<[WriteV]> {
4207   bits<5> Rd;
4208   bits<5> Rn;
4209   let Inst{31}    = 0;
4210   let Inst{30}    = Q;
4211   let Inst{29-24} = 0b101110;
4212   let Inst{23-22} = size;
4213   let Inst{21-10} = 0b100001001110;
4214   let Inst{9-5}   = Rn;
4215   let Inst{4-0}   = Rd;
4216 }
4217
4218 multiclass SIMDVectorLShiftLongBySizeBHS {
4219   let neverHasSideEffects = 1 in {
4220   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4221                                              "shll", ".8h",  ".8b", "8">;
4222   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4223                                              "shll2", ".8h", ".16b", "8">;
4224   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4225                                              "shll", ".4s",  ".4h", "16">;
4226   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4227                                              "shll2", ".4s", ".8h", "16">;
4228   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4229                                              "shll", ".2d",  ".2s", "32">;
4230   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4231                                              "shll2", ".2d", ".4s", "32">;
4232   }
4233 }
4234
4235 // Supports all element sizes.
4236 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4237                              SDPatternOperator OpNode> {
4238   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4239                                       asm, ".4h", ".8b",
4240                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4241   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4242                                       asm, ".8h", ".16b",
4243                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4244   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4245                                       asm, ".2s", ".4h",
4246                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4247   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4248                                       asm, ".4s", ".8h",
4249                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4250   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4251                                       asm, ".1d", ".2s",
4252                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4253   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4254                                       asm, ".2d", ".4s",
4255                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4256 }
4257
4258 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4259                                  SDPatternOperator OpNode> {
4260   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4261                                           asm, ".4h", ".8b",
4262       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4263                                       (v8i8 V64:$Rn)))]>;
4264   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4265                                           asm, ".8h", ".16b",
4266       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4267                                       (v16i8 V128:$Rn)))]>;
4268   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4269                                           asm, ".2s", ".4h",
4270       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4271                                       (v4i16 V64:$Rn)))]>;
4272   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4273                                           asm, ".4s", ".8h",
4274       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4275                                       (v8i16 V128:$Rn)))]>;
4276   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4277                                           asm, ".1d", ".2s",
4278       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4279                                       (v2i32 V64:$Rn)))]>;
4280   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4281                                           asm, ".2d", ".4s",
4282       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4283                                       (v4i32 V128:$Rn)))]>;
4284 }
4285
4286 // Supports all element sizes, except 1xD.
4287 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4288                                   SDPatternOperator OpNode> {
4289   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4290                                     asm, ".8b", ".8b",
4291     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4292   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4293                                     asm, ".16b", ".16b",
4294     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4295   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4296                                     asm, ".4h", ".4h",
4297     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4298   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4299                                     asm, ".8h", ".8h",
4300     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4301   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4302                                     asm, ".2s", ".2s",
4303     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4304   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4305                                     asm, ".4s", ".4s",
4306     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4307   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4308                                     asm, ".2d", ".2d",
4309     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4310 }
4311
4312 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4313                              SDPatternOperator OpNode = null_frag> {
4314   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4315                                 asm, ".8b", ".8b",
4316     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4317   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4318                                 asm, ".16b", ".16b",
4319     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4320   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4321                                 asm, ".4h", ".4h",
4322     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4323   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4324                                 asm, ".8h", ".8h",
4325     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4326   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4327                                 asm, ".2s", ".2s",
4328     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4329   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4330                                 asm, ".4s", ".4s",
4331     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4332   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4333                                 asm, ".2d", ".2d",
4334     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4335 }
4336
4337
4338 // Supports only B element sizes.
4339 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4340                           SDPatternOperator OpNode> {
4341   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4342                                 asm, ".8b", ".8b",
4343                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4344   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4345                                 asm, ".16b", ".16b",
4346                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4347
4348 }
4349
4350 // Supports only B and H element sizes.
4351 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4352                                 SDPatternOperator OpNode> {
4353   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4354                                 asm, ".8b", ".8b",
4355                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4356   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4357                                 asm, ".16b", ".16b",
4358                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4359   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4360                                 asm, ".4h", ".4h",
4361                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4362   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4363                                 asm, ".8h", ".8h",
4364                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4365 }
4366
4367 // Supports only S and D element sizes, uses high bit of the size field
4368 // as an extra opcode bit.
4369 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4370                            SDPatternOperator OpNode> {
4371   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4372                                 asm, ".2s", ".2s",
4373                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4374   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4375                                 asm, ".4s", ".4s",
4376                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4377   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4378                                 asm, ".2d", ".2d",
4379                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4380 }
4381
4382 // Supports only S element size.
4383 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4384                            SDPatternOperator OpNode> {
4385   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4386                                 asm, ".2s", ".2s",
4387                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4388   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4389                                 asm, ".4s", ".4s",
4390                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4391 }
4392
4393
4394 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4395                            SDPatternOperator OpNode> {
4396   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4397                                 asm, ".2s", ".2s",
4398                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4399   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4400                                 asm, ".4s", ".4s",
4401                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4402   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4403                                 asm, ".2d", ".2d",
4404                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4405 }
4406
4407 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4408                            SDPatternOperator OpNode> {
4409   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4410                                 asm, ".2s", ".2s",
4411                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4412   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4413                                 asm, ".4s", ".4s",
4414                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4415   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4416                                 asm, ".2d", ".2d",
4417                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4418 }
4419
4420
4421 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4422                            RegisterOperand inreg, RegisterOperand outreg,
4423                            string asm, string outkind, string inkind,
4424                            list<dag> pattern>
4425   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4426       "{\t$Rd" # outkind # ", $Rn" # inkind #
4427       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4428     Sched<[WriteV]> {
4429   bits<5> Rd;
4430   bits<5> Rn;
4431   let Inst{31}    = 0;
4432   let Inst{30}    = Q;
4433   let Inst{29}    = U;
4434   let Inst{28-24} = 0b01110;
4435   let Inst{23-22} = size;
4436   let Inst{21-17} = 0b10000;
4437   let Inst{16-12} = opcode;
4438   let Inst{11-10} = 0b10;
4439   let Inst{9-5}   = Rn;
4440   let Inst{4-0}   = Rd;
4441 }
4442
4443 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4444                            RegisterOperand inreg, RegisterOperand outreg,
4445                            string asm, string outkind, string inkind,
4446                            list<dag> pattern>
4447   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4448       "{\t$Rd" # outkind # ", $Rn" # inkind #
4449       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4450     Sched<[WriteV]> {
4451   bits<5> Rd;
4452   bits<5> Rn;
4453   let Inst{31}    = 0;
4454   let Inst{30}    = Q;
4455   let Inst{29}    = U;
4456   let Inst{28-24} = 0b01110;
4457   let Inst{23-22} = size;
4458   let Inst{21-17} = 0b10000;
4459   let Inst{16-12} = opcode;
4460   let Inst{11-10} = 0b10;
4461   let Inst{9-5}   = Rn;
4462   let Inst{4-0}   = Rd;
4463 }
4464
4465 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4466                               SDPatternOperator OpNode> {
4467   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4468                                       asm, ".8b", ".8h",
4469         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4470   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4471                                       asm#"2", ".16b", ".8h", []>;
4472   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4473                                       asm, ".4h", ".4s",
4474         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4475   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4476                                       asm#"2", ".8h", ".4s", []>;
4477   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4478                                       asm, ".2s", ".2d",
4479         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4480   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4481                                       asm#"2", ".4s", ".2d", []>;
4482
4483   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4484             (!cast<Instruction>(NAME # "v16i8")
4485                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4486   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4487             (!cast<Instruction>(NAME # "v8i16")
4488                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4489   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4490             (!cast<Instruction>(NAME # "v4i32")
4491                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4492 }
4493
4494 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4495                            RegisterOperand regtype,
4496                            string asm, string kind, string zero,
4497                            ValueType dty, ValueType sty, SDNode OpNode>
4498   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4499       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4500       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4501       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4502     Sched<[WriteV]> {
4503   bits<5> Rd;
4504   bits<5> Rn;
4505   let Inst{31}    = 0;
4506   let Inst{30}    = Q;
4507   let Inst{29}    = U;
4508   let Inst{28-24} = 0b01110;
4509   let Inst{23-22} = size;
4510   let Inst{21-17} = 0b10000;
4511   let Inst{16-12} = opcode;
4512   let Inst{11-10} = 0b10;
4513   let Inst{9-5}   = Rn;
4514   let Inst{4-0}   = Rd;
4515 }
4516
4517 // Comparisons support all element sizes, except 1xD.
4518 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4519                             SDNode OpNode> {
4520   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4521                                      asm, ".8b", "0",
4522                                      v8i8, v8i8, OpNode>;
4523   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4524                                      asm, ".16b", "0",
4525                                      v16i8, v16i8, OpNode>;
4526   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4527                                      asm, ".4h", "0",
4528                                      v4i16, v4i16, OpNode>;
4529   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4530                                      asm, ".8h", "0",
4531                                      v8i16, v8i16, OpNode>;
4532   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4533                                      asm, ".2s", "0",
4534                                      v2i32, v2i32, OpNode>;
4535   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4536                                      asm, ".4s", "0",
4537                                      v4i32, v4i32, OpNode>;
4538   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4539                                      asm, ".2d", "0",
4540                                      v2i64, v2i64, OpNode>;
4541 }
4542
4543 // FP Comparisons support only S and D element sizes.
4544 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4545                               string asm, SDNode OpNode> {
4546
4547   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4548                                      asm, ".2s", "0.0",
4549                                      v2i32, v2f32, OpNode>;
4550   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4551                                      asm, ".4s", "0.0",
4552                                      v4i32, v4f32, OpNode>;
4553   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4554                                      asm, ".2d", "0.0",
4555                                      v2i64, v2f64, OpNode>;
4556
4557   def : InstAlias<asm # " $Vd.2s, $Vn.2s, #0",
4558                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4559   def : InstAlias<asm # " $Vd.4s, $Vn.4s, #0",
4560                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4561   def : InstAlias<asm # " $Vd.2d, $Vn.2d, #0",
4562                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4563   def : InstAlias<asm # ".2s $Vd, $Vn, #0",
4564                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4565   def : InstAlias<asm # ".4s $Vd, $Vn, #0",
4566                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4567   def : InstAlias<asm # ".2d $Vd, $Vn, #0",
4568                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4569 }
4570
4571 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4572 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4573                              RegisterOperand outtype, RegisterOperand intype,
4574                              string asm, string VdTy, string VnTy,
4575                              list<dag> pattern>
4576   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4577       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4578     Sched<[WriteV]> {
4579   bits<5> Rd;
4580   bits<5> Rn;
4581   let Inst{31}    = 0;
4582   let Inst{30}    = Q;
4583   let Inst{29}    = U;
4584   let Inst{28-24} = 0b01110;
4585   let Inst{23-22} = size;
4586   let Inst{21-17} = 0b10000;
4587   let Inst{16-12} = opcode;
4588   let Inst{11-10} = 0b10;
4589   let Inst{9-5}   = Rn;
4590   let Inst{4-0}   = Rd;
4591 }
4592
4593 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4594                              RegisterOperand outtype, RegisterOperand intype,
4595                              string asm, string VdTy, string VnTy,
4596                              list<dag> pattern>
4597   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4598       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4599     Sched<[WriteV]> {
4600   bits<5> Rd;
4601   bits<5> Rn;
4602   let Inst{31}    = 0;
4603   let Inst{30}    = Q;
4604   let Inst{29}    = U;
4605   let Inst{28-24} = 0b01110;
4606   let Inst{23-22} = size;
4607   let Inst{21-17} = 0b10000;
4608   let Inst{16-12} = opcode;
4609   let Inst{11-10} = 0b10;
4610   let Inst{9-5}   = Rn;
4611   let Inst{4-0}   = Rd;
4612 }
4613
4614 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4615   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4616                                     asm, ".4s", ".4h", []>;
4617   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4618                                     asm#"2", ".4s", ".8h", []>;
4619   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4620                                     asm, ".2d", ".2s", []>;
4621   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4622                                     asm#"2", ".2d", ".4s", []>;
4623 }
4624
4625 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4626   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4627                                     asm, ".4h", ".4s", []>;
4628   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4629                                     asm#"2", ".8h", ".4s", []>;
4630   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4631                                     asm, ".2s", ".2d", []>;
4632   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4633                                     asm#"2", ".4s", ".2d", []>;
4634 }
4635
4636 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4637                                      Intrinsic OpNode> {
4638   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4639                                      asm, ".2s", ".2d",
4640                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4641   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4642                                     asm#"2", ".4s", ".2d", []>;
4643
4644   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4645             (!cast<Instruction>(NAME # "v4f32")
4646                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4647 }
4648
4649 //----------------------------------------------------------------------------
4650 // AdvSIMD three register different-size vector instructions.
4651 //----------------------------------------------------------------------------
4652
4653 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4654 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4655                       RegisterOperand outtype, RegisterOperand intype1,
4656                       RegisterOperand intype2, string asm,
4657                       string outkind, string inkind1, string inkind2,
4658                       list<dag> pattern>
4659   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4660       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4661       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4662     Sched<[WriteV]> {
4663   bits<5> Rd;
4664   bits<5> Rn;
4665   bits<5> Rm;
4666   let Inst{31}    = 0;
4667   let Inst{30}    = size{0};
4668   let Inst{29}    = U;
4669   let Inst{28-24} = 0b01110;
4670   let Inst{23-22} = size{2-1};
4671   let Inst{21}    = 1;
4672   let Inst{20-16} = Rm;
4673   let Inst{15-12} = opcode;
4674   let Inst{11-10} = 0b00;
4675   let Inst{9-5}   = Rn;
4676   let Inst{4-0}   = Rd;
4677 }
4678
4679 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4680 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4681                       RegisterOperand outtype, RegisterOperand intype1,
4682                       RegisterOperand intype2, string asm,
4683                       string outkind, string inkind1, string inkind2,
4684                       list<dag> pattern>
4685   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4686       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4687       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4688     Sched<[WriteV]> {
4689   bits<5> Rd;
4690   bits<5> Rn;
4691   bits<5> Rm;
4692   let Inst{31}    = 0;
4693   let Inst{30}    = size{0};
4694   let Inst{29}    = U;
4695   let Inst{28-24} = 0b01110;
4696   let Inst{23-22} = size{2-1};
4697   let Inst{21}    = 1;
4698   let Inst{20-16} = Rm;
4699   let Inst{15-12} = opcode;
4700   let Inst{11-10} = 0b00;
4701   let Inst{9-5}   = Rn;
4702   let Inst{4-0}   = Rd;
4703 }
4704
4705 // FIXME: TableGen doesn't know how to deal with expanded types that also
4706 //        change the element count (in this case, placing the results in
4707 //        the high elements of the result register rather than the low
4708 //        elements). Until that's fixed, we can't code-gen those.
4709 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4710                                     Intrinsic IntOp> {
4711   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4712                                                   V64, V128, V128,
4713                                                   asm, ".8b", ".8h", ".8h",
4714      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4715   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4716                                                   V128, V128, V128,
4717                                                   asm#"2", ".16b", ".8h", ".8h",
4718      []>;
4719   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4720                                                   V64, V128, V128,
4721                                                   asm, ".4h", ".4s", ".4s",
4722      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4723   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4724                                                   V128, V128, V128,
4725                                                   asm#"2", ".8h", ".4s", ".4s",
4726      []>;
4727   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4728                                                   V64, V128, V128,
4729                                                   asm, ".2s", ".2d", ".2d",
4730      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4731   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4732                                                   V128, V128, V128,
4733                                                   asm#"2", ".4s", ".2d", ".2d",
4734      []>;
4735
4736
4737   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4738   // a version attached to an instruction.
4739   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4740                                                    (v8i16 V128:$Rm))),
4741             (!cast<Instruction>(NAME # "v8i16_v16i8")
4742                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4743                 V128:$Rn, V128:$Rm)>;
4744   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4745                                                     (v4i32 V128:$Rm))),
4746             (!cast<Instruction>(NAME # "v4i32_v8i16")
4747                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4748                 V128:$Rn, V128:$Rm)>;
4749   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4750                                                     (v2i64 V128:$Rm))),
4751             (!cast<Instruction>(NAME # "v2i64_v4i32")
4752                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4753                 V128:$Rn, V128:$Rm)>;
4754 }
4755
4756 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4757                                       Intrinsic IntOp> {
4758   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4759                                             V128, V64, V64,
4760                                             asm, ".8h", ".8b", ".8b",
4761       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4762   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4763                                             V128, V128, V128,
4764                                             asm#"2", ".8h", ".16b", ".16b", []>;
4765   let Predicates = [HasCrypto] in {
4766     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4767                                               V128, V64, V64,
4768                                               asm, ".1q", ".1d", ".1d", []>;
4769     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4770                                               V128, V128, V128,
4771                                               asm#"2", ".1q", ".2d", ".2d", []>;
4772   }
4773
4774   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4775                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
4776       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4777 }
4778
4779 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4780                                  SDPatternOperator OpNode> {
4781   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4782                                                   V128, V64, V64,
4783                                                   asm, ".4s", ".4h", ".4h",
4784       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4785   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4786                                                   V128, V128, V128,
4787                                                   asm#"2", ".4s", ".8h", ".8h",
4788       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4789                                       (extract_high_v8i16 V128:$Rm)))]>;
4790   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4791                                                   V128, V64, V64,
4792                                                   asm, ".2d", ".2s", ".2s",
4793       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4794   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4795                                                   V128, V128, V128,
4796                                                   asm#"2", ".2d", ".4s", ".4s",
4797       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4798                                       (extract_high_v4i32 V128:$Rm)))]>;
4799 }
4800
4801 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4802                                   SDPatternOperator OpNode = null_frag> {
4803   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4804                                                   V128, V64, V64,
4805                                                   asm, ".8h", ".8b", ".8b",
4806       [(set (v8i16 V128:$Rd),
4807             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4808   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4809                                                  V128, V128, V128,
4810                                                  asm#"2", ".8h", ".16b", ".16b",
4811       [(set (v8i16 V128:$Rd),
4812             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4813                                 (extract_high_v16i8 V128:$Rm)))))]>;
4814   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4815                                                   V128, V64, V64,
4816                                                   asm, ".4s", ".4h", ".4h",
4817       [(set (v4i32 V128:$Rd),
4818             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4819   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4820                                                   V128, V128, V128,
4821                                                   asm#"2", ".4s", ".8h", ".8h",
4822       [(set (v4i32 V128:$Rd),
4823             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4824                                   (extract_high_v8i16 V128:$Rm)))))]>;
4825   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4826                                                   V128, V64, V64,
4827                                                   asm, ".2d", ".2s", ".2s",
4828       [(set (v2i64 V128:$Rd),
4829             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4830   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4831                                                   V128, V128, V128,
4832                                                   asm#"2", ".2d", ".4s", ".4s",
4833       [(set (v2i64 V128:$Rd),
4834             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4835                                  (extract_high_v4i32 V128:$Rm)))))]>;
4836 }
4837
4838 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4839                                           string asm,
4840                                           SDPatternOperator OpNode> {
4841   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4842                                                   V128, V64, V64,
4843                                                   asm, ".8h", ".8b", ".8b",
4844     [(set (v8i16 V128:$dst),
4845           (add (v8i16 V128:$Rd),
4846                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4847   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4848                                                  V128, V128, V128,
4849                                                  asm#"2", ".8h", ".16b", ".16b",
4850     [(set (v8i16 V128:$dst),
4851           (add (v8i16 V128:$Rd),
4852                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4853                                    (extract_high_v16i8 V128:$Rm))))))]>;
4854   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4855                                                   V128, V64, V64,
4856                                                   asm, ".4s", ".4h", ".4h",
4857     [(set (v4i32 V128:$dst),
4858           (add (v4i32 V128:$Rd),
4859                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4860   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4861                                                   V128, V128, V128,
4862                                                   asm#"2", ".4s", ".8h", ".8h",
4863     [(set (v4i32 V128:$dst),
4864           (add (v4i32 V128:$Rd),
4865                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4866                                     (extract_high_v8i16 V128:$Rm))))))]>;
4867   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4868                                                   V128, V64, V64,
4869                                                   asm, ".2d", ".2s", ".2s",
4870     [(set (v2i64 V128:$dst),
4871           (add (v2i64 V128:$Rd),
4872                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4873   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4874                                                   V128, V128, V128,
4875                                                   asm#"2", ".2d", ".4s", ".4s",
4876     [(set (v2i64 V128:$dst),
4877           (add (v2i64 V128:$Rd),
4878                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4879                                     (extract_high_v4i32 V128:$Rm))))))]>;
4880 }
4881
4882 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4883                                   SDPatternOperator OpNode = null_frag> {
4884   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4885                                                   V128, V64, V64,
4886                                                   asm, ".8h", ".8b", ".8b",
4887       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4888   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4889                                                  V128, V128, V128,
4890                                                  asm#"2", ".8h", ".16b", ".16b",
4891       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4892                                       (extract_high_v16i8 V128:$Rm)))]>;
4893   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4894                                                   V128, V64, V64,
4895                                                   asm, ".4s", ".4h", ".4h",
4896       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4897   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4898                                                   V128, V128, V128,
4899                                                   asm#"2", ".4s", ".8h", ".8h",
4900       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4901                                       (extract_high_v8i16 V128:$Rm)))]>;
4902   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4903                                                   V128, V64, V64,
4904                                                   asm, ".2d", ".2s", ".2s",
4905       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4906   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4907                                                   V128, V128, V128,
4908                                                   asm#"2", ".2d", ".4s", ".4s",
4909       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4910                                       (extract_high_v4i32 V128:$Rm)))]>;
4911 }
4912
4913 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4914                                       string asm,
4915                                       SDPatternOperator OpNode> {
4916   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4917                                                   V128, V64, V64,
4918                                                   asm, ".8h", ".8b", ".8b",
4919     [(set (v8i16 V128:$dst),
4920           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4921   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4922                                                  V128, V128, V128,
4923                                                  asm#"2", ".8h", ".16b", ".16b",
4924     [(set (v8i16 V128:$dst),
4925           (OpNode (v8i16 V128:$Rd),
4926                   (extract_high_v16i8 V128:$Rn),
4927                   (extract_high_v16i8 V128:$Rm)))]>;
4928   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4929                                                   V128, V64, V64,
4930                                                   asm, ".4s", ".4h", ".4h",
4931     [(set (v4i32 V128:$dst),
4932           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4933   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4934                                                   V128, V128, V128,
4935                                                   asm#"2", ".4s", ".8h", ".8h",
4936     [(set (v4i32 V128:$dst),
4937           (OpNode (v4i32 V128:$Rd),
4938                   (extract_high_v8i16 V128:$Rn),
4939                   (extract_high_v8i16 V128:$Rm)))]>;
4940   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4941                                                   V128, V64, V64,
4942                                                   asm, ".2d", ".2s", ".2s",
4943     [(set (v2i64 V128:$dst),
4944           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4945   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4946                                                   V128, V128, V128,
4947                                                   asm#"2", ".2d", ".4s", ".4s",
4948     [(set (v2i64 V128:$dst),
4949           (OpNode (v2i64 V128:$Rd),
4950                   (extract_high_v4i32 V128:$Rn),
4951                   (extract_high_v4i32 V128:$Rm)))]>;
4952 }
4953
4954 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4955                                            SDPatternOperator Accum> {
4956   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4957                                                   V128, V64, V64,
4958                                                   asm, ".4s", ".4h", ".4h",
4959     [(set (v4i32 V128:$dst),
4960           (Accum (v4i32 V128:$Rd),
4961                  (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4962                                                 (v4i16 V64:$Rm)))))]>;
4963   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4964                                                   V128, V128, V128,
4965                                                   asm#"2", ".4s", ".8h", ".8h",
4966     [(set (v4i32 V128:$dst),
4967           (Accum (v4i32 V128:$Rd),
4968                  (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4969                                             (extract_high_v8i16 V128:$Rm)))))]>;
4970   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4971                                                   V128, V64, V64,
4972                                                   asm, ".2d", ".2s", ".2s",
4973     [(set (v2i64 V128:$dst),
4974           (Accum (v2i64 V128:$Rd),
4975                  (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4976                                                 (v2i32 V64:$Rm)))))]>;
4977   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4978                                                   V128, V128, V128,
4979                                                   asm#"2", ".2d", ".4s", ".4s",
4980     [(set (v2i64 V128:$dst),
4981           (Accum (v2i64 V128:$Rd),
4982                  (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4983                                             (extract_high_v4i32 V128:$Rm)))))]>;
4984 }
4985
4986 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4987                                   SDPatternOperator OpNode> {
4988   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4989                                                   V128, V128, V64,
4990                                                   asm, ".8h", ".8h", ".8b",
4991        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4992   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4993                                                   V128, V128, V128,
4994                                                   asm#"2", ".8h", ".8h", ".16b",
4995        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4996                                        (extract_high_v16i8 V128:$Rm)))]>;
4997   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4998                                                   V128, V128, V64,
4999                                                   asm, ".4s", ".4s", ".4h",
5000        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5001   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5002                                                   V128, V128, V128,
5003                                                   asm#"2", ".4s", ".4s", ".8h",
5004        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5005                                        (extract_high_v8i16 V128:$Rm)))]>;
5006   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5007                                                   V128, V128, V64,
5008                                                   asm, ".2d", ".2d", ".2s",
5009        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5010   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5011                                                   V128, V128, V128,
5012                                                   asm#"2", ".2d", ".2d", ".4s",
5013        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5014                                        (extract_high_v4i32 V128:$Rm)))]>;
5015 }
5016
5017 //----------------------------------------------------------------------------
5018 // AdvSIMD bitwise extract from vector
5019 //----------------------------------------------------------------------------
5020
5021 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5022                              string asm, string kind>
5023   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5024       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5025       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5026       [(set (vty regtype:$Rd),
5027             (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5028     Sched<[WriteV]> {
5029   bits<5> Rd;
5030   bits<5> Rn;
5031   bits<5> Rm;
5032   bits<4> imm;
5033   let Inst{31}    = 0;
5034   let Inst{30}    = size;
5035   let Inst{29-21} = 0b101110000;
5036   let Inst{20-16} = Rm;
5037   let Inst{15}    = 0;
5038   let Inst{14-11} = imm;
5039   let Inst{10}    = 0;
5040   let Inst{9-5}   = Rn;
5041   let Inst{4-0}   = Rd;
5042 }
5043
5044
5045 multiclass SIMDBitwiseExtract<string asm> {
5046   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5047     let imm{3} = 0;
5048   }
5049   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5050 }
5051
5052 //----------------------------------------------------------------------------
5053 // AdvSIMD zip vector
5054 //----------------------------------------------------------------------------
5055
5056 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5057                         string asm, string kind, SDNode OpNode, ValueType valty>
5058   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5059       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5060       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5061       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5062     Sched<[WriteV]> {
5063   bits<5> Rd;
5064   bits<5> Rn;
5065   bits<5> Rm;
5066   let Inst{31}    = 0;
5067   let Inst{30}    = size{0};
5068   let Inst{29-24} = 0b001110;
5069   let Inst{23-22} = size{2-1};
5070   let Inst{21}    = 0;
5071   let Inst{20-16} = Rm;
5072   let Inst{15}    = 0;
5073   let Inst{14-12} = opc;
5074   let Inst{11-10} = 0b10;
5075   let Inst{9-5}   = Rn;
5076   let Inst{4-0}   = Rd;
5077 }
5078
5079 multiclass SIMDZipVector<bits<3>opc, string asm,
5080                          SDNode OpNode> {
5081   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5082       asm, ".8b", OpNode, v8i8>;
5083   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5084       asm, ".16b", OpNode, v16i8>;
5085   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5086       asm, ".4h", OpNode, v4i16>;
5087   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5088       asm, ".8h", OpNode, v8i16>;
5089   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5090       asm, ".2s", OpNode, v2i32>;
5091   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5092       asm, ".4s", OpNode, v4i32>;
5093   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5094       asm, ".2d", OpNode, v2i64>;
5095
5096   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5097         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5098   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5099         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5100   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5101         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5102 }
5103
5104 //----------------------------------------------------------------------------
5105 // AdvSIMD three register scalar instructions
5106 //----------------------------------------------------------------------------
5107
5108 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5109 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5110                         RegisterClass regtype, string asm,
5111                         list<dag> pattern>
5112   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5113       "\t$Rd, $Rn, $Rm", "", pattern>,
5114     Sched<[WriteV]> {
5115   bits<5> Rd;
5116   bits<5> Rn;
5117   bits<5> Rm;
5118   let Inst{31-30} = 0b01;
5119   let Inst{29}    = U;
5120   let Inst{28-24} = 0b11110;
5121   let Inst{23-22} = size;
5122   let Inst{21}    = 1;
5123   let Inst{20-16} = Rm;
5124   let Inst{15-11} = opcode;
5125   let Inst{10}    = 1;
5126   let Inst{9-5}   = Rn;
5127   let Inst{4-0}   = Rd;
5128 }
5129
5130 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5131                             SDPatternOperator OpNode> {
5132   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5133     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5134 }
5135
5136 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5137                                SDPatternOperator OpNode> {
5138   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5139     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5140   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5141   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5142   def v1i8   : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5143
5144   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5145             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5146   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5147             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5148 }
5149
5150 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5151                              SDPatternOperator OpNode> {
5152   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5153                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5154   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5155 }
5156
5157 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5158                              SDPatternOperator OpNode = null_frag> {
5159   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5160     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5161       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5162     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5163       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5164   }
5165
5166   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5167             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5168 }
5169
5170 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5171                                 SDPatternOperator OpNode = null_frag> {
5172   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5173     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5174       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5175     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5176       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5177   }
5178
5179   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5180             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5181 }
5182
5183 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5184               dag oops, dag iops, string asm, string cstr, list<dag> pat>
5185   : I<oops, iops, asm,
5186       "\t$Rd, $Rn, $Rm", cstr, pat>,
5187     Sched<[WriteV]> {
5188   bits<5> Rd;
5189   bits<5> Rn;
5190   bits<5> Rm;
5191   let Inst{31-30} = 0b01;
5192   let Inst{29}    = U;
5193   let Inst{28-24} = 0b11110;
5194   let Inst{23-22} = size;
5195   let Inst{21}    = 1;
5196   let Inst{20-16} = Rm;
5197   let Inst{15-11} = opcode;
5198   let Inst{10}    = 0;
5199   let Inst{9-5}   = Rn;
5200   let Inst{4-0}   = Rd;
5201 }
5202
5203 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5204 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5205                                   SDPatternOperator OpNode = null_frag> {
5206   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5207                                       (outs FPR32:$Rd),
5208                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5209   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5210                                       (outs FPR64:$Rd),
5211                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5212             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5213 }
5214
5215 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5216 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5217                                   SDPatternOperator OpNode = null_frag> {
5218   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5219                                       (outs FPR32:$dst),
5220                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5221                                       asm, "$Rd = $dst", []>;
5222   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5223                                       (outs FPR64:$dst),
5224                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5225                                       asm, "$Rd = $dst",
5226             [(set (i64 FPR64:$dst),
5227                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5228 }
5229
5230 //----------------------------------------------------------------------------
5231 // AdvSIMD two register scalar instructions
5232 //----------------------------------------------------------------------------
5233
5234 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5235 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5236                         RegisterClass regtype, RegisterClass regtype2,
5237                         string asm, list<dag> pat>
5238   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5239       "\t$Rd, $Rn", "", pat>,
5240     Sched<[WriteV]> {
5241   bits<5> Rd;
5242   bits<5> Rn;
5243   let Inst{31-30} = 0b01;
5244   let Inst{29}    = U;
5245   let Inst{28-24} = 0b11110;
5246   let Inst{23-22} = size;
5247   let Inst{21-17} = 0b10000;
5248   let Inst{16-12} = opcode;
5249   let Inst{11-10} = 0b10;
5250   let Inst{9-5}   = Rn;
5251   let Inst{4-0}   = Rd;
5252 }
5253
5254 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5255 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5256                         RegisterClass regtype, RegisterClass regtype2,
5257                         string asm, list<dag> pat>
5258   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5259       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5260     Sched<[WriteV]> {
5261   bits<5> Rd;
5262   bits<5> Rn;
5263   let Inst{31-30} = 0b01;
5264   let Inst{29}    = U;
5265   let Inst{28-24} = 0b11110;
5266   let Inst{23-22} = size;
5267   let Inst{21-17} = 0b10000;
5268   let Inst{16-12} = opcode;
5269   let Inst{11-10} = 0b10;
5270   let Inst{9-5}   = Rn;
5271   let Inst{4-0}   = Rd;
5272 }
5273
5274
5275 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5276 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5277                         RegisterClass regtype, string asm, string zero>
5278   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5279       "\t$Rd, $Rn, #" # zero, "", []>,
5280     Sched<[WriteV]> {
5281   bits<5> Rd;
5282   bits<5> Rn;
5283   let Inst{31-30} = 0b01;
5284   let Inst{29}    = U;
5285   let Inst{28-24} = 0b11110;
5286   let Inst{23-22} = size;
5287   let Inst{21-17} = 0b10000;
5288   let Inst{16-12} = opcode;
5289   let Inst{11-10} = 0b10;
5290   let Inst{9-5}   = Rn;
5291   let Inst{4-0}   = Rd;
5292 }
5293
5294 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5295   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5296      [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5297     Sched<[WriteV]> {
5298   bits<5> Rd;
5299   bits<5> Rn;
5300   let Inst{31-17} = 0b011111100110000;
5301   let Inst{16-12} = opcode;
5302   let Inst{11-10} = 0b10;
5303   let Inst{9-5}   = Rn;
5304   let Inst{4-0}   = Rd;
5305 }
5306
5307 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5308                              SDPatternOperator OpNode> {
5309   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5310
5311   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5312             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5313 }
5314
5315 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5316                               SDPatternOperator OpNode> {
5317   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5318   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5319
5320   def : InstAlias<asm # " $Rd, $Rn, #0",
5321                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn)>;
5322   def : InstAlias<asm # " $Rd, $Rn, #0",
5323                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn)>;
5324
5325   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5326             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5327 }
5328
5329 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5330                           SDPatternOperator OpNode = null_frag> {
5331   def v1i64       : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5332     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5333
5334   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5335             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5336 }
5337
5338 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5339   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5340   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5341 }
5342
5343 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5344                               SDPatternOperator OpNode> {
5345   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5346                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5347   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5348                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5349 }
5350
5351 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5352                              SDPatternOperator OpNode = null_frag> {
5353   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5354     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5355            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5356     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5357            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5358     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5359     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5360   }
5361
5362   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5363             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5364 }
5365
5366 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5367                                  Intrinsic OpNode> {
5368   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5369     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5370         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5371     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5372         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5373     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5374     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5375   }
5376
5377   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5378             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5379 }
5380
5381
5382
5383 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5384 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5385                                  SDPatternOperator OpNode = null_frag> {
5386   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5387         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5388   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5389   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5390 }
5391
5392 //----------------------------------------------------------------------------
5393 // AdvSIMD scalar pairwise instructions
5394 //----------------------------------------------------------------------------
5395
5396 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5397 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5398                         RegisterOperand regtype, RegisterOperand vectype,
5399                         string asm, string kind>
5400   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5401       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5402     Sched<[WriteV]> {
5403   bits<5> Rd;
5404   bits<5> Rn;
5405   let Inst{31-30} = 0b01;
5406   let Inst{29}    = U;
5407   let Inst{28-24} = 0b11110;
5408   let Inst{23-22} = size;
5409   let Inst{21-17} = 0b11000;
5410   let Inst{16-12} = opcode;
5411   let Inst{11-10} = 0b10;
5412   let Inst{9-5}   = Rn;
5413   let Inst{4-0}   = Rd;
5414 }
5415
5416 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5417   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5418                                       asm, ".2d">;
5419 }
5420
5421 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5422   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5423                                       asm, ".2s">;
5424   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5425                                       asm, ".2d">;
5426 }
5427
5428 //----------------------------------------------------------------------------
5429 // AdvSIMD across lanes instructions
5430 //----------------------------------------------------------------------------
5431
5432 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5433 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5434                           RegisterClass regtype, RegisterOperand vectype,
5435                           string asm, string kind, list<dag> pattern>
5436   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5437       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5438     Sched<[WriteV]> {
5439   bits<5> Rd;
5440   bits<5> Rn;
5441   let Inst{31}    = 0;
5442   let Inst{30}    = Q;
5443   let Inst{29}    = U;
5444   let Inst{28-24} = 0b01110;
5445   let Inst{23-22} = size;
5446   let Inst{21-17} = 0b11000;
5447   let Inst{16-12} = opcode;
5448   let Inst{11-10} = 0b10;
5449   let Inst{9-5}   = Rn;
5450   let Inst{4-0}   = Rd;
5451 }
5452
5453 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5454                               string asm> {
5455   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5456                                    asm, ".8b", []>;
5457   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5458                                    asm, ".16b", []>;
5459   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5460                                    asm, ".4h", []>;
5461   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5462                                    asm, ".8h", []>;
5463   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5464                                    asm, ".4s", []>;
5465 }
5466
5467 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5468   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5469                                    asm, ".8b", []>;
5470   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5471                                    asm, ".16b", []>;
5472   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5473                                    asm, ".4h", []>;
5474   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5475                                    asm, ".8h", []>;
5476   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5477                                    asm, ".4s", []>;
5478 }
5479
5480 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5481                             Intrinsic intOp> {
5482   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5483                                    asm, ".4s",
5484         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5485 }
5486
5487 //----------------------------------------------------------------------------
5488 // AdvSIMD INS/DUP instructions
5489 //----------------------------------------------------------------------------
5490
5491 // FIXME: There has got to be a better way to factor these. ugh.
5492
5493 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5494                      string operands, string constraints, list<dag> pattern>
5495   : I<outs, ins, asm, operands, constraints, pattern>,
5496     Sched<[WriteV]> {
5497   bits<5> Rd;
5498   bits<5> Rn;
5499   let Inst{31} = 0;
5500   let Inst{30} = Q;
5501   let Inst{29} = op;
5502   let Inst{28-21} = 0b01110000;
5503   let Inst{15} = 0;
5504   let Inst{10} = 1;
5505   let Inst{9-5} = Rn;
5506   let Inst{4-0} = Rd;
5507 }
5508
5509 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5510                       RegisterOperand vecreg, RegisterClass regtype>
5511   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5512                    "{\t$Rd" # size # ", $Rn" #
5513                    "|" # size # "\t$Rd, $Rn}", "",
5514                    [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5515   let Inst{20-16} = imm5;
5516   let Inst{14-11} = 0b0001;
5517 }
5518
5519 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5520                          ValueType vectype, ValueType insreg,
5521                          RegisterOperand vecreg, Operand idxtype,
5522                          ValueType elttype, SDNode OpNode>
5523   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5524                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5525                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5526                  [(set (vectype vecreg:$Rd),
5527                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5528   let Inst{14-11} = 0b0000;
5529 }
5530
5531 class SIMDDup64FromElement
5532   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5533                        VectorIndexD, i64, ARM64duplane64> {
5534   bits<1> idx;
5535   let Inst{20} = idx;
5536   let Inst{19-16} = 0b1000;
5537 }
5538
5539 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5540                            RegisterOperand vecreg>
5541   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5542                        VectorIndexS, i64, ARM64duplane32> {
5543   bits<2> idx;
5544   let Inst{20-19} = idx;
5545   let Inst{18-16} = 0b100;
5546 }
5547
5548 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5549                            RegisterOperand vecreg>
5550   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5551                        VectorIndexH, i64, ARM64duplane16> {
5552   bits<3> idx;
5553   let Inst{20-18} = idx;
5554   let Inst{17-16} = 0b10;
5555 }
5556
5557 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5558                           RegisterOperand vecreg>
5559   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5560                        VectorIndexB, i64, ARM64duplane8> {
5561   bits<4> idx;
5562   let Inst{20-17} = idx;
5563   let Inst{16} = 1;
5564 }
5565
5566 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5567                   Operand idxtype, string asm, list<dag> pattern>
5568   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5569                    "{\t$Rd, $Rn" # size # "$idx" #
5570                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5571   let Inst{14-11} = imm4;
5572 }
5573
5574 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5575                Operand idxtype>
5576   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5577 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5578                Operand idxtype>
5579   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5580       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5581
5582 // FIXME: these aliases should be canonical, but TableGen can't handle the
5583 // alternate syntaxes.
5584 class SIMDMovAlias<string asm, string size, Instruction inst,
5585                    RegisterClass regtype, Operand idxtype>
5586     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5587                     "|" # size # "\t$dst, $src$idx}",
5588                 (inst regtype:$dst, V128:$src, idxtype:$idx), 0>;
5589
5590 multiclass SMov {
5591   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5592     bits<4> idx;
5593     let Inst{20-17} = idx;
5594     let Inst{16} = 1;
5595   }
5596   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5597     bits<4> idx;
5598     let Inst{20-17} = idx;
5599     let Inst{16} = 1;
5600   }
5601   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5602     bits<3> idx;
5603     let Inst{20-18} = idx;
5604     let Inst{17-16} = 0b10;
5605   }
5606   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5607     bits<3> idx;
5608     let Inst{20-18} = idx;
5609     let Inst{17-16} = 0b10;
5610   }
5611   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5612     bits<2> idx;
5613     let Inst{20-19} = idx;
5614     let Inst{18-16} = 0b100;
5615   }
5616 }
5617
5618 multiclass UMov {
5619   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5620     bits<4> idx;
5621     let Inst{20-17} = idx;
5622     let Inst{16} = 1;
5623   }
5624   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5625     bits<3> idx;
5626     let Inst{20-18} = idx;
5627     let Inst{17-16} = 0b10;
5628   }
5629   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5630     bits<2> idx;
5631     let Inst{20-19} = idx;
5632     let Inst{18-16} = 0b100;
5633   }
5634   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5635     bits<1> idx;
5636     let Inst{20} = idx;
5637     let Inst{19-16} = 0b1000;
5638   }
5639   def : SIMDMovAlias<"mov", ".s",
5640                      !cast<Instruction>(NAME#"vi32"),
5641                      GPR32, VectorIndexS>;
5642   def : SIMDMovAlias<"mov", ".d",
5643                      !cast<Instruction>(NAME#"vi64"),
5644                      GPR64, VectorIndexD>;
5645 }
5646
5647 class SIMDInsFromMain<string size, ValueType vectype,
5648                       RegisterClass regtype, Operand idxtype>
5649   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5650                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5651                    "{\t$Rd" # size # "$idx, $Rn" #
5652                    "|" # size # "\t$Rd$idx, $Rn}",
5653                    "$Rd = $dst",
5654             [(set V128:$dst,
5655               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5656   let Inst{14-11} = 0b0011;
5657 }
5658
5659 class SIMDInsFromElement<string size, ValueType vectype,
5660                          ValueType elttype, Operand idxtype>
5661   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5662                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5663                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5664                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
5665                    "$Rd = $dst",
5666          [(set V128:$dst,
5667                (vector_insert
5668                  (vectype V128:$Rd),
5669                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5670                  idxtype:$idx))]>;
5671
5672 // FIXME: the MOVs should be canonical, but TableGen's alias printing can't cope
5673 // with syntax variants.
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), 0>;
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), 0>;
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">;