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