752a153c0574e020c3a1c7d23b506a3c8771cc98
[oota-llvm.git] / lib / Target / AArch64 / AArch64InstrFormats.td
1 //===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 //===----------------------------------------------------------------------===//
11 //  Describe AArch64 instructions format here
12 //
13
14 // Format specifies the encoding used by the instruction.  This is part of the
15 // ad-hoc solution used to emit machine instruction encodings by our machine
16 // code emitter.
17 class Format<bits<2> val> {
18   bits<2> Value = val;
19 }
20
21 def PseudoFrm   : Format<0>;
22 def NormalFrm   : Format<1>; // Do we need any others?
23
24 // AArch64 Instruction Format
25 class AArch64Inst<Format f, string cstr> : Instruction {
26   field bits<32> Inst; // Instruction encoding.
27   // Mask of bits that cause an encoding to be UNPREDICTABLE.
28   // If a bit is set, then if the corresponding bit in the
29   // target encoding differs from its value in the "Inst" field,
30   // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
31   field bits<32> Unpredictable = 0;
32   // SoftFail is the generic name for this field, but we alias it so
33   // as to make it more obvious what it means in ARM-land.
34   field bits<32> SoftFail = Unpredictable;
35   let Namespace   = "AArch64";
36   Format F        = f;
37   bits<2> Form    = F.Value;
38   let Pattern     = [];
39   let Constraints = cstr;
40 }
41
42 // Pseudo instructions (don't have encoding information)
43 class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
44     : AArch64Inst<PseudoFrm, cstr> {
45   dag OutOperandList = oops;
46   dag InOperandList  = iops;
47   let Pattern        = pattern;
48   let isCodeGenOnly  = 1;
49 }
50
51 // Real instructions (have encoding information)
52 class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
53   let Pattern = pattern;
54   let Size = 4;
55 }
56
57 // Normal instructions
58 class I<dag oops, dag iops, string asm, string operands, string cstr,
59         list<dag> pattern>
60     : EncodedI<cstr, pattern> {
61   dag OutOperandList = oops;
62   dag InOperandList  = iops;
63   let AsmString      = !strconcat(asm, operands);
64 }
65
66 class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
67 class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
68 class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
69
70 // Helper fragment for an extract of the high portion of a 128-bit vector.
71 def extract_high_v16i8 :
72    UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
73 def extract_high_v8i16 :
74    UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
75 def extract_high_v4i32 :
76    UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
77 def extract_high_v2i64 :
78    UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
79
80 //===----------------------------------------------------------------------===//
81 // Asm Operand Classes.
82 //
83
84 // Shifter operand for arithmetic shifted encodings.
85 def ShifterOperand : AsmOperandClass {
86   let Name = "Shifter";
87 }
88
89 // Shifter operand for mov immediate encodings.
90 def MovImm32ShifterOperand : AsmOperandClass {
91   let SuperClasses = [ShifterOperand];
92   let Name = "MovImm32Shifter";
93   let RenderMethod = "addShifterOperands";
94   let DiagnosticType = "InvalidMovImm32Shift";
95 }
96 def MovImm64ShifterOperand : AsmOperandClass {
97   let SuperClasses = [ShifterOperand];
98   let Name = "MovImm64Shifter";
99   let RenderMethod = "addShifterOperands";
100   let DiagnosticType = "InvalidMovImm64Shift";
101 }
102
103 // Shifter operand for arithmetic register shifted encodings.
104 class ArithmeticShifterOperand<int width> : AsmOperandClass {
105   let SuperClasses = [ShifterOperand];
106   let Name = "ArithmeticShifter" # width;
107   let PredicateMethod = "isArithmeticShifter<" # width # ">";
108   let RenderMethod = "addShifterOperands";
109   let DiagnosticType = "AddSubRegShift" # width;
110 }
111
112 def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
113 def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
114
115 // Shifter operand for logical register shifted encodings.
116 class LogicalShifterOperand<int width> : AsmOperandClass {
117   let SuperClasses = [ShifterOperand];
118   let Name = "LogicalShifter" # width;
119   let PredicateMethod = "isLogicalShifter<" # width # ">";
120   let RenderMethod = "addShifterOperands";
121   let DiagnosticType = "AddSubRegShift" # width;
122 }
123
124 def LogicalShifterOperand32 : LogicalShifterOperand<32>;
125 def LogicalShifterOperand64 : LogicalShifterOperand<64>;
126
127 // Shifter operand for logical vector 128/64-bit shifted encodings.
128 def LogicalVecShifterOperand : AsmOperandClass {
129   let SuperClasses = [ShifterOperand];
130   let Name = "LogicalVecShifter";
131   let RenderMethod = "addShifterOperands";
132 }
133 def LogicalVecHalfWordShifterOperand : AsmOperandClass {
134   let SuperClasses = [LogicalVecShifterOperand];
135   let Name = "LogicalVecHalfWordShifter";
136   let RenderMethod = "addShifterOperands";
137 }
138
139 // The "MSL" shifter on the vector MOVI instruction.
140 def MoveVecShifterOperand : AsmOperandClass {
141   let SuperClasses = [ShifterOperand];
142   let Name = "MoveVecShifter";
143   let RenderMethod = "addShifterOperands";
144 }
145
146 // Extend operand for arithmetic encodings.
147 def ExtendOperand : AsmOperandClass {
148   let Name = "Extend";
149   let DiagnosticType = "AddSubRegExtendLarge";
150 }
151 def ExtendOperand64 : AsmOperandClass {
152   let SuperClasses = [ExtendOperand];
153   let Name = "Extend64";
154   let DiagnosticType = "AddSubRegExtendSmall";
155 }
156 // 'extend' that's a lsl of a 64-bit register.
157 def ExtendOperandLSL64 : AsmOperandClass {
158   let SuperClasses = [ExtendOperand];
159   let Name = "ExtendLSL64";
160   let RenderMethod = "addExtend64Operands";
161   let DiagnosticType = "AddSubRegExtendLarge";
162 }
163
164 // 8-bit floating-point immediate encodings.
165 def FPImmOperand : AsmOperandClass {
166   let Name = "FPImm";
167   let ParserMethod = "tryParseFPImm";
168   let DiagnosticType = "InvalidFPImm";
169 }
170
171 def CondCode : AsmOperandClass {
172   let Name = "CondCode";
173   let DiagnosticType = "InvalidCondCode";
174 }
175
176 // A 32-bit register pasrsed as 64-bit
177 def GPR32as64Operand : AsmOperandClass {
178   let Name = "GPR32as64";
179 }
180 def GPR32as64 : RegisterOperand<GPR32> {
181   let ParserMatchClass = GPR32as64Operand;
182 }
183
184 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
185 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
186 // are encoded as the eight bit value 'abcdefgh'.
187 def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
188
189
190 //===----------------------------------------------------------------------===//
191 // Operand Definitions.
192 //
193
194 // ADR[P] instruction labels.
195 def AdrpOperand : AsmOperandClass {
196   let Name = "AdrpLabel";
197   let ParserMethod = "tryParseAdrpLabel";
198   let DiagnosticType = "InvalidLabel";
199 }
200 def adrplabel : Operand<i64> {
201   let EncoderMethod = "getAdrLabelOpValue";
202   let PrintMethod = "printAdrpLabel";
203   let ParserMatchClass = AdrpOperand;
204 }
205
206 def AdrOperand : AsmOperandClass {
207   let Name = "AdrLabel";
208   let ParserMethod = "tryParseAdrLabel";
209   let DiagnosticType = "InvalidLabel";
210 }
211 def adrlabel : Operand<i64> {
212   let EncoderMethod = "getAdrLabelOpValue";
213   let ParserMatchClass = AdrOperand;
214 }
215
216 // simm9 predicate - True if the immediate is in the range [-256, 255].
217 def SImm9Operand : AsmOperandClass {
218   let Name = "SImm9";
219   let DiagnosticType = "InvalidMemoryIndexedSImm9";
220 }
221 def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
222   let ParserMatchClass = SImm9Operand;
223 }
224
225 // simm7sN predicate - True if the immediate is a multiple of N in the range
226 // [-64 * N, 63 * N].
227 class SImm7Scaled<int Scale> : AsmOperandClass {
228   let Name = "SImm7s" # Scale;
229   let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm7";
230 }
231
232 def SImm7s4Operand : SImm7Scaled<4>;
233 def SImm7s8Operand : SImm7Scaled<8>;
234 def SImm7s16Operand : SImm7Scaled<16>;
235
236 def simm7s4 : Operand<i32> {
237   let ParserMatchClass = SImm7s4Operand;
238   let PrintMethod = "printImmScale<4>";
239 }
240
241 def simm7s8 : Operand<i32> {
242   let ParserMatchClass = SImm7s8Operand;
243   let PrintMethod = "printImmScale<8>";
244 }
245
246 def simm7s16 : Operand<i32> {
247   let ParserMatchClass = SImm7s16Operand;
248   let PrintMethod = "printImmScale<16>";
249 }
250
251 def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
252 def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
253 def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
254 def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
255 def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
256
257 class AsmImmRange<int Low, int High> : AsmOperandClass {
258   let Name = "Imm" # Low # "_" # High;
259   let DiagnosticType = "InvalidImm" # Low # "_" # High;
260 }
261
262 def Imm1_8Operand : AsmImmRange<1, 8>;
263 def Imm1_16Operand : AsmImmRange<1, 16>;
264 def Imm1_32Operand : AsmImmRange<1, 32>;
265 def Imm1_64Operand : AsmImmRange<1, 64>;
266
267 def MovZSymbolG3AsmOperand : AsmOperandClass {
268   let Name = "MovZSymbolG3";
269   let RenderMethod = "addImmOperands";
270 }
271
272 def movz_symbol_g3 : Operand<i32> {
273   let ParserMatchClass = MovZSymbolG3AsmOperand;
274 }
275
276 def MovZSymbolG2AsmOperand : AsmOperandClass {
277   let Name = "MovZSymbolG2";
278   let RenderMethod = "addImmOperands";
279 }
280
281 def movz_symbol_g2 : Operand<i32> {
282   let ParserMatchClass = MovZSymbolG2AsmOperand;
283 }
284
285 def MovZSymbolG1AsmOperand : AsmOperandClass {
286   let Name = "MovZSymbolG1";
287   let RenderMethod = "addImmOperands";
288 }
289
290 def movz_symbol_g1 : Operand<i32> {
291   let ParserMatchClass = MovZSymbolG1AsmOperand;
292 }
293
294 def MovZSymbolG0AsmOperand : AsmOperandClass {
295   let Name = "MovZSymbolG0";
296   let RenderMethod = "addImmOperands";
297 }
298
299 def movz_symbol_g0 : Operand<i32> {
300   let ParserMatchClass = MovZSymbolG0AsmOperand;
301 }
302
303 def MovKSymbolG3AsmOperand : AsmOperandClass {
304   let Name = "MovKSymbolG3";
305   let RenderMethod = "addImmOperands";
306 }
307
308 def movk_symbol_g3 : Operand<i32> {
309   let ParserMatchClass = MovKSymbolG3AsmOperand;
310 }
311
312 def MovKSymbolG2AsmOperand : AsmOperandClass {
313   let Name = "MovKSymbolG2";
314   let RenderMethod = "addImmOperands";
315 }
316
317 def movk_symbol_g2 : Operand<i32> {
318   let ParserMatchClass = MovKSymbolG2AsmOperand;
319 }
320
321 def MovKSymbolG1AsmOperand : AsmOperandClass {
322   let Name = "MovKSymbolG1";
323   let RenderMethod = "addImmOperands";
324 }
325
326 def movk_symbol_g1 : Operand<i32> {
327   let ParserMatchClass = MovKSymbolG1AsmOperand;
328 }
329
330 def MovKSymbolG0AsmOperand : AsmOperandClass {
331   let Name = "MovKSymbolG0";
332   let RenderMethod = "addImmOperands";
333 }
334
335 def movk_symbol_g0 : Operand<i32> {
336   let ParserMatchClass = MovKSymbolG0AsmOperand;
337 }
338
339 class fixedpoint_i32<ValueType FloatVT>
340   : Operand<FloatVT>,
341     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
342   let EncoderMethod = "getFixedPointScaleOpValue";
343   let DecoderMethod = "DecodeFixedPointScaleImm32";
344   let ParserMatchClass = Imm1_32Operand;
345 }
346
347 class fixedpoint_i64<ValueType FloatVT>
348   : Operand<FloatVT>,
349     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
350   let EncoderMethod = "getFixedPointScaleOpValue";
351   let DecoderMethod = "DecodeFixedPointScaleImm64";
352   let ParserMatchClass = Imm1_64Operand;
353 }
354
355 def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
356 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
357 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
358
359 def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
360 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
361 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
362
363 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
364   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
365 }]> {
366   let EncoderMethod = "getVecShiftR8OpValue";
367   let DecoderMethod = "DecodeVecShiftR8Imm";
368   let ParserMatchClass = Imm1_8Operand;
369 }
370 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
371   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
372 }]> {
373   let EncoderMethod = "getVecShiftR16OpValue";
374   let DecoderMethod = "DecodeVecShiftR16Imm";
375   let ParserMatchClass = Imm1_16Operand;
376 }
377 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
378   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
379 }]> {
380   let EncoderMethod = "getVecShiftR16OpValue";
381   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
382   let ParserMatchClass = Imm1_8Operand;
383 }
384 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
385   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
386 }]> {
387   let EncoderMethod = "getVecShiftR32OpValue";
388   let DecoderMethod = "DecodeVecShiftR32Imm";
389   let ParserMatchClass = Imm1_32Operand;
390 }
391 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
392   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
393 }]> {
394   let EncoderMethod = "getVecShiftR32OpValue";
395   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
396   let ParserMatchClass = Imm1_16Operand;
397 }
398 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
399   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
400 }]> {
401   let EncoderMethod = "getVecShiftR64OpValue";
402   let DecoderMethod = "DecodeVecShiftR64Imm";
403   let ParserMatchClass = Imm1_64Operand;
404 }
405 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
406   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
407 }]> {
408   let EncoderMethod = "getVecShiftR64OpValue";
409   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
410   let ParserMatchClass = Imm1_32Operand;
411 }
412
413 def Imm0_1Operand : AsmImmRange<0, 1>;
414 def Imm0_7Operand : AsmImmRange<0, 7>;
415 def Imm0_15Operand : AsmImmRange<0, 15>;
416 def Imm0_31Operand : AsmImmRange<0, 31>;
417 def Imm0_63Operand : AsmImmRange<0, 63>;
418
419 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
420   return (((uint32_t)Imm) < 8);
421 }]> {
422   let EncoderMethod = "getVecShiftL8OpValue";
423   let DecoderMethod = "DecodeVecShiftL8Imm";
424   let ParserMatchClass = Imm0_7Operand;
425 }
426 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
427   return (((uint32_t)Imm) < 16);
428 }]> {
429   let EncoderMethod = "getVecShiftL16OpValue";
430   let DecoderMethod = "DecodeVecShiftL16Imm";
431   let ParserMatchClass = Imm0_15Operand;
432 }
433 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
434   return (((uint32_t)Imm) < 32);
435 }]> {
436   let EncoderMethod = "getVecShiftL32OpValue";
437   let DecoderMethod = "DecodeVecShiftL32Imm";
438   let ParserMatchClass = Imm0_31Operand;
439 }
440 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
441   return (((uint32_t)Imm) < 64);
442 }]> {
443   let EncoderMethod = "getVecShiftL64OpValue";
444   let DecoderMethod = "DecodeVecShiftL64Imm";
445   let ParserMatchClass = Imm0_63Operand;
446 }
447
448
449 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
450 // instructions for splatting repeating bit patterns across the immediate.
451 def logical_imm32_XFORM : SDNodeXForm<imm, [{
452   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
453   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
454 }]>;
455 def logical_imm64_XFORM : SDNodeXForm<imm, [{
456   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
457   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
458 }]>;
459
460 let DiagnosticType = "LogicalSecondSource" in {
461   def LogicalImm32Operand : AsmOperandClass {
462     let Name = "LogicalImm32";
463   }
464   def LogicalImm64Operand : AsmOperandClass {
465     let Name = "LogicalImm64";
466   }
467   def LogicalImm32NotOperand : AsmOperandClass {
468     let Name = "LogicalImm32Not";
469   }
470   def LogicalImm64NotOperand : AsmOperandClass {
471     let Name = "LogicalImm64Not";
472   }
473 }
474 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
475   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
476 }], logical_imm32_XFORM> {
477   let PrintMethod = "printLogicalImm32";
478   let ParserMatchClass = LogicalImm32Operand;
479 }
480 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
481   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
482 }], logical_imm64_XFORM> {
483   let PrintMethod = "printLogicalImm64";
484   let ParserMatchClass = LogicalImm64Operand;
485 }
486 def logical_imm32_not : Operand<i32> {
487   let ParserMatchClass = LogicalImm32NotOperand;
488 }
489 def logical_imm64_not : Operand<i64> {
490   let ParserMatchClass = LogicalImm64NotOperand;
491 }
492
493 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
494 def Imm0_65535Operand : AsmImmRange<0, 65535>;
495 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
496   return ((uint32_t)Imm) < 65536;
497 }]> {
498   let ParserMatchClass = Imm0_65535Operand;
499   let PrintMethod = "printHexImm";
500 }
501
502 // imm0_255 predicate - True if the immediate is in the range [0,255].
503 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
504 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
505   return ((uint32_t)Imm) < 256;
506 }]> {
507   let ParserMatchClass = Imm0_255Operand;
508   let PrintMethod = "printHexImm";
509 }
510
511 // imm0_127 predicate - True if the immediate is in the range [0,127]
512 def Imm0_127Operand : AsmImmRange<0, 127>;
513 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
514   return ((uint32_t)Imm) < 128;
515 }]> {
516   let ParserMatchClass = Imm0_127Operand;
517   let PrintMethod = "printHexImm";
518 }
519
520 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
521 // for all shift-amounts.
522
523 // imm0_63 predicate - True if the immediate is in the range [0,63]
524 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
525   return ((uint64_t)Imm) < 64;
526 }]> {
527   let ParserMatchClass = Imm0_63Operand;
528 }
529
530 // imm0_31 predicate - True if the immediate is in the range [0,31]
531 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
532   return ((uint64_t)Imm) < 32;
533 }]> {
534   let ParserMatchClass = Imm0_31Operand;
535 }
536
537 // True if the 32-bit immediate is in the range [0,31]
538 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
539   return ((uint64_t)Imm) < 32;
540 }]> {
541   let ParserMatchClass = Imm0_31Operand;
542 }
543
544 // imm0_1 predicate - True if the immediate is in the range [0,1]
545 def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
546   return ((uint64_t)Imm) < 2;
547 }]> {
548   let ParserMatchClass = Imm0_1Operand;
549 }
550
551 // imm0_15 predicate - True if the immediate is in the range [0,15]
552 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
553   return ((uint64_t)Imm) < 16;
554 }]> {
555   let ParserMatchClass = Imm0_15Operand;
556 }
557
558 // imm0_7 predicate - True if the immediate is in the range [0,7]
559 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
560   return ((uint64_t)Imm) < 8;
561 }]> {
562   let ParserMatchClass = Imm0_7Operand;
563 }
564
565 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
566 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
567   return ((uint32_t)Imm) < 16;
568 }]> {
569   let ParserMatchClass = Imm0_15Operand;
570 }
571
572 // An arithmetic shifter operand:
573 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
574 //  {5-0} - imm6
575 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
576   let PrintMethod = "printShifter";
577   let ParserMatchClass = !cast<AsmOperandClass>(
578                          "ArithmeticShifterOperand" # width);
579 }
580
581 def arith_shift32 : arith_shift<i32, 32>;
582 def arith_shift64 : arith_shift<i64, 64>;
583
584 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
585     : Operand<Ty>,
586       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
587   let PrintMethod = "printShiftedRegister";
588   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
589 }
590
591 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
592 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
593
594 // An arithmetic shifter operand:
595 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
596 //  {5-0} - imm6
597 class logical_shift<int width> : Operand<i32> {
598   let PrintMethod = "printShifter";
599   let ParserMatchClass = !cast<AsmOperandClass>(
600                          "LogicalShifterOperand" # width);
601 }
602
603 def logical_shift32 : logical_shift<32>;
604 def logical_shift64 : logical_shift<64>;
605
606 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
607     : Operand<Ty>,
608       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
609   let PrintMethod = "printShiftedRegister";
610   let MIOperandInfo = (ops regclass, shiftop);
611 }
612
613 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
614 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
615
616 // A logical vector shifter operand:
617 //  {7-6} - shift type: 00 = lsl
618 //  {5-0} - imm6: #0, #8, #16, or #24
619 def logical_vec_shift : Operand<i32> {
620   let PrintMethod = "printShifter";
621   let EncoderMethod = "getVecShifterOpValue";
622   let ParserMatchClass = LogicalVecShifterOperand;
623 }
624
625 // A logical vector half-word shifter operand:
626 //  {7-6} - shift type: 00 = lsl
627 //  {5-0} - imm6: #0 or #8
628 def logical_vec_hw_shift : Operand<i32> {
629   let PrintMethod = "printShifter";
630   let EncoderMethod = "getVecShifterOpValue";
631   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
632 }
633
634 // A vector move shifter operand:
635 //  {0} - imm1: #8 or #16
636 def move_vec_shift : Operand<i32> {
637   let PrintMethod = "printShifter";
638   let EncoderMethod = "getMoveVecShifterOpValue";
639   let ParserMatchClass = MoveVecShifterOperand;
640 }
641
642 let DiagnosticType = "AddSubSecondSource" in {
643   def AddSubImmOperand : AsmOperandClass {
644     let Name = "AddSubImm";
645     let ParserMethod = "tryParseAddSubImm";
646   }
647   def AddSubImmNegOperand : AsmOperandClass {
648     let Name = "AddSubImmNeg";
649     let ParserMethod = "tryParseAddSubImm";
650   }
651 }
652 // An ADD/SUB immediate shifter operand:
653 //  second operand:
654 //  {7-6} - shift type: 00 = lsl
655 //  {5-0} - imm6: #0 or #12
656 class addsub_shifted_imm<ValueType Ty>
657     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
658   let PrintMethod = "printAddSubImm";
659   let EncoderMethod = "getAddSubImmOpValue";
660   let ParserMatchClass = AddSubImmOperand;
661   let MIOperandInfo = (ops i32imm, i32imm);
662 }
663
664 class addsub_shifted_imm_neg<ValueType Ty>
665     : Operand<Ty> {
666   let EncoderMethod = "getAddSubImmOpValue";
667   let ParserMatchClass = AddSubImmNegOperand;
668   let MIOperandInfo = (ops i32imm, i32imm);
669 }
670
671 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
672 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
673 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
674 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
675
676 class neg_addsub_shifted_imm<ValueType Ty>
677     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
678   let PrintMethod = "printAddSubImm";
679   let EncoderMethod = "getAddSubImmOpValue";
680   let ParserMatchClass = AddSubImmOperand;
681   let MIOperandInfo = (ops i32imm, i32imm);
682 }
683
684 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
685 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
686
687 // An extend operand:
688 //  {5-3} - extend type
689 //  {2-0} - imm3
690 def arith_extend : Operand<i32> {
691   let PrintMethod = "printArithExtend";
692   let ParserMatchClass = ExtendOperand;
693 }
694 def arith_extend64 : Operand<i32> {
695   let PrintMethod = "printArithExtend";
696   let ParserMatchClass = ExtendOperand64;
697 }
698
699 // 'extend' that's a lsl of a 64-bit register.
700 def arith_extendlsl64 : Operand<i32> {
701   let PrintMethod = "printArithExtend";
702   let ParserMatchClass = ExtendOperandLSL64;
703 }
704
705 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
706                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
707   let PrintMethod = "printExtendedRegister";
708   let MIOperandInfo = (ops GPR32, arith_extend);
709 }
710
711 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
712                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
713   let PrintMethod = "printExtendedRegister";
714   let MIOperandInfo = (ops GPR32, arith_extend64);
715 }
716
717 // Floating-point immediate.
718 def fpimm16 : Operand<f16>,
719               PatLeaf<(f16 fpimm), [{
720       return AArch64_AM::getFP16Imm(N->getValueAPF()) != -1;
721     }], SDNodeXForm<fpimm, [{
722       APFloat InVal = N->getValueAPF();
723       uint32_t enc = AArch64_AM::getFP16Imm(InVal);
724       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
725     }]>> {
726   let ParserMatchClass = FPImmOperand;
727   let PrintMethod = "printFPImmOperand";
728 }
729 def fpimm32 : Operand<f32>,
730               PatLeaf<(f32 fpimm), [{
731       return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
732     }], SDNodeXForm<fpimm, [{
733       APFloat InVal = N->getValueAPF();
734       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
735       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
736     }]>> {
737   let ParserMatchClass = FPImmOperand;
738   let PrintMethod = "printFPImmOperand";
739 }
740 def fpimm64 : Operand<f64>,
741               PatLeaf<(f64 fpimm), [{
742       return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
743     }], SDNodeXForm<fpimm, [{
744       APFloat InVal = N->getValueAPF();
745       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
746       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
747     }]>> {
748   let ParserMatchClass = FPImmOperand;
749   let PrintMethod = "printFPImmOperand";
750 }
751
752 def fpimm8 : Operand<i32> {
753   let ParserMatchClass = FPImmOperand;
754   let PrintMethod = "printFPImmOperand";
755 }
756
757 def fpimm0 : PatLeaf<(fpimm), [{
758   return N->isExactlyValue(+0.0);
759 }]>;
760
761 // Vector lane operands
762 class AsmVectorIndex<string Suffix> : AsmOperandClass {
763   let Name = "VectorIndex" # Suffix;
764   let DiagnosticType = "InvalidIndex" # Suffix;
765 }
766 def VectorIndex1Operand : AsmVectorIndex<"1">;
767 def VectorIndexBOperand : AsmVectorIndex<"B">;
768 def VectorIndexHOperand : AsmVectorIndex<"H">;
769 def VectorIndexSOperand : AsmVectorIndex<"S">;
770 def VectorIndexDOperand : AsmVectorIndex<"D">;
771
772 def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
773   return ((uint64_t)Imm) == 1;
774 }]> {
775   let ParserMatchClass = VectorIndex1Operand;
776   let PrintMethod = "printVectorIndex";
777   let MIOperandInfo = (ops i64imm);
778 }
779 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
780   return ((uint64_t)Imm) < 16;
781 }]> {
782   let ParserMatchClass = VectorIndexBOperand;
783   let PrintMethod = "printVectorIndex";
784   let MIOperandInfo = (ops i64imm);
785 }
786 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
787   return ((uint64_t)Imm) < 8;
788 }]> {
789   let ParserMatchClass = VectorIndexHOperand;
790   let PrintMethod = "printVectorIndex";
791   let MIOperandInfo = (ops i64imm);
792 }
793 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
794   return ((uint64_t)Imm) < 4;
795 }]> {
796   let ParserMatchClass = VectorIndexSOperand;
797   let PrintMethod = "printVectorIndex";
798   let MIOperandInfo = (ops i64imm);
799 }
800 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
801   return ((uint64_t)Imm) < 2;
802 }]> {
803   let ParserMatchClass = VectorIndexDOperand;
804   let PrintMethod = "printVectorIndex";
805   let MIOperandInfo = (ops i64imm);
806 }
807
808 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
809 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
810 // are encoded as the eight bit value 'abcdefgh'.
811 def simdimmtype10 : Operand<i32>,
812                     PatLeaf<(f64 fpimm), [{
813       return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
814                                                .bitcastToAPInt()
815                                                .getZExtValue());
816     }], SDNodeXForm<fpimm, [{
817       APFloat InVal = N->getValueAPF();
818       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
819                                                            .bitcastToAPInt()
820                                                            .getZExtValue());
821       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
822     }]>> {
823   let ParserMatchClass = SIMDImmType10Operand;
824   let PrintMethod = "printSIMDType10Operand";
825 }
826
827
828 //---
829 // System management
830 //---
831
832 // Base encoding for system instruction operands.
833 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
834 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
835                   list<dag> pattern = []>
836     : I<oops, iops, asm, operands, "", pattern> {
837   let Inst{31-22} = 0b1101010100;
838   let Inst{21}    = L;
839 }
840
841 // System instructions which do not have an Rt register.
842 class SimpleSystemI<bit L, dag iops, string asm, string operands,
843                     list<dag> pattern = []>
844     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
845   let Inst{4-0} = 0b11111;
846 }
847
848 // System instructions which have an Rt register.
849 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
850     : BaseSystemI<L, oops, iops, asm, operands>,
851       Sched<[WriteSys]> {
852   bits<5> Rt;
853   let Inst{4-0} = Rt;
854 }
855
856 // Hint instructions that take both a CRm and a 3-bit immediate.
857 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
858 // model patterns with sufficiently fine granularity
859 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
860   class HintI<string mnemonic>
861       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
862                       [(int_aarch64_hint imm0_127:$imm)]>,
863         Sched<[WriteHint]> {
864     bits <7> imm;
865     let Inst{20-12} = 0b000110010;
866     let Inst{11-5} = imm;
867   }
868
869 // System instructions taking a single literal operand which encodes into
870 // CRm. op2 differentiates the opcodes.
871 def BarrierAsmOperand : AsmOperandClass {
872   let Name = "Barrier";
873   let ParserMethod = "tryParseBarrierOperand";
874 }
875 def barrier_op : Operand<i32> {
876   let PrintMethod = "printBarrierOption";
877   let ParserMatchClass = BarrierAsmOperand;
878 }
879 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
880                  list<dag> pattern = []>
881     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
882       Sched<[WriteBarrier]> {
883   bits<4> CRm;
884   let Inst{20-12} = 0b000110011;
885   let Inst{11-8} = CRm;
886   let Inst{7-5} = opc;
887 }
888
889 // MRS/MSR system instructions. These have different operand classes because
890 // a different subset of registers can be accessed through each instruction.
891 def MRSSystemRegisterOperand : AsmOperandClass {
892   let Name = "MRSSystemRegister";
893   let ParserMethod = "tryParseSysReg";
894   let DiagnosticType = "MRS";
895 }
896 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
897 def mrs_sysreg_op : Operand<i32> {
898   let ParserMatchClass = MRSSystemRegisterOperand;
899   let DecoderMethod = "DecodeMRSSystemRegister";
900   let PrintMethod = "printMRSSystemRegister";
901 }
902
903 def MSRSystemRegisterOperand : AsmOperandClass {
904   let Name = "MSRSystemRegister";
905   let ParserMethod = "tryParseSysReg";
906   let DiagnosticType = "MSR";
907 }
908 def msr_sysreg_op : Operand<i32> {
909   let ParserMatchClass = MSRSystemRegisterOperand;
910   let DecoderMethod = "DecodeMSRSystemRegister";
911   let PrintMethod = "printMSRSystemRegister";
912 }
913
914 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
915                        "mrs", "\t$Rt, $systemreg"> {
916   bits<16> systemreg;
917   let Inst{20-5} = systemreg;
918 }
919
920 // FIXME: Some of these def NZCV, others don't. Best way to model that?
921 // Explicitly modeling each of the system register as a register class
922 // would do it, but feels like overkill at this point.
923 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
924                        "msr", "\t$systemreg, $Rt"> {
925   bits<16> systemreg;
926   let Inst{20-5} = systemreg;
927 }
928
929 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
930   let Name = "SystemPStateFieldWithImm0_15";
931   let ParserMethod = "tryParseSysReg";
932 }
933 def pstatefield4_op : Operand<i32> {
934   let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
935   let PrintMethod = "printSystemPStateField";
936 }
937
938 let Defs = [NZCV] in
939 class MSRpstateImm0_15
940   : SimpleSystemI<0, (ins pstatefield4_op:$pstatefield, imm0_15:$imm),
941                   "msr", "\t$pstatefield, $imm">,
942     Sched<[WriteSys]> {
943   bits<6> pstatefield;
944   bits<4> imm;
945   let Inst{20-19} = 0b00;
946   let Inst{18-16} = pstatefield{5-3};
947   let Inst{15-12} = 0b0100;
948   let Inst{11-8} = imm;
949   let Inst{7-5} = pstatefield{2-0};
950
951   let DecoderMethod = "DecodeSystemPStateInstruction";
952   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
953   // Fail the decoder should attempt to decode the instruction as MSRI.
954   let hasCompleteDecoder = 0;
955 }
956
957 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
958   let Name = "SystemPStateFieldWithImm0_1";
959   let ParserMethod = "tryParseSysReg";
960 }
961 def pstatefield1_op : Operand<i32> {
962   let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
963   let PrintMethod = "printSystemPStateField";
964 }
965
966 let Defs = [NZCV] in
967 class MSRpstateImm0_1
968   : SimpleSystemI<0, (ins pstatefield1_op:$pstatefield, imm0_1:$imm),
969                   "msr", "\t$pstatefield, $imm">,
970     Sched<[WriteSys]> {
971   bits<6> pstatefield;
972   bit imm;
973   let Inst{20-19} = 0b00;
974   let Inst{18-16} = pstatefield{5-3};
975   let Inst{15-9} = 0b0100000;
976   let Inst{8} = imm;
977   let Inst{7-5} = pstatefield{2-0};
978
979   let DecoderMethod = "DecodeSystemPStateInstruction";
980   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
981   // Fail the decoder should attempt to decode the instruction as MSRI.
982   let hasCompleteDecoder = 0;
983 }
984
985 // SYS and SYSL generic system instructions.
986 def SysCRAsmOperand : AsmOperandClass {
987   let Name = "SysCR";
988   let ParserMethod = "tryParseSysCROperand";
989 }
990
991 def sys_cr_op : Operand<i32> {
992   let PrintMethod = "printSysCROperand";
993   let ParserMatchClass = SysCRAsmOperand;
994 }
995
996 class SystemXtI<bit L, string asm>
997   : RtSystemI<L, (outs),
998        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
999        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1000   bits<3> op1;
1001   bits<4> Cn;
1002   bits<4> Cm;
1003   bits<3> op2;
1004   let Inst{20-19} = 0b01;
1005   let Inst{18-16} = op1;
1006   let Inst{15-12} = Cn;
1007   let Inst{11-8}  = Cm;
1008   let Inst{7-5}   = op2;
1009 }
1010
1011 class SystemLXtI<bit L, string asm>
1012   : RtSystemI<L, (outs),
1013        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1014        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1015   bits<3> op1;
1016   bits<4> Cn;
1017   bits<4> Cm;
1018   bits<3> op2;
1019   let Inst{20-19} = 0b01;
1020   let Inst{18-16} = op1;
1021   let Inst{15-12} = Cn;
1022   let Inst{11-8}  = Cm;
1023   let Inst{7-5}   = op2;
1024 }
1025
1026
1027 // Branch (register) instructions:
1028 //
1029 //  case opc of
1030 //    0001 blr
1031 //    0000 br
1032 //    0101 dret
1033 //    0100 eret
1034 //    0010 ret
1035 //    otherwise UNDEFINED
1036 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1037                     string operands, list<dag> pattern>
1038     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1039   let Inst{31-25} = 0b1101011;
1040   let Inst{24-21} = opc;
1041   let Inst{20-16} = 0b11111;
1042   let Inst{15-10} = 0b000000;
1043   let Inst{4-0}   = 0b00000;
1044 }
1045
1046 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1047     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1048   bits<5> Rn;
1049   let Inst{9-5} = Rn;
1050 }
1051
1052 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1053 class SpecialReturn<bits<4> opc, string asm>
1054     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1055   let Inst{9-5} = 0b11111;
1056 }
1057
1058 //---
1059 // Conditional branch instruction.
1060 //---
1061
1062 // Condition code.
1063 // 4-bit immediate. Pretty-printed as <cc>
1064 def ccode : Operand<i32> {
1065   let PrintMethod = "printCondCode";
1066   let ParserMatchClass = CondCode;
1067 }
1068 def inv_ccode : Operand<i32> {
1069   // AL and NV are invalid in the aliases which use inv_ccode
1070   let PrintMethod = "printInverseCondCode";
1071   let ParserMatchClass = CondCode;
1072   let MCOperandPredicate = [{
1073     return MCOp.isImm() &&
1074            MCOp.getImm() != AArch64CC::AL &&
1075            MCOp.getImm() != AArch64CC::NV;
1076   }];
1077 }
1078
1079 // Conditional branch target. 19-bit immediate. The low two bits of the target
1080 // offset are implied zero and so are not part of the immediate.
1081 def PCRelLabel19Operand : AsmOperandClass {
1082   let Name = "PCRelLabel19";
1083   let DiagnosticType = "InvalidLabel";
1084 }
1085 def am_brcond : Operand<OtherVT> {
1086   let EncoderMethod = "getCondBranchTargetOpValue";
1087   let DecoderMethod = "DecodePCRelLabel19";
1088   let PrintMethod = "printAlignedLabel";
1089   let ParserMatchClass = PCRelLabel19Operand;
1090 }
1091
1092 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1093                      "b", ".$cond\t$target", "",
1094                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1095                    Sched<[WriteBr]> {
1096   let isBranch = 1;
1097   let isTerminator = 1;
1098   let Uses = [NZCV];
1099
1100   bits<4> cond;
1101   bits<19> target;
1102   let Inst{31-24} = 0b01010100;
1103   let Inst{23-5} = target;
1104   let Inst{4} = 0;
1105   let Inst{3-0} = cond;
1106 }
1107
1108 //---
1109 // Compare-and-branch instructions.
1110 //---
1111 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1112     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1113          asm, "\t$Rt, $target", "",
1114          [(node regtype:$Rt, bb:$target)]>,
1115       Sched<[WriteBr]> {
1116   let isBranch = 1;
1117   let isTerminator = 1;
1118
1119   bits<5> Rt;
1120   bits<19> target;
1121   let Inst{30-25} = 0b011010;
1122   let Inst{24}    = op;
1123   let Inst{23-5}  = target;
1124   let Inst{4-0}   = Rt;
1125 }
1126
1127 multiclass CmpBranch<bit op, string asm, SDNode node> {
1128   def W : BaseCmpBranch<GPR32, op, asm, node> {
1129     let Inst{31} = 0;
1130   }
1131   def X : BaseCmpBranch<GPR64, op, asm, node> {
1132     let Inst{31} = 1;
1133   }
1134 }
1135
1136 //---
1137 // Test-bit-and-branch instructions.
1138 //---
1139 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1140 // the target offset are implied zero and so are not part of the immediate.
1141 def BranchTarget14Operand : AsmOperandClass {
1142   let Name = "BranchTarget14";
1143 }
1144 def am_tbrcond : Operand<OtherVT> {
1145   let EncoderMethod = "getTestBranchTargetOpValue";
1146   let PrintMethod = "printAlignedLabel";
1147   let ParserMatchClass = BranchTarget14Operand;
1148 }
1149
1150 // AsmOperand classes to emit (or not) special diagnostics
1151 def TBZImm0_31Operand : AsmOperandClass {
1152   let Name = "TBZImm0_31";
1153   let PredicateMethod = "isImm0_31";
1154   let RenderMethod = "addImm0_31Operands";
1155 }
1156 def TBZImm32_63Operand : AsmOperandClass {
1157   let Name = "Imm32_63";
1158   let DiagnosticType = "InvalidImm0_63";
1159 }
1160
1161 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1162   return (((uint32_t)Imm) < 32);
1163 }]> {
1164   let ParserMatchClass = matcher;
1165 }
1166
1167 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1168 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1169
1170 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1171   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1172 }]> {
1173   let ParserMatchClass = TBZImm32_63Operand;
1174 }
1175
1176 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1177                      bit op, string asm, SDNode node>
1178     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1179        asm, "\t$Rt, $bit_off, $target", "",
1180        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1181       Sched<[WriteBr]> {
1182   let isBranch = 1;
1183   let isTerminator = 1;
1184
1185   bits<5> Rt;
1186   bits<6> bit_off;
1187   bits<14> target;
1188
1189   let Inst{30-25} = 0b011011;
1190   let Inst{24}    = op;
1191   let Inst{23-19} = bit_off{4-0};
1192   let Inst{18-5}  = target;
1193   let Inst{4-0}   = Rt;
1194
1195   let DecoderMethod = "DecodeTestAndBranch";
1196 }
1197
1198 multiclass TestBranch<bit op, string asm, SDNode node> {
1199   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1200     let Inst{31} = 0;
1201   }
1202
1203   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1204     let Inst{31} = 1;
1205   }
1206
1207   // Alias X-reg with 0-31 imm to W-Reg.
1208   def : InstAlias<asm # "\t$Rd, $imm, $target",
1209                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1210                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1211   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1212             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1213             tbz_imm0_31_diag:$imm, bb:$target)>;
1214 }
1215
1216 //---
1217 // Unconditional branch (immediate) instructions.
1218 //---
1219 def BranchTarget26Operand : AsmOperandClass {
1220   let Name = "BranchTarget26";
1221   let DiagnosticType = "InvalidLabel";
1222 }
1223 def am_b_target : Operand<OtherVT> {
1224   let EncoderMethod = "getBranchTargetOpValue";
1225   let PrintMethod = "printAlignedLabel";
1226   let ParserMatchClass = BranchTarget26Operand;
1227 }
1228 def am_bl_target : Operand<i64> {
1229   let EncoderMethod = "getBranchTargetOpValue";
1230   let PrintMethod = "printAlignedLabel";
1231   let ParserMatchClass = BranchTarget26Operand;
1232 }
1233
1234 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1235     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1236   bits<26> addr;
1237   let Inst{31}    = op;
1238   let Inst{30-26} = 0b00101;
1239   let Inst{25-0}  = addr;
1240
1241   let DecoderMethod = "DecodeUnconditionalBranch";
1242 }
1243
1244 class BranchImm<bit op, string asm, list<dag> pattern>
1245     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1246 class CallImm<bit op, string asm, list<dag> pattern>
1247     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1248
1249 //---
1250 // Basic one-operand data processing instructions.
1251 //---
1252
1253 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1254 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1255                          SDPatternOperator node>
1256   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1257       [(set regtype:$Rd, (node regtype:$Rn))]>,
1258     Sched<[WriteI, ReadI]> {
1259   bits<5> Rd;
1260   bits<5> Rn;
1261
1262   let Inst{30-13} = 0b101101011000000000;
1263   let Inst{12-10} = opc;
1264   let Inst{9-5}   = Rn;
1265   let Inst{4-0}   = Rd;
1266 }
1267
1268 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1269 multiclass OneOperandData<bits<3> opc, string asm,
1270                           SDPatternOperator node = null_frag> {
1271   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1272     let Inst{31} = 0;
1273   }
1274
1275   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1276     let Inst{31} = 1;
1277   }
1278 }
1279
1280 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1281     : BaseOneOperandData<opc, GPR32, asm, node> {
1282   let Inst{31} = 0;
1283 }
1284
1285 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1286     : BaseOneOperandData<opc, GPR64, asm, node> {
1287   let Inst{31} = 1;
1288 }
1289
1290 //---
1291 // Basic two-operand data processing instructions.
1292 //---
1293 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1294                           list<dag> pattern>
1295     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1296         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1297       Sched<[WriteI, ReadI, ReadI]> {
1298   let Uses = [NZCV];
1299   bits<5> Rd;
1300   bits<5> Rn;
1301   bits<5> Rm;
1302   let Inst{30}    = isSub;
1303   let Inst{28-21} = 0b11010000;
1304   let Inst{20-16} = Rm;
1305   let Inst{15-10} = 0;
1306   let Inst{9-5}   = Rn;
1307   let Inst{4-0}   = Rd;
1308 }
1309
1310 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1311                       SDNode OpNode>
1312     : BaseBaseAddSubCarry<isSub, regtype, asm,
1313         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1314
1315 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1316                               SDNode OpNode>
1317     : BaseBaseAddSubCarry<isSub, regtype, asm,
1318         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1319          (implicit NZCV)]> {
1320   let Defs = [NZCV];
1321 }
1322
1323 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1324                        SDNode OpNode, SDNode OpNode_setflags> {
1325   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1326     let Inst{31} = 0;
1327     let Inst{29} = 0;
1328   }
1329   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1330     let Inst{31} = 1;
1331     let Inst{29} = 0;
1332   }
1333
1334   // Sets flags.
1335   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1336                                     OpNode_setflags> {
1337     let Inst{31} = 0;
1338     let Inst{29} = 1;
1339   }
1340   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1341                                     OpNode_setflags> {
1342     let Inst{31} = 1;
1343     let Inst{29} = 1;
1344   }
1345 }
1346
1347 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1348                      SDPatternOperator OpNode>
1349   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1350       asm, "\t$Rd, $Rn, $Rm", "",
1351       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1352   bits<5> Rd;
1353   bits<5> Rn;
1354   bits<5> Rm;
1355   let Inst{30-21} = 0b0011010110;
1356   let Inst{20-16} = Rm;
1357   let Inst{15-14} = 0b00;
1358   let Inst{13-10} = opc;
1359   let Inst{9-5}   = Rn;
1360   let Inst{4-0}   = Rd;
1361 }
1362
1363 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1364               SDPatternOperator OpNode>
1365     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1366   let Inst{10}    = isSigned;
1367 }
1368
1369 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1370   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1371            Sched<[WriteID32, ReadID, ReadID]> {
1372     let Inst{31} = 0;
1373   }
1374   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1375            Sched<[WriteID64, ReadID, ReadID]> {
1376     let Inst{31} = 1;
1377   }
1378 }
1379
1380 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1381                 SDPatternOperator OpNode = null_frag>
1382   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1383     Sched<[WriteIS, ReadI]> {
1384   let Inst{11-10} = shift_type;
1385 }
1386
1387 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1388   def Wr : BaseShift<shift_type, GPR32, asm> {
1389     let Inst{31} = 0;
1390   }
1391
1392   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1393     let Inst{31} = 1;
1394   }
1395
1396   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1397             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1398                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1399
1400   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1401             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1402
1403   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1404             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1405
1406   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1407             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1408 }
1409
1410 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1411     : InstAlias<asm#"\t$dst, $src1, $src2",
1412                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1413
1414 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1415                        RegisterClass addtype, string asm,
1416                        list<dag> pattern>
1417   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1418       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1419   bits<5> Rd;
1420   bits<5> Rn;
1421   bits<5> Rm;
1422   bits<5> Ra;
1423   let Inst{30-24} = 0b0011011;
1424   let Inst{23-21} = opc;
1425   let Inst{20-16} = Rm;
1426   let Inst{15}    = isSub;
1427   let Inst{14-10} = Ra;
1428   let Inst{9-5}   = Rn;
1429   let Inst{4-0}   = Rd;
1430 }
1431
1432 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1433   // MADD/MSUB generation is decided by MachineCombiner.cpp
1434   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1435       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1436       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1437     let Inst{31} = 0;
1438   }
1439
1440   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1441       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1442       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1443     let Inst{31} = 1;
1444   }
1445 }
1446
1447 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1448                    SDNode AccNode, SDNode ExtNode>
1449   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1450     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1451                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1452     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1453   let Inst{31} = 1;
1454 }
1455
1456 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1457   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1458       asm, "\t$Rd, $Rn, $Rm", "",
1459       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1460     Sched<[WriteIM64, ReadIM, ReadIM]> {
1461   bits<5> Rd;
1462   bits<5> Rn;
1463   bits<5> Rm;
1464   let Inst{31-24} = 0b10011011;
1465   let Inst{23-21} = opc;
1466   let Inst{20-16} = Rm;
1467   let Inst{15}    = 0;
1468   let Inst{9-5}   = Rn;
1469   let Inst{4-0}   = Rd;
1470
1471   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1472   // (i.e. all bits 1) but is ignored by the processor.
1473   let PostEncoderMethod = "fixMulHigh";
1474 }
1475
1476 class MulAccumWAlias<string asm, Instruction inst>
1477     : InstAlias<asm#"\t$dst, $src1, $src2",
1478                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1479 class MulAccumXAlias<string asm, Instruction inst>
1480     : InstAlias<asm#"\t$dst, $src1, $src2",
1481                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1482 class WideMulAccumAlias<string asm, Instruction inst>
1483     : InstAlias<asm#"\t$dst, $src1, $src2",
1484                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1485
1486 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1487               SDPatternOperator OpNode, string asm>
1488   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1489       asm, "\t$Rd, $Rn, $Rm", "",
1490       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1491     Sched<[WriteISReg, ReadI, ReadISReg]> {
1492   bits<5> Rd;
1493   bits<5> Rn;
1494   bits<5> Rm;
1495
1496   let Inst{31} = sf;
1497   let Inst{30-21} = 0b0011010110;
1498   let Inst{20-16} = Rm;
1499   let Inst{15-13} = 0b010;
1500   let Inst{12} = C;
1501   let Inst{11-10} = sz;
1502   let Inst{9-5} = Rn;
1503   let Inst{4-0} = Rd;
1504   let Predicates = [HasCRC];
1505 }
1506
1507 //---
1508 // Address generation.
1509 //---
1510
1511 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1512     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1513         pattern>,
1514       Sched<[WriteI]> {
1515   bits<5>  Xd;
1516   bits<21> label;
1517   let Inst{31}    = page;
1518   let Inst{30-29} = label{1-0};
1519   let Inst{28-24} = 0b10000;
1520   let Inst{23-5}  = label{20-2};
1521   let Inst{4-0}   = Xd;
1522
1523   let DecoderMethod = "DecodeAdrInstruction";
1524 }
1525
1526 //---
1527 // Move immediate.
1528 //---
1529
1530 def movimm32_imm : Operand<i32> {
1531   let ParserMatchClass = Imm0_65535Operand;
1532   let EncoderMethod = "getMoveWideImmOpValue";
1533   let PrintMethod = "printHexImm";
1534 }
1535 def movimm32_shift : Operand<i32> {
1536   let PrintMethod = "printShifter";
1537   let ParserMatchClass = MovImm32ShifterOperand;
1538 }
1539 def movimm64_shift : Operand<i32> {
1540   let PrintMethod = "printShifter";
1541   let ParserMatchClass = MovImm64ShifterOperand;
1542 }
1543
1544 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1545 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1546                         string asm>
1547   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1548        asm, "\t$Rd, $imm$shift", "", []>,
1549     Sched<[WriteImm]> {
1550   bits<5> Rd;
1551   bits<16> imm;
1552   bits<6> shift;
1553   let Inst{30-29} = opc;
1554   let Inst{28-23} = 0b100101;
1555   let Inst{22-21} = shift{5-4};
1556   let Inst{20-5}  = imm;
1557   let Inst{4-0}   = Rd;
1558
1559   let DecoderMethod = "DecodeMoveImmInstruction";
1560 }
1561
1562 multiclass MoveImmediate<bits<2> opc, string asm> {
1563   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1564     let Inst{31} = 0;
1565   }
1566
1567   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1568     let Inst{31} = 1;
1569   }
1570 }
1571
1572 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1573 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1574                           string asm>
1575   : I<(outs regtype:$Rd),
1576       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1577        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1578     Sched<[WriteI, ReadI]> {
1579   bits<5> Rd;
1580   bits<16> imm;
1581   bits<6> shift;
1582   let Inst{30-29} = opc;
1583   let Inst{28-23} = 0b100101;
1584   let Inst{22-21} = shift{5-4};
1585   let Inst{20-5}  = imm;
1586   let Inst{4-0}   = Rd;
1587
1588   let DecoderMethod = "DecodeMoveImmInstruction";
1589 }
1590
1591 multiclass InsertImmediate<bits<2> opc, string asm> {
1592   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1593     let Inst{31} = 0;
1594   }
1595
1596   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1597     let Inst{31} = 1;
1598   }
1599 }
1600
1601 //---
1602 // Add/Subtract
1603 //---
1604
1605 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1606                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1607                     string asm, SDPatternOperator OpNode>
1608     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1609         asm, "\t$Rd, $Rn, $imm", "",
1610         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1611       Sched<[WriteI, ReadI]>  {
1612   bits<5>  Rd;
1613   bits<5>  Rn;
1614   bits<14> imm;
1615   let Inst{30}    = isSub;
1616   let Inst{29}    = setFlags;
1617   let Inst{28-24} = 0b10001;
1618   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1619   let Inst{21-10} = imm{11-0};
1620   let Inst{9-5}   = Rn;
1621   let Inst{4-0}   = Rd;
1622   let DecoderMethod = "DecodeBaseAddSubImm";
1623 }
1624
1625 class BaseAddSubRegPseudo<RegisterClass regtype,
1626                           SDPatternOperator OpNode>
1627     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1628              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1629       Sched<[WriteI, ReadI, ReadI]>;
1630
1631 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1632                      arith_shifted_reg shifted_regtype, string asm,
1633                      SDPatternOperator OpNode>
1634     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1635         asm, "\t$Rd, $Rn, $Rm", "",
1636         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1637       Sched<[WriteISReg, ReadI, ReadISReg]> {
1638   // The operands are in order to match the 'addr' MI operands, so we
1639   // don't need an encoder method and by-name matching. Just use the default
1640   // in-order handling. Since we're using by-order, make sure the names
1641   // do not match.
1642   bits<5> dst;
1643   bits<5> src1;
1644   bits<5> src2;
1645   bits<8> shift;
1646   let Inst{30}    = isSub;
1647   let Inst{29}    = setFlags;
1648   let Inst{28-24} = 0b01011;
1649   let Inst{23-22} = shift{7-6};
1650   let Inst{21}    = 0;
1651   let Inst{20-16} = src2;
1652   let Inst{15-10} = shift{5-0};
1653   let Inst{9-5}   = src1;
1654   let Inst{4-0}   = dst;
1655
1656   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1657 }
1658
1659 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1660                      RegisterClass src1Regtype, Operand src2Regtype,
1661                      string asm, SDPatternOperator OpNode>
1662     : I<(outs dstRegtype:$R1),
1663         (ins src1Regtype:$R2, src2Regtype:$R3),
1664         asm, "\t$R1, $R2, $R3", "",
1665         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1666       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1667   bits<5> Rd;
1668   bits<5> Rn;
1669   bits<5> Rm;
1670   bits<6> ext;
1671   let Inst{30}    = isSub;
1672   let Inst{29}    = setFlags;
1673   let Inst{28-24} = 0b01011;
1674   let Inst{23-21} = 0b001;
1675   let Inst{20-16} = Rm;
1676   let Inst{15-13} = ext{5-3};
1677   let Inst{12-10} = ext{2-0};
1678   let Inst{9-5}   = Rn;
1679   let Inst{4-0}   = Rd;
1680
1681   let DecoderMethod = "DecodeAddSubERegInstruction";
1682 }
1683
1684 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1685 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1686                        RegisterClass src1Regtype, RegisterClass src2Regtype,
1687                        Operand ext_op, string asm>
1688     : I<(outs dstRegtype:$Rd),
1689         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1690         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1691       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1692   bits<5> Rd;
1693   bits<5> Rn;
1694   bits<5> Rm;
1695   bits<6> ext;
1696   let Inst{30}    = isSub;
1697   let Inst{29}    = setFlags;
1698   let Inst{28-24} = 0b01011;
1699   let Inst{23-21} = 0b001;
1700   let Inst{20-16} = Rm;
1701   let Inst{15}    = ext{5};
1702   let Inst{12-10} = ext{2-0};
1703   let Inst{9-5}   = Rn;
1704   let Inst{4-0}   = Rd;
1705
1706   let DecoderMethod = "DecodeAddSubERegInstruction";
1707 }
1708
1709 // Aliases for register+register add/subtract.
1710 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1711                      RegisterClass src1Regtype, RegisterClass src2Regtype,
1712                      int shiftExt>
1713     : InstAlias<asm#"\t$dst, $src1, $src2",
1714                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1715                       shiftExt)>;
1716
1717 multiclass AddSub<bit isSub, string mnemonic, string alias,
1718                   SDPatternOperator OpNode = null_frag> {
1719   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1720   // Add/Subtract immediate
1721   // Increase the weight of the immediate variant to try to match it before
1722   // the extended register variant.
1723   // We used to match the register variant before the immediate when the
1724   // register argument could be implicitly zero-extended.
1725   let AddedComplexity = 6 in
1726   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1727                            mnemonic, OpNode> {
1728     let Inst{31} = 0;
1729   }
1730   let AddedComplexity = 6 in
1731   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1732                            mnemonic, OpNode> {
1733     let Inst{31} = 1;
1734   }
1735
1736   // Add/Subtract register - Only used for CodeGen
1737   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1738   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1739
1740   // Add/Subtract shifted register
1741   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1742                            OpNode> {
1743     let Inst{31} = 0;
1744   }
1745   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1746                            OpNode> {
1747     let Inst{31} = 1;
1748   }
1749   }
1750
1751   // Add/Subtract extended register
1752   let AddedComplexity = 1, hasSideEffects = 0 in {
1753   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1754                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1755     let Inst{31} = 0;
1756   }
1757   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1758                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1759     let Inst{31} = 1;
1760   }
1761   }
1762
1763   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1764                                arith_extendlsl64, mnemonic> {
1765     // UXTX and SXTX only.
1766     let Inst{14-13} = 0b11;
1767     let Inst{31} = 1;
1768   }
1769
1770   // add Rd, Rb, -imm -> sub Rd, Rn, imm
1771   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1772                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
1773                       addsub_shifted_imm32_neg:$imm), 0>;
1774   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1775                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
1776                        addsub_shifted_imm64_neg:$imm), 0>;
1777
1778   // Register/register aliases with no shift when SP is not used.
1779   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1780                        GPR32, GPR32, GPR32, 0>;
1781   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1782                        GPR64, GPR64, GPR64, 0>;
1783
1784   // Register/register aliases with no shift when either the destination or
1785   // first source register is SP.
1786   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1787                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1788   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1789                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1790   def : AddSubRegAlias<mnemonic,
1791                        !cast<Instruction>(NAME#"Xrx64"),
1792                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1793   def : AddSubRegAlias<mnemonic,
1794                        !cast<Instruction>(NAME#"Xrx64"),
1795                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1796 }
1797
1798 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
1799                    string alias, string cmpAlias> {
1800   let isCompare = 1, Defs = [NZCV] in {
1801   // Add/Subtract immediate
1802   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1803                            mnemonic, OpNode> {
1804     let Inst{31} = 0;
1805   }
1806   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1807                            mnemonic, OpNode> {
1808     let Inst{31} = 1;
1809   }
1810
1811   // Add/Subtract register
1812   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1813   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1814
1815   // Add/Subtract shifted register
1816   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1817                            OpNode> {
1818     let Inst{31} = 0;
1819   }
1820   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1821                            OpNode> {
1822     let Inst{31} = 1;
1823   }
1824
1825   // Add/Subtract extended register
1826   let AddedComplexity = 1 in {
1827   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1828                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1829     let Inst{31} = 0;
1830   }
1831   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1832                            arith_extended_reg32<i64>, mnemonic, OpNode> {
1833     let Inst{31} = 1;
1834   }
1835   }
1836
1837   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1838                                arith_extendlsl64, mnemonic> {
1839     // UXTX and SXTX only.
1840     let Inst{14-13} = 0b11;
1841     let Inst{31} = 1;
1842   }
1843   } // Defs = [NZCV]
1844
1845   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
1846   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1847                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
1848                       addsub_shifted_imm32_neg:$imm), 0>;
1849   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1850                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
1851                        addsub_shifted_imm64_neg:$imm), 0>;
1852
1853   // Compare aliases
1854   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1855                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1856   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1857                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1858   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1859                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1860   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1861                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1862   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1863                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1864   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1865                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1866   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1867                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1868
1869   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
1870   def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1871                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
1872   def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1873                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
1874
1875   // Compare shorthands
1876   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1877                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1878   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1879                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1880   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1881                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1882   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1883                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1884
1885   // Register/register aliases with no shift when SP is not used.
1886   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1887                        GPR32, GPR32, GPR32, 0>;
1888   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1889                        GPR64, GPR64, GPR64, 0>;
1890
1891   // Register/register aliases with no shift when the first source register
1892   // is SP.
1893   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1894                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1895   def : AddSubRegAlias<mnemonic,
1896                        !cast<Instruction>(NAME#"Xrx64"),
1897                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1898 }
1899
1900 //---
1901 // Extract
1902 //---
1903 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1904                                       SDTCisPtrTy<3>]>;
1905 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1906
1907 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1908                      list<dag> patterns>
1909     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1910          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1911       Sched<[WriteExtr, ReadExtrHi]> {
1912   bits<5> Rd;
1913   bits<5> Rn;
1914   bits<5> Rm;
1915   bits<6> imm;
1916
1917   let Inst{30-23} = 0b00100111;
1918   let Inst{21}    = 0;
1919   let Inst{20-16} = Rm;
1920   let Inst{15-10} = imm;
1921   let Inst{9-5}   = Rn;
1922   let Inst{4-0}   = Rd;
1923 }
1924
1925 multiclass ExtractImm<string asm> {
1926   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1927                       [(set GPR32:$Rd,
1928                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1929     let Inst{31} = 0;
1930     let Inst{22} = 0;
1931     // imm<5> must be zero.
1932     let imm{5}   = 0;
1933   }
1934   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1935                       [(set GPR64:$Rd,
1936                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1937
1938     let Inst{31} = 1;
1939     let Inst{22} = 1;
1940   }
1941 }
1942
1943 //---
1944 // Bitfield
1945 //---
1946
1947 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1948 class BaseBitfieldImm<bits<2> opc,
1949                       RegisterClass regtype, Operand imm_type, string asm>
1950     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1951          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1952       Sched<[WriteIS, ReadI]> {
1953   bits<5> Rd;
1954   bits<5> Rn;
1955   bits<6> immr;
1956   bits<6> imms;
1957
1958   let Inst{30-29} = opc;
1959   let Inst{28-23} = 0b100110;
1960   let Inst{21-16} = immr;
1961   let Inst{15-10} = imms;
1962   let Inst{9-5}   = Rn;
1963   let Inst{4-0}   = Rd;
1964 }
1965
1966 multiclass BitfieldImm<bits<2> opc, string asm> {
1967   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1968     let Inst{31} = 0;
1969     let Inst{22} = 0;
1970     // imms<5> and immr<5> must be zero, else ReservedValue().
1971     let Inst{21} = 0;
1972     let Inst{15} = 0;
1973   }
1974   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1975     let Inst{31} = 1;
1976     let Inst{22} = 1;
1977   }
1978 }
1979
1980 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1981 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1982                       RegisterClass regtype, Operand imm_type, string asm>
1983     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1984                              imm_type:$imms),
1985          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1986       Sched<[WriteIS, ReadI]> {
1987   bits<5> Rd;
1988   bits<5> Rn;
1989   bits<6> immr;
1990   bits<6> imms;
1991
1992   let Inst{30-29} = opc;
1993   let Inst{28-23} = 0b100110;
1994   let Inst{21-16} = immr;
1995   let Inst{15-10} = imms;
1996   let Inst{9-5}   = Rn;
1997   let Inst{4-0}   = Rd;
1998 }
1999
2000 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2001   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2002     let Inst{31} = 0;
2003     let Inst{22} = 0;
2004     // imms<5> and immr<5> must be zero, else ReservedValue().
2005     let Inst{21} = 0;
2006     let Inst{15} = 0;
2007   }
2008   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2009     let Inst{31} = 1;
2010     let Inst{22} = 1;
2011   }
2012 }
2013
2014 //---
2015 // Logical
2016 //---
2017
2018 // Logical (immediate)
2019 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2020                      RegisterClass sregtype, Operand imm_type, string asm,
2021                      list<dag> pattern>
2022     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2023          asm, "\t$Rd, $Rn, $imm", "", pattern>,
2024       Sched<[WriteI, ReadI]> {
2025   bits<5>  Rd;
2026   bits<5>  Rn;
2027   bits<13> imm;
2028   let Inst{30-29} = opc;
2029   let Inst{28-23} = 0b100100;
2030   let Inst{22}    = imm{12};
2031   let Inst{21-16} = imm{11-6};
2032   let Inst{15-10} = imm{5-0};
2033   let Inst{9-5}   = Rn;
2034   let Inst{4-0}   = Rd;
2035
2036   let DecoderMethod = "DecodeLogicalImmInstruction";
2037 }
2038
2039 // Logical (shifted register)
2040 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2041                       logical_shifted_reg shifted_regtype, string asm,
2042                       list<dag> pattern>
2043     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2044         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2045       Sched<[WriteISReg, ReadI, ReadISReg]> {
2046   // The operands are in order to match the 'addr' MI operands, so we
2047   // don't need an encoder method and by-name matching. Just use the default
2048   // in-order handling. Since we're using by-order, make sure the names
2049   // do not match.
2050   bits<5> dst;
2051   bits<5> src1;
2052   bits<5> src2;
2053   bits<8> shift;
2054   let Inst{30-29} = opc;
2055   let Inst{28-24} = 0b01010;
2056   let Inst{23-22} = shift{7-6};
2057   let Inst{21}    = N;
2058   let Inst{20-16} = src2;
2059   let Inst{15-10} = shift{5-0};
2060   let Inst{9-5}   = src1;
2061   let Inst{4-0}   = dst;
2062
2063   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2064 }
2065
2066 // Aliases for register+register logical instructions.
2067 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2068     : InstAlias<asm#"\t$dst, $src1, $src2",
2069                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2070
2071 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2072                       string Alias> {
2073   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2074   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2075                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2076                                                logical_imm32:$imm))]> {
2077     let Inst{31} = 0;
2078     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2079   }
2080   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2081   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2082                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2083                                                logical_imm64:$imm))]> {
2084     let Inst{31} = 1;
2085   }
2086
2087   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2088                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2089                       logical_imm32_not:$imm), 0>;
2090   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2091                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2092                        logical_imm64_not:$imm), 0>;
2093 }
2094
2095 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2096                        string Alias> {
2097   let isCompare = 1, Defs = [NZCV] in {
2098   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2099       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2100     let Inst{31} = 0;
2101     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2102   }
2103   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2104       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2105     let Inst{31} = 1;
2106   }
2107   } // end Defs = [NZCV]
2108
2109   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2110                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2111                       logical_imm32_not:$imm), 0>;
2112   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2113                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2114                        logical_imm64_not:$imm), 0>;
2115 }
2116
2117 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2118     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2119              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2120       Sched<[WriteI, ReadI, ReadI]>;
2121
2122 // Split from LogicalImm as not all instructions have both.
2123 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2124                       SDPatternOperator OpNode> {
2125   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2126   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2127   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2128   }
2129
2130   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2131                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2132                                                  logical_shifted_reg32:$Rm))]> {
2133     let Inst{31} = 0;
2134   }
2135   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2136                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2137                                                  logical_shifted_reg64:$Rm))]> {
2138     let Inst{31} = 1;
2139   }
2140
2141   def : LogicalRegAlias<mnemonic,
2142                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2143   def : LogicalRegAlias<mnemonic,
2144                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2145 }
2146
2147 // Split from LogicalReg to allow setting NZCV Defs
2148 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2149                        SDPatternOperator OpNode = null_frag> {
2150   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2151   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2152   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2153
2154   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2155             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2156     let Inst{31} = 0;
2157   }
2158   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2159             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2160     let Inst{31} = 1;
2161   }
2162   } // Defs = [NZCV]
2163
2164   def : LogicalRegAlias<mnemonic,
2165                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2166   def : LogicalRegAlias<mnemonic,
2167                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2168 }
2169
2170 //---
2171 // Conditionally set flags
2172 //---
2173
2174 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2175 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2176                             string mnemonic, SDNode OpNode>
2177     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2178          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2179          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2180                              (i32 imm:$cond), NZCV))]>,
2181       Sched<[WriteI, ReadI]> {
2182   let Uses = [NZCV];
2183   let Defs = [NZCV];
2184
2185   bits<5> Rn;
2186   bits<5> imm;
2187   bits<4> nzcv;
2188   bits<4> cond;
2189
2190   let Inst{30}    = op;
2191   let Inst{29-21} = 0b111010010;
2192   let Inst{20-16} = imm;
2193   let Inst{15-12} = cond;
2194   let Inst{11-10} = 0b10;
2195   let Inst{9-5}   = Rn;
2196   let Inst{4}     = 0b0;
2197   let Inst{3-0}   = nzcv;
2198 }
2199
2200 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2201 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2202                             SDNode OpNode>
2203     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2204          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2205          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2206                              (i32 imm:$cond), NZCV))]>,
2207       Sched<[WriteI, ReadI, ReadI]> {
2208   let Uses = [NZCV];
2209   let Defs = [NZCV];
2210
2211   bits<5> Rn;
2212   bits<5> Rm;
2213   bits<4> nzcv;
2214   bits<4> cond;
2215
2216   let Inst{30}    = op;
2217   let Inst{29-21} = 0b111010010;
2218   let Inst{20-16} = Rm;
2219   let Inst{15-12} = cond;
2220   let Inst{11-10} = 0b00;
2221   let Inst{9-5}   = Rn;
2222   let Inst{4}     = 0b0;
2223   let Inst{3-0}   = nzcv;
2224 }
2225
2226 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2227   // immediate operand variants
2228   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2229     let Inst{31} = 0;
2230   }
2231   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2232     let Inst{31} = 1;
2233   }
2234   // register operand variants
2235   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2236     let Inst{31} = 0;
2237   }
2238   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2239     let Inst{31} = 1;
2240   }
2241 }
2242
2243 //---
2244 // Conditional select
2245 //---
2246
2247 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2248     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2249          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2250          [(set regtype:$Rd,
2251                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2252       Sched<[WriteI, ReadI, ReadI]> {
2253   let Uses = [NZCV];
2254
2255   bits<5> Rd;
2256   bits<5> Rn;
2257   bits<5> Rm;
2258   bits<4> cond;
2259
2260   let Inst{30}    = op;
2261   let Inst{29-21} = 0b011010100;
2262   let Inst{20-16} = Rm;
2263   let Inst{15-12} = cond;
2264   let Inst{11-10} = op2;
2265   let Inst{9-5}   = Rn;
2266   let Inst{4-0}   = Rd;
2267 }
2268
2269 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2270   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2271     let Inst{31} = 0;
2272   }
2273   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2274     let Inst{31} = 1;
2275   }
2276 }
2277
2278 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2279                        PatFrag frag>
2280     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2281          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2282          [(set regtype:$Rd,
2283                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2284                (i32 imm:$cond), NZCV))]>,
2285       Sched<[WriteI, ReadI, ReadI]> {
2286   let Uses = [NZCV];
2287
2288   bits<5> Rd;
2289   bits<5> Rn;
2290   bits<5> Rm;
2291   bits<4> cond;
2292
2293   let Inst{30}    = op;
2294   let Inst{29-21} = 0b011010100;
2295   let Inst{20-16} = Rm;
2296   let Inst{15-12} = cond;
2297   let Inst{11-10} = op2;
2298   let Inst{9-5}   = Rn;
2299   let Inst{4-0}   = Rd;
2300 }
2301
2302 def inv_cond_XFORM : SDNodeXForm<imm, [{
2303   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2304   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2305                                    MVT::i32);
2306 }]>;
2307
2308 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2309   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2310     let Inst{31} = 0;
2311   }
2312   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2313     let Inst{31} = 1;
2314   }
2315
2316   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2317             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2318                                            (inv_cond_XFORM imm:$cond))>;
2319
2320   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2321             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2322                                            (inv_cond_XFORM imm:$cond))>;
2323 }
2324
2325 //---
2326 // Special Mask Value
2327 //---
2328 def maski8_or_more : Operand<i32>,
2329   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2330 }
2331 def maski16_or_more : Operand<i32>,
2332   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2333 }
2334
2335
2336 //---
2337 // Load/store
2338 //---
2339
2340 // (unsigned immediate)
2341 // Indexed for 8-bit registers. offset is in range [0,4095].
2342 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2343 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2344 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2345 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2346 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2347
2348 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2349   let Name = "UImm12Offset" # Scale;
2350   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2351   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2352   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2353 }
2354
2355 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2356 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2357 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2358 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2359 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2360
2361 class uimm12_scaled<int Scale> : Operand<i64> {
2362   let ParserMatchClass
2363    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2364   let EncoderMethod
2365    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2366   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2367 }
2368
2369 def uimm12s1 : uimm12_scaled<1>;
2370 def uimm12s2 : uimm12_scaled<2>;
2371 def uimm12s4 : uimm12_scaled<4>;
2372 def uimm12s8 : uimm12_scaled<8>;
2373 def uimm12s16 : uimm12_scaled<16>;
2374
2375 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2376                       string asm, list<dag> pattern>
2377     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2378   bits<5> Rt;
2379
2380   bits<5> Rn;
2381   bits<12> offset;
2382
2383   let Inst{31-30} = sz;
2384   let Inst{29-27} = 0b111;
2385   let Inst{26}    = V;
2386   let Inst{25-24} = 0b01;
2387   let Inst{23-22} = opc;
2388   let Inst{21-10} = offset;
2389   let Inst{9-5}   = Rn;
2390   let Inst{4-0}   = Rt;
2391
2392   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2393 }
2394
2395 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2396                   Operand indextype, string asm, list<dag> pattern> {
2397   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2398   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2399                            (ins GPR64sp:$Rn, indextype:$offset),
2400                            asm, pattern>,
2401            Sched<[WriteLD]>;
2402
2403   def : InstAlias<asm # "\t$Rt, [$Rn]",
2404                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2405 }
2406
2407 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2408              Operand indextype, string asm, list<dag> pattern> {
2409   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2410   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2411                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2412                            asm, pattern>,
2413            Sched<[WriteST]>;
2414
2415   def : InstAlias<asm # "\t$Rt, [$Rn]",
2416                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2417 }
2418
2419 def PrefetchOperand : AsmOperandClass {
2420   let Name = "Prefetch";
2421   let ParserMethod = "tryParsePrefetch";
2422 }
2423 def prfop : Operand<i32> {
2424   let PrintMethod = "printPrefetchOp";
2425   let ParserMatchClass = PrefetchOperand;
2426 }
2427
2428 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2429 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2430     : BaseLoadStoreUI<sz, V, opc,
2431                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2432                       asm, pat>,
2433       Sched<[WriteLD]>;
2434
2435 //---
2436 // Load literal
2437 //---
2438
2439 // Load literal address: 19-bit immediate. The low two bits of the target
2440 // offset are implied zero and so are not part of the immediate.
2441 def am_ldrlit : Operand<OtherVT> {
2442   let EncoderMethod = "getLoadLiteralOpValue";
2443   let DecoderMethod = "DecodePCRelLabel19";
2444   let PrintMethod = "printAlignedLabel";
2445   let ParserMatchClass = PCRelLabel19Operand;
2446 }
2447
2448 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2449 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2450     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2451         asm, "\t$Rt, $label", "", []>,
2452       Sched<[WriteLD]> {
2453   bits<5> Rt;
2454   bits<19> label;
2455   let Inst{31-30} = opc;
2456   let Inst{29-27} = 0b011;
2457   let Inst{26}    = V;
2458   let Inst{25-24} = 0b00;
2459   let Inst{23-5}  = label;
2460   let Inst{4-0}   = Rt;
2461 }
2462
2463 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2464 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2465     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2466         asm, "\t$Rt, $label", "", pat>,
2467       Sched<[WriteLD]> {
2468   bits<5> Rt;
2469   bits<19> label;
2470   let Inst{31-30} = opc;
2471   let Inst{29-27} = 0b011;
2472   let Inst{26}    = V;
2473   let Inst{25-24} = 0b00;
2474   let Inst{23-5}  = label;
2475   let Inst{4-0}   = Rt;
2476 }
2477
2478 //---
2479 // Load/store register offset
2480 //---
2481
2482 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2483 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2484 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2485 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2486 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2487
2488 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2489 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2490 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2491 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2492 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2493
2494 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2495   let Name = "Mem" # Reg # "Extend" # Width;
2496   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2497   let RenderMethod = "addMemExtendOperands";
2498   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2499 }
2500
2501 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2502   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2503   // the trivial shift.
2504   let RenderMethod = "addMemExtend8Operands";
2505 }
2506 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2507 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2508 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2509 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2510
2511 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2512   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2513   // the trivial shift.
2514   let RenderMethod = "addMemExtend8Operands";
2515 }
2516 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2517 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2518 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2519 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2520
2521 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2522         : Operand<i32> {
2523   let ParserMatchClass = ParserClass;
2524   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2525   let DecoderMethod = "DecodeMemExtend";
2526   let EncoderMethod = "getMemExtendOpValue";
2527   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2528 }
2529
2530 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2531 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2532 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2533 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2534 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2535
2536 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2537 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2538 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2539 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2540 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2541
2542 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2543                   Operand wextend, Operand xextend>  {
2544   // CodeGen-level pattern covering the entire addressing mode.
2545   ComplexPattern Wpat = windex;
2546   ComplexPattern Xpat = xindex;
2547
2548   // Asm-level Operand covering the valid "uxtw #3" style syntax.
2549   Operand Wext = wextend;
2550   Operand Xext = xextend;
2551 }
2552
2553 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2554 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2555 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2556 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2557 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2558                        ro_Xextend128>;
2559
2560 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2561                       string asm, dag ins, dag outs, list<dag> pat>
2562     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2563   bits<5> Rt;
2564   bits<5> Rn;
2565   bits<5> Rm;
2566   bits<2> extend;
2567   let Inst{31-30} = sz;
2568   let Inst{29-27} = 0b111;
2569   let Inst{26}    = V;
2570   let Inst{25-24} = 0b00;
2571   let Inst{23-22} = opc;
2572   let Inst{21}    = 1;
2573   let Inst{20-16} = Rm;
2574   let Inst{15}    = extend{1}; // sign extend Rm?
2575   let Inst{14}    = 1;
2576   let Inst{12}    = extend{0}; // do shift?
2577   let Inst{11-10} = 0b10;
2578   let Inst{9-5}   = Rn;
2579   let Inst{4-0}   = Rt;
2580 }
2581
2582 class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2583   : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
2584               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2585
2586 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2587                    string asm, ValueType Ty, SDPatternOperator loadop> {
2588   let AddedComplexity = 10 in
2589   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2590                  (outs regtype:$Rt),
2591                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2592                  [(set (Ty regtype:$Rt),
2593                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2594                                              ro_Wextend8:$extend)))]>,
2595            Sched<[WriteLDIdx, ReadAdrBase]> {
2596     let Inst{13} = 0b0;
2597   }
2598
2599   let AddedComplexity = 10 in
2600   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2601                  (outs regtype:$Rt),
2602                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2603                  [(set (Ty regtype:$Rt),
2604                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2605                                              ro_Xextend8:$extend)))]>,
2606            Sched<[WriteLDIdx, ReadAdrBase]> {
2607     let Inst{13} = 0b1;
2608   }
2609
2610   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2611 }
2612
2613 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2614                     string asm, ValueType Ty, SDPatternOperator storeop> {
2615   let AddedComplexity = 10 in
2616   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2617                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2618                  [(storeop (Ty regtype:$Rt),
2619                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2620                                          ro_Wextend8:$extend))]>,
2621             Sched<[WriteSTIdx, ReadAdrBase]> {
2622     let Inst{13} = 0b0;
2623   }
2624
2625   let AddedComplexity = 10 in
2626   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2627                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2628                  [(storeop (Ty regtype:$Rt),
2629                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2630                                          ro_Xextend8:$extend))]>,
2631             Sched<[WriteSTIdx, ReadAdrBase]> {
2632     let Inst{13} = 0b1;
2633   }
2634
2635   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2636 }
2637
2638 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2639                       string asm, dag ins, dag outs, list<dag> pat>
2640     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2641   bits<5> Rt;
2642   bits<5> Rn;
2643   bits<5> Rm;
2644   bits<2> extend;
2645   let Inst{31-30} = sz;
2646   let Inst{29-27} = 0b111;
2647   let Inst{26}    = V;
2648   let Inst{25-24} = 0b00;
2649   let Inst{23-22} = opc;
2650   let Inst{21}    = 1;
2651   let Inst{20-16} = Rm;
2652   let Inst{15}    = extend{1}; // sign extend Rm?
2653   let Inst{14}    = 1;
2654   let Inst{12}    = extend{0}; // do shift?
2655   let Inst{11-10} = 0b10;
2656   let Inst{9-5}   = Rn;
2657   let Inst{4-0}   = Rt;
2658 }
2659
2660 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2661                     string asm, ValueType Ty, SDPatternOperator loadop> {
2662   let AddedComplexity = 10 in
2663   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2664                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2665                  [(set (Ty regtype:$Rt),
2666                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2667                                               ro_Wextend16:$extend)))]>,
2668             Sched<[WriteLDIdx, ReadAdrBase]> {
2669     let Inst{13} = 0b0;
2670   }
2671
2672   let AddedComplexity = 10 in
2673   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2674                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2675                  [(set (Ty regtype:$Rt),
2676                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2677                                              ro_Xextend16:$extend)))]>,
2678             Sched<[WriteLDIdx, ReadAdrBase]> {
2679     let Inst{13} = 0b1;
2680   }
2681
2682   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2683 }
2684
2685 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2686                      string asm, ValueType Ty, SDPatternOperator storeop> {
2687   let AddedComplexity = 10 in
2688   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2689                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2690                 [(storeop (Ty regtype:$Rt),
2691                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2692                                          ro_Wextend16:$extend))]>,
2693            Sched<[WriteSTIdx, ReadAdrBase]> {
2694     let Inst{13} = 0b0;
2695   }
2696
2697   let AddedComplexity = 10 in
2698   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2699                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2700                 [(storeop (Ty regtype:$Rt),
2701                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2702                                          ro_Xextend16:$extend))]>,
2703            Sched<[WriteSTIdx, ReadAdrBase]> {
2704     let Inst{13} = 0b1;
2705   }
2706
2707   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2708 }
2709
2710 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2711                       string asm, dag ins, dag outs, list<dag> pat>
2712     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2713   bits<5> Rt;
2714   bits<5> Rn;
2715   bits<5> Rm;
2716   bits<2> extend;
2717   let Inst{31-30} = sz;
2718   let Inst{29-27} = 0b111;
2719   let Inst{26}    = V;
2720   let Inst{25-24} = 0b00;
2721   let Inst{23-22} = opc;
2722   let Inst{21}    = 1;
2723   let Inst{20-16} = Rm;
2724   let Inst{15}    = extend{1}; // sign extend Rm?
2725   let Inst{14}    = 1;
2726   let Inst{12}    = extend{0}; // do shift?
2727   let Inst{11-10} = 0b10;
2728   let Inst{9-5}   = Rn;
2729   let Inst{4-0}   = Rt;
2730 }
2731
2732 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2733                     string asm, ValueType Ty, SDPatternOperator loadop> {
2734   let AddedComplexity = 10 in
2735   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2736                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2737                  [(set (Ty regtype:$Rt),
2738                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2739                                               ro_Wextend32:$extend)))]>,
2740            Sched<[WriteLDIdx, ReadAdrBase]> {
2741     let Inst{13} = 0b0;
2742   }
2743
2744   let AddedComplexity = 10 in
2745   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2746                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2747                  [(set (Ty regtype:$Rt),
2748                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2749                                               ro_Xextend32:$extend)))]>,
2750            Sched<[WriteLDIdx, ReadAdrBase]> {
2751     let Inst{13} = 0b1;
2752   }
2753
2754   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2755 }
2756
2757 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2758                      string asm, ValueType Ty, SDPatternOperator storeop> {
2759   let AddedComplexity = 10 in
2760   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2761                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2762                 [(storeop (Ty regtype:$Rt),
2763                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2764                                          ro_Wextend32:$extend))]>,
2765             Sched<[WriteSTIdx, ReadAdrBase]> {
2766     let Inst{13} = 0b0;
2767   }
2768
2769   let AddedComplexity = 10 in
2770   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2771                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2772                 [(storeop (Ty regtype:$Rt),
2773                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2774                                         ro_Xextend32:$extend))]>,
2775             Sched<[WriteSTIdx, ReadAdrBase]> {
2776     let Inst{13} = 0b1;
2777   }
2778
2779   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2780 }
2781
2782 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2783                       string asm, dag ins, dag outs, list<dag> pat>
2784     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2785   bits<5> Rt;
2786   bits<5> Rn;
2787   bits<5> Rm;
2788   bits<2> extend;
2789   let Inst{31-30} = sz;
2790   let Inst{29-27} = 0b111;
2791   let Inst{26}    = V;
2792   let Inst{25-24} = 0b00;
2793   let Inst{23-22} = opc;
2794   let Inst{21}    = 1;
2795   let Inst{20-16} = Rm;
2796   let Inst{15}    = extend{1}; // sign extend Rm?
2797   let Inst{14}    = 1;
2798   let Inst{12}    = extend{0}; // do shift?
2799   let Inst{11-10} = 0b10;
2800   let Inst{9-5}   = Rn;
2801   let Inst{4-0}   = Rt;
2802 }
2803
2804 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2805                     string asm, ValueType Ty, SDPatternOperator loadop> {
2806   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2807   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2808                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2809                 [(set (Ty regtype:$Rt),
2810                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2811                                              ro_Wextend64:$extend)))]>,
2812            Sched<[WriteLDIdx, ReadAdrBase]> {
2813     let Inst{13} = 0b0;
2814   }
2815
2816   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2817   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2818                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2819                  [(set (Ty regtype:$Rt),
2820                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2821                                               ro_Xextend64:$extend)))]>,
2822            Sched<[WriteLDIdx, ReadAdrBase]> {
2823     let Inst{13} = 0b1;
2824   }
2825
2826   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2827 }
2828
2829 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2830                      string asm, ValueType Ty, SDPatternOperator storeop> {
2831   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2832   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2833                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2834                 [(storeop (Ty regtype:$Rt),
2835                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2836                                          ro_Wextend64:$extend))]>,
2837             Sched<[WriteSTIdx, ReadAdrBase]> {
2838     let Inst{13} = 0b0;
2839   }
2840
2841   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2842   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2843                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2844                 [(storeop (Ty regtype:$Rt),
2845                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2846                                          ro_Xextend64:$extend))]>,
2847             Sched<[WriteSTIdx, ReadAdrBase]> {
2848     let Inst{13} = 0b1;
2849   }
2850
2851   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2852 }
2853
2854 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2855                       string asm, dag ins, dag outs, list<dag> pat>
2856     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2857   bits<5> Rt;
2858   bits<5> Rn;
2859   bits<5> Rm;
2860   bits<2> extend;
2861   let Inst{31-30} = sz;
2862   let Inst{29-27} = 0b111;
2863   let Inst{26}    = V;
2864   let Inst{25-24} = 0b00;
2865   let Inst{23-22} = opc;
2866   let Inst{21}    = 1;
2867   let Inst{20-16} = Rm;
2868   let Inst{15}    = extend{1}; // sign extend Rm?
2869   let Inst{14}    = 1;
2870   let Inst{12}    = extend{0}; // do shift?
2871   let Inst{11-10} = 0b10;
2872   let Inst{9-5}   = Rn;
2873   let Inst{4-0}   = Rt;
2874 }
2875
2876 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2877                      string asm, ValueType Ty, SDPatternOperator loadop> {
2878   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2879   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2880                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2881                  [(set (Ty regtype:$Rt),
2882                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2883                                                ro_Wextend128:$extend)))]>,
2884             Sched<[WriteLDIdx, ReadAdrBase]> {
2885     let Inst{13} = 0b0;
2886   }
2887
2888   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2889   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2890                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2891                  [(set (Ty regtype:$Rt),
2892                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2893                                                ro_Xextend128:$extend)))]>,
2894             Sched<[WriteLDIdx, ReadAdrBase]> {
2895     let Inst{13} = 0b1;
2896   }
2897
2898   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2899 }
2900
2901 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2902                       string asm, ValueType Ty, SDPatternOperator storeop> {
2903   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2904   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2905                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2906                 [(storeop (Ty regtype:$Rt),
2907                           (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2908                                           ro_Wextend128:$extend))]>,
2909             Sched<[WriteSTIdx, ReadAdrBase]> {
2910     let Inst{13} = 0b0;
2911   }
2912
2913   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2914   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2915                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2916                 [(storeop (Ty regtype:$Rt),
2917                           (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2918                                           ro_Xextend128:$extend))]>,
2919             Sched<[WriteSTIdx, ReadAdrBase]> {
2920     let Inst{13} = 0b1;
2921   }
2922
2923   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2924 }
2925
2926 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2927 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2928                      string asm, list<dag> pat>
2929     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2930       Sched<[WriteLD]> {
2931   bits<5> Rt;
2932   bits<5> Rn;
2933   bits<5> Rm;
2934   bits<2> extend;
2935   let Inst{31-30} = sz;
2936   let Inst{29-27} = 0b111;
2937   let Inst{26}    = V;
2938   let Inst{25-24} = 0b00;
2939   let Inst{23-22} = opc;
2940   let Inst{21}    = 1;
2941   let Inst{20-16} = Rm;
2942   let Inst{15}    = extend{1}; // sign extend Rm?
2943   let Inst{14}    = 1;
2944   let Inst{12}    = extend{0}; // do shift?
2945   let Inst{11-10} = 0b10;
2946   let Inst{9-5}   = Rn;
2947   let Inst{4-0}   = Rt;
2948 }
2949
2950 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2951   def roW : BasePrefetchRO<sz, V, opc, (outs),
2952                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2953                 asm, [(AArch64Prefetch imm:$Rt,
2954                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2955                                                     ro_Wextend64:$extend))]> {
2956     let Inst{13} = 0b0;
2957   }
2958
2959   def roX : BasePrefetchRO<sz, V, opc, (outs),
2960                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2961                 asm,  [(AArch64Prefetch imm:$Rt,
2962                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2963                                                      ro_Xextend64:$extend))]> {
2964     let Inst{13} = 0b1;
2965   }
2966
2967   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2968                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2969                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2970 }
2971
2972 //---
2973 // Load/store unscaled immediate
2974 //---
2975
2976 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2977 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2978 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2979 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2980 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2981
2982 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2983                            string asm, list<dag> pattern>
2984     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2985   bits<5> Rt;
2986   bits<5> Rn;
2987   bits<9> offset;
2988   let Inst{31-30} = sz;
2989   let Inst{29-27} = 0b111;
2990   let Inst{26}    = V;
2991   let Inst{25-24} = 0b00;
2992   let Inst{23-22} = opc;
2993   let Inst{21}    = 0;
2994   let Inst{20-12} = offset;
2995   let Inst{11-10} = 0b00;
2996   let Inst{9-5}   = Rn;
2997   let Inst{4-0}   = Rt;
2998
2999   let DecoderMethod = "DecodeSignedLdStInstruction";
3000 }
3001
3002 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3003                    string asm, list<dag> pattern> {
3004   let AddedComplexity = 1 in // try this before LoadUI
3005   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3006                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3007           Sched<[WriteLD]>;
3008
3009   def : InstAlias<asm # "\t$Rt, [$Rn]",
3010                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3011 }
3012
3013 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3014                          string asm, list<dag> pattern> {
3015   let AddedComplexity = 1 in // try this before StoreUI
3016   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3017                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3018                                asm, pattern>,
3019           Sched<[WriteST]>;
3020
3021   def : InstAlias<asm # "\t$Rt, [$Rn]",
3022                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3023 }
3024
3025 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3026                             list<dag> pat> {
3027   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3028   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3029                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3030                                asm, pat>,
3031           Sched<[WriteLD]>;
3032
3033   def : InstAlias<asm # "\t$Rt, [$Rn]",
3034                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3035 }
3036
3037 //---
3038 // Load/store unscaled immediate, unprivileged
3039 //---
3040
3041 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3042                                 dag oops, dag iops, string asm>
3043     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3044   bits<5> Rt;
3045   bits<5> Rn;
3046   bits<9> offset;
3047   let Inst{31-30} = sz;
3048   let Inst{29-27} = 0b111;
3049   let Inst{26}    = V;
3050   let Inst{25-24} = 0b00;
3051   let Inst{23-22} = opc;
3052   let Inst{21}    = 0;
3053   let Inst{20-12} = offset;
3054   let Inst{11-10} = 0b10;
3055   let Inst{9-5}   = Rn;
3056   let Inst{4-0}   = Rt;
3057
3058   let DecoderMethod = "DecodeSignedLdStInstruction";
3059 }
3060
3061 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3062                             RegisterClass regtype, string asm> {
3063   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3064   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3065                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
3066           Sched<[WriteLD]>;
3067
3068   def : InstAlias<asm # "\t$Rt, [$Rn]",
3069                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3070 }
3071
3072 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3073                              RegisterClass regtype, string asm> {
3074   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3075   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3076                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3077                                  asm>,
3078           Sched<[WriteST]>;
3079
3080   def : InstAlias<asm # "\t$Rt, [$Rn]",
3081                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3082 }
3083
3084 //---
3085 // Load/store pre-indexed
3086 //---
3087
3088 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3089                           string asm, string cstr, list<dag> pat>
3090     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3091   bits<5> Rt;
3092   bits<5> Rn;
3093   bits<9> offset;
3094   let Inst{31-30} = sz;
3095   let Inst{29-27} = 0b111;
3096   let Inst{26}    = V;
3097   let Inst{25-24} = 0;
3098   let Inst{23-22} = opc;
3099   let Inst{21}    = 0;
3100   let Inst{20-12} = offset;
3101   let Inst{11-10} = 0b11;
3102   let Inst{9-5}   = Rn;
3103   let Inst{4-0}   = Rt;
3104
3105   let DecoderMethod = "DecodeSignedLdStInstruction";
3106 }
3107
3108 let hasSideEffects = 0 in {
3109 let mayStore = 0, mayLoad = 1 in
3110 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3111              string asm>
3112     : BaseLoadStorePreIdx<sz, V, opc,
3113                      (outs GPR64sp:$wback, regtype:$Rt),
3114                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3115                      "$Rn = $wback,@earlyclobber $wback", []>,
3116       Sched<[WriteLD, WriteAdr]>;
3117
3118 let mayStore = 1, mayLoad = 0 in
3119 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3120                   string asm, SDPatternOperator storeop, ValueType Ty>
3121     : BaseLoadStorePreIdx<sz, V, opc,
3122                       (outs GPR64sp:$wback),
3123                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3124                       asm, "$Rn = $wback,@earlyclobber $wback",
3125       [(set GPR64sp:$wback,
3126             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3127       Sched<[WriteAdr, WriteST]>;
3128 } // hasSideEffects = 0
3129
3130 //---
3131 // Load/store post-indexed
3132 //---
3133
3134 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3135                           string asm, string cstr, list<dag> pat>
3136     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3137   bits<5> Rt;
3138   bits<5> Rn;
3139   bits<9> offset;
3140   let Inst{31-30} = sz;
3141   let Inst{29-27} = 0b111;
3142   let Inst{26}    = V;
3143   let Inst{25-24} = 0b00;
3144   let Inst{23-22} = opc;
3145   let Inst{21}    = 0b0;
3146   let Inst{20-12} = offset;
3147   let Inst{11-10} = 0b01;
3148   let Inst{9-5}   = Rn;
3149   let Inst{4-0}   = Rt;
3150
3151   let DecoderMethod = "DecodeSignedLdStInstruction";
3152 }
3153
3154 let hasSideEffects = 0 in {
3155 let mayStore = 0, mayLoad = 1 in
3156 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3157              string asm>
3158     : BaseLoadStorePostIdx<sz, V, opc,
3159                       (outs GPR64sp:$wback, regtype:$Rt),
3160                       (ins GPR64sp:$Rn, simm9:$offset),
3161                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3162       Sched<[WriteLD, WriteI]>;
3163
3164 let mayStore = 1, mayLoad = 0 in
3165 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3166                    string asm, SDPatternOperator storeop, ValueType Ty>
3167     : BaseLoadStorePostIdx<sz, V, opc,
3168                       (outs GPR64sp:$wback),
3169                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3170                        asm, "$Rn = $wback,@earlyclobber $wback",
3171       [(set GPR64sp:$wback,
3172             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3173     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3174 } // hasSideEffects = 0
3175
3176
3177 //---
3178 // Load/store pair
3179 //---
3180
3181 // (indexed, offset)
3182
3183 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3184                               string asm>
3185     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3186   bits<5> Rt;
3187   bits<5> Rt2;
3188   bits<5> Rn;
3189   bits<7> offset;
3190   let Inst{31-30} = opc;
3191   let Inst{29-27} = 0b101;
3192   let Inst{26}    = V;
3193   let Inst{25-23} = 0b010;
3194   let Inst{22}    = L;
3195   let Inst{21-15} = offset;
3196   let Inst{14-10} = Rt2;
3197   let Inst{9-5}   = Rn;
3198   let Inst{4-0}   = Rt;
3199
3200   let DecoderMethod = "DecodePairLdStInstruction";
3201 }
3202
3203 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3204                           Operand indextype, string asm> {
3205   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3206   def i : BaseLoadStorePairOffset<opc, V, 1,
3207                                   (outs regtype:$Rt, regtype:$Rt2),
3208                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3209           Sched<[WriteLD, WriteLDHi]>;
3210
3211   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3212                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3213                                                   GPR64sp:$Rn, 0)>;
3214 }
3215
3216
3217 multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3218                            Operand indextype, string asm> {
3219   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3220   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3221                                   (ins regtype:$Rt, regtype:$Rt2,
3222                                        GPR64sp:$Rn, indextype:$offset),
3223                                   asm>,
3224           Sched<[WriteSTP]>;
3225
3226   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3227                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3228                                                   GPR64sp:$Rn, 0)>;
3229 }
3230
3231 // (pre-indexed)
3232 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3233                               string asm>
3234     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3235   bits<5> Rt;
3236   bits<5> Rt2;
3237   bits<5> Rn;
3238   bits<7> offset;
3239   let Inst{31-30} = opc;
3240   let Inst{29-27} = 0b101;
3241   let Inst{26}    = V;
3242   let Inst{25-23} = 0b011;
3243   let Inst{22}    = L;
3244   let Inst{21-15} = offset;
3245   let Inst{14-10} = Rt2;
3246   let Inst{9-5}   = Rn;
3247   let Inst{4-0}   = Rt;
3248
3249   let DecoderMethod = "DecodePairLdStInstruction";
3250 }
3251
3252 let hasSideEffects = 0 in {
3253 let mayStore = 0, mayLoad = 1 in
3254 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3255                      Operand indextype, string asm>
3256     : BaseLoadStorePairPreIdx<opc, V, 1,
3257                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3258                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3259       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3260
3261 let mayStore = 1, mayLoad = 0 in
3262 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3263                       Operand indextype, string asm>
3264     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3265                              (ins regtype:$Rt, regtype:$Rt2,
3266                                   GPR64sp:$Rn, indextype:$offset),
3267                              asm>,
3268       Sched<[WriteAdr, WriteSTP]>;
3269 } // hasSideEffects = 0
3270
3271 // (post-indexed)
3272
3273 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3274                               string asm>
3275     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3276   bits<5> Rt;
3277   bits<5> Rt2;
3278   bits<5> Rn;
3279   bits<7> offset;
3280   let Inst{31-30} = opc;
3281   let Inst{29-27} = 0b101;
3282   let Inst{26}    = V;
3283   let Inst{25-23} = 0b001;
3284   let Inst{22}    = L;
3285   let Inst{21-15} = offset;
3286   let Inst{14-10} = Rt2;
3287   let Inst{9-5}   = Rn;
3288   let Inst{4-0}   = Rt;
3289
3290   let DecoderMethod = "DecodePairLdStInstruction";
3291 }
3292
3293 let hasSideEffects = 0 in {
3294 let mayStore = 0, mayLoad = 1 in
3295 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3296                       Operand idxtype, string asm>
3297     : BaseLoadStorePairPostIdx<opc, V, 1,
3298                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3299                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3300       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3301
3302 let mayStore = 1, mayLoad = 0 in
3303 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3304                        Operand idxtype, string asm>
3305     : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3306                              (ins regtype:$Rt, regtype:$Rt2,
3307                                   GPR64sp:$Rn, idxtype:$offset),
3308                              asm>,
3309       Sched<[WriteAdr, WriteSTP]>;
3310 } // hasSideEffects = 0
3311
3312 //  (no-allocate)
3313
3314 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3315                               string asm>
3316     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3317   bits<5> Rt;
3318   bits<5> Rt2;
3319   bits<5> Rn;
3320   bits<7> offset;
3321   let Inst{31-30} = opc;
3322   let Inst{29-27} = 0b101;
3323   let Inst{26}    = V;
3324   let Inst{25-23} = 0b000;
3325   let Inst{22}    = L;
3326   let Inst{21-15} = offset;
3327   let Inst{14-10} = Rt2;
3328   let Inst{9-5}   = Rn;
3329   let Inst{4-0}   = Rt;
3330
3331   let DecoderMethod = "DecodePairLdStInstruction";
3332 }
3333
3334 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3335                            Operand indextype, string asm> {
3336   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3337   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3338                                    (outs regtype:$Rt, regtype:$Rt2),
3339                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3340           Sched<[WriteLD, WriteLDHi]>;
3341
3342
3343   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3344                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3345                                                   GPR64sp:$Rn, 0)>;
3346 }
3347
3348 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3349                       Operand indextype, string asm> {
3350   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3351   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3352                                    (ins regtype:$Rt, regtype:$Rt2,
3353                                         GPR64sp:$Rn, indextype:$offset),
3354                                    asm>,
3355           Sched<[WriteSTP]>;
3356
3357   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3358                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3359                                                   GPR64sp:$Rn, 0)>;
3360 }
3361
3362 //---
3363 // Load/store exclusive
3364 //---
3365
3366 // True exclusive operations write to and/or read from the system's exclusive
3367 // monitors, which as far as a compiler is concerned can be modelled as a
3368 // random shared memory address. Hence LoadExclusive mayStore.
3369 //
3370 // Since these instructions have the undefined register bits set to 1 in
3371 // their canonical form, we need a post encoder method to set those bits
3372 // to 1 when encoding these instructions. We do this using the
3373 // fixLoadStoreExclusive function. This function has template parameters:
3374 //
3375 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3376 //
3377 // hasRs indicates that the instruction uses the Rs field, so we won't set
3378 // it to 1 (and the same for Rt2). We don't need template parameters for
3379 // the other register fields since Rt and Rn are always used.
3380 //
3381 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3382 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3383                              dag oops, dag iops, string asm, string operands>
3384     : I<oops, iops, asm, operands, "", []> {
3385   let Inst{31-30} = sz;
3386   let Inst{29-24} = 0b001000;
3387   let Inst{23}    = o2;
3388   let Inst{22}    = L;
3389   let Inst{21}    = o1;
3390   let Inst{15}    = o0;
3391
3392   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3393 }
3394
3395 // Neither Rs nor Rt2 operands.
3396 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3397                                dag oops, dag iops, string asm, string operands>
3398     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3399   bits<5> Rt;
3400   bits<5> Rn;
3401   let Inst{20-16} = 0b11111;
3402   let Unpredictable{20-16} = 0b11111;
3403   let Inst{14-10} = 0b11111;
3404   let Unpredictable{14-10} = 0b11111;
3405   let Inst{9-5} = Rn;
3406   let Inst{4-0} = Rt;
3407
3408   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3409 }
3410
3411 // Simple load acquires don't set the exclusive monitor
3412 let mayLoad = 1, mayStore = 0 in
3413 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3414                   RegisterClass regtype, string asm>
3415     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3416                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3417       Sched<[WriteLD]>;
3418
3419 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3420                     RegisterClass regtype, string asm>
3421     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3422                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3423       Sched<[WriteLD]>;
3424
3425 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3426                        RegisterClass regtype, string asm>
3427     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3428                              (outs regtype:$Rt, regtype:$Rt2),
3429                              (ins GPR64sp0:$Rn), asm,
3430                              "\t$Rt, $Rt2, [$Rn]">,
3431       Sched<[WriteLD, WriteLDHi]> {
3432   bits<5> Rt;
3433   bits<5> Rt2;
3434   bits<5> Rn;
3435   let Inst{14-10} = Rt2;
3436   let Inst{9-5} = Rn;
3437   let Inst{4-0} = Rt;
3438
3439   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3440 }
3441
3442 // Simple store release operations do not check the exclusive monitor.
3443 let mayLoad = 0, mayStore = 1 in
3444 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3445                    RegisterClass regtype, string asm>
3446     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3447                                (ins regtype:$Rt, GPR64sp0:$Rn),
3448                                asm, "\t$Rt, [$Rn]">,
3449       Sched<[WriteST]>;
3450
3451 let mayLoad = 1, mayStore = 1 in
3452 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3453                      RegisterClass regtype, string asm>
3454     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3455                              (ins regtype:$Rt, GPR64sp0:$Rn),
3456                              asm, "\t$Ws, $Rt, [$Rn]">,
3457       Sched<[WriteSTX]> {
3458   bits<5> Ws;
3459   bits<5> Rt;
3460   bits<5> Rn;
3461   let Inst{20-16} = Ws;
3462   let Inst{9-5} = Rn;
3463   let Inst{4-0} = Rt;
3464
3465   let Constraints = "@earlyclobber $Ws";
3466   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3467 }
3468
3469 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3470                          RegisterClass regtype, string asm>
3471     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3472                              (outs GPR32:$Ws),
3473                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3474                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3475       Sched<[WriteSTX]> {
3476   bits<5> Ws;
3477   bits<5> Rt;
3478   bits<5> Rt2;
3479   bits<5> Rn;
3480   let Inst{20-16} = Ws;
3481   let Inst{14-10} = Rt2;
3482   let Inst{9-5} = Rn;
3483   let Inst{4-0} = Rt;
3484
3485   let Constraints = "@earlyclobber $Ws";
3486 }
3487
3488 //---
3489 // Exception generation
3490 //---
3491
3492 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3493 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3494     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3495       Sched<[WriteSys]> {
3496   bits<16> imm;
3497   let Inst{31-24} = 0b11010100;
3498   let Inst{23-21} = op1;
3499   let Inst{20-5}  = imm;
3500   let Inst{4-2}   = 0b000;
3501   let Inst{1-0}   = ll;
3502 }
3503
3504 let Predicates = [HasFPARMv8] in {
3505
3506 //---
3507 // Floating point to integer conversion
3508 //---
3509
3510 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3511                       RegisterClass srcType, RegisterClass dstType,
3512                       string asm, list<dag> pattern>
3513     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3514          asm, "\t$Rd, $Rn", "", pattern>,
3515       Sched<[WriteFCvt]> {
3516   bits<5> Rd;
3517   bits<5> Rn;
3518   let Inst{30-29} = 0b00;
3519   let Inst{28-24} = 0b11110;
3520   let Inst{23-22} = type;
3521   let Inst{21}    = 1;
3522   let Inst{20-19} = rmode;
3523   let Inst{18-16} = opcode;
3524   let Inst{15-10} = 0;
3525   let Inst{9-5}   = Rn;
3526   let Inst{4-0}   = Rd;
3527 }
3528
3529 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3530 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3531                       RegisterClass srcType, RegisterClass dstType,
3532                       Operand immType, string asm, list<dag> pattern>
3533     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3534          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3535       Sched<[WriteFCvt]> {
3536   bits<5> Rd;
3537   bits<5> Rn;
3538   bits<6> scale;
3539   let Inst{30-29} = 0b00;
3540   let Inst{28-24} = 0b11110;
3541   let Inst{23-22} = type;
3542   let Inst{21}    = 0;
3543   let Inst{20-19} = rmode;
3544   let Inst{18-16} = opcode;
3545   let Inst{15-10} = scale;
3546   let Inst{9-5}   = Rn;
3547   let Inst{4-0}   = Rd;
3548 }
3549
3550 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3551            SDPatternOperator OpN> {
3552   // Unscaled half-precision to 32-bit
3553   def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
3554                                      [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
3555     let Inst{31} = 0; // 32-bit GPR flag
3556     let Predicates = [HasFullFP16];
3557   }
3558
3559   // Unscaled half-precision to 64-bit
3560   def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
3561                                      [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
3562     let Inst{31} = 1; // 64-bit GPR flag
3563     let Predicates = [HasFullFP16];
3564   }
3565
3566   // Unscaled single-precision to 32-bit
3567   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3568                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3569     let Inst{31} = 0; // 32-bit GPR flag
3570   }
3571
3572   // Unscaled single-precision to 64-bit
3573   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3574                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3575     let Inst{31} = 1; // 64-bit GPR flag
3576   }
3577
3578   // Unscaled double-precision to 32-bit
3579   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3580                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3581     let Inst{31} = 0; // 32-bit GPR flag
3582   }
3583
3584   // Unscaled double-precision to 64-bit
3585   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3586                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3587     let Inst{31} = 1; // 64-bit GPR flag
3588   }
3589 }
3590
3591 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3592                              SDPatternOperator OpN> {
3593   // Scaled half-precision to 32-bit
3594   def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
3595                               fixedpoint_f16_i32, asm,
3596               [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
3597                                           fixedpoint_f16_i32:$scale)))]> {
3598     let Inst{31} = 0; // 32-bit GPR flag
3599     let scale{5} = 1;
3600     let Predicates = [HasFullFP16];
3601   }
3602
3603   // Scaled half-precision to 64-bit
3604   def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
3605                               fixedpoint_f16_i64, asm,
3606               [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
3607                                           fixedpoint_f16_i64:$scale)))]> {
3608     let Inst{31} = 1; // 64-bit GPR flag
3609     let Predicates = [HasFullFP16];
3610   }
3611
3612   // Scaled single-precision to 32-bit
3613   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3614                               fixedpoint_f32_i32, asm,
3615               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3616                                           fixedpoint_f32_i32:$scale)))]> {
3617     let Inst{31} = 0; // 32-bit GPR flag
3618     let scale{5} = 1;
3619   }
3620
3621   // Scaled single-precision to 64-bit
3622   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3623                               fixedpoint_f32_i64, asm,
3624               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3625                                           fixedpoint_f32_i64:$scale)))]> {
3626     let Inst{31} = 1; // 64-bit GPR flag
3627   }
3628
3629   // Scaled double-precision to 32-bit
3630   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3631                               fixedpoint_f64_i32, asm,
3632               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3633                                           fixedpoint_f64_i32:$scale)))]> {
3634     let Inst{31} = 0; // 32-bit GPR flag
3635     let scale{5} = 1;
3636   }
3637
3638   // Scaled double-precision to 64-bit
3639   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3640                               fixedpoint_f64_i64, asm,
3641               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3642                                           fixedpoint_f64_i64:$scale)))]> {
3643     let Inst{31} = 1; // 64-bit GPR flag
3644   }
3645 }
3646
3647 //---
3648 // Integer to floating point conversion
3649 //---
3650
3651 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3652 class BaseIntegerToFP<bit isUnsigned,
3653                       RegisterClass srcType, RegisterClass dstType,
3654                       Operand immType, string asm, list<dag> pattern>
3655     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3656          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3657       Sched<[WriteFCvt]> {
3658   bits<5> Rd;
3659   bits<5> Rn;
3660   bits<6> scale;
3661   let Inst{30-24} = 0b0011110;
3662   let Inst{21-17} = 0b00001;
3663   let Inst{16}    = isUnsigned;
3664   let Inst{15-10} = scale;
3665   let Inst{9-5}   = Rn;
3666   let Inst{4-0}   = Rd;
3667 }
3668
3669 class BaseIntegerToFPUnscaled<bit isUnsigned,
3670                       RegisterClass srcType, RegisterClass dstType,
3671                       ValueType dvt, string asm, SDNode node>
3672     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3673          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3674       Sched<[WriteFCvt]> {
3675   bits<5> Rd;
3676   bits<5> Rn;
3677   bits<6> scale;
3678   let Inst{30-24} = 0b0011110;
3679   let Inst{21-17} = 0b10001;
3680   let Inst{16}    = isUnsigned;
3681   let Inst{15-10} = 0b000000;
3682   let Inst{9-5}   = Rn;
3683   let Inst{4-0}   = Rd;
3684 }
3685
3686 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3687   // Unscaled
3688   def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
3689     let Inst{31} = 0; // 32-bit GPR flag
3690     let Inst{23-22} = 0b11; // 16-bit FPR flag
3691     let Predicates = [HasFullFP16];
3692   }
3693
3694   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3695     let Inst{31} = 0; // 32-bit GPR flag
3696     let Inst{23-22} = 0b00; // 32-bit FPR flag
3697   }
3698
3699   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3700     let Inst{31} = 0; // 32-bit GPR flag
3701     let Inst{23-22} = 0b01; // 64-bit FPR flag
3702   }
3703
3704   def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
3705     let Inst{31} = 1; // 64-bit GPR flag
3706     let Inst{23-22} = 0b11; // 16-bit FPR flag
3707     let Predicates = [HasFullFP16];
3708   }
3709
3710   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3711     let Inst{31} = 1; // 64-bit GPR flag
3712     let Inst{23-22} = 0b00; // 32-bit FPR flag
3713   }
3714
3715   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3716     let Inst{31} = 1; // 64-bit GPR flag
3717     let Inst{23-22} = 0b01; // 64-bit FPR flag
3718   }
3719
3720   // Scaled
3721   def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
3722                              [(set FPR16:$Rd,
3723                                    (fdiv (node GPR32:$Rn),
3724                                          fixedpoint_f16_i32:$scale))]> {
3725     let Inst{31} = 0; // 32-bit GPR flag
3726     let Inst{23-22} = 0b11; // 16-bit FPR flag
3727     let scale{5} = 1;
3728     let Predicates = [HasFullFP16];
3729   }
3730
3731   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3732                              [(set FPR32:$Rd,
3733                                    (fdiv (node GPR32:$Rn),
3734                                          fixedpoint_f32_i32:$scale))]> {
3735     let Inst{31} = 0; // 32-bit GPR flag
3736     let Inst{23-22} = 0b00; // 32-bit FPR flag
3737     let scale{5} = 1;
3738   }
3739
3740   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3741                              [(set FPR64:$Rd,
3742                                    (fdiv (node GPR32:$Rn),
3743                                          fixedpoint_f64_i32:$scale))]> {
3744     let Inst{31} = 0; // 32-bit GPR flag
3745     let Inst{23-22} = 0b01; // 64-bit FPR flag
3746     let scale{5} = 1;
3747   }
3748
3749   def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
3750                              [(set FPR16:$Rd,
3751                                    (fdiv (node GPR64:$Rn),
3752                                          fixedpoint_f16_i64:$scale))]> {
3753     let Inst{31} = 1; // 64-bit GPR flag
3754     let Inst{23-22} = 0b11; // 16-bit FPR flag
3755     let Predicates = [HasFullFP16];
3756   }
3757
3758   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3759                              [(set FPR32:$Rd,
3760                                    (fdiv (node GPR64:$Rn),
3761                                          fixedpoint_f32_i64:$scale))]> {
3762     let Inst{31} = 1; // 64-bit GPR flag
3763     let Inst{23-22} = 0b00; // 32-bit FPR flag
3764   }
3765
3766   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3767                              [(set FPR64:$Rd,
3768                                    (fdiv (node GPR64:$Rn),
3769                                          fixedpoint_f64_i64:$scale))]> {
3770     let Inst{31} = 1; // 64-bit GPR flag
3771     let Inst{23-22} = 0b01; // 64-bit FPR flag
3772   }
3773 }
3774
3775 //---
3776 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3777 //---
3778
3779 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3780 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3781                       RegisterClass srcType, RegisterClass dstType,
3782                       string asm>
3783     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3784         // We use COPY_TO_REGCLASS for these bitconvert operations.
3785         // copyPhysReg() expands the resultant COPY instructions after
3786         // regalloc is done. This gives greater freedom for the allocator
3787         // and related passes (coalescing, copy propagation, et. al.) to
3788         // be more effective.
3789         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3790       Sched<[WriteFCopy]> {
3791   bits<5> Rd;
3792   bits<5> Rn;
3793   let Inst{30-24} = 0b0011110;
3794   let Inst{21}    = 1;
3795   let Inst{20-19} = rmode;
3796   let Inst{18-16} = opcode;
3797   let Inst{15-10} = 0b000000;
3798   let Inst{9-5}   = Rn;
3799   let Inst{4-0}   = Rd;
3800 }
3801
3802 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3803 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3804                      RegisterClass srcType, RegisterOperand dstType, string asm,
3805                      string kind>
3806     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3807         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3808       Sched<[WriteFCopy]> {
3809   bits<5> Rd;
3810   bits<5> Rn;
3811   let Inst{30-23} = 0b00111101;
3812   let Inst{21}    = 1;
3813   let Inst{20-19} = rmode;
3814   let Inst{18-16} = opcode;
3815   let Inst{15-10} = 0b000000;
3816   let Inst{9-5}   = Rn;
3817   let Inst{4-0}   = Rd;
3818
3819   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3820 }
3821
3822 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3823 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3824                      RegisterOperand srcType, RegisterClass dstType, string asm,
3825                      string kind>
3826     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3827         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3828       Sched<[WriteFCopy]> {
3829   bits<5> Rd;
3830   bits<5> Rn;
3831   let Inst{30-23} = 0b00111101;
3832   let Inst{21}    = 1;
3833   let Inst{20-19} = rmode;
3834   let Inst{18-16} = opcode;
3835   let Inst{15-10} = 0b000000;
3836   let Inst{9-5}   = Rn;
3837   let Inst{4-0}   = Rd;
3838
3839   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3840 }
3841
3842
3843 multiclass UnscaledConversion<string asm> {
3844   def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
3845     let Inst{31} = 0; // 32-bit GPR flag
3846     let Inst{23-22} = 0b11; // 16-bit FPR flag
3847     let Predicates = [HasFullFP16];
3848   }
3849
3850   def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
3851     let Inst{31} = 1; // 64-bit GPR flag
3852     let Inst{23-22} = 0b11; // 16-bit FPR flag
3853     let Predicates = [HasFullFP16];
3854   }
3855
3856   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3857     let Inst{31} = 0; // 32-bit GPR flag
3858     let Inst{23-22} = 0b00; // 32-bit FPR flag
3859   }
3860
3861   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3862     let Inst{31} = 1; // 64-bit GPR flag
3863     let Inst{23-22} = 0b01; // 64-bit FPR flag
3864   }
3865
3866   def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
3867     let Inst{31} = 0; // 32-bit GPR flag
3868     let Inst{23-22} = 0b11; // 16-bit FPR flag
3869     let Predicates = [HasFullFP16];
3870   }
3871
3872   def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
3873     let Inst{31} = 1; // 64-bit GPR flag
3874     let Inst{23-22} = 0b11; // 16-bit FPR flag
3875     let Predicates = [HasFullFP16];
3876   }
3877
3878   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3879     let Inst{31} = 0; // 32-bit GPR flag
3880     let Inst{23-22} = 0b00; // 32-bit FPR flag
3881   }
3882
3883   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3884     let Inst{31} = 1; // 64-bit GPR flag
3885     let Inst{23-22} = 0b01; // 64-bit FPR flag
3886   }
3887
3888   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3889                                              asm, ".d"> {
3890     let Inst{31} = 1;
3891     let Inst{22} = 0;
3892   }
3893
3894   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3895                                                asm, ".d"> {
3896     let Inst{31} = 1;
3897     let Inst{22} = 0;
3898   }
3899 }
3900
3901 //---
3902 // Floating point conversion
3903 //---
3904
3905 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3906                        RegisterClass srcType, string asm, list<dag> pattern>
3907     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3908       Sched<[WriteFCvt]> {
3909   bits<5> Rd;
3910   bits<5> Rn;
3911   let Inst{31-24} = 0b00011110;
3912   let Inst{23-22} = type;
3913   let Inst{21-17} = 0b10001;
3914   let Inst{16-15} = opcode;
3915   let Inst{14-10} = 0b10000;
3916   let Inst{9-5}   = Rn;
3917   let Inst{4-0}   = Rd;
3918 }
3919
3920 multiclass FPConversion<string asm> {
3921   // Double-precision to Half-precision
3922   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3923                              [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3924
3925   // Double-precision to Single-precision
3926   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3927                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3928
3929   // Half-precision to Double-precision
3930   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3931                              [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3932
3933   // Half-precision to Single-precision
3934   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3935                              [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3936
3937   // Single-precision to Double-precision
3938   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3939                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3940
3941   // Single-precision to Half-precision
3942   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3943                              [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3944 }
3945
3946 //---
3947 // Single operand floating point data processing
3948 //---
3949
3950 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3951 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3952                               ValueType vt, string asm, SDPatternOperator node>
3953     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3954          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3955       Sched<[WriteF]> {
3956   bits<5> Rd;
3957   bits<5> Rn;
3958   let Inst{31-24} = 0b00011110;
3959   let Inst{21-19} = 0b100;
3960   let Inst{18-15} = opcode;
3961   let Inst{14-10} = 0b10000;
3962   let Inst{9-5}   = Rn;
3963   let Inst{4-0}   = Rd;
3964 }
3965
3966 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3967                                SDPatternOperator node = null_frag> {
3968   def Hr : BaseSingleOperandFPData<opcode, FPR16, f16, asm, node> {
3969     let Inst{23-22} = 0b11; // 16-bit size flag
3970     let Predicates = [HasFullFP16];
3971   }
3972
3973   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3974     let Inst{23-22} = 0b00; // 32-bit size flag
3975   }
3976
3977   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3978     let Inst{23-22} = 0b01; // 64-bit size flag
3979   }
3980 }
3981
3982 //---
3983 // Two operand floating point data processing
3984 //---
3985
3986 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3987 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3988                            string asm, list<dag> pat>
3989     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3990          asm, "\t$Rd, $Rn, $Rm", "", pat>,
3991       Sched<[WriteF]> {
3992   bits<5> Rd;
3993   bits<5> Rn;
3994   bits<5> Rm;
3995   let Inst{31-24} = 0b00011110;
3996   let Inst{21}    = 1;
3997   let Inst{20-16} = Rm;
3998   let Inst{15-12} = opcode;
3999   let Inst{11-10} = 0b10;
4000   let Inst{9-5}   = Rn;
4001   let Inst{4-0}   = Rd;
4002 }
4003
4004 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4005                             SDPatternOperator node = null_frag> {
4006   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4007                          [(set (f16 FPR16:$Rd),
4008                                (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4009     let Inst{23-22} = 0b11; // 16-bit size flag
4010     let Predicates = [HasFullFP16];
4011   }
4012
4013   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4014                          [(set (f32 FPR32:$Rd),
4015                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4016     let Inst{23-22} = 0b00; // 32-bit size flag
4017   }
4018
4019   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4020                          [(set (f64 FPR64:$Rd),
4021                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4022     let Inst{23-22} = 0b01; // 64-bit size flag
4023   }
4024 }
4025
4026 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4027   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4028                   [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4029     let Inst{23-22} = 0b11; // 16-bit size flag
4030     let Predicates = [HasFullFP16];
4031   }
4032
4033   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4034                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4035     let Inst{23-22} = 0b00; // 32-bit size flag
4036   }
4037
4038   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4039                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4040     let Inst{23-22} = 0b01; // 64-bit size flag
4041   }
4042 }
4043
4044
4045 //---
4046 // Three operand floating point data processing
4047 //---
4048
4049 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4050                              RegisterClass regtype, string asm, list<dag> pat>
4051     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4052          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4053       Sched<[WriteFMul]> {
4054   bits<5> Rd;
4055   bits<5> Rn;
4056   bits<5> Rm;
4057   bits<5> Ra;
4058   let Inst{31-24} = 0b00011111;
4059   let Inst{21}    = isNegated;
4060   let Inst{20-16} = Rm;
4061   let Inst{15}    = isSub;
4062   let Inst{14-10} = Ra;
4063   let Inst{9-5}   = Rn;
4064   let Inst{4-0}   = Rd;
4065 }
4066
4067 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4068                               SDPatternOperator node> {
4069   def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4070             [(set FPR16:$Rd,
4071                   (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4072     let Inst{23-22} = 0b11; // 16-bit size flag
4073     let Predicates = [HasFullFP16];
4074   }
4075
4076   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4077             [(set FPR32:$Rd,
4078                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4079     let Inst{23-22} = 0b00; // 32-bit size flag
4080   }
4081
4082   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4083             [(set FPR64:$Rd,
4084                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4085     let Inst{23-22} = 0b01; // 64-bit size flag
4086   }
4087 }
4088
4089 //---
4090 // Floating point data comparisons
4091 //---
4092
4093 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4094 class BaseOneOperandFPComparison<bit signalAllNans,
4095                                  RegisterClass regtype, string asm,
4096                                  list<dag> pat>
4097     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4098       Sched<[WriteFCmp]> {
4099   bits<5> Rn;
4100   let Inst{31-24} = 0b00011110;
4101   let Inst{21}    = 1;
4102
4103   let Inst{15-10} = 0b001000;
4104   let Inst{9-5}   = Rn;
4105   let Inst{4}     = signalAllNans;
4106   let Inst{3-0}   = 0b1000;
4107
4108   // Rm should be 0b00000 canonically, but we need to accept any value.
4109   let PostEncoderMethod = "fixOneOperandFPComparison";
4110 }
4111
4112 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4113 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4114                                 string asm, list<dag> pat>
4115     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4116       Sched<[WriteFCmp]> {
4117   bits<5> Rm;
4118   bits<5> Rn;
4119   let Inst{31-24} = 0b00011110;
4120   let Inst{21}    = 1;
4121   let Inst{20-16} = Rm;
4122   let Inst{15-10} = 0b001000;
4123   let Inst{9-5}   = Rn;
4124   let Inst{4}     = signalAllNans;
4125   let Inst{3-0}   = 0b0000;
4126 }
4127
4128 multiclass FPComparison<bit signalAllNans, string asm,
4129                         SDPatternOperator OpNode = null_frag> {
4130   let Defs = [NZCV] in {
4131   def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4132       [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4133     let Inst{23-22} = 0b11;
4134     let Predicates = [HasFullFP16];
4135   }
4136
4137   def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4138       [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4139     let Inst{23-22} = 0b11;
4140     let Predicates = [HasFullFP16];
4141   }
4142
4143   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4144       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4145     let Inst{23-22} = 0b00;
4146   }
4147
4148   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4149       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4150     let Inst{23-22} = 0b00;
4151   }
4152
4153   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4154       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4155     let Inst{23-22} = 0b01;
4156   }
4157
4158   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4159       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4160     let Inst{23-22} = 0b01;
4161   }
4162   } // Defs = [NZCV]
4163 }
4164
4165 //---
4166 // Floating point conditional comparisons
4167 //---
4168
4169 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4170 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4171                            string mnemonic, list<dag> pat>
4172     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4173          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4174       Sched<[WriteFCmp]> {
4175   let Uses = [NZCV];
4176   let Defs = [NZCV];
4177
4178   bits<5> Rn;
4179   bits<5> Rm;
4180   bits<4> nzcv;
4181   bits<4> cond;
4182
4183   let Inst{31-24} = 0b00011110;
4184   let Inst{21}    = 1;
4185   let Inst{20-16} = Rm;
4186   let Inst{15-12} = cond;
4187   let Inst{11-10} = 0b01;
4188   let Inst{9-5}   = Rn;
4189   let Inst{4}     = signalAllNans;
4190   let Inst{3-0}   = nzcv;
4191 }
4192
4193 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4194                             SDPatternOperator OpNode = null_frag> {
4195   def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic, []> {
4196     let Inst{23-22} = 0b11;
4197     let Predicates = [HasFullFP16];
4198   }
4199
4200   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4201       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4202                           (i32 imm:$cond), NZCV))]> {
4203     let Inst{23-22} = 0b00;
4204   }
4205
4206   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4207       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4208                           (i32 imm:$cond), NZCV))]> {
4209     let Inst{23-22} = 0b01;
4210   }
4211 }
4212
4213 //---
4214 // Floating point conditional select
4215 //---
4216
4217 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4218     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4219          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4220          [(set regtype:$Rd,
4221                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4222                           (i32 imm:$cond), NZCV))]>,
4223       Sched<[WriteF]> {
4224   bits<5> Rd;
4225   bits<5> Rn;
4226   bits<5> Rm;
4227   bits<4> cond;
4228
4229   let Inst{31-24} = 0b00011110;
4230   let Inst{21}    = 1;
4231   let Inst{20-16} = Rm;
4232   let Inst{15-12} = cond;
4233   let Inst{11-10} = 0b11;
4234   let Inst{9-5}   = Rn;
4235   let Inst{4-0}   = Rd;
4236 }
4237
4238 multiclass FPCondSelect<string asm> {
4239   let Uses = [NZCV] in {
4240   def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4241     let Inst{23-22} = 0b11;
4242     let Predicates = [HasFullFP16];
4243   }
4244
4245   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4246     let Inst{23-22} = 0b00;
4247   }
4248
4249   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4250     let Inst{23-22} = 0b01;
4251   }
4252   } // Uses = [NZCV]
4253 }
4254
4255 //---
4256 // Floating move immediate
4257 //---
4258
4259 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4260   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4261       [(set regtype:$Rd, fpimmtype:$imm)]>,
4262     Sched<[WriteFImm]> {
4263   bits<5> Rd;
4264   bits<8> imm;
4265   let Inst{31-24} = 0b00011110;
4266   let Inst{21}    = 1;
4267   let Inst{20-13} = imm;
4268   let Inst{12-5}  = 0b10000000;
4269   let Inst{4-0}   = Rd;
4270 }
4271
4272 multiclass FPMoveImmediate<string asm> {
4273   def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4274     let Inst{23-22} = 0b11;
4275     let Predicates = [HasFullFP16];
4276   }
4277
4278   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4279     let Inst{23-22} = 0b00;
4280   }
4281
4282   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4283     let Inst{23-22} = 0b01;
4284   }
4285 }
4286 } // end of 'let Predicates = [HasFPARMv8]'
4287
4288 //----------------------------------------------------------------------------
4289 // AdvSIMD
4290 //----------------------------------------------------------------------------
4291
4292 let Predicates = [HasNEON] in {
4293
4294 //----------------------------------------------------------------------------
4295 // AdvSIMD three register vector instructions
4296 //----------------------------------------------------------------------------
4297
4298 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4299 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4300                         RegisterOperand regtype, string asm, string kind,
4301                         list<dag> pattern>
4302   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4303       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4304       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4305     Sched<[WriteV]> {
4306   bits<5> Rd;
4307   bits<5> Rn;
4308   bits<5> Rm;
4309   let Inst{31}    = 0;
4310   let Inst{30}    = Q;
4311   let Inst{29}    = U;
4312   let Inst{28-24} = 0b01110;
4313   let Inst{23-22} = size;
4314   let Inst{21}    = 1;
4315   let Inst{20-16} = Rm;
4316   let Inst{15-11} = opcode;
4317   let Inst{10}    = 1;
4318   let Inst{9-5}   = Rn;
4319   let Inst{4-0}   = Rd;
4320 }
4321
4322 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4323 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4324                         RegisterOperand regtype, string asm, string kind,
4325                         list<dag> pattern>
4326   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4327       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4328       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4329     Sched<[WriteV]> {
4330   bits<5> Rd;
4331   bits<5> Rn;
4332   bits<5> Rm;
4333   let Inst{31}    = 0;
4334   let Inst{30}    = Q;
4335   let Inst{29}    = U;
4336   let Inst{28-24} = 0b01110;
4337   let Inst{23-22} = size;
4338   let Inst{21}    = 1;
4339   let Inst{20-16} = Rm;
4340   let Inst{15-11} = opcode;
4341   let Inst{10}    = 1;
4342   let Inst{9-5}   = Rn;
4343   let Inst{4-0}   = Rd;
4344 }
4345
4346 // All operand sizes distinguished in the encoding.
4347 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4348                                SDPatternOperator OpNode> {
4349   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4350                                       asm, ".8b",
4351          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4352   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4353                                       asm, ".16b",
4354          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4355   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4356                                       asm, ".4h",
4357          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4358   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4359                                       asm, ".8h",
4360          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4361   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4362                                       asm, ".2s",
4363          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4364   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4365                                       asm, ".4s",
4366          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4367   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
4368                                       asm, ".2d",
4369          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4370 }
4371
4372 // As above, but D sized elements unsupported.
4373 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4374                                   SDPatternOperator OpNode> {
4375   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4376                                       asm, ".8b",
4377         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4378   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4379                                       asm, ".16b",
4380         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4381   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4382                                       asm, ".4h",
4383         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4384   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4385                                       asm, ".8h",
4386         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4387   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4388                                       asm, ".2s",
4389         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4390   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4391                                       asm, ".4s",
4392         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4393 }
4394
4395 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4396                                   SDPatternOperator OpNode> {
4397   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
4398                                       asm, ".8b",
4399       [(set (v8i8 V64:$dst),
4400             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4401   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
4402                                       asm, ".16b",
4403       [(set (v16i8 V128:$dst),
4404             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4405   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
4406                                       asm, ".4h",
4407       [(set (v4i16 V64:$dst),
4408             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4409   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
4410                                       asm, ".8h",
4411       [(set (v8i16 V128:$dst),
4412             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4413   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
4414                                       asm, ".2s",
4415       [(set (v2i32 V64:$dst),
4416             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4417   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
4418                                       asm, ".4s",
4419       [(set (v4i32 V128:$dst),
4420             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4421 }
4422
4423 // As above, but only B sized elements supported.
4424 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4425                                 SDPatternOperator OpNode> {
4426   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4427                                       asm, ".8b",
4428     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4429   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4430                                       asm, ".16b",
4431     [(set (v16i8 V128:$Rd),
4432           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4433 }
4434
4435 // As above, but only S and D sized floating point elements supported.
4436 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
4437                                  string asm, SDPatternOperator OpNode> {
4438   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4439                                       asm, ".2s",
4440         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4441   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4442                                       asm, ".4s",
4443         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4444   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4445                                       asm, ".2d",
4446         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4447 }
4448
4449 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
4450                                     string asm,
4451                                     SDPatternOperator OpNode> {
4452   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4453                                       asm, ".2s",
4454         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4455   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4456                                       asm, ".4s",
4457         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4458   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4459                                       asm, ".2d",
4460         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4461 }
4462
4463 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
4464                                  string asm, SDPatternOperator OpNode> {
4465   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
4466                                       asm, ".2s",
4467      [(set (v2f32 V64:$dst),
4468            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4469   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
4470                                       asm, ".4s",
4471      [(set (v4f32 V128:$dst),
4472            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4473   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
4474                                       asm, ".2d",
4475      [(set (v2f64 V128:$dst),
4476            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4477 }
4478
4479 // As above, but D and B sized elements unsupported.
4480 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4481                                 SDPatternOperator OpNode> {
4482   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4483                                       asm, ".4h",
4484         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4485   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4486                                       asm, ".8h",
4487         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4488   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4489                                       asm, ".2s",
4490         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4491   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4492                                       asm, ".4s",
4493         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4494 }
4495
4496 // Logical three vector ops share opcode bits, and only use B sized elements.
4497 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4498                                   SDPatternOperator OpNode = null_frag> {
4499   def v8i8  : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4500                                      asm, ".8b",
4501                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4502   def v16i8  : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4503                                      asm, ".16b",
4504                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4505
4506   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4507           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4508   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4509           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4510   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4511           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4512
4513   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4514       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4515   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4516       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4517   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4518       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4519 }
4520
4521 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4522                                   string asm, SDPatternOperator OpNode> {
4523   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4524                                      asm, ".8b",
4525              [(set (v8i8 V64:$dst),
4526                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4527   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4528                                      asm, ".16b",
4529              [(set (v16i8 V128:$dst),
4530                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4531                            (v16i8 V128:$Rm)))]>;
4532
4533   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4534                            (v4i16 V64:$RHS))),
4535           (!cast<Instruction>(NAME#"v8i8")
4536             V64:$LHS, V64:$MHS, V64:$RHS)>;
4537   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4538                            (v2i32 V64:$RHS))),
4539           (!cast<Instruction>(NAME#"v8i8")
4540             V64:$LHS, V64:$MHS, V64:$RHS)>;
4541   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4542                            (v1i64 V64:$RHS))),
4543           (!cast<Instruction>(NAME#"v8i8")
4544             V64:$LHS, V64:$MHS, V64:$RHS)>;
4545
4546   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4547                            (v8i16 V128:$RHS))),
4548       (!cast<Instruction>(NAME#"v16i8")
4549         V128:$LHS, V128:$MHS, V128:$RHS)>;
4550   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4551                            (v4i32 V128:$RHS))),
4552       (!cast<Instruction>(NAME#"v16i8")
4553         V128:$LHS, V128:$MHS, V128:$RHS)>;
4554   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4555                            (v2i64 V128:$RHS))),
4556       (!cast<Instruction>(NAME#"v16i8")
4557         V128:$LHS, V128:$MHS, V128:$RHS)>;
4558 }
4559
4560
4561 //----------------------------------------------------------------------------
4562 // AdvSIMD two register vector instructions.
4563 //----------------------------------------------------------------------------
4564
4565 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4566 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4567                         RegisterOperand regtype, string asm, string dstkind,
4568                         string srckind, list<dag> pattern>
4569   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4570       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4571       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4572     Sched<[WriteV]> {
4573   bits<5> Rd;
4574   bits<5> Rn;
4575   let Inst{31}    = 0;
4576   let Inst{30}    = Q;
4577   let Inst{29}    = U;
4578   let Inst{28-24} = 0b01110;
4579   let Inst{23-22} = size;
4580   let Inst{21-17} = 0b10000;
4581   let Inst{16-12} = opcode;
4582   let Inst{11-10} = 0b10;
4583   let Inst{9-5}   = Rn;
4584   let Inst{4-0}   = Rd;
4585 }
4586
4587 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4588 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4589                             RegisterOperand regtype, string asm, string dstkind,
4590                             string srckind, list<dag> pattern>
4591   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4592       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4593       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4594     Sched<[WriteV]> {
4595   bits<5> Rd;
4596   bits<5> Rn;
4597   let Inst{31}    = 0;
4598   let Inst{30}    = Q;
4599   let Inst{29}    = U;
4600   let Inst{28-24} = 0b01110;
4601   let Inst{23-22} = size;
4602   let Inst{21-17} = 0b10000;
4603   let Inst{16-12} = opcode;
4604   let Inst{11-10} = 0b10;
4605   let Inst{9-5}   = Rn;
4606   let Inst{4-0}   = Rd;
4607 }
4608
4609 // Supports B, H, and S element sizes.
4610 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4611                             SDPatternOperator OpNode> {
4612   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4613                                       asm, ".8b", ".8b",
4614                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4615   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4616                                       asm, ".16b", ".16b",
4617                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4618   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4619                                       asm, ".4h", ".4h",
4620                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4621   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4622                                       asm, ".8h", ".8h",
4623                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4624   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4625                                       asm, ".2s", ".2s",
4626                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4627   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4628                                       asm, ".4s", ".4s",
4629                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4630 }
4631
4632 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4633                             RegisterOperand regtype, string asm, string dstkind,
4634                             string srckind, string amount>
4635   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4636       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4637       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4638     Sched<[WriteV]> {
4639   bits<5> Rd;
4640   bits<5> Rn;
4641   let Inst{31}    = 0;
4642   let Inst{30}    = Q;
4643   let Inst{29-24} = 0b101110;
4644   let Inst{23-22} = size;
4645   let Inst{21-10} = 0b100001001110;
4646   let Inst{9-5}   = Rn;
4647   let Inst{4-0}   = Rd;
4648 }
4649
4650 multiclass SIMDVectorLShiftLongBySizeBHS {
4651   let hasSideEffects = 0 in {
4652   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4653                                              "shll", ".8h",  ".8b", "8">;
4654   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4655                                              "shll2", ".8h", ".16b", "8">;
4656   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4657                                              "shll", ".4s",  ".4h", "16">;
4658   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4659                                              "shll2", ".4s", ".8h", "16">;
4660   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4661                                              "shll", ".2d",  ".2s", "32">;
4662   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4663                                              "shll2", ".2d", ".4s", "32">;
4664   }
4665 }
4666
4667 // Supports all element sizes.
4668 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4669                              SDPatternOperator OpNode> {
4670   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4671                                       asm, ".4h", ".8b",
4672                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4673   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4674                                       asm, ".8h", ".16b",
4675                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4676   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4677                                       asm, ".2s", ".4h",
4678                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4679   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4680                                       asm, ".4s", ".8h",
4681                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4682   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4683                                       asm, ".1d", ".2s",
4684                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4685   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4686                                       asm, ".2d", ".4s",
4687                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4688 }
4689
4690 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4691                                  SDPatternOperator OpNode> {
4692   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4693                                           asm, ".4h", ".8b",
4694       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4695                                       (v8i8 V64:$Rn)))]>;
4696   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4697                                           asm, ".8h", ".16b",
4698       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4699                                       (v16i8 V128:$Rn)))]>;
4700   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4701                                           asm, ".2s", ".4h",
4702       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4703                                       (v4i16 V64:$Rn)))]>;
4704   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4705                                           asm, ".4s", ".8h",
4706       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4707                                       (v8i16 V128:$Rn)))]>;
4708   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4709                                           asm, ".1d", ".2s",
4710       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4711                                       (v2i32 V64:$Rn)))]>;
4712   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4713                                           asm, ".2d", ".4s",
4714       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4715                                       (v4i32 V128:$Rn)))]>;
4716 }
4717
4718 // Supports all element sizes, except 1xD.
4719 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4720                                   SDPatternOperator OpNode> {
4721   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4722                                     asm, ".8b", ".8b",
4723     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4724   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4725                                     asm, ".16b", ".16b",
4726     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4727   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4728                                     asm, ".4h", ".4h",
4729     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4730   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4731                                     asm, ".8h", ".8h",
4732     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4733   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4734                                     asm, ".2s", ".2s",
4735     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4736   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4737                                     asm, ".4s", ".4s",
4738     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4739   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4740                                     asm, ".2d", ".2d",
4741     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4742 }
4743
4744 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4745                              SDPatternOperator OpNode = null_frag> {
4746   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4747                                 asm, ".8b", ".8b",
4748     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4749   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4750                                 asm, ".16b", ".16b",
4751     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4752   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4753                                 asm, ".4h", ".4h",
4754     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4755   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4756                                 asm, ".8h", ".8h",
4757     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4758   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4759                                 asm, ".2s", ".2s",
4760     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4761   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4762                                 asm, ".4s", ".4s",
4763     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4764   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4765                                 asm, ".2d", ".2d",
4766     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4767 }
4768
4769
4770 // Supports only B element sizes.
4771 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4772                           SDPatternOperator OpNode> {
4773   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4774                                 asm, ".8b", ".8b",
4775                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4776   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4777                                 asm, ".16b", ".16b",
4778                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4779
4780 }
4781
4782 // Supports only B and H element sizes.
4783 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4784                                 SDPatternOperator OpNode> {
4785   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4786                                 asm, ".8b", ".8b",
4787                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4788   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4789                                 asm, ".16b", ".16b",
4790                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4791   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4792                                 asm, ".4h", ".4h",
4793                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4794   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4795                                 asm, ".8h", ".8h",
4796                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4797 }
4798
4799 // Supports only S and D element sizes, uses high bit of the size field
4800 // as an extra opcode bit.
4801 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4802                            SDPatternOperator OpNode> {
4803   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4804                                 asm, ".2s", ".2s",
4805                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4806   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4807                                 asm, ".4s", ".4s",
4808                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4809   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4810                                 asm, ".2d", ".2d",
4811                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4812 }
4813
4814 // Supports only S element size.
4815 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4816                            SDPatternOperator OpNode> {
4817   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4818                                 asm, ".2s", ".2s",
4819                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4820   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4821                                 asm, ".4s", ".4s",
4822                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4823 }
4824
4825
4826 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4827                            SDPatternOperator OpNode> {
4828   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4829                                 asm, ".2s", ".2s",
4830                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4831   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4832                                 asm, ".4s", ".4s",
4833                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4834   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4835                                 asm, ".2d", ".2d",
4836                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4837 }
4838
4839 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4840                            SDPatternOperator OpNode> {
4841   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4842                                 asm, ".2s", ".2s",
4843                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4844   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4845                                 asm, ".4s", ".4s",
4846                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4847   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4848                                 asm, ".2d", ".2d",
4849                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4850 }
4851
4852
4853 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4854                            RegisterOperand inreg, RegisterOperand outreg,
4855                            string asm, string outkind, string inkind,
4856                            list<dag> pattern>
4857   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4858       "{\t$Rd" # outkind # ", $Rn" # inkind #
4859       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4860     Sched<[WriteV]> {
4861   bits<5> Rd;
4862   bits<5> Rn;
4863   let Inst{31}    = 0;
4864   let Inst{30}    = Q;
4865   let Inst{29}    = U;
4866   let Inst{28-24} = 0b01110;
4867   let Inst{23-22} = size;
4868   let Inst{21-17} = 0b10000;
4869   let Inst{16-12} = opcode;
4870   let Inst{11-10} = 0b10;
4871   let Inst{9-5}   = Rn;
4872   let Inst{4-0}   = Rd;
4873 }
4874
4875 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4876                            RegisterOperand inreg, RegisterOperand outreg,
4877                            string asm, string outkind, string inkind,
4878                            list<dag> pattern>
4879   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4880       "{\t$Rd" # outkind # ", $Rn" # inkind #
4881       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4882     Sched<[WriteV]> {
4883   bits<5> Rd;
4884   bits<5> Rn;
4885   let Inst{31}    = 0;
4886   let Inst{30}    = Q;
4887   let Inst{29}    = U;
4888   let Inst{28-24} = 0b01110;
4889   let Inst{23-22} = size;
4890   let Inst{21-17} = 0b10000;
4891   let Inst{16-12} = opcode;
4892   let Inst{11-10} = 0b10;
4893   let Inst{9-5}   = Rn;
4894   let Inst{4-0}   = Rd;
4895 }
4896
4897 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4898                               SDPatternOperator OpNode> {
4899   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4900                                       asm, ".8b", ".8h",
4901         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4902   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4903                                       asm#"2", ".16b", ".8h", []>;
4904   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4905                                       asm, ".4h", ".4s",
4906         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4907   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4908                                       asm#"2", ".8h", ".4s", []>;
4909   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4910                                       asm, ".2s", ".2d",
4911         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4912   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4913                                       asm#"2", ".4s", ".2d", []>;
4914
4915   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4916             (!cast<Instruction>(NAME # "v16i8")
4917                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4918   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4919             (!cast<Instruction>(NAME # "v8i16")
4920                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4921   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4922             (!cast<Instruction>(NAME # "v4i32")
4923                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4924 }
4925
4926 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4927                            RegisterOperand regtype,
4928                            string asm, string kind, string zero,
4929                            ValueType dty, ValueType sty, SDNode OpNode>
4930   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4931       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4932       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4933       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4934     Sched<[WriteV]> {
4935   bits<5> Rd;
4936   bits<5> Rn;
4937   let Inst{31}    = 0;
4938   let Inst{30}    = Q;
4939   let Inst{29}    = U;
4940   let Inst{28-24} = 0b01110;
4941   let Inst{23-22} = size;
4942   let Inst{21-17} = 0b10000;
4943   let Inst{16-12} = opcode;
4944   let Inst{11-10} = 0b10;
4945   let Inst{9-5}   = Rn;
4946   let Inst{4-0}   = Rd;
4947 }
4948
4949 // Comparisons support all element sizes, except 1xD.
4950 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4951                             SDNode OpNode> {
4952   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4953                                      asm, ".8b", "0",
4954                                      v8i8, v8i8, OpNode>;
4955   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4956                                      asm, ".16b", "0",
4957                                      v16i8, v16i8, OpNode>;
4958   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4959                                      asm, ".4h", "0",
4960                                      v4i16, v4i16, OpNode>;
4961   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4962                                      asm, ".8h", "0",
4963                                      v8i16, v8i16, OpNode>;
4964   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4965                                      asm, ".2s", "0",
4966                                      v2i32, v2i32, OpNode>;
4967   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4968                                      asm, ".4s", "0",
4969                                      v4i32, v4i32, OpNode>;
4970   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4971                                      asm, ".2d", "0",
4972                                      v2i64, v2i64, OpNode>;
4973 }
4974
4975 // FP Comparisons support only S and D element sizes.
4976 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4977                               string asm, SDNode OpNode> {
4978
4979   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4980                                      asm, ".2s", "0.0",
4981                                      v2i32, v2f32, OpNode>;
4982   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4983                                      asm, ".4s", "0.0",
4984                                      v4i32, v4f32, OpNode>;
4985   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4986                                      asm, ".2d", "0.0",
4987                                      v2i64, v2f64, OpNode>;
4988
4989   def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
4990                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4991   def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
4992                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4993   def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
4994                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4995   def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
4996                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4997   def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
4998                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4999   def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5000                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5001 }
5002
5003 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5004 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5005                              RegisterOperand outtype, RegisterOperand intype,
5006                              string asm, string VdTy, string VnTy,
5007                              list<dag> pattern>
5008   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5009       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5010     Sched<[WriteV]> {
5011   bits<5> Rd;
5012   bits<5> Rn;
5013   let Inst{31}    = 0;
5014   let Inst{30}    = Q;
5015   let Inst{29}    = U;
5016   let Inst{28-24} = 0b01110;
5017   let Inst{23-22} = size;
5018   let Inst{21-17} = 0b10000;
5019   let Inst{16-12} = opcode;
5020   let Inst{11-10} = 0b10;
5021   let Inst{9-5}   = Rn;
5022   let Inst{4-0}   = Rd;
5023 }
5024
5025 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5026                              RegisterOperand outtype, RegisterOperand intype,
5027                              string asm, string VdTy, string VnTy,
5028                              list<dag> pattern>
5029   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5030       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5031     Sched<[WriteV]> {
5032   bits<5> Rd;
5033   bits<5> Rn;
5034   let Inst{31}    = 0;
5035   let Inst{30}    = Q;
5036   let Inst{29}    = U;
5037   let Inst{28-24} = 0b01110;
5038   let Inst{23-22} = size;
5039   let Inst{21-17} = 0b10000;
5040   let Inst{16-12} = opcode;
5041   let Inst{11-10} = 0b10;
5042   let Inst{9-5}   = Rn;
5043   let Inst{4-0}   = Rd;
5044 }
5045
5046 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5047   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5048                                     asm, ".4s", ".4h", []>;
5049   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5050                                     asm#"2", ".4s", ".8h", []>;
5051   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5052                                     asm, ".2d", ".2s", []>;
5053   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5054                                     asm#"2", ".2d", ".4s", []>;
5055 }
5056
5057 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5058   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5059                                     asm, ".4h", ".4s", []>;
5060   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5061                                     asm#"2", ".8h", ".4s", []>;
5062   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5063                                     asm, ".2s", ".2d", []>;
5064   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5065                                     asm#"2", ".4s", ".2d", []>;
5066 }
5067
5068 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5069                                      Intrinsic OpNode> {
5070   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5071                                      asm, ".2s", ".2d",
5072                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5073   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5074                                     asm#"2", ".4s", ".2d", []>;
5075
5076   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5077             (!cast<Instruction>(NAME # "v4f32")
5078                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5079 }
5080
5081 //----------------------------------------------------------------------------
5082 // AdvSIMD three register different-size vector instructions.
5083 //----------------------------------------------------------------------------
5084
5085 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5086 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5087                       RegisterOperand outtype, RegisterOperand intype1,
5088                       RegisterOperand intype2, string asm,
5089                       string outkind, string inkind1, string inkind2,
5090                       list<dag> pattern>
5091   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5092       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5093       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5094     Sched<[WriteV]> {
5095   bits<5> Rd;
5096   bits<5> Rn;
5097   bits<5> Rm;
5098   let Inst{31}    = 0;
5099   let Inst{30}    = size{0};
5100   let Inst{29}    = U;
5101   let Inst{28-24} = 0b01110;
5102   let Inst{23-22} = size{2-1};
5103   let Inst{21}    = 1;
5104   let Inst{20-16} = Rm;
5105   let Inst{15-12} = opcode;
5106   let Inst{11-10} = 0b00;
5107   let Inst{9-5}   = Rn;
5108   let Inst{4-0}   = Rd;
5109 }
5110
5111 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5112 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5113                       RegisterOperand outtype, RegisterOperand intype1,
5114                       RegisterOperand intype2, string asm,
5115                       string outkind, string inkind1, string inkind2,
5116                       list<dag> pattern>
5117   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5118       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5119       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5120     Sched<[WriteV]> {
5121   bits<5> Rd;
5122   bits<5> Rn;
5123   bits<5> Rm;
5124   let Inst{31}    = 0;
5125   let Inst{30}    = size{0};
5126   let Inst{29}    = U;
5127   let Inst{28-24} = 0b01110;
5128   let Inst{23-22} = size{2-1};
5129   let Inst{21}    = 1;
5130   let Inst{20-16} = Rm;
5131   let Inst{15-12} = opcode;
5132   let Inst{11-10} = 0b00;
5133   let Inst{9-5}   = Rn;
5134   let Inst{4-0}   = Rd;
5135 }
5136
5137 // FIXME: TableGen doesn't know how to deal with expanded types that also
5138 //        change the element count (in this case, placing the results in
5139 //        the high elements of the result register rather than the low
5140 //        elements). Until that's fixed, we can't code-gen those.
5141 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5142                                     Intrinsic IntOp> {
5143   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5144                                                   V64, V128, V128,
5145                                                   asm, ".8b", ".8h", ".8h",
5146      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5147   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5148                                                   V128, V128, V128,
5149                                                   asm#"2", ".16b", ".8h", ".8h",
5150      []>;
5151   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5152                                                   V64, V128, V128,
5153                                                   asm, ".4h", ".4s", ".4s",
5154      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5155   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5156                                                   V128, V128, V128,
5157                                                   asm#"2", ".8h", ".4s", ".4s",
5158      []>;
5159   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5160                                                   V64, V128, V128,
5161                                                   asm, ".2s", ".2d", ".2d",
5162      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5163   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5164                                                   V128, V128, V128,
5165                                                   asm#"2", ".4s", ".2d", ".2d",
5166      []>;
5167
5168
5169   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5170   // a version attached to an instruction.
5171   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5172                                                    (v8i16 V128:$Rm))),
5173             (!cast<Instruction>(NAME # "v8i16_v16i8")
5174                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5175                 V128:$Rn, V128:$Rm)>;
5176   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5177                                                     (v4i32 V128:$Rm))),
5178             (!cast<Instruction>(NAME # "v4i32_v8i16")
5179                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5180                 V128:$Rn, V128:$Rm)>;
5181   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5182                                                     (v2i64 V128:$Rm))),
5183             (!cast<Instruction>(NAME # "v2i64_v4i32")
5184                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5185                 V128:$Rn, V128:$Rm)>;
5186 }
5187
5188 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5189                                       Intrinsic IntOp> {
5190   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5191                                             V128, V64, V64,
5192                                             asm, ".8h", ".8b", ".8b",
5193       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5194   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5195                                             V128, V128, V128,
5196                                             asm#"2", ".8h", ".16b", ".16b", []>;
5197   let Predicates = [HasCrypto] in {
5198     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5199                                               V128, V64, V64,
5200                                               asm, ".1q", ".1d", ".1d", []>;
5201     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5202                                               V128, V128, V128,
5203                                               asm#"2", ".1q", ".2d", ".2d", []>;
5204   }
5205
5206   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5207                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
5208       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5209 }
5210
5211 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5212                                  SDPatternOperator OpNode> {
5213   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5214                                                   V128, V64, V64,
5215                                                   asm, ".4s", ".4h", ".4h",
5216       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5217   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5218                                                   V128, V128, V128,
5219                                                   asm#"2", ".4s", ".8h", ".8h",
5220       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5221                                       (extract_high_v8i16 V128:$Rm)))]>;
5222   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5223                                                   V128, V64, V64,
5224                                                   asm, ".2d", ".2s", ".2s",
5225       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5226   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5227                                                   V128, V128, V128,
5228                                                   asm#"2", ".2d", ".4s", ".4s",
5229       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5230                                       (extract_high_v4i32 V128:$Rm)))]>;
5231 }
5232
5233 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5234                                   SDPatternOperator OpNode = null_frag> {
5235   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5236                                                   V128, V64, V64,
5237                                                   asm, ".8h", ".8b", ".8b",
5238       [(set (v8i16 V128:$Rd),
5239             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5240   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5241                                                  V128, V128, V128,
5242                                                  asm#"2", ".8h", ".16b", ".16b",
5243       [(set (v8i16 V128:$Rd),
5244             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5245                                 (extract_high_v16i8 V128:$Rm)))))]>;
5246   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5247                                                   V128, V64, V64,
5248                                                   asm, ".4s", ".4h", ".4h",
5249       [(set (v4i32 V128:$Rd),
5250             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5251   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5252                                                   V128, V128, V128,
5253                                                   asm#"2", ".4s", ".8h", ".8h",
5254       [(set (v4i32 V128:$Rd),
5255             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5256                                   (extract_high_v8i16 V128:$Rm)))))]>;
5257   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5258                                                   V128, V64, V64,
5259                                                   asm, ".2d", ".2s", ".2s",
5260       [(set (v2i64 V128:$Rd),
5261             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5262   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5263                                                   V128, V128, V128,
5264                                                   asm#"2", ".2d", ".4s", ".4s",
5265       [(set (v2i64 V128:$Rd),
5266             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5267                                  (extract_high_v4i32 V128:$Rm)))))]>;
5268 }
5269
5270 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5271                                           string asm,
5272                                           SDPatternOperator OpNode> {
5273   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5274                                                   V128, V64, V64,
5275                                                   asm, ".8h", ".8b", ".8b",
5276     [(set (v8i16 V128:$dst),
5277           (add (v8i16 V128:$Rd),
5278                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5279   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5280                                                  V128, V128, V128,
5281                                                  asm#"2", ".8h", ".16b", ".16b",
5282     [(set (v8i16 V128:$dst),
5283           (add (v8i16 V128:$Rd),
5284                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5285                                    (extract_high_v16i8 V128:$Rm))))))]>;
5286   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5287                                                   V128, V64, V64,
5288                                                   asm, ".4s", ".4h", ".4h",
5289     [(set (v4i32 V128:$dst),
5290           (add (v4i32 V128:$Rd),
5291                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5292   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5293                                                   V128, V128, V128,
5294                                                   asm#"2", ".4s", ".8h", ".8h",
5295     [(set (v4i32 V128:$dst),
5296           (add (v4i32 V128:$Rd),
5297                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5298                                     (extract_high_v8i16 V128:$Rm))))))]>;
5299   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5300                                                   V128, V64, V64,
5301                                                   asm, ".2d", ".2s", ".2s",
5302     [(set (v2i64 V128:$dst),
5303           (add (v2i64 V128:$Rd),
5304                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5305   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5306                                                   V128, V128, V128,
5307                                                   asm#"2", ".2d", ".4s", ".4s",
5308     [(set (v2i64 V128:$dst),
5309           (add (v2i64 V128:$Rd),
5310                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5311                                     (extract_high_v4i32 V128:$Rm))))))]>;
5312 }
5313
5314 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5315                                   SDPatternOperator OpNode = null_frag> {
5316   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5317                                                   V128, V64, V64,
5318                                                   asm, ".8h", ".8b", ".8b",
5319       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5320   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5321                                                  V128, V128, V128,
5322                                                  asm#"2", ".8h", ".16b", ".16b",
5323       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5324                                       (extract_high_v16i8 V128:$Rm)))]>;
5325   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5326                                                   V128, V64, V64,
5327                                                   asm, ".4s", ".4h", ".4h",
5328       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5329   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5330                                                   V128, V128, V128,
5331                                                   asm#"2", ".4s", ".8h", ".8h",
5332       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5333                                       (extract_high_v8i16 V128:$Rm)))]>;
5334   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5335                                                   V128, V64, V64,
5336                                                   asm, ".2d", ".2s", ".2s",
5337       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5338   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5339                                                   V128, V128, V128,
5340                                                   asm#"2", ".2d", ".4s", ".4s",
5341       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5342                                       (extract_high_v4i32 V128:$Rm)))]>;
5343 }
5344
5345 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5346                                       string asm,
5347                                       SDPatternOperator OpNode> {
5348   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5349                                                   V128, V64, V64,
5350                                                   asm, ".8h", ".8b", ".8b",
5351     [(set (v8i16 V128:$dst),
5352           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5353   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5354                                                  V128, V128, V128,
5355                                                  asm#"2", ".8h", ".16b", ".16b",
5356     [(set (v8i16 V128:$dst),
5357           (OpNode (v8i16 V128:$Rd),
5358                   (extract_high_v16i8 V128:$Rn),
5359                   (extract_high_v16i8 V128:$Rm)))]>;
5360   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5361                                                   V128, V64, V64,
5362                                                   asm, ".4s", ".4h", ".4h",
5363     [(set (v4i32 V128:$dst),
5364           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5365   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5366                                                   V128, V128, V128,
5367                                                   asm#"2", ".4s", ".8h", ".8h",
5368     [(set (v4i32 V128:$dst),
5369           (OpNode (v4i32 V128:$Rd),
5370                   (extract_high_v8i16 V128:$Rn),
5371                   (extract_high_v8i16 V128:$Rm)))]>;
5372   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5373                                                   V128, V64, V64,
5374                                                   asm, ".2d", ".2s", ".2s",
5375     [(set (v2i64 V128:$dst),
5376           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5377   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5378                                                   V128, V128, V128,
5379                                                   asm#"2", ".2d", ".4s", ".4s",
5380     [(set (v2i64 V128:$dst),
5381           (OpNode (v2i64 V128:$Rd),
5382                   (extract_high_v4i32 V128:$Rn),
5383                   (extract_high_v4i32 V128:$Rm)))]>;
5384 }
5385
5386 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5387                                            SDPatternOperator Accum> {
5388   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5389                                                   V128, V64, V64,
5390                                                   asm, ".4s", ".4h", ".4h",
5391     [(set (v4i32 V128:$dst),
5392           (Accum (v4i32 V128:$Rd),
5393                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5394                                                 (v4i16 V64:$Rm)))))]>;
5395   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5396                                                   V128, V128, V128,
5397                                                   asm#"2", ".4s", ".8h", ".8h",
5398     [(set (v4i32 V128:$dst),
5399           (Accum (v4i32 V128:$Rd),
5400                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5401                                             (extract_high_v8i16 V128:$Rm)))))]>;
5402   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5403                                                   V128, V64, V64,
5404                                                   asm, ".2d", ".2s", ".2s",
5405     [(set (v2i64 V128:$dst),
5406           (Accum (v2i64 V128:$Rd),
5407                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5408                                                 (v2i32 V64:$Rm)))))]>;
5409   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5410                                                   V128, V128, V128,
5411                                                   asm#"2", ".2d", ".4s", ".4s",
5412     [(set (v2i64 V128:$dst),
5413           (Accum (v2i64 V128:$Rd),
5414                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5415                                             (extract_high_v4i32 V128:$Rm)))))]>;
5416 }
5417
5418 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5419                                   SDPatternOperator OpNode> {
5420   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5421                                                   V128, V128, V64,
5422                                                   asm, ".8h", ".8h", ".8b",
5423        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5424   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5425                                                   V128, V128, V128,
5426                                                   asm#"2", ".8h", ".8h", ".16b",
5427        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5428                                        (extract_high_v16i8 V128:$Rm)))]>;
5429   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5430                                                   V128, V128, V64,
5431                                                   asm, ".4s", ".4s", ".4h",
5432        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5433   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5434                                                   V128, V128, V128,
5435                                                   asm#"2", ".4s", ".4s", ".8h",
5436        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5437                                        (extract_high_v8i16 V128:$Rm)))]>;
5438   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5439                                                   V128, V128, V64,
5440                                                   asm, ".2d", ".2d", ".2s",
5441        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5442   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5443                                                   V128, V128, V128,
5444                                                   asm#"2", ".2d", ".2d", ".4s",
5445        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5446                                        (extract_high_v4i32 V128:$Rm)))]>;
5447 }
5448
5449 //----------------------------------------------------------------------------
5450 // AdvSIMD bitwise extract from vector
5451 //----------------------------------------------------------------------------
5452
5453 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5454                              string asm, string kind>
5455   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5456       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5457       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5458       [(set (vty regtype:$Rd),
5459             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5460     Sched<[WriteV]> {
5461   bits<5> Rd;
5462   bits<5> Rn;
5463   bits<5> Rm;
5464   bits<4> imm;
5465   let Inst{31}    = 0;
5466   let Inst{30}    = size;
5467   let Inst{29-21} = 0b101110000;
5468   let Inst{20-16} = Rm;
5469   let Inst{15}    = 0;
5470   let Inst{14-11} = imm;
5471   let Inst{10}    = 0;
5472   let Inst{9-5}   = Rn;
5473   let Inst{4-0}   = Rd;
5474 }
5475
5476
5477 multiclass SIMDBitwiseExtract<string asm> {
5478   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5479     let imm{3} = 0;
5480   }
5481   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5482 }
5483
5484 //----------------------------------------------------------------------------
5485 // AdvSIMD zip vector
5486 //----------------------------------------------------------------------------
5487
5488 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5489                         string asm, string kind, SDNode OpNode, ValueType valty>
5490   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5491       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5492       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5493       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5494     Sched<[WriteV]> {
5495   bits<5> Rd;
5496   bits<5> Rn;
5497   bits<5> Rm;
5498   let Inst{31}    = 0;
5499   let Inst{30}    = size{0};
5500   let Inst{29-24} = 0b001110;
5501   let Inst{23-22} = size{2-1};
5502   let Inst{21}    = 0;
5503   let Inst{20-16} = Rm;
5504   let Inst{15}    = 0;
5505   let Inst{14-12} = opc;
5506   let Inst{11-10} = 0b10;
5507   let Inst{9-5}   = Rn;
5508   let Inst{4-0}   = Rd;
5509 }
5510
5511 multiclass SIMDZipVector<bits<3>opc, string asm,
5512                          SDNode OpNode> {
5513   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5514       asm, ".8b", OpNode, v8i8>;
5515   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5516       asm, ".16b", OpNode, v16i8>;
5517   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5518       asm, ".4h", OpNode, v4i16>;
5519   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5520       asm, ".8h", OpNode, v8i16>;
5521   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5522       asm, ".2s", OpNode, v2i32>;
5523   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5524       asm, ".4s", OpNode, v4i32>;
5525   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5526       asm, ".2d", OpNode, v2i64>;
5527
5528   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5529         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5530   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5531         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5532   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5533         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5534   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5535         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5536   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5537         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5538 }
5539
5540 //----------------------------------------------------------------------------
5541 // AdvSIMD three register scalar instructions
5542 //----------------------------------------------------------------------------
5543
5544 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5545 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5546                         RegisterClass regtype, string asm,
5547                         list<dag> pattern>
5548   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5549       "\t$Rd, $Rn, $Rm", "", pattern>,
5550     Sched<[WriteV]> {
5551   bits<5> Rd;
5552   bits<5> Rn;
5553   bits<5> Rm;
5554   let Inst{31-30} = 0b01;
5555   let Inst{29}    = U;
5556   let Inst{28-24} = 0b11110;
5557   let Inst{23-22} = size;
5558   let Inst{21}    = 1;
5559   let Inst{20-16} = Rm;
5560   let Inst{15-11} = opcode;
5561   let Inst{10}    = 1;
5562   let Inst{9-5}   = Rn;
5563   let Inst{4-0}   = Rd;
5564 }
5565
5566 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5567 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5568                         dag oops, dag iops, string asm,
5569             list<dag> pattern>
5570   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5571     Sched<[WriteV]> {
5572   bits<5> Rd;
5573   bits<5> Rn;
5574   bits<5> Rm;
5575   let Inst{31-30} = 0b01;
5576   let Inst{29}    = U;
5577   let Inst{28-24} = 0b11110;
5578   let Inst{23-22} = size;
5579   let Inst{21}    = R;
5580   let Inst{20-16} = Rm;
5581   let Inst{15-11} = opcode;
5582   let Inst{10}    = 1;
5583   let Inst{9-5}   = Rn;
5584   let Inst{4-0}   = Rd;
5585 }
5586
5587 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5588                             SDPatternOperator OpNode> {
5589   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5590     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5591 }
5592
5593 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5594                                SDPatternOperator OpNode> {
5595   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5596     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5597   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5598   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5599   def v1i8   : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5600
5601   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5602             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5603   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5604             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5605 }
5606
5607 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5608                              SDPatternOperator OpNode> {
5609   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5610                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5611   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5612 }
5613
5614 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5615                                  SDPatternOperator OpNode = null_frag> {
5616   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5617                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm), 
5618                                      asm, []>;
5619   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5620                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm), 
5621                                      asm, []>;
5622 }
5623
5624 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5625                              SDPatternOperator OpNode = null_frag> {
5626   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5627     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5628       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5629     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5630       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5631   }
5632
5633   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5634             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5635 }
5636
5637 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5638                                 SDPatternOperator OpNode = null_frag> {
5639   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5640     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5641       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5642     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5643       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5644   }
5645
5646   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5647             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5648 }
5649
5650 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5651               dag oops, dag iops, string asm, string cstr, list<dag> pat>
5652   : I<oops, iops, asm,
5653       "\t$Rd, $Rn, $Rm", cstr, pat>,
5654     Sched<[WriteV]> {
5655   bits<5> Rd;
5656   bits<5> Rn;
5657   bits<5> Rm;
5658   let Inst{31-30} = 0b01;
5659   let Inst{29}    = U;
5660   let Inst{28-24} = 0b11110;
5661   let Inst{23-22} = size;
5662   let Inst{21}    = 1;
5663   let Inst{20-16} = Rm;
5664   let Inst{15-11} = opcode;
5665   let Inst{10}    = 0;
5666   let Inst{9-5}   = Rn;
5667   let Inst{4-0}   = Rd;
5668 }
5669
5670 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5671 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5672                                   SDPatternOperator OpNode = null_frag> {
5673   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5674                                       (outs FPR32:$Rd),
5675                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5676   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5677                                       (outs FPR64:$Rd),
5678                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5679             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5680 }
5681
5682 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5683 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5684                                   SDPatternOperator OpNode = null_frag> {
5685   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5686                                       (outs FPR32:$dst),
5687                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5688                                       asm, "$Rd = $dst", []>;
5689   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5690                                       (outs FPR64:$dst),
5691                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5692                                       asm, "$Rd = $dst",
5693             [(set (i64 FPR64:$dst),
5694                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5695 }
5696
5697 //----------------------------------------------------------------------------
5698 // AdvSIMD two register scalar instructions
5699 //----------------------------------------------------------------------------
5700
5701 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5702 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5703                         RegisterClass regtype, RegisterClass regtype2,
5704                         string asm, list<dag> pat>
5705   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5706       "\t$Rd, $Rn", "", pat>,
5707     Sched<[WriteV]> {
5708   bits<5> Rd;
5709   bits<5> Rn;
5710   let Inst{31-30} = 0b01;
5711   let Inst{29}    = U;
5712   let Inst{28-24} = 0b11110;
5713   let Inst{23-22} = size;
5714   let Inst{21-17} = 0b10000;
5715   let Inst{16-12} = opcode;
5716   let Inst{11-10} = 0b10;
5717   let Inst{9-5}   = Rn;
5718   let Inst{4-0}   = Rd;
5719 }
5720
5721 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5722 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5723                         RegisterClass regtype, RegisterClass regtype2,
5724                         string asm, list<dag> pat>
5725   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5726       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5727     Sched<[WriteV]> {
5728   bits<5> Rd;
5729   bits<5> Rn;
5730   let Inst{31-30} = 0b01;
5731   let Inst{29}    = U;
5732   let Inst{28-24} = 0b11110;
5733   let Inst{23-22} = size;
5734   let Inst{21-17} = 0b10000;
5735   let Inst{16-12} = opcode;
5736   let Inst{11-10} = 0b10;
5737   let Inst{9-5}   = Rn;
5738   let Inst{4-0}   = Rd;
5739 }
5740
5741
5742 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5743 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5744                         RegisterClass regtype, string asm, string zero>
5745   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5746       "\t$Rd, $Rn, #" # zero, "", []>,
5747     Sched<[WriteV]> {
5748   bits<5> Rd;
5749   bits<5> Rn;
5750   let Inst{31-30} = 0b01;
5751   let Inst{29}    = U;
5752   let Inst{28-24} = 0b11110;
5753   let Inst{23-22} = size;
5754   let Inst{21-17} = 0b10000;
5755   let Inst{16-12} = opcode;
5756   let Inst{11-10} = 0b10;
5757   let Inst{9-5}   = Rn;
5758   let Inst{4-0}   = Rd;
5759 }
5760
5761 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5762   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5763      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5764     Sched<[WriteV]> {
5765   bits<5> Rd;
5766   bits<5> Rn;
5767   let Inst{31-17} = 0b011111100110000;
5768   let Inst{16-12} = opcode;
5769   let Inst{11-10} = 0b10;
5770   let Inst{9-5}   = Rn;
5771   let Inst{4-0}   = Rd;
5772 }
5773
5774 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5775                              SDPatternOperator OpNode> {
5776   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5777
5778   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5779             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5780 }
5781
5782 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
5783                               SDPatternOperator OpNode> {
5784   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5785   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5786
5787   def : InstAlias<asm # "\t$Rd, $Rn, #0",
5788                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5789   def : InstAlias<asm # "\t$Rd, $Rn, #0",
5790                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5791
5792   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5793             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5794 }
5795
5796 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5797                           SDPatternOperator OpNode = null_frag> {
5798   def v1i64       : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5799     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5800
5801   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5802             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5803 }
5804
5805 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
5806   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5807   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5808 }
5809
5810 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5811                               SDPatternOperator OpNode> {
5812   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5813                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5814   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5815                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5816 }
5817
5818 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5819                              SDPatternOperator OpNode = null_frag> {
5820   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5821     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5822            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5823     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5824            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5825     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5826     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5827   }
5828
5829   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5830             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5831 }
5832
5833 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5834                                  Intrinsic OpNode> {
5835   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5836     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5837         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5838     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5839         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5840     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5841     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5842   }
5843
5844   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5845             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5846 }
5847
5848
5849
5850 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5851 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5852                                  SDPatternOperator OpNode = null_frag> {
5853   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5854         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5855   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5856   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5857 }
5858
5859 //----------------------------------------------------------------------------
5860 // AdvSIMD scalar pairwise instructions
5861 //----------------------------------------------------------------------------
5862
5863 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5864 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5865                         RegisterOperand regtype, RegisterOperand vectype,
5866                         string asm, string kind>
5867   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5868       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5869     Sched<[WriteV]> {
5870   bits<5> Rd;
5871   bits<5> Rn;
5872   let Inst{31-30} = 0b01;
5873   let Inst{29}    = U;
5874   let Inst{28-24} = 0b11110;
5875   let Inst{23-22} = size;
5876   let Inst{21-17} = 0b11000;
5877   let Inst{16-12} = opcode;
5878   let Inst{11-10} = 0b10;
5879   let Inst{9-5}   = Rn;
5880   let Inst{4-0}   = Rd;
5881 }
5882
5883 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5884   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5885                                       asm, ".2d">;
5886 }
5887
5888 multiclass SIMDFPPairwiseScalar<bit U, bit S, bits<5> opc, string asm> {
5889   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5890                                       asm, ".2s">;
5891   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5892                                       asm, ".2d">;
5893 }
5894
5895 //----------------------------------------------------------------------------
5896 // AdvSIMD across lanes instructions
5897 //----------------------------------------------------------------------------
5898
5899 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5900 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5901                           RegisterClass regtype, RegisterOperand vectype,
5902                           string asm, string kind, list<dag> pattern>
5903   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5904       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5905     Sched<[WriteV]> {
5906   bits<5> Rd;
5907   bits<5> Rn;
5908   let Inst{31}    = 0;
5909   let Inst{30}    = Q;
5910   let Inst{29}    = U;
5911   let Inst{28-24} = 0b01110;
5912   let Inst{23-22} = size;
5913   let Inst{21-17} = 0b11000;
5914   let Inst{16-12} = opcode;
5915   let Inst{11-10} = 0b10;
5916   let Inst{9-5}   = Rn;
5917   let Inst{4-0}   = Rd;
5918 }
5919
5920 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5921                               string asm> {
5922   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5923                                    asm, ".8b", []>;
5924   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5925                                    asm, ".16b", []>;
5926   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5927                                    asm, ".4h", []>;
5928   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5929                                    asm, ".8h", []>;
5930   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5931                                    asm, ".4s", []>;
5932 }
5933
5934 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5935   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5936                                    asm, ".8b", []>;
5937   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5938                                    asm, ".16b", []>;
5939   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5940                                    asm, ".4h", []>;
5941   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5942                                    asm, ".8h", []>;
5943   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5944                                    asm, ".4s", []>;
5945 }
5946
5947 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5948                             Intrinsic intOp> {
5949   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5950                                    asm, ".4s",
5951         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5952 }
5953
5954 //----------------------------------------------------------------------------
5955 // AdvSIMD INS/DUP instructions
5956 //----------------------------------------------------------------------------
5957
5958 // FIXME: There has got to be a better way to factor these. ugh.
5959
5960 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5961                      string operands, string constraints, list<dag> pattern>
5962   : I<outs, ins, asm, operands, constraints, pattern>,
5963     Sched<[WriteV]> {
5964   bits<5> Rd;
5965   bits<5> Rn;
5966   let Inst{31} = 0;
5967   let Inst{30} = Q;
5968   let Inst{29} = op;
5969   let Inst{28-21} = 0b01110000;
5970   let Inst{15} = 0;
5971   let Inst{10} = 1;
5972   let Inst{9-5} = Rn;
5973   let Inst{4-0} = Rd;
5974 }
5975
5976 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5977                       RegisterOperand vecreg, RegisterClass regtype>
5978   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5979                    "{\t$Rd" # size # ", $Rn" #
5980                    "|" # size # "\t$Rd, $Rn}", "",
5981                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
5982   let Inst{20-16} = imm5;
5983   let Inst{14-11} = 0b0001;
5984 }
5985
5986 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5987                          ValueType vectype, ValueType insreg,
5988                          RegisterOperand vecreg, Operand idxtype,
5989                          ValueType elttype, SDNode OpNode>
5990   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5991                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5992                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5993                  [(set (vectype vecreg:$Rd),
5994                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5995   let Inst{14-11} = 0b0000;
5996 }
5997
5998 class SIMDDup64FromElement
5999   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6000                        VectorIndexD, i64, AArch64duplane64> {
6001   bits<1> idx;
6002   let Inst{20} = idx;
6003   let Inst{19-16} = 0b1000;
6004 }
6005
6006 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6007                            RegisterOperand vecreg>
6008   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6009                        VectorIndexS, i64, AArch64duplane32> {
6010   bits<2> idx;
6011   let Inst{20-19} = idx;
6012   let Inst{18-16} = 0b100;
6013 }
6014
6015 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6016                            RegisterOperand vecreg>
6017   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6018                        VectorIndexH, i64, AArch64duplane16> {
6019   bits<3> idx;
6020   let Inst{20-18} = idx;
6021   let Inst{17-16} = 0b10;
6022 }
6023
6024 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6025                           RegisterOperand vecreg>
6026   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6027                        VectorIndexB, i64, AArch64duplane8> {
6028   bits<4> idx;
6029   let Inst{20-17} = idx;
6030   let Inst{16} = 1;
6031 }
6032
6033 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6034                   Operand idxtype, string asm, list<dag> pattern>
6035   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6036                    "{\t$Rd, $Rn" # size # "$idx" #
6037                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6038   let Inst{14-11} = imm4;
6039 }
6040
6041 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6042                Operand idxtype>
6043   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6044 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6045                Operand idxtype>
6046   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6047       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6048
6049 class SIMDMovAlias<string asm, string size, Instruction inst,
6050                    RegisterClass regtype, Operand idxtype>
6051     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6052                     "|" # size # "\t$dst, $src$idx}",
6053                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6054
6055 multiclass SMov {
6056   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6057     bits<4> idx;
6058     let Inst{20-17} = idx;
6059     let Inst{16} = 1;
6060   }
6061   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6062     bits<4> idx;
6063     let Inst{20-17} = idx;
6064     let Inst{16} = 1;
6065   }
6066   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6067     bits<3> idx;
6068     let Inst{20-18} = idx;
6069     let Inst{17-16} = 0b10;
6070   }
6071   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6072     bits<3> idx;
6073     let Inst{20-18} = idx;
6074     let Inst{17-16} = 0b10;
6075   }
6076   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6077     bits<2> idx;
6078     let Inst{20-19} = idx;
6079     let Inst{18-16} = 0b100;
6080   }
6081 }
6082
6083 multiclass UMov {
6084   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6085     bits<4> idx;
6086     let Inst{20-17} = idx;
6087     let Inst{16} = 1;
6088   }
6089   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6090     bits<3> idx;
6091     let Inst{20-18} = idx;
6092     let Inst{17-16} = 0b10;
6093   }
6094   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6095     bits<2> idx;
6096     let Inst{20-19} = idx;
6097     let Inst{18-16} = 0b100;
6098   }
6099   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6100     bits<1> idx;
6101     let Inst{20} = idx;
6102     let Inst{19-16} = 0b1000;
6103   }
6104   def : SIMDMovAlias<"mov", ".s",
6105                      !cast<Instruction>(NAME#"vi32"),
6106                      GPR32, VectorIndexS>;
6107   def : SIMDMovAlias<"mov", ".d",
6108                      !cast<Instruction>(NAME#"vi64"),
6109                      GPR64, VectorIndexD>;
6110 }
6111
6112 class SIMDInsFromMain<string size, ValueType vectype,
6113                       RegisterClass regtype, Operand idxtype>
6114   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6115                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6116                    "{\t$Rd" # size # "$idx, $Rn" #
6117                    "|" # size # "\t$Rd$idx, $Rn}",
6118                    "$Rd = $dst",
6119             [(set V128:$dst,
6120               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6121   let Inst{14-11} = 0b0011;
6122 }
6123
6124 class SIMDInsFromElement<string size, ValueType vectype,
6125                          ValueType elttype, Operand idxtype>
6126   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6127                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6128                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6129                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
6130                    "$Rd = $dst",
6131          [(set V128:$dst,
6132                (vector_insert
6133                  (vectype V128:$Rd),
6134                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6135                  idxtype:$idx))]>;
6136
6137 class SIMDInsMainMovAlias<string size, Instruction inst,
6138                           RegisterClass regtype, Operand idxtype>
6139     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6140                         "|" # size #"\t$dst$idx, $src}",
6141                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6142 class SIMDInsElementMovAlias<string size, Instruction inst,
6143                              Operand idxtype>
6144     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6145                       # "|" # size #"\t$dst$idx, $src$idx2}",
6146                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6147
6148
6149 multiclass SIMDIns {
6150   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6151     bits<4> idx;
6152     let Inst{20-17} = idx;
6153     let Inst{16} = 1;
6154   }
6155   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6156     bits<3> idx;
6157     let Inst{20-18} = idx;
6158     let Inst{17-16} = 0b10;
6159   }
6160   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6161     bits<2> idx;
6162     let Inst{20-19} = idx;
6163     let Inst{18-16} = 0b100;
6164   }
6165   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6166     bits<1> idx;
6167     let Inst{20} = idx;
6168     let Inst{19-16} = 0b1000;
6169   }
6170
6171   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6172     bits<4> idx;
6173     bits<4> idx2;
6174     let Inst{20-17} = idx;
6175     let Inst{16} = 1;
6176     let Inst{14-11} = idx2;
6177   }
6178   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6179     bits<3> idx;
6180     bits<3> idx2;
6181     let Inst{20-18} = idx;
6182     let Inst{17-16} = 0b10;
6183     let Inst{14-12} = idx2;
6184     let Inst{11} = {?};
6185   }
6186   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6187     bits<2> idx;
6188     bits<2> idx2;
6189     let Inst{20-19} = idx;
6190     let Inst{18-16} = 0b100;
6191     let Inst{14-13} = idx2;
6192     let Inst{12-11} = {?,?};
6193   }
6194   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6195     bits<1> idx;
6196     bits<1> idx2;
6197     let Inst{20} = idx;
6198     let Inst{19-16} = 0b1000;
6199     let Inst{14} = idx2;
6200     let Inst{13-11} = {?,?,?};
6201   }
6202
6203   // For all forms of the INS instruction, the "mov" mnemonic is the
6204   // preferred alias. Why they didn't just call the instruction "mov" in
6205   // the first place is a very good question indeed...
6206   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6207                          GPR32, VectorIndexB>;
6208   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6209                          GPR32, VectorIndexH>;
6210   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6211                          GPR32, VectorIndexS>;
6212   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6213                          GPR64, VectorIndexD>;
6214
6215   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6216                          VectorIndexB>;
6217   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6218                          VectorIndexH>;
6219   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6220                          VectorIndexS>;
6221   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6222                          VectorIndexD>;
6223 }
6224
6225 //----------------------------------------------------------------------------
6226 // AdvSIMD TBL/TBX
6227 //----------------------------------------------------------------------------
6228
6229 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6230 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6231                           RegisterOperand listtype, string asm, string kind>
6232   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6233        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6234     Sched<[WriteV]> {
6235   bits<5> Vd;
6236   bits<5> Vn;
6237   bits<5> Vm;
6238   let Inst{31}    = 0;
6239   let Inst{30}    = Q;
6240   let Inst{29-21} = 0b001110000;
6241   let Inst{20-16} = Vm;
6242   let Inst{15}    = 0;
6243   let Inst{14-13} = len;
6244   let Inst{12}    = op;
6245   let Inst{11-10} = 0b00;
6246   let Inst{9-5}   = Vn;
6247   let Inst{4-0}   = Vd;
6248 }
6249
6250 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6251 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6252                           RegisterOperand listtype, string asm, string kind>
6253   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6254        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6255     Sched<[WriteV]> {
6256   bits<5> Vd;
6257   bits<5> Vn;
6258   bits<5> Vm;
6259   let Inst{31}    = 0;
6260   let Inst{30}    = Q;
6261   let Inst{29-21} = 0b001110000;
6262   let Inst{20-16} = Vm;
6263   let Inst{15}    = 0;
6264   let Inst{14-13} = len;
6265   let Inst{12}    = op;
6266   let Inst{11-10} = 0b00;
6267   let Inst{9-5}   = Vn;
6268   let Inst{4-0}   = Vd;
6269 }
6270
6271 class SIMDTableLookupAlias<string asm, Instruction inst,
6272                           RegisterOperand vectype, RegisterOperand listtype>
6273     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6274                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6275
6276 multiclass SIMDTableLookup<bit op, string asm> {
6277   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6278                                       asm, ".8b">;
6279   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6280                                       asm, ".8b">;
6281   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6282                                       asm, ".8b">;
6283   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6284                                       asm, ".8b">;
6285   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6286                                       asm, ".16b">;
6287   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6288                                       asm, ".16b">;
6289   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6290                                       asm, ".16b">;
6291   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6292                                       asm, ".16b">;
6293
6294   def : SIMDTableLookupAlias<asm # ".8b",
6295                          !cast<Instruction>(NAME#"v8i8One"),
6296                          V64, VecListOne128>;
6297   def : SIMDTableLookupAlias<asm # ".8b",
6298                          !cast<Instruction>(NAME#"v8i8Two"),
6299                          V64, VecListTwo128>;
6300   def : SIMDTableLookupAlias<asm # ".8b",
6301                          !cast<Instruction>(NAME#"v8i8Three"),
6302                          V64, VecListThree128>;
6303   def : SIMDTableLookupAlias<asm # ".8b",
6304                          !cast<Instruction>(NAME#"v8i8Four"),
6305                          V64, VecListFour128>;
6306   def : SIMDTableLookupAlias<asm # ".16b",
6307                          !cast<Instruction>(NAME#"v16i8One"),
6308                          V128, VecListOne128>;
6309   def : SIMDTableLookupAlias<asm # ".16b",
6310                          !cast<Instruction>(NAME#"v16i8Two"),
6311                          V128, VecListTwo128>;
6312   def : SIMDTableLookupAlias<asm # ".16b",
6313                          !cast<Instruction>(NAME#"v16i8Three"),
6314                          V128, VecListThree128>;
6315   def : SIMDTableLookupAlias<asm # ".16b",
6316                          !cast<Instruction>(NAME#"v16i8Four"),
6317                          V128, VecListFour128>;
6318 }
6319
6320 multiclass SIMDTableLookupTied<bit op, string asm> {
6321   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6322                                       asm, ".8b">;
6323   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6324                                       asm, ".8b">;
6325   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6326                                       asm, ".8b">;
6327   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6328                                       asm, ".8b">;
6329   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6330                                       asm, ".16b">;
6331   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6332                                       asm, ".16b">;
6333   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6334                                       asm, ".16b">;
6335   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6336                                       asm, ".16b">;
6337
6338   def : SIMDTableLookupAlias<asm # ".8b",
6339                          !cast<Instruction>(NAME#"v8i8One"),
6340                          V64, VecListOne128>;
6341   def : SIMDTableLookupAlias<asm # ".8b",
6342                          !cast<Instruction>(NAME#"v8i8Two"),
6343                          V64, VecListTwo128>;
6344   def : SIMDTableLookupAlias<asm # ".8b",
6345                          !cast<Instruction>(NAME#"v8i8Three"),
6346                          V64, VecListThree128>;
6347   def : SIMDTableLookupAlias<asm # ".8b",
6348                          !cast<Instruction>(NAME#"v8i8Four"),
6349                          V64, VecListFour128>;
6350   def : SIMDTableLookupAlias<asm # ".16b",
6351                          !cast<Instruction>(NAME#"v16i8One"),
6352                          V128, VecListOne128>;
6353   def : SIMDTableLookupAlias<asm # ".16b",
6354                          !cast<Instruction>(NAME#"v16i8Two"),
6355                          V128, VecListTwo128>;
6356   def : SIMDTableLookupAlias<asm # ".16b",
6357                          !cast<Instruction>(NAME#"v16i8Three"),
6358                          V128, VecListThree128>;
6359   def : SIMDTableLookupAlias<asm # ".16b",
6360                          !cast<Instruction>(NAME#"v16i8Four"),
6361                          V128, VecListFour128>;
6362 }
6363
6364
6365 //----------------------------------------------------------------------------
6366 // AdvSIMD scalar CPY
6367 //----------------------------------------------------------------------------
6368 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6369 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6370                         string kind, Operand idxtype>
6371   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6372        "{\t$dst, $src" # kind # "$idx" #
6373        "|\t$dst, $src$idx}", "", []>,
6374     Sched<[WriteV]> {
6375   bits<5> dst;
6376   bits<5> src;
6377   let Inst{31-21} = 0b01011110000;
6378   let Inst{15-10} = 0b000001;
6379   let Inst{9-5}   = src;
6380   let Inst{4-0}   = dst;
6381 }
6382
6383 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6384       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6385     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6386                     # "|\t$dst, $src$index}",
6387                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6388
6389
6390 multiclass SIMDScalarCPY<string asm> {
6391   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6392     bits<4> idx;
6393     let Inst{20-17} = idx;
6394     let Inst{16} = 1;
6395   }
6396   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6397     bits<3> idx;
6398     let Inst{20-18} = idx;
6399     let Inst{17-16} = 0b10;
6400   }
6401   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6402     bits<2> idx;
6403     let Inst{20-19} = idx;
6404     let Inst{18-16} = 0b100;
6405   }
6406   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6407     bits<1> idx;
6408     let Inst{20} = idx;
6409     let Inst{19-16} = 0b1000;
6410   }
6411
6412   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6413                                                           VectorIndexD:$idx)))),
6414             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6415
6416   // 'DUP' mnemonic aliases.
6417   def : SIMDScalarCPYAlias<"dup", ".b",
6418                            !cast<Instruction>(NAME#"i8"),
6419                            FPR8, V128, VectorIndexB>;
6420   def : SIMDScalarCPYAlias<"dup", ".h",
6421                            !cast<Instruction>(NAME#"i16"),
6422                            FPR16, V128, VectorIndexH>;
6423   def : SIMDScalarCPYAlias<"dup", ".s",
6424                            !cast<Instruction>(NAME#"i32"),
6425                            FPR32, V128, VectorIndexS>;
6426   def : SIMDScalarCPYAlias<"dup", ".d",
6427                            !cast<Instruction>(NAME#"i64"),
6428                            FPR64, V128, VectorIndexD>;
6429 }
6430
6431 //----------------------------------------------------------------------------
6432 // AdvSIMD modified immediate instructions
6433 //----------------------------------------------------------------------------
6434
6435 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
6436                           string asm, string op_string,
6437                           string cstr, list<dag> pattern>
6438   : I<oops, iops, asm, op_string, cstr, pattern>,
6439     Sched<[WriteV]> {
6440   bits<5> Rd;
6441   bits<8> imm8;
6442   let Inst{31}    = 0;
6443   let Inst{30}    = Q;
6444   let Inst{29}    = op;
6445   let Inst{28-19} = 0b0111100000;
6446   let Inst{18-16} = imm8{7-5};
6447   let Inst{11-10} = 0b01;
6448   let Inst{9-5}   = imm8{4-0};
6449   let Inst{4-0}   = Rd;
6450 }
6451
6452 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
6453                                 Operand immtype, dag opt_shift_iop,
6454                                 string opt_shift, string asm, string kind,
6455                                 list<dag> pattern>
6456   : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
6457                         !con((ins immtype:$imm8), opt_shift_iop), asm,
6458                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
6459                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6460                         "", pattern> {
6461   let DecoderMethod = "DecodeModImmInstruction";
6462 }
6463
6464 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6465                                 Operand immtype, dag opt_shift_iop,
6466                                 string opt_shift, string asm, string kind,
6467                                 list<dag> pattern>
6468   : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
6469                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6470                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6471                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6472                         "$Rd = $dst", pattern> {
6473   let DecoderMethod = "DecodeModImmTiedInstruction";
6474 }
6475
6476 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6477                                      RegisterOperand vectype, string asm,
6478                                      string kind, list<dag> pattern>
6479   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6480                               (ins logical_vec_shift:$shift),
6481                               "$shift", asm, kind, pattern> {
6482   bits<2> shift;
6483   let Inst{15}    = b15_b12{1};
6484   let Inst{14-13} = shift;
6485   let Inst{12}    = b15_b12{0};
6486 }
6487
6488 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6489                                      RegisterOperand vectype, string asm,
6490                                      string kind, list<dag> pattern>
6491   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6492                               (ins logical_vec_shift:$shift),
6493                               "$shift", asm, kind, pattern> {
6494   bits<2> shift;
6495   let Inst{15}    = b15_b12{1};
6496   let Inst{14-13} = shift;
6497   let Inst{12}    = b15_b12{0};
6498 }
6499
6500
6501 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6502                                          RegisterOperand vectype, string asm,
6503                                          string kind, list<dag> pattern>
6504   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6505                               (ins logical_vec_hw_shift:$shift),
6506                               "$shift", asm, kind, pattern> {
6507   bits<2> shift;
6508   let Inst{15} = b15_b12{1};
6509   let Inst{14} = 0;
6510   let Inst{13} = shift{0};
6511   let Inst{12} = b15_b12{0};
6512 }
6513
6514 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6515                                          RegisterOperand vectype, string asm,
6516                                          string kind, list<dag> pattern>
6517   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6518                               (ins logical_vec_hw_shift:$shift),
6519                               "$shift", asm, kind, pattern> {
6520   bits<2> shift;
6521   let Inst{15} = b15_b12{1};
6522   let Inst{14} = 0;
6523   let Inst{13} = shift{0};
6524   let Inst{12} = b15_b12{0};
6525 }
6526
6527 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6528                                       string asm> {
6529   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6530                                                  asm, ".4h", []>;
6531   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6532                                                  asm, ".8h", []>;
6533
6534   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6535                                              asm, ".2s", []>;
6536   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6537                                              asm, ".4s", []>;
6538 }
6539
6540 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6541                                       bits<2> w_cmode, string asm,
6542                                       SDNode OpNode> {
6543   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6544                                                  asm, ".4h",
6545              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6546                                              imm0_255:$imm8,
6547                                              (i32 imm:$shift)))]>;
6548   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6549                                                  asm, ".8h",
6550              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6551                                               imm0_255:$imm8,
6552                                               (i32 imm:$shift)))]>;
6553
6554   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6555                                              asm, ".2s",
6556              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6557                                              imm0_255:$imm8,
6558                                              (i32 imm:$shift)))]>;
6559   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6560                                              asm, ".4s",
6561              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6562                                               imm0_255:$imm8,
6563                                               (i32 imm:$shift)))]>;
6564 }
6565
6566 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6567                              RegisterOperand vectype, string asm,
6568                              string kind, list<dag> pattern>
6569   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6570                               (ins move_vec_shift:$shift),
6571                               "$shift", asm, kind, pattern> {
6572   bits<1> shift;
6573   let Inst{15-13} = cmode{3-1};
6574   let Inst{12}    = shift;
6575 }
6576
6577 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
6578                                    RegisterOperand vectype,
6579                                    Operand imm_type, string asm,
6580                                    string kind, list<dag> pattern>
6581   : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
6582                               asm, kind, pattern> {
6583   let Inst{15-12} = cmode;
6584 }
6585
6586 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6587                                    list<dag> pattern>
6588   : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6589                         "\t$Rd, $imm8", "", pattern> {
6590   let Inst{15-12} = cmode;
6591   let DecoderMethod = "DecodeModImmInstruction";
6592 }
6593
6594 //----------------------------------------------------------------------------
6595 // AdvSIMD indexed element
6596 //----------------------------------------------------------------------------
6597
6598 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6599 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6600                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6601                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6602                       string apple_kind, string dst_kind, string lhs_kind,
6603                       string rhs_kind, list<dag> pattern>
6604   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6605       asm,
6606       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6607       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6608     Sched<[WriteV]> {
6609   bits<5> Rd;
6610   bits<5> Rn;
6611   bits<5> Rm;
6612
6613   let Inst{31}    = 0;
6614   let Inst{30}    = Q;
6615   let Inst{29}    = U;
6616   let Inst{28}    = Scalar;
6617   let Inst{27-24} = 0b1111;
6618   let Inst{23-22} = size;
6619   // Bit 21 must be set by the derived class.
6620   let Inst{20-16} = Rm;
6621   let Inst{15-12} = opc;
6622   // Bit 11 must be set by the derived class.
6623   let Inst{10}    = 0;
6624   let Inst{9-5}   = Rn;
6625   let Inst{4-0}   = Rd;
6626 }
6627
6628 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6629 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6630                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6631                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6632                       string apple_kind, string dst_kind, string lhs_kind,
6633                       string rhs_kind, list<dag> pattern>
6634   : I<(outs dst_reg:$dst),
6635       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6636       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6637       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6638     Sched<[WriteV]> {
6639   bits<5> Rd;
6640   bits<5> Rn;
6641   bits<5> Rm;
6642
6643   let Inst{31}    = 0;
6644   let Inst{30}    = Q;
6645   let Inst{29}    = U;
6646   let Inst{28}    = Scalar;
6647   let Inst{27-24} = 0b1111;
6648   let Inst{23-22} = size;
6649   // Bit 21 must be set by the derived class.
6650   let Inst{20-16} = Rm;
6651   let Inst{15-12} = opc;
6652   // Bit 11 must be set by the derived class.
6653   let Inst{10}    = 0;
6654   let Inst{9-5}   = Rn;
6655   let Inst{4-0}   = Rd;
6656 }
6657
6658 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
6659                          SDPatternOperator OpNode> {
6660   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6661                                       V64, V64,
6662                                       V128, VectorIndexS,
6663                                       asm, ".2s", ".2s", ".2s", ".s",
6664     [(set (v2f32 V64:$Rd),
6665         (OpNode (v2f32 V64:$Rn),
6666          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6667     bits<2> idx;
6668     let Inst{11} = idx{1};
6669     let Inst{21} = idx{0};
6670   }
6671
6672   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6673                                       V128, V128,
6674                                       V128, VectorIndexS,
6675                                       asm, ".4s", ".4s", ".4s", ".s",
6676     [(set (v4f32 V128:$Rd),
6677         (OpNode (v4f32 V128:$Rn),
6678          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6679     bits<2> idx;
6680     let Inst{11} = idx{1};
6681     let Inst{21} = idx{0};
6682   }
6683
6684   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6685                                       V128, V128,
6686                                       V128, VectorIndexD,
6687                                       asm, ".2d", ".2d", ".2d", ".d",
6688     [(set (v2f64 V128:$Rd),
6689         (OpNode (v2f64 V128:$Rn),
6690          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6691     bits<1> idx;
6692     let Inst{11} = idx{0};
6693     let Inst{21} = 0;
6694   }
6695
6696   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6697                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6698                                       asm, ".s", "", "", ".s",
6699     [(set (f32 FPR32Op:$Rd),
6700           (OpNode (f32 FPR32Op:$Rn),
6701                   (f32 (vector_extract (v4f32 V128:$Rm),
6702                                        VectorIndexS:$idx))))]> {
6703     bits<2> idx;
6704     let Inst{11} = idx{1};
6705     let Inst{21} = idx{0};
6706   }
6707
6708   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6709                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6710                                       asm, ".d", "", "", ".d",
6711     [(set (f64 FPR64Op:$Rd),
6712           (OpNode (f64 FPR64Op:$Rn),
6713                   (f64 (vector_extract (v2f64 V128:$Rm),
6714                                        VectorIndexD:$idx))))]> {
6715     bits<1> idx;
6716     let Inst{11} = idx{0};
6717     let Inst{21} = 0;
6718   }
6719 }
6720
6721 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
6722   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6723   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6724                            (AArch64duplane32 (v4f32 V128:$Rm),
6725                                            VectorIndexS:$idx))),
6726             (!cast<Instruction>(INST # v2i32_indexed)
6727                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6728   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6729                            (AArch64dup (f32 FPR32Op:$Rm)))),
6730             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6731                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6732
6733
6734   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6735   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6736                            (AArch64duplane32 (v4f32 V128:$Rm),
6737                                            VectorIndexS:$idx))),
6738             (!cast<Instruction>(INST # "v4i32_indexed")
6739                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6740   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6741                            (AArch64dup (f32 FPR32Op:$Rm)))),
6742             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6743                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6744
6745   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6746   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6747                            (AArch64duplane64 (v2f64 V128:$Rm),
6748                                            VectorIndexD:$idx))),
6749             (!cast<Instruction>(INST # "v2i64_indexed")
6750                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6751   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6752                            (AArch64dup (f64 FPR64Op:$Rm)))),
6753             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6754                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6755
6756   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6757   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6758                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6759             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6760                 V128:$Rm, VectorIndexS:$idx)>;
6761   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6762                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6763             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6764                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6765
6766   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6767   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6768                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6769             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6770                 V128:$Rm, VectorIndexD:$idx)>;
6771 }
6772
6773 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
6774   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6775                                           V128, VectorIndexS,
6776                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6777     bits<2> idx;
6778     let Inst{11} = idx{1};
6779     let Inst{21} = idx{0};
6780   }
6781
6782   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6783                                       V128, V128,
6784                                       V128, VectorIndexS,
6785                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6786     bits<2> idx;
6787     let Inst{11} = idx{1};
6788     let Inst{21} = idx{0};
6789   }
6790
6791   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6792                                       V128, V128,
6793                                       V128, VectorIndexD,
6794                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6795     bits<1> idx;
6796     let Inst{11} = idx{0};
6797     let Inst{21} = 0;
6798   }
6799
6800
6801   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6802                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6803                                       asm, ".s", "", "", ".s", []> {
6804     bits<2> idx;
6805     let Inst{11} = idx{1};
6806     let Inst{21} = idx{0};
6807   }
6808
6809   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6810                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6811                                       asm, ".d", "", "", ".d", []> {
6812     bits<1> idx;
6813     let Inst{11} = idx{0};
6814     let Inst{21} = 0;
6815   }
6816 }
6817
6818 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6819                          SDPatternOperator OpNode> {
6820   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6821                                       V128_lo, VectorIndexH,
6822                                       asm, ".4h", ".4h", ".4h", ".h",
6823     [(set (v4i16 V64:$Rd),
6824         (OpNode (v4i16 V64:$Rn),
6825          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6826     bits<3> idx;
6827     let Inst{11} = idx{2};
6828     let Inst{21} = idx{1};
6829     let Inst{20} = idx{0};
6830   }
6831
6832   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6833                                       V128, V128,
6834                                       V128_lo, VectorIndexH,
6835                                       asm, ".8h", ".8h", ".8h", ".h",
6836     [(set (v8i16 V128:$Rd),
6837        (OpNode (v8i16 V128:$Rn),
6838          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6839     bits<3> idx;
6840     let Inst{11} = idx{2};
6841     let Inst{21} = idx{1};
6842     let Inst{20} = idx{0};
6843   }
6844
6845   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6846                                       V64, V64,
6847                                       V128, VectorIndexS,
6848                                       asm, ".2s", ".2s", ".2s",  ".s",
6849     [(set (v2i32 V64:$Rd),
6850        (OpNode (v2i32 V64:$Rn),
6851           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6852     bits<2> idx;
6853     let Inst{11} = idx{1};
6854     let Inst{21} = idx{0};
6855   }
6856
6857   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6858                                       V128, V128,
6859                                       V128, VectorIndexS,
6860                                       asm, ".4s", ".4s", ".4s", ".s",
6861     [(set (v4i32 V128:$Rd),
6862        (OpNode (v4i32 V128:$Rn),
6863           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6864     bits<2> idx;
6865     let Inst{11} = idx{1};
6866     let Inst{21} = idx{0};
6867   }
6868
6869   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6870                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6871                                       asm, ".h", "", "", ".h", []> {
6872     bits<3> idx;
6873     let Inst{11} = idx{2};
6874     let Inst{21} = idx{1};
6875     let Inst{20} = idx{0};
6876   }
6877
6878   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6879                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6880                                       asm, ".s", "", "", ".s",
6881       [(set (i32 FPR32Op:$Rd),
6882             (OpNode FPR32Op:$Rn,
6883                     (i32 (vector_extract (v4i32 V128:$Rm),
6884                                          VectorIndexS:$idx))))]> {
6885     bits<2> idx;
6886     let Inst{11} = idx{1};
6887     let Inst{21} = idx{0};
6888   }
6889 }
6890
6891 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6892                                SDPatternOperator OpNode> {
6893   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6894                                       V64, V64,
6895                                       V128_lo, VectorIndexH,
6896                                       asm, ".4h", ".4h", ".4h", ".h",
6897     [(set (v4i16 V64:$Rd),
6898         (OpNode (v4i16 V64:$Rn),
6899          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6900     bits<3> idx;
6901     let Inst{11} = idx{2};
6902     let Inst{21} = idx{1};
6903     let Inst{20} = idx{0};
6904   }
6905
6906   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6907                                       V128, V128,
6908                                       V128_lo, VectorIndexH,
6909                                       asm, ".8h", ".8h", ".8h", ".h",
6910     [(set (v8i16 V128:$Rd),
6911        (OpNode (v8i16 V128:$Rn),
6912          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6913     bits<3> idx;
6914     let Inst{11} = idx{2};
6915     let Inst{21} = idx{1};
6916     let Inst{20} = idx{0};
6917   }
6918
6919   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6920                                       V64, V64,
6921                                       V128, VectorIndexS,
6922                                       asm, ".2s", ".2s", ".2s", ".s",
6923     [(set (v2i32 V64:$Rd),
6924        (OpNode (v2i32 V64:$Rn),
6925           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6926     bits<2> idx;
6927     let Inst{11} = idx{1};
6928     let Inst{21} = idx{0};
6929   }
6930
6931   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6932                                       V128, V128,
6933                                       V128, VectorIndexS,
6934                                       asm, ".4s", ".4s", ".4s", ".s",
6935     [(set (v4i32 V128:$Rd),
6936        (OpNode (v4i32 V128:$Rn),
6937           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6938     bits<2> idx;
6939     let Inst{11} = idx{1};
6940     let Inst{21} = idx{0};
6941   }
6942 }
6943
6944 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6945                                    SDPatternOperator OpNode> {
6946   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6947                                           V128_lo, VectorIndexH,
6948                                           asm, ".4h", ".4h", ".4h", ".h",
6949     [(set (v4i16 V64:$dst),
6950         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6951          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6952     bits<3> idx;
6953     let Inst{11} = idx{2};
6954     let Inst{21} = idx{1};
6955     let Inst{20} = idx{0};
6956   }
6957
6958   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6959                                       V128, V128,
6960                                       V128_lo, VectorIndexH,
6961                                       asm, ".8h", ".8h", ".8h", ".h",
6962     [(set (v8i16 V128:$dst),
6963        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6964          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6965     bits<3> idx;
6966     let Inst{11} = idx{2};
6967     let Inst{21} = idx{1};
6968     let Inst{20} = idx{0};
6969   }
6970
6971   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6972                                       V64, V64,
6973                                       V128, VectorIndexS,
6974                                       asm, ".2s", ".2s", ".2s", ".s",
6975     [(set (v2i32 V64:$dst),
6976        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6977           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6978     bits<2> idx;
6979     let Inst{11} = idx{1};
6980     let Inst{21} = idx{0};
6981   }
6982
6983   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6984                                       V128, V128,
6985                                       V128, VectorIndexS,
6986                                       asm, ".4s", ".4s", ".4s", ".s",
6987     [(set (v4i32 V128:$dst),
6988        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6989           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6990     bits<2> idx;
6991     let Inst{11} = idx{1};
6992     let Inst{21} = idx{0};
6993   }
6994 }
6995
6996 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6997                              SDPatternOperator OpNode> {
6998   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6999                                       V128, V64,
7000                                       V128_lo, VectorIndexH,
7001                                       asm, ".4s", ".4s", ".4h", ".h",
7002     [(set (v4i32 V128:$Rd),
7003         (OpNode (v4i16 V64:$Rn),
7004          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7005     bits<3> idx;
7006     let Inst{11} = idx{2};
7007     let Inst{21} = idx{1};
7008     let Inst{20} = idx{0};
7009   }
7010
7011   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7012                                       V128, V128,
7013                                       V128_lo, VectorIndexH,
7014                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7015     [(set (v4i32 V128:$Rd),
7016           (OpNode (extract_high_v8i16 V128:$Rn),
7017                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7018                                                       VectorIndexH:$idx))))]> {
7019
7020     bits<3> idx;
7021     let Inst{11} = idx{2};
7022     let Inst{21} = idx{1};
7023     let Inst{20} = idx{0};
7024   }
7025
7026   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7027                                       V128, V64,
7028                                       V128, VectorIndexS,
7029                                       asm, ".2d", ".2d", ".2s", ".s",
7030     [(set (v2i64 V128:$Rd),
7031         (OpNode (v2i32 V64:$Rn),
7032          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7033     bits<2> idx;
7034     let Inst{11} = idx{1};
7035     let Inst{21} = idx{0};
7036   }
7037
7038   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7039                                       V128, V128,
7040                                       V128, VectorIndexS,
7041                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7042     [(set (v2i64 V128:$Rd),
7043           (OpNode (extract_high_v4i32 V128:$Rn),
7044                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7045                                                       VectorIndexS:$idx))))]> {
7046     bits<2> idx;
7047     let Inst{11} = idx{1};
7048     let Inst{21} = idx{0};
7049   }
7050
7051   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7052                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7053                                       asm, ".h", "", "", ".h", []> {
7054     bits<3> idx;
7055     let Inst{11} = idx{2};
7056     let Inst{21} = idx{1};
7057     let Inst{20} = idx{0};
7058   }
7059
7060   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7061                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7062                                       asm, ".s", "", "", ".s", []> {
7063     bits<2> idx;
7064     let Inst{11} = idx{1};
7065     let Inst{21} = idx{0};
7066   }
7067 }
7068
7069 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
7070                                        SDPatternOperator Accum> {
7071   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7072                                       V128, V64,
7073                                       V128_lo, VectorIndexH,
7074                                       asm, ".4s", ".4s", ".4h", ".h",
7075     [(set (v4i32 V128:$dst),
7076           (Accum (v4i32 V128:$Rd),
7077                  (v4i32 (int_aarch64_neon_sqdmull
7078                              (v4i16 V64:$Rn),
7079                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7080                                                     VectorIndexH:$idx))))))]> {
7081     bits<3> idx;
7082     let Inst{11} = idx{2};
7083     let Inst{21} = idx{1};
7084     let Inst{20} = idx{0};
7085   }
7086
7087   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
7088   // intermediate EXTRACT_SUBREG would be untyped.
7089   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
7090                 (i32 (vector_extract (v4i32
7091                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7092                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7093                                                     VectorIndexH:$idx)))),
7094                          (i64 0))))),
7095             (EXTRACT_SUBREG
7096                 (!cast<Instruction>(NAME # v4i16_indexed)
7097                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
7098                     V128_lo:$Rm, VectorIndexH:$idx),
7099                 ssub)>;
7100
7101   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7102                                       V128, V128,
7103                                       V128_lo, VectorIndexH,
7104                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7105     [(set (v4i32 V128:$dst),
7106           (Accum (v4i32 V128:$Rd),
7107                  (v4i32 (int_aarch64_neon_sqdmull
7108                             (extract_high_v8i16 V128:$Rn),
7109                             (extract_high_v8i16
7110                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7111                                                 VectorIndexH:$idx))))))]> {
7112     bits<3> idx;
7113     let Inst{11} = idx{2};
7114     let Inst{21} = idx{1};
7115     let Inst{20} = idx{0};
7116   }
7117
7118   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7119                                       V128, V64,
7120                                       V128, VectorIndexS,
7121                                       asm, ".2d", ".2d", ".2s", ".s",
7122     [(set (v2i64 V128:$dst),
7123         (Accum (v2i64 V128:$Rd),
7124                (v2i64 (int_aarch64_neon_sqdmull
7125                           (v2i32 V64:$Rn),
7126                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
7127                                                  VectorIndexS:$idx))))))]> {
7128     bits<2> idx;
7129     let Inst{11} = idx{1};
7130     let Inst{21} = idx{0};
7131   }
7132
7133   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7134                                       V128, V128,
7135                                       V128, VectorIndexS,
7136                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7137     [(set (v2i64 V128:$dst),
7138           (Accum (v2i64 V128:$Rd),
7139                  (v2i64 (int_aarch64_neon_sqdmull
7140                             (extract_high_v4i32 V128:$Rn),
7141                             (extract_high_v4i32
7142                                 (AArch64duplane32 (v4i32 V128:$Rm),
7143                                                 VectorIndexS:$idx))))))]> {
7144     bits<2> idx;
7145     let Inst{11} = idx{1};
7146     let Inst{21} = idx{0};
7147   }
7148
7149   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
7150                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7151                                       asm, ".h", "", "", ".h", []> {
7152     bits<3> idx;
7153     let Inst{11} = idx{2};
7154     let Inst{21} = idx{1};
7155     let Inst{20} = idx{0};
7156   }
7157
7158
7159   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7160                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7161                                       asm, ".s", "", "", ".s",
7162     [(set (i64 FPR64Op:$dst),
7163           (Accum (i64 FPR64Op:$Rd),
7164                  (i64 (int_aarch64_neon_sqdmulls_scalar
7165                             (i32 FPR32Op:$Rn),
7166                             (i32 (vector_extract (v4i32 V128:$Rm),
7167                                                  VectorIndexS:$idx))))))]> {
7168
7169     bits<2> idx;
7170     let Inst{11} = idx{1};
7171     let Inst{21} = idx{0};
7172   }
7173 }
7174
7175 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
7176                                    SDPatternOperator OpNode> {
7177   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7178   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7179                                       V128, V64,
7180                                       V128_lo, VectorIndexH,
7181                                       asm, ".4s", ".4s", ".4h", ".h",
7182     [(set (v4i32 V128:$Rd),
7183         (OpNode (v4i16 V64:$Rn),
7184          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7185     bits<3> idx;
7186     let Inst{11} = idx{2};
7187     let Inst{21} = idx{1};
7188     let Inst{20} = idx{0};
7189   }
7190
7191   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7192                                       V128, V128,
7193                                       V128_lo, VectorIndexH,
7194                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7195     [(set (v4i32 V128:$Rd),
7196           (OpNode (extract_high_v8i16 V128:$Rn),
7197                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7198                                                       VectorIndexH:$idx))))]> {
7199
7200     bits<3> idx;
7201     let Inst{11} = idx{2};
7202     let Inst{21} = idx{1};
7203     let Inst{20} = idx{0};
7204   }
7205
7206   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7207                                       V128, V64,
7208                                       V128, VectorIndexS,
7209                                       asm, ".2d", ".2d", ".2s", ".s",
7210     [(set (v2i64 V128:$Rd),
7211         (OpNode (v2i32 V64:$Rn),
7212          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7213     bits<2> idx;
7214     let Inst{11} = idx{1};
7215     let Inst{21} = idx{0};
7216   }
7217
7218   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7219                                       V128, V128,
7220                                       V128, VectorIndexS,
7221                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7222     [(set (v2i64 V128:$Rd),
7223           (OpNode (extract_high_v4i32 V128:$Rn),
7224                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7225                                                       VectorIndexS:$idx))))]> {
7226     bits<2> idx;
7227     let Inst{11} = idx{1};
7228     let Inst{21} = idx{0};
7229   }
7230   }
7231 }
7232
7233 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7234                                        SDPatternOperator OpNode> {
7235   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7236   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7237                                       V128, V64,
7238                                       V128_lo, VectorIndexH,
7239                                       asm, ".4s", ".4s", ".4h", ".h",
7240     [(set (v4i32 V128:$dst),
7241         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7242          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7243     bits<3> idx;
7244     let Inst{11} = idx{2};
7245     let Inst{21} = idx{1};
7246     let Inst{20} = idx{0};
7247   }
7248
7249   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7250                                       V128, V128,
7251                                       V128_lo, VectorIndexH,
7252                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7253     [(set (v4i32 V128:$dst),
7254           (OpNode (v4i32 V128:$Rd),
7255                   (extract_high_v8i16 V128:$Rn),
7256                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7257                                                       VectorIndexH:$idx))))]> {
7258     bits<3> idx;
7259     let Inst{11} = idx{2};
7260     let Inst{21} = idx{1};
7261     let Inst{20} = idx{0};
7262   }
7263
7264   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7265                                       V128, V64,
7266                                       V128, VectorIndexS,
7267                                       asm, ".2d", ".2d", ".2s", ".s",
7268     [(set (v2i64 V128:$dst),
7269         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7270          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7271     bits<2> idx;
7272     let Inst{11} = idx{1};
7273     let Inst{21} = idx{0};
7274   }
7275
7276   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7277                                       V128, V128,
7278                                       V128, VectorIndexS,
7279                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7280     [(set (v2i64 V128:$dst),
7281           (OpNode (v2i64 V128:$Rd),
7282                   (extract_high_v4i32 V128:$Rn),
7283                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7284                                                       VectorIndexS:$idx))))]> {
7285     bits<2> idx;
7286     let Inst{11} = idx{1};
7287     let Inst{21} = idx{0};
7288   }
7289   }
7290 }
7291
7292 //----------------------------------------------------------------------------
7293 // AdvSIMD scalar shift by immediate
7294 //----------------------------------------------------------------------------
7295
7296 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7297 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7298                      RegisterClass regtype1, RegisterClass regtype2,
7299                      Operand immtype, string asm, list<dag> pattern>
7300   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7301       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7302     Sched<[WriteV]> {
7303   bits<5> Rd;
7304   bits<5> Rn;
7305   bits<7> imm;
7306   let Inst{31-30} = 0b01;
7307   let Inst{29}    = U;
7308   let Inst{28-23} = 0b111110;
7309   let Inst{22-16} = fixed_imm;
7310   let Inst{15-11} = opc;
7311   let Inst{10}    = 1;
7312   let Inst{9-5} = Rn;
7313   let Inst{4-0} = Rd;
7314 }
7315
7316 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7317 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7318                      RegisterClass regtype1, RegisterClass regtype2,
7319                      Operand immtype, string asm, list<dag> pattern>
7320   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7321       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7322     Sched<[WriteV]> {
7323   bits<5> Rd;
7324   bits<5> Rn;
7325   bits<7> imm;
7326   let Inst{31-30} = 0b01;
7327   let Inst{29}    = U;
7328   let Inst{28-23} = 0b111110;
7329   let Inst{22-16} = fixed_imm;
7330   let Inst{15-11} = opc;
7331   let Inst{10}    = 1;
7332   let Inst{9-5} = Rn;
7333   let Inst{4-0} = Rd;
7334 }
7335
7336
7337 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
7338   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7339                               FPR32, FPR32, vecshiftR32, asm, []> {
7340     let Inst{20-16} = imm{4-0};
7341   }
7342
7343   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7344                               FPR64, FPR64, vecshiftR64, asm, []> {
7345     let Inst{21-16} = imm{5-0};
7346   }
7347 }
7348
7349 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7350                              SDPatternOperator OpNode> {
7351   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7352                               FPR64, FPR64, vecshiftR64, asm,
7353   [(set (i64 FPR64:$Rd),
7354      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7355     let Inst{21-16} = imm{5-0};
7356   }
7357
7358   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7359             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7360 }
7361
7362 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7363                                  SDPatternOperator OpNode = null_frag> {
7364   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7365                               FPR64, FPR64, vecshiftR64, asm,
7366   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7367                                                    (i32 vecshiftR64:$imm)))]> {
7368     let Inst{21-16} = imm{5-0};
7369   }
7370
7371   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7372                            (i32 vecshiftR64:$imm))),
7373             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7374                                             vecshiftR64:$imm)>;
7375 }
7376
7377 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7378                              SDPatternOperator OpNode> {
7379   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7380                               FPR64, FPR64, vecshiftL64, asm,
7381     [(set (v1i64 FPR64:$Rd),
7382        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7383     let Inst{21-16} = imm{5-0};
7384   }
7385 }
7386
7387 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7388 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7389   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7390                               FPR64, FPR64, vecshiftL64, asm, []> {
7391     let Inst{21-16} = imm{5-0};
7392   }
7393 }
7394
7395 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7396 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7397                                SDPatternOperator OpNode = null_frag> {
7398   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7399                               FPR8, FPR16, vecshiftR8, asm, []> {
7400     let Inst{18-16} = imm{2-0};
7401   }
7402
7403   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7404                               FPR16, FPR32, vecshiftR16, asm, []> {
7405     let Inst{19-16} = imm{3-0};
7406   }
7407
7408   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7409                               FPR32, FPR64, vecshiftR32, asm,
7410     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7411     let Inst{20-16} = imm{4-0};
7412   }
7413 }
7414
7415 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7416                                 SDPatternOperator OpNode> {
7417   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7418                               FPR8, FPR8, vecshiftL8, asm, []> {
7419     let Inst{18-16} = imm{2-0};
7420   }
7421
7422   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7423                               FPR16, FPR16, vecshiftL16, asm, []> {
7424     let Inst{19-16} = imm{3-0};
7425   }
7426
7427   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7428                               FPR32, FPR32, vecshiftL32, asm,
7429     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7430     let Inst{20-16} = imm{4-0};
7431   }
7432
7433   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7434                               FPR64, FPR64, vecshiftL64, asm,
7435     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7436     let Inst{21-16} = imm{5-0};
7437   }
7438
7439   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7440             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7441 }
7442
7443 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7444   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7445                               FPR8, FPR8, vecshiftR8, asm, []> {
7446     let Inst{18-16} = imm{2-0};
7447   }
7448
7449   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7450                               FPR16, FPR16, vecshiftR16, asm, []> {
7451     let Inst{19-16} = imm{3-0};
7452   }
7453
7454   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7455                               FPR32, FPR32, vecshiftR32, asm, []> {
7456     let Inst{20-16} = imm{4-0};
7457   }
7458
7459   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7460                               FPR64, FPR64, vecshiftR64, asm, []> {
7461     let Inst{21-16} = imm{5-0};
7462   }
7463 }
7464
7465 //----------------------------------------------------------------------------
7466 // AdvSIMD vector x indexed element
7467 //----------------------------------------------------------------------------
7468
7469 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7470 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7471                      RegisterOperand dst_reg, RegisterOperand src_reg,
7472                      Operand immtype,
7473                      string asm, string dst_kind, string src_kind,
7474                      list<dag> pattern>
7475   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7476       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7477            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7478     Sched<[WriteV]> {
7479   bits<5> Rd;
7480   bits<5> Rn;
7481   let Inst{31}    = 0;
7482   let Inst{30}    = Q;
7483   let Inst{29}    = U;
7484   let Inst{28-23} = 0b011110;
7485   let Inst{22-16} = fixed_imm;
7486   let Inst{15-11} = opc;
7487   let Inst{10}    = 1;
7488   let Inst{9-5}   = Rn;
7489   let Inst{4-0}   = Rd;
7490 }
7491
7492 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7493 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7494                      RegisterOperand vectype1, RegisterOperand vectype2,
7495                      Operand immtype,
7496                      string asm, string dst_kind, string src_kind,
7497                      list<dag> pattern>
7498   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7499       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7500            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7501     Sched<[WriteV]> {
7502   bits<5> Rd;
7503   bits<5> Rn;
7504   let Inst{31}    = 0;
7505   let Inst{30}    = Q;
7506   let Inst{29}    = U;
7507   let Inst{28-23} = 0b011110;
7508   let Inst{22-16} = fixed_imm;
7509   let Inst{15-11} = opc;
7510   let Inst{10}    = 1;
7511   let Inst{9-5}   = Rn;
7512   let Inst{4-0}   = Rd;
7513 }
7514
7515 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7516                               Intrinsic OpNode> {
7517   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7518                                   V64, V64, vecshiftR32,
7519                                   asm, ".2s", ".2s",
7520       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
7521     bits<5> imm;
7522     let Inst{20-16} = imm;
7523   }
7524
7525   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7526                                   V128, V128, vecshiftR32,
7527                                   asm, ".4s", ".4s",
7528       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7529     bits<5> imm;
7530     let Inst{20-16} = imm;
7531   }
7532
7533   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7534                                   V128, V128, vecshiftR64,
7535                                   asm, ".2d", ".2d",
7536       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7537     bits<6> imm;
7538     let Inst{21-16} = imm;
7539   }
7540 }
7541
7542 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
7543                                   Intrinsic OpNode> {
7544   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7545                                   V64, V64, vecshiftR32,
7546                                   asm, ".2s", ".2s",
7547       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7548     bits<5> imm;
7549     let Inst{20-16} = imm;
7550   }
7551
7552   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7553                                   V128, V128, vecshiftR32,
7554                                   asm, ".4s", ".4s",
7555       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7556     bits<5> imm;
7557     let Inst{20-16} = imm;
7558   }
7559
7560   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7561                                   V128, V128, vecshiftR64,
7562                                   asm, ".2d", ".2d",
7563       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7564     bits<6> imm;
7565     let Inst{21-16} = imm;
7566   }
7567 }
7568
7569 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7570                                      SDPatternOperator OpNode> {
7571   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7572                                   V64, V128, vecshiftR16Narrow,
7573                                   asm, ".8b", ".8h",
7574       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7575     bits<3> imm;
7576     let Inst{18-16} = imm;
7577   }
7578
7579   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7580                                   V128, V128, vecshiftR16Narrow,
7581                                   asm#"2", ".16b", ".8h", []> {
7582     bits<3> imm;
7583     let Inst{18-16} = imm;
7584     let hasSideEffects = 0;
7585   }
7586
7587   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7588                                   V64, V128, vecshiftR32Narrow,
7589                                   asm, ".4h", ".4s",
7590       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7591     bits<4> imm;
7592     let Inst{19-16} = imm;
7593   }
7594
7595   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7596                                   V128, V128, vecshiftR32Narrow,
7597                                   asm#"2", ".8h", ".4s", []> {
7598     bits<4> imm;
7599     let Inst{19-16} = imm;
7600     let hasSideEffects = 0;
7601   }
7602
7603   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7604                                   V64, V128, vecshiftR64Narrow,
7605                                   asm, ".2s", ".2d",
7606       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7607     bits<5> imm;
7608     let Inst{20-16} = imm;
7609   }
7610
7611   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7612                                   V128, V128, vecshiftR64Narrow,
7613                                   asm#"2", ".4s", ".2d", []> {
7614     bits<5> imm;
7615     let Inst{20-16} = imm;
7616     let hasSideEffects = 0;
7617   }
7618
7619   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7620   // themselves, so put them here instead.
7621
7622   // Patterns involving what's effectively an insert high and a normal
7623   // intrinsic, represented by CONCAT_VECTORS.
7624   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7625                                                    vecshiftR16Narrow:$imm)),
7626             (!cast<Instruction>(NAME # "v16i8_shift")
7627                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7628                 V128:$Rn, vecshiftR16Narrow:$imm)>;
7629   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7630                                                      vecshiftR32Narrow:$imm)),
7631             (!cast<Instruction>(NAME # "v8i16_shift")
7632                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7633                 V128:$Rn, vecshiftR32Narrow:$imm)>;
7634   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7635                                                      vecshiftR64Narrow:$imm)),
7636             (!cast<Instruction>(NAME # "v4i32_shift")
7637                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7638                 V128:$Rn, vecshiftR64Narrow:$imm)>;
7639 }
7640
7641 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7642                                 SDPatternOperator OpNode> {
7643   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7644                                   V64, V64, vecshiftL8,
7645                                   asm, ".8b", ".8b",
7646                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7647                        (i32 vecshiftL8:$imm)))]> {
7648     bits<3> imm;
7649     let Inst{18-16} = imm;
7650   }
7651
7652   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7653                                   V128, V128, vecshiftL8,
7654                                   asm, ".16b", ".16b",
7655              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7656                    (i32 vecshiftL8:$imm)))]> {
7657     bits<3> imm;
7658     let Inst{18-16} = imm;
7659   }
7660
7661   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7662                                   V64, V64, vecshiftL16,
7663                                   asm, ".4h", ".4h",
7664               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7665                     (i32 vecshiftL16:$imm)))]> {
7666     bits<4> imm;
7667     let Inst{19-16} = imm;
7668   }
7669
7670   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7671                                   V128, V128, vecshiftL16,
7672                                   asm, ".8h", ".8h",
7673             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7674                   (i32 vecshiftL16:$imm)))]> {
7675     bits<4> imm;
7676     let Inst{19-16} = imm;
7677   }
7678
7679   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7680                                   V64, V64, vecshiftL32,
7681                                   asm, ".2s", ".2s",
7682               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7683                     (i32 vecshiftL32:$imm)))]> {
7684     bits<5> imm;
7685     let Inst{20-16} = imm;
7686   }
7687
7688   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7689                                   V128, V128, vecshiftL32,
7690                                   asm, ".4s", ".4s",
7691             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7692                   (i32 vecshiftL32:$imm)))]> {
7693     bits<5> imm;
7694     let Inst{20-16} = imm;
7695   }
7696
7697   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7698                                   V128, V128, vecshiftL64,
7699                                   asm, ".2d", ".2d",
7700             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7701                   (i32 vecshiftL64:$imm)))]> {
7702     bits<6> imm;
7703     let Inst{21-16} = imm;
7704   }
7705 }
7706
7707 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7708                                 SDPatternOperator OpNode> {
7709   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7710                                   V64, V64, vecshiftR8,
7711                                   asm, ".8b", ".8b",
7712                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7713                        (i32 vecshiftR8:$imm)))]> {
7714     bits<3> imm;
7715     let Inst{18-16} = imm;
7716   }
7717
7718   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7719                                   V128, V128, vecshiftR8,
7720                                   asm, ".16b", ".16b",
7721              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7722                    (i32 vecshiftR8:$imm)))]> {
7723     bits<3> imm;
7724     let Inst{18-16} = imm;
7725   }
7726
7727   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7728                                   V64, V64, vecshiftR16,
7729                                   asm, ".4h", ".4h",
7730               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7731                     (i32 vecshiftR16:$imm)))]> {
7732     bits<4> imm;
7733     let Inst{19-16} = imm;
7734   }
7735
7736   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7737                                   V128, V128, vecshiftR16,
7738                                   asm, ".8h", ".8h",
7739             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7740                   (i32 vecshiftR16:$imm)))]> {
7741     bits<4> imm;
7742     let Inst{19-16} = imm;
7743   }
7744
7745   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7746                                   V64, V64, vecshiftR32,
7747                                   asm, ".2s", ".2s",
7748               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7749                     (i32 vecshiftR32:$imm)))]> {
7750     bits<5> imm;
7751     let Inst{20-16} = imm;
7752   }
7753
7754   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7755                                   V128, V128, vecshiftR32,
7756                                   asm, ".4s", ".4s",
7757             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7758                   (i32 vecshiftR32:$imm)))]> {
7759     bits<5> imm;
7760     let Inst{20-16} = imm;
7761   }
7762
7763   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7764                                   V128, V128, vecshiftR64,
7765                                   asm, ".2d", ".2d",
7766             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7767                   (i32 vecshiftR64:$imm)))]> {
7768     bits<6> imm;
7769     let Inst{21-16} = imm;
7770   }
7771 }
7772
7773 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7774 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7775                                     SDPatternOperator OpNode = null_frag> {
7776   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7777                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
7778                  [(set (v8i8 V64:$dst),
7779                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7780                            (i32 vecshiftR8:$imm)))]> {
7781     bits<3> imm;
7782     let Inst{18-16} = imm;
7783   }
7784
7785   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7786                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
7787              [(set (v16i8 V128:$dst),
7788                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7789                        (i32 vecshiftR8:$imm)))]> {
7790     bits<3> imm;
7791     let Inst{18-16} = imm;
7792   }
7793
7794   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7795                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
7796               [(set (v4i16 V64:$dst),
7797                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7798                         (i32 vecshiftR16:$imm)))]> {
7799     bits<4> imm;
7800     let Inst{19-16} = imm;
7801   }
7802
7803   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7804                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
7805             [(set (v8i16 V128:$dst),
7806               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7807                       (i32 vecshiftR16:$imm)))]> {
7808     bits<4> imm;
7809     let Inst{19-16} = imm;
7810   }
7811
7812   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7813                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
7814               [(set (v2i32 V64:$dst),
7815                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7816                         (i32 vecshiftR32:$imm)))]> {
7817     bits<5> imm;
7818     let Inst{20-16} = imm;
7819   }
7820
7821   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7822                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
7823             [(set (v4i32 V128:$dst),
7824               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7825                       (i32 vecshiftR32:$imm)))]> {
7826     bits<5> imm;
7827     let Inst{20-16} = imm;
7828   }
7829
7830   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7831                                   V128, V128, vecshiftR64,
7832                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7833               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7834                       (i32 vecshiftR64:$imm)))]> {
7835     bits<6> imm;
7836     let Inst{21-16} = imm;
7837   }
7838 }
7839
7840 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7841                                     SDPatternOperator OpNode = null_frag> {
7842   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7843                                   V64, V64, vecshiftL8,
7844                                   asm, ".8b", ".8b",
7845                     [(set (v8i8 V64:$dst),
7846                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7847                                   (i32 vecshiftL8:$imm)))]> {
7848     bits<3> imm;
7849     let Inst{18-16} = imm;
7850   }
7851
7852   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7853                                   V128, V128, vecshiftL8,
7854                                   asm, ".16b", ".16b",
7855                     [(set (v16i8 V128:$dst),
7856                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7857                                   (i32 vecshiftL8:$imm)))]> {
7858     bits<3> imm;
7859     let Inst{18-16} = imm;
7860   }
7861
7862   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7863                                   V64, V64, vecshiftL16,
7864                                   asm, ".4h", ".4h",
7865                     [(set (v4i16 V64:$dst),
7866                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7867                                    (i32 vecshiftL16:$imm)))]> {
7868     bits<4> imm;
7869     let Inst{19-16} = imm;
7870   }
7871
7872   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7873                                   V128, V128, vecshiftL16,
7874                                   asm, ".8h", ".8h",
7875                     [(set (v8i16 V128:$dst),
7876                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7877                                   (i32 vecshiftL16:$imm)))]> {
7878     bits<4> imm;
7879     let Inst{19-16} = imm;
7880   }
7881
7882   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7883                                   V64, V64, vecshiftL32,
7884                                   asm, ".2s", ".2s",
7885                     [(set (v2i32 V64:$dst),
7886                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7887                                   (i32 vecshiftL32:$imm)))]> {
7888     bits<5> imm;
7889     let Inst{20-16} = imm;
7890   }
7891
7892   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7893                                   V128, V128, vecshiftL32,
7894                                   asm, ".4s", ".4s",
7895                     [(set (v4i32 V128:$dst),
7896                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7897                                   (i32 vecshiftL32:$imm)))]> {
7898     bits<5> imm;
7899     let Inst{20-16} = imm;
7900   }
7901
7902   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7903                                   V128, V128, vecshiftL64,
7904                                   asm, ".2d", ".2d",
7905                     [(set (v2i64 V128:$dst),
7906                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7907                                   (i32 vecshiftL64:$imm)))]> {
7908     bits<6> imm;
7909     let Inst{21-16} = imm;
7910   }
7911 }
7912
7913 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7914                                    SDPatternOperator OpNode> {
7915   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7916                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
7917       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7918     bits<3> imm;
7919     let Inst{18-16} = imm;
7920   }
7921
7922   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7923                                   V128, V128, vecshiftL8,
7924                                   asm#"2", ".8h", ".16b",
7925       [(set (v8i16 V128:$Rd),
7926             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7927     bits<3> imm;
7928     let Inst{18-16} = imm;
7929   }
7930
7931   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7932                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
7933       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7934     bits<4> imm;
7935     let Inst{19-16} = imm;
7936   }
7937
7938   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7939                                   V128, V128, vecshiftL16,
7940                                   asm#"2", ".4s", ".8h",
7941       [(set (v4i32 V128:$Rd),
7942             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7943
7944     bits<4> imm;
7945     let Inst{19-16} = imm;
7946   }
7947
7948   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7949                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
7950       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7951     bits<5> imm;
7952     let Inst{20-16} = imm;
7953   }
7954
7955   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7956                                   V128, V128, vecshiftL32,
7957                                   asm#"2", ".2d", ".4s",
7958       [(set (v2i64 V128:$Rd),
7959             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7960     bits<5> imm;
7961     let Inst{20-16} = imm;
7962   }
7963 }
7964
7965
7966 //---
7967 // Vector load/store
7968 //---
7969 // SIMD ldX/stX no-index memory references don't allow the optional
7970 // ", #0" constant and handle post-indexing explicitly, so we use
7971 // a more specialized parse method for them. Otherwise, it's the same as
7972 // the general GPR64sp handling.
7973
7974 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7975                    string asm, dag oops, dag iops, list<dag> pattern>
7976   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
7977   bits<5> Vt;
7978   bits<5> Rn;
7979   let Inst{31} = 0;
7980   let Inst{30} = Q;
7981   let Inst{29-23} = 0b0011000;
7982   let Inst{22} = L;
7983   let Inst{21-16} = 0b000000;
7984   let Inst{15-12} = opcode;
7985   let Inst{11-10} = size;
7986   let Inst{9-5} = Rn;
7987   let Inst{4-0} = Vt;
7988 }
7989
7990 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7991                        string asm, dag oops, dag iops>
7992   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
7993   bits<5> Vt;
7994   bits<5> Rn;
7995   bits<5> Xm;
7996   let Inst{31} = 0;
7997   let Inst{30} = Q;
7998   let Inst{29-23} = 0b0011001;
7999   let Inst{22} = L;
8000   let Inst{21} = 0;
8001   let Inst{20-16} = Xm;
8002   let Inst{15-12} = opcode;
8003   let Inst{11-10} = size;
8004   let Inst{9-5} = Rn;
8005   let Inst{4-0} = Vt;
8006 }
8007
8008 // The immediate form of AdvSIMD post-indexed addressing is encoded with
8009 // register post-index addressing from the zero register.
8010 multiclass SIMDLdStAliases<string asm, string layout, string Count,
8011                            int Offset, int Size> {
8012   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8013   //      "ld1\t$Vt, [$Rn], #16"
8014   // may get mapped to
8015   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8016   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8017                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8018                       GPR64sp:$Rn,
8019                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8020                       XZR), 1>;
8021
8022   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8023   //      "ld1.8b\t$Vt, [$Rn], #16"
8024   // may get mapped to
8025   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8026   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8027                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8028                       GPR64sp:$Rn,
8029                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8030                       XZR), 0>;
8031
8032   // E.g. "ld1.8b { v0, v1 }, [x1]"
8033   //      "ld1\t$Vt, [$Rn]"
8034   // may get mapped to
8035   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
8036   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8037                   (!cast<Instruction>(NAME # Count # "v" # layout)
8038                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8039                       GPR64sp:$Rn), 0>;
8040
8041   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
8042   //      "ld1\t$Vt, [$Rn], $Xm"
8043   // may get mapped to
8044   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
8045   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8046                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8047                       GPR64sp:$Rn,
8048                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8049                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8050 }
8051
8052 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
8053                        int Offset64, bits<4> opcode> {
8054   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8055     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
8056                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
8057                            (ins GPR64sp:$Rn), []>;
8058     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
8059                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
8060                            (ins GPR64sp:$Rn), []>;
8061     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
8062                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
8063                            (ins GPR64sp:$Rn), []>;
8064     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
8065                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
8066                            (ins GPR64sp:$Rn), []>;
8067     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
8068                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
8069                            (ins GPR64sp:$Rn), []>;
8070     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
8071                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
8072                            (ins GPR64sp:$Rn), []>;
8073     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
8074                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
8075                            (ins GPR64sp:$Rn), []>;
8076
8077
8078     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
8079                        (outs GPR64sp:$wback,
8080                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
8081                        (ins GPR64sp:$Rn,
8082                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8083     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
8084                        (outs GPR64sp:$wback,
8085                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
8086                        (ins GPR64sp:$Rn,
8087                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8088     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
8089                        (outs GPR64sp:$wback,
8090                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
8091                        (ins GPR64sp:$Rn,
8092                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8093     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
8094                        (outs GPR64sp:$wback,
8095                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
8096                        (ins GPR64sp:$Rn,
8097                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8098     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
8099                        (outs GPR64sp:$wback,
8100                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
8101                        (ins GPR64sp:$Rn,
8102                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8103     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
8104                        (outs GPR64sp:$wback,
8105                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
8106                        (ins GPR64sp:$Rn,
8107                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8108     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
8109                        (outs GPR64sp:$wback,
8110                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
8111                        (ins GPR64sp:$Rn,
8112                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8113   }
8114
8115   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8116   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8117   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8118   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8119   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8120   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8121   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8122 }
8123
8124 // Only ld1/st1 has a v1d version.
8125 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
8126                        int Offset64, bits<4> opcode> {
8127   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
8128     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
8129                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8130                                  GPR64sp:$Rn), []>;
8131     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
8132                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8133                                 GPR64sp:$Rn), []>;
8134     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
8135                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8136                                 GPR64sp:$Rn), []>;
8137     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
8138                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8139                                 GPR64sp:$Rn), []>;
8140     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
8141                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8142                                 GPR64sp:$Rn), []>;
8143     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
8144                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8145                                 GPR64sp:$Rn), []>;
8146     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
8147                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8148                                 GPR64sp:$Rn), []>;
8149
8150     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
8151                        (outs GPR64sp:$wback),
8152                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8153                             GPR64sp:$Rn,
8154                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8155     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
8156                        (outs GPR64sp:$wback),
8157                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8158                             GPR64sp:$Rn,
8159                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8160     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
8161                        (outs GPR64sp:$wback),
8162                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8163                             GPR64sp:$Rn,
8164                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8165     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
8166                        (outs GPR64sp:$wback),
8167                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8168                             GPR64sp:$Rn,
8169                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8170     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
8171                        (outs GPR64sp:$wback),
8172                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8173                             GPR64sp:$Rn,
8174                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8175     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
8176                        (outs GPR64sp:$wback),
8177                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8178                             GPR64sp:$Rn,
8179                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8180     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
8181                        (outs GPR64sp:$wback),
8182                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8183                             GPR64sp:$Rn,
8184                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8185   }
8186
8187   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8188   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8189   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8190   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8191   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8192   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8193   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8194 }
8195
8196 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
8197                        int Offset128, int Offset64, bits<4> opcode>
8198   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
8199
8200   // LD1 instructions have extra "1d" variants.
8201   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8202     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8203                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8204                            (ins GPR64sp:$Rn), []>;
8205
8206     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8207                        (outs GPR64sp:$wback,
8208                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
8209                        (ins GPR64sp:$Rn,
8210                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8211   }
8212
8213   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8214 }
8215
8216 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
8217                        int Offset128, int Offset64, bits<4> opcode>
8218   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
8219
8220   // ST1 instructions have extra "1d" variants.
8221   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8222     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8223                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8224                                 GPR64sp:$Rn), []>;
8225
8226     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8227                        (outs GPR64sp:$wback),
8228                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8229                             GPR64sp:$Rn,
8230                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8231   }
8232
8233   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8234 }
8235
8236 multiclass SIMDLd1Multiple<string asm> {
8237   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8238   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8239   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8240   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8241 }
8242
8243 multiclass SIMDSt1Multiple<string asm> {
8244   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8245   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8246   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8247   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8248 }
8249
8250 multiclass SIMDLd2Multiple<string asm> {
8251   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8252 }
8253
8254 multiclass SIMDSt2Multiple<string asm> {
8255   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8256 }
8257
8258 multiclass SIMDLd3Multiple<string asm> {
8259   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8260 }
8261
8262 multiclass SIMDSt3Multiple<string asm> {
8263   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8264 }
8265
8266 multiclass SIMDLd4Multiple<string asm> {
8267   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8268 }
8269
8270 multiclass SIMDSt4Multiple<string asm> {
8271   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8272 }
8273
8274 //---
8275 // AdvSIMD Load/store single-element
8276 //---
8277
8278 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8279                          string asm, string operands, string cst,
8280                          dag oops, dag iops, list<dag> pattern>
8281   : I<oops, iops, asm, operands, cst, pattern> {
8282   bits<5> Vt;
8283   bits<5> Rn;
8284   let Inst{31} = 0;
8285   let Inst{29-24} = 0b001101;
8286   let Inst{22} = L;
8287   let Inst{21} = R;
8288   let Inst{15-13} = opcode;
8289   let Inst{9-5} = Rn;
8290   let Inst{4-0} = Vt;
8291 }
8292
8293 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8294                          string asm, string operands, string cst,
8295                          dag oops, dag iops, list<dag> pattern>
8296   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8297   bits<5> Vt;
8298   bits<5> Rn;
8299   let Inst{31} = 0;
8300   let Inst{29-24} = 0b001101;
8301   let Inst{22} = L;
8302   let Inst{21} = R;
8303   let Inst{15-13} = opcode;
8304   let Inst{9-5} = Rn;
8305   let Inst{4-0} = Vt;
8306 }
8307
8308
8309 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8310 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8311                   Operand listtype>
8312   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8313                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
8314                        []> {
8315   let Inst{30} = Q;
8316   let Inst{23} = 0;
8317   let Inst{20-16} = 0b00000;
8318   let Inst{12} = S;
8319   let Inst{11-10} = size;
8320 }
8321 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8322 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8323                       string asm, Operand listtype, Operand GPR64pi>
8324   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8325                        "$Rn = $wback",
8326                        (outs GPR64sp:$wback, listtype:$Vt),
8327                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8328   bits<5> Xm;
8329   let Inst{30} = Q;
8330   let Inst{23} = 1;
8331   let Inst{20-16} = Xm;
8332   let Inst{12} = S;
8333   let Inst{11-10} = size;
8334 }
8335
8336 multiclass SIMDLdrAliases<string asm, string layout, string Count,
8337                           int Offset, int Size> {
8338   // E.g. "ld1r { v0.8b }, [x1], #1"
8339   //      "ld1r.8b\t$Vt, [$Rn], #1"
8340   // may get mapped to
8341   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8342   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8343                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8344                       GPR64sp:$Rn,
8345                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8346                       XZR), 1>;
8347
8348   // E.g. "ld1r.8b { v0 }, [x1], #1"
8349   //      "ld1r.8b\t$Vt, [$Rn], #1"
8350   // may get mapped to
8351   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8352   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8353                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8354                       GPR64sp:$Rn,
8355                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8356                       XZR), 0>;
8357
8358   // E.g. "ld1r.8b { v0 }, [x1]"
8359   //      "ld1r.8b\t$Vt, [$Rn]"
8360   // may get mapped to
8361   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8362   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8363                   (!cast<Instruction>(NAME # "v" # layout)
8364                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8365                       GPR64sp:$Rn), 0>;
8366
8367   // E.g. "ld1r.8b { v0 }, [x1], x2"
8368   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
8369   // may get mapped to
8370   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8371   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8372                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8373                       GPR64sp:$Rn,
8374                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8375                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8376 }
8377
8378 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8379   int Offset1, int Offset2, int Offset4, int Offset8> {
8380   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8381                         !cast<Operand>("VecList" # Count # "8b")>;
8382   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8383                         !cast<Operand>("VecList" # Count #"16b")>;
8384   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8385                         !cast<Operand>("VecList" # Count #"4h")>;
8386   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8387                         !cast<Operand>("VecList" # Count #"8h")>;
8388   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8389                         !cast<Operand>("VecList" # Count #"2s")>;
8390   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8391                         !cast<Operand>("VecList" # Count #"4s")>;
8392   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8393                         !cast<Operand>("VecList" # Count #"1d")>;
8394   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8395                         !cast<Operand>("VecList" # Count #"2d")>;
8396
8397   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8398                                  !cast<Operand>("VecList" # Count # "8b"),
8399                                  !cast<Operand>("GPR64pi" # Offset1)>;
8400   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8401                                  !cast<Operand>("VecList" # Count # "16b"),
8402                                  !cast<Operand>("GPR64pi" # Offset1)>;
8403   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8404                                  !cast<Operand>("VecList" # Count # "4h"),
8405                                  !cast<Operand>("GPR64pi" # Offset2)>;
8406   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8407                                  !cast<Operand>("VecList" # Count # "8h"),
8408                                  !cast<Operand>("GPR64pi" # Offset2)>;
8409   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8410                                  !cast<Operand>("VecList" # Count # "2s"),
8411                                  !cast<Operand>("GPR64pi" # Offset4)>;
8412   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8413                                  !cast<Operand>("VecList" # Count # "4s"),
8414                                  !cast<Operand>("GPR64pi" # Offset4)>;
8415   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8416                                  !cast<Operand>("VecList" # Count # "1d"),
8417                                  !cast<Operand>("GPR64pi" # Offset8)>;
8418   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8419                                  !cast<Operand>("VecList" # Count # "2d"),
8420                                  !cast<Operand>("GPR64pi" # Offset8)>;
8421
8422   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
8423   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8424   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
8425   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
8426   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
8427   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
8428   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
8429   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
8430 }
8431
8432 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8433                       dag oops, dag iops, list<dag> pattern>
8434   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8435                        pattern> {
8436   // idx encoded in Q:S:size fields.
8437   bits<4> idx;
8438   let Inst{30} = idx{3};
8439   let Inst{23} = 0;
8440   let Inst{20-16} = 0b00000;
8441   let Inst{12} = idx{2};
8442   let Inst{11-10} = idx{1-0};
8443 }
8444 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8445                       dag oops, dag iops, list<dag> pattern>
8446   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8447                            oops, iops, pattern> {
8448   // idx encoded in Q:S:size fields.
8449   bits<4> idx;
8450   let Inst{30} = idx{3};
8451   let Inst{23} = 0;
8452   let Inst{20-16} = 0b00000;
8453   let Inst{12} = idx{2};
8454   let Inst{11-10} = idx{1-0};
8455 }
8456 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8457                           dag oops, dag iops>
8458   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8459                        "$Rn = $wback", oops, iops, []> {
8460   // idx encoded in Q:S:size fields.
8461   bits<4> idx;
8462   bits<5> Xm;
8463   let Inst{30} = idx{3};
8464   let Inst{23} = 1;
8465   let Inst{20-16} = Xm;
8466   let Inst{12} = idx{2};
8467   let Inst{11-10} = idx{1-0};
8468 }
8469 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8470                           dag oops, dag iops>
8471   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8472                            "$Rn = $wback", oops, iops, []> {
8473   // idx encoded in Q:S:size fields.
8474   bits<4> idx;
8475   bits<5> Xm;
8476   let Inst{30} = idx{3};
8477   let Inst{23} = 1;
8478   let Inst{20-16} = Xm;
8479   let Inst{12} = idx{2};
8480   let Inst{11-10} = idx{1-0};
8481 }
8482
8483 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8484                       dag oops, dag iops, list<dag> pattern>
8485   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8486                        pattern> {
8487   // idx encoded in Q:S:size<1> fields.
8488   bits<3> idx;
8489   let Inst{30} = idx{2};
8490   let Inst{23} = 0;
8491   let Inst{20-16} = 0b00000;
8492   let Inst{12} = idx{1};
8493   let Inst{11} = idx{0};
8494   let Inst{10} = size;
8495 }
8496 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8497                       dag oops, dag iops, list<dag> pattern>
8498   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8499                            oops, iops, pattern> {
8500   // idx encoded in Q:S:size<1> fields.
8501   bits<3> idx;
8502   let Inst{30} = idx{2};
8503   let Inst{23} = 0;
8504   let Inst{20-16} = 0b00000;
8505   let Inst{12} = idx{1};
8506   let Inst{11} = idx{0};
8507   let Inst{10} = size;
8508 }
8509
8510 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8511                           dag oops, dag iops>
8512   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8513                        "$Rn = $wback", oops, iops, []> {
8514   // idx encoded in Q:S:size<1> fields.
8515   bits<3> idx;
8516   bits<5> Xm;
8517   let Inst{30} = idx{2};
8518   let Inst{23} = 1;
8519   let Inst{20-16} = Xm;
8520   let Inst{12} = idx{1};
8521   let Inst{11} = idx{0};
8522   let Inst{10} = size;
8523 }
8524 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8525                           dag oops, dag iops>
8526   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8527                            "$Rn = $wback", oops, iops, []> {
8528   // idx encoded in Q:S:size<1> fields.
8529   bits<3> idx;
8530   bits<5> Xm;
8531   let Inst{30} = idx{2};
8532   let Inst{23} = 1;
8533   let Inst{20-16} = Xm;
8534   let Inst{12} = idx{1};
8535   let Inst{11} = idx{0};
8536   let Inst{10} = size;
8537 }
8538 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8539                       dag oops, dag iops, list<dag> pattern>
8540   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8541                        pattern> {
8542   // idx encoded in Q:S fields.
8543   bits<2> idx;
8544   let Inst{30} = idx{1};
8545   let Inst{23} = 0;
8546   let Inst{20-16} = 0b00000;
8547   let Inst{12} = idx{0};
8548   let Inst{11-10} = size;
8549 }
8550 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8551                       dag oops, dag iops, list<dag> pattern>
8552   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8553                            oops, iops, pattern> {
8554   // idx encoded in Q:S fields.
8555   bits<2> idx;
8556   let Inst{30} = idx{1};
8557   let Inst{23} = 0;
8558   let Inst{20-16} = 0b00000;
8559   let Inst{12} = idx{0};
8560   let Inst{11-10} = size;
8561 }
8562 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8563                           string asm, dag oops, dag iops>
8564   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8565                        "$Rn = $wback", oops, iops, []> {
8566   // idx encoded in Q:S fields.
8567   bits<2> idx;
8568   bits<5> Xm;
8569   let Inst{30} = idx{1};
8570   let Inst{23} = 1;
8571   let Inst{20-16} = Xm;
8572   let Inst{12} = idx{0};
8573   let Inst{11-10} = size;
8574 }
8575 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8576                           string asm, dag oops, dag iops>
8577   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8578                            "$Rn = $wback", oops, iops, []> {
8579   // idx encoded in Q:S fields.
8580   bits<2> idx;
8581   bits<5> Xm;
8582   let Inst{30} = idx{1};
8583   let Inst{23} = 1;
8584   let Inst{20-16} = Xm;
8585   let Inst{12} = idx{0};
8586   let Inst{11-10} = size;
8587 }
8588 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8589                       dag oops, dag iops, list<dag> pattern>
8590   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8591                        pattern> {
8592   // idx encoded in Q field.
8593   bits<1> idx;
8594   let Inst{30} = idx;
8595   let Inst{23} = 0;
8596   let Inst{20-16} = 0b00000;
8597   let Inst{12} = 0;
8598   let Inst{11-10} = size;
8599 }
8600 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8601                       dag oops, dag iops, list<dag> pattern>
8602   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8603                            oops, iops, pattern> {
8604   // idx encoded in Q field.
8605   bits<1> idx;
8606   let Inst{30} = idx;
8607   let Inst{23} = 0;
8608   let Inst{20-16} = 0b00000;
8609   let Inst{12} = 0;
8610   let Inst{11-10} = size;
8611 }
8612 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8613                           string asm, dag oops, dag iops>
8614   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8615                        "$Rn = $wback", oops, iops, []> {
8616   // idx encoded in Q field.
8617   bits<1> idx;
8618   bits<5> Xm;
8619   let Inst{30} = idx;
8620   let Inst{23} = 1;
8621   let Inst{20-16} = Xm;
8622   let Inst{12} = 0;
8623   let Inst{11-10} = size;
8624 }
8625 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8626                           string asm, dag oops, dag iops>
8627   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8628                            "$Rn = $wback", oops, iops, []> {
8629   // idx encoded in Q field.
8630   bits<1> idx;
8631   bits<5> Xm;
8632   let Inst{30} = idx;
8633   let Inst{23} = 1;
8634   let Inst{20-16} = Xm;
8635   let Inst{12} = 0;
8636   let Inst{11-10} = size;
8637 }
8638
8639 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8640 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8641                          RegisterOperand listtype,
8642                          RegisterOperand GPR64pi> {
8643   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8644                            (outs listtype:$dst),
8645                            (ins listtype:$Vt, VectorIndexB:$idx,
8646                                 GPR64sp:$Rn), []>;
8647
8648   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8649                             (outs GPR64sp:$wback, listtype:$dst),
8650                             (ins listtype:$Vt, VectorIndexB:$idx,
8651                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8652 }
8653 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8654 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8655                          RegisterOperand listtype,
8656                          RegisterOperand GPR64pi> {
8657   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8658                             (outs listtype:$dst),
8659                             (ins listtype:$Vt, VectorIndexH:$idx,
8660                                  GPR64sp:$Rn), []>;
8661
8662   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8663                             (outs GPR64sp:$wback, listtype:$dst),
8664                             (ins listtype:$Vt, VectorIndexH:$idx,
8665                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8666 }
8667 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8668 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8669                          RegisterOperand listtype,
8670                          RegisterOperand GPR64pi> {
8671   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8672                             (outs listtype:$dst),
8673                             (ins listtype:$Vt, VectorIndexS:$idx,
8674                                  GPR64sp:$Rn), []>;
8675
8676   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8677                             (outs GPR64sp:$wback, listtype:$dst),
8678                             (ins listtype:$Vt, VectorIndexS:$idx,
8679                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8680 }
8681 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8682 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8683                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8684   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8685                             (outs listtype:$dst),
8686                             (ins listtype:$Vt, VectorIndexD:$idx,
8687                                  GPR64sp:$Rn), []>;
8688
8689   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8690                             (outs GPR64sp:$wback, listtype:$dst),
8691                             (ins listtype:$Vt, VectorIndexD:$idx,
8692                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8693 }
8694 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8695 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8696                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8697   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8698                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8699                                         GPR64sp:$Rn), []>;
8700
8701   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8702                                     (outs GPR64sp:$wback),
8703                                     (ins listtype:$Vt, VectorIndexB:$idx,
8704                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
8705 }
8706 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8707 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8708                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8709   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8710                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8711                                          GPR64sp:$Rn), []>;
8712
8713   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8714                             (outs GPR64sp:$wback),
8715                             (ins listtype:$Vt, VectorIndexH:$idx,
8716                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8717 }
8718 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8719 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8720                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8721   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8722                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8723                                          GPR64sp:$Rn), []>;
8724
8725   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8726                             (outs GPR64sp:$wback),
8727                             (ins listtype:$Vt, VectorIndexS:$idx,
8728                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8729 }
8730 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8731 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8732                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8733   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8734                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8735                                          GPR64sp:$Rn), []>;
8736
8737   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8738                             (outs GPR64sp:$wback),
8739                             (ins listtype:$Vt, VectorIndexD:$idx,
8740                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8741 }
8742
8743 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8744                                  string Count, int Offset, Operand idxtype> {
8745   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8746   //      "ld1\t$Vt, [$Rn], #1"
8747   // may get mapped to
8748   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8749   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8750                   (!cast<Instruction>(NAME # Type  # "_POST")
8751                       GPR64sp:$Rn,
8752                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8753                       idxtype:$idx, XZR), 1>;
8754
8755   // E.g. "ld1.8b { v0 }[0], [x1], #1"
8756   //      "ld1.8b\t$Vt, [$Rn], #1"
8757   // may get mapped to
8758   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8759   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
8760                   (!cast<Instruction>(NAME # Type # "_POST")
8761                       GPR64sp:$Rn,
8762                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8763                       idxtype:$idx, XZR), 0>;
8764
8765   // E.g. "ld1.8b { v0 }[0], [x1]"
8766   //      "ld1.8b\t$Vt, [$Rn]"
8767   // may get mapped to
8768   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8769   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
8770                       (!cast<Instruction>(NAME # Type)
8771                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8772                          idxtype:$idx, GPR64sp:$Rn), 0>;
8773
8774   // E.g. "ld1.8b { v0 }[0], [x1], x2"
8775   //      "ld1.8b\t$Vt, [$Rn], $Xm"
8776   // may get mapped to
8777   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8778   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
8779                       (!cast<Instruction>(NAME # Type # "_POST")
8780                          GPR64sp:$Rn,
8781                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8782                          idxtype:$idx,
8783                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8784 }
8785
8786 multiclass SIMDLdSt1SingleAliases<string asm> {
8787   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
8788   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8789   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8790   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8791 }
8792
8793 multiclass SIMDLdSt2SingleAliases<string asm> {
8794   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
8795   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
8796   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
8797   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8798 }
8799
8800 multiclass SIMDLdSt3SingleAliases<string asm> {
8801   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
8802   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
8803   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8804   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8805 }
8806
8807 multiclass SIMDLdSt4SingleAliases<string asm> {
8808   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
8809   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
8810   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8811   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8812 }
8813 } // end of 'let Predicates = [HasNEON]'
8814
8815 //----------------------------------------------------------------------------
8816 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
8817 //----------------------------------------------------------------------------
8818
8819 let Predicates = [HasNEON, HasV8_1a] in {
8820
8821 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
8822                                     RegisterOperand regtype, string asm, 
8823                                     string kind, list<dag> pattern>
8824   : BaseSIMDThreeSameVectorTied<Q, U, size, opcode, regtype, asm, kind, 
8825                                 pattern> {
8826   let Inst{21}=0;
8827 }
8828 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
8829                                              SDPatternOperator Accum> {
8830   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
8831     [(set (v4i16 V64:$dst),
8832           (Accum (v4i16 V64:$Rd),
8833                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
8834                                                    (v4i16 V64:$Rm)))))]>;         
8835   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
8836     [(set (v8i16 V128:$dst),
8837           (Accum (v8i16 V128:$Rd),
8838                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
8839                                                    (v8i16 V128:$Rm)))))]>;
8840   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
8841     [(set (v2i32 V64:$dst),
8842           (Accum (v2i32 V64:$Rd),
8843                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
8844                                                    (v2i32 V64:$Rm)))))]>;
8845   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
8846     [(set (v4i32 V128:$dst),
8847           (Accum (v4i32 V128:$Rd),
8848                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
8849                                                    (v4i32 V128:$Rm)))))]>;
8850 }
8851
8852 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
8853                                      SDPatternOperator Accum> {
8854   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8855                                           V64, V64, V128_lo, VectorIndexH,
8856                                           asm, ".4h", ".4h", ".4h", ".h",
8857     [(set (v4i16 V64:$dst),
8858           (Accum (v4i16 V64:$Rd),
8859                  (v4i16 (int_aarch64_neon_sqrdmulh
8860                           (v4i16 V64:$Rn),
8861                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8862                                                     VectorIndexH:$idx))))))]> {
8863     bits<3> idx;
8864     let Inst{11} = idx{2};
8865     let Inst{21} = idx{1};
8866     let Inst{20} = idx{0};
8867   }
8868
8869   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8870                                           V128, V128, V128_lo, VectorIndexH,
8871                                           asm, ".8h", ".8h", ".8h", ".h",
8872     [(set (v8i16 V128:$dst),
8873           (Accum (v8i16 V128:$Rd),
8874                  (v8i16 (int_aarch64_neon_sqrdmulh
8875                           (v8i16 V128:$Rn),
8876                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8877                                                    VectorIndexH:$idx))))))]> {
8878     bits<3> idx;
8879     let Inst{11} = idx{2};
8880     let Inst{21} = idx{1};
8881     let Inst{20} = idx{0};
8882   }
8883
8884   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8885                                           V64, V64, V128, VectorIndexS,
8886                                           asm, ".2s", ".2s", ".2s", ".s",
8887     [(set (v2i32 V64:$dst),
8888         (Accum (v2i32 V64:$Rd),
8889                (v2i32 (int_aarch64_neon_sqrdmulh
8890                         (v2i32 V64:$Rn),
8891                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8892                                                  VectorIndexS:$idx))))))]> {
8893     bits<2> idx;
8894     let Inst{11} = idx{1};
8895     let Inst{21} = idx{0};
8896   }
8897
8898   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but 
8899   // an intermediate EXTRACT_SUBREG would be untyped.
8900   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we 
8901   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
8902   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8903                        (i32 (vector_extract 
8904                                (v4i32 (insert_subvector
8905                                        (undef), 
8906                                         (v2i32 (int_aarch64_neon_sqrdmulh 
8907                                                  (v2i32 V64:$Rn),
8908                                                  (v2i32 (AArch64duplane32 
8909                                                           (v4i32 V128:$Rm),
8910                                                           VectorIndexS:$idx)))),
8911                                       (i32 0))),
8912                                (i64 0))))),
8913             (EXTRACT_SUBREG
8914                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
8915                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), 
8916                                                 FPR32Op:$Rd, 
8917                                                 ssub)), 
8918                           V64:$Rn,
8919                           V128:$Rm, 
8920                           VectorIndexS:$idx)),
8921                 ssub)>;
8922
8923   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8924                                           V128, V128, V128, VectorIndexS,
8925                                           asm, ".4s", ".4s", ".4s", ".s",
8926     [(set (v4i32 V128:$dst),
8927           (Accum (v4i32 V128:$Rd),
8928                  (v4i32 (int_aarch64_neon_sqrdmulh
8929                           (v4i32 V128:$Rn),
8930                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8931                                                    VectorIndexS:$idx))))))]> {
8932     bits<2> idx;
8933     let Inst{11} = idx{1};
8934     let Inst{21} = idx{0};
8935   }
8936
8937   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
8938   // an intermediate EXTRACT_SUBREG would be untyped.
8939   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8940                         (i32 (vector_extract 
8941                                (v4i32 (int_aarch64_neon_sqrdmulh 
8942                                         (v4i32 V128:$Rn),
8943                                         (v4i32 (AArch64duplane32 
8944                                                  (v4i32 V128:$Rm),
8945                                                  VectorIndexS:$idx)))),
8946                                (i64 0))))),
8947             (EXTRACT_SUBREG
8948                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
8949                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), 
8950                                                FPR32Op:$Rd, 
8951                                                ssub)), 
8952                          V128:$Rn,
8953                          V128:$Rm, 
8954                          VectorIndexS:$idx)),
8955                 ssub)>;
8956
8957   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8958                                         FPR16Op, FPR16Op, V128_lo,
8959                                         VectorIndexH, asm, ".h", "", "", ".h", 
8960                                         []> {
8961     bits<3> idx;
8962     let Inst{11} = idx{2};
8963     let Inst{21} = idx{1};
8964     let Inst{20} = idx{0};
8965   }
8966
8967   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8968                                         FPR32Op, FPR32Op, V128, VectorIndexS,
8969                                         asm, ".s", "", "", ".s",
8970     [(set (i32 FPR32Op:$dst),
8971           (Accum (i32 FPR32Op:$Rd),
8972                  (i32 (int_aarch64_neon_sqrdmulh
8973                         (i32 FPR32Op:$Rn),
8974                         (i32 (vector_extract (v4i32 V128:$Rm),
8975                                              VectorIndexS:$idx))))))]> {
8976     bits<2> idx;
8977     let Inst{11} = idx{1};
8978     let Inst{21} = idx{0};
8979   }
8980 }
8981 } // let Predicates = [HasNeon, HasV8_1a]
8982
8983 //----------------------------------------------------------------------------
8984 // Crypto extensions
8985 //----------------------------------------------------------------------------
8986
8987 let Predicates = [HasCrypto] in {
8988 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8989 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8990               list<dag> pat>
8991   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8992     Sched<[WriteV]>{
8993   bits<5> Rd;
8994   bits<5> Rn;
8995   let Inst{31-16} = 0b0100111000101000;
8996   let Inst{15-12} = opc;
8997   let Inst{11-10} = 0b10;
8998   let Inst{9-5}   = Rn;
8999   let Inst{4-0}   = Rd;
9000 }
9001
9002 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
9003   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
9004             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
9005
9006 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
9007   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
9008             "$Rd = $dst",
9009             [(set (v16i8 V128:$dst),
9010                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
9011
9012 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9013 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
9014                      dag oops, dag iops, list<dag> pat>
9015   : I<oops, iops, asm,
9016       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
9017       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
9018     Sched<[WriteV]>{
9019   bits<5> Rd;
9020   bits<5> Rn;
9021   bits<5> Rm;
9022   let Inst{31-21} = 0b01011110000;
9023   let Inst{20-16} = Rm;
9024   let Inst{15}    = 0;
9025   let Inst{14-12} = opc;
9026   let Inst{11-10} = 0b00;
9027   let Inst{9-5}   = Rn;
9028   let Inst{4-0}   = Rd;
9029 }
9030
9031 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
9032   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9033                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
9034                    [(set (v4i32 FPR128:$dst),
9035                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
9036                                  (v4i32 V128:$Rm)))]>;
9037
9038 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
9039   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
9040                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
9041                    [(set (v4i32 V128:$dst),
9042                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9043                                  (v4i32 V128:$Rm)))]>;
9044
9045 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
9046   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9047                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
9048                    [(set (v4i32 FPR128:$dst),
9049                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
9050                                  (v4i32 V128:$Rm)))]>;
9051
9052 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9053 class SHA2OpInst<bits<4> opc, string asm, string kind,
9054                  string cstr, dag oops, dag iops,
9055                  list<dag> pat>
9056   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
9057                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
9058     Sched<[WriteV]>{
9059   bits<5> Rd;
9060   bits<5> Rn;
9061   let Inst{31-16} = 0b0101111000101000;
9062   let Inst{15-12} = opc;
9063   let Inst{11-10} = 0b10;
9064   let Inst{9-5}   = Rn;
9065   let Inst{4-0}   = Rd;
9066 }
9067
9068 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
9069   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
9070                (ins V128:$Rd, V128:$Rn),
9071                [(set (v4i32 V128:$dst),
9072                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
9073
9074 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
9075   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
9076                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
9077 } // end of 'let Predicates = [HasCrypto]'
9078
9079 //----------------------------------------------------------------------------
9080 // v8.1 atomic instructions extension:
9081 // * CAS
9082 // * CASP
9083 // * SWP
9084 // * LDOPregister<OP>, and aliases STOPregister<OP>
9085
9086 // Instruction encodings:
9087 //
9088 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
9089 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
9090 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
9091 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
9092 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
9093 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
9094
9095 // Instruction syntax:
9096 //
9097 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9098 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
9099 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
9100 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
9101 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9102 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
9103 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9104 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
9105 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
9106 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
9107
9108 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9109 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
9110                       string cstr, list<dag> pattern>
9111       : I<oops, iops, asm, operands, cstr, pattern> {
9112   bits<2> Sz;
9113   bit NP;
9114   bit Acq;
9115   bit Rel;
9116   bits<5> Rs;
9117   bits<5> Rn;
9118   bits<5> Rt;
9119   let Inst{31-30} = Sz;
9120   let Inst{29-24} = 0b001000;
9121   let Inst{23} = NP;
9122   let Inst{22} = Acq;
9123   let Inst{21} = 0b1;
9124   let Inst{20-16} = Rs;
9125   let Inst{15} = Rel;
9126   let Inst{14-10} = 0b11111;
9127   let Inst{9-5} = Rn;
9128   let Inst{4-0} = Rt;
9129 }
9130
9131 class BaseCAS<string order, string size, RegisterClass RC>
9132       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9133                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
9134                         "$out = $Rs",[]> {
9135   let NP = 1;
9136 }
9137
9138 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
9139   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
9140   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
9141   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
9142   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
9143 }
9144
9145 class BaseCASP<string order, string size, RegisterOperand RC>
9146       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9147                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
9148                         "$out = $Rs",[]> {
9149   let NP = 0;
9150 }
9151
9152 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
9153   let Sz = 0b00, Acq = Acq, Rel = Rel in 
9154     def s : BaseCASP<order, "", WSeqPairClassOperand>;
9155   let Sz = 0b01, Acq = Acq, Rel = Rel in 
9156     def d : BaseCASP<order, "", XSeqPairClassOperand>;
9157 }
9158
9159 let Predicates = [HasV8_1a] in
9160 class BaseSWP<string order, string size, RegisterClass RC>
9161       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
9162           "\t$Rs, $Rt, [$Rn]","",[]> {
9163   bits<2> Sz;
9164   bit Acq;
9165   bit Rel;
9166   bits<5> Rs;
9167   bits<3> opc = 0b000;
9168   bits<5> Rn;
9169   bits<5> Rt;
9170   let Inst{31-30} = Sz;
9171   let Inst{29-24} = 0b111000;
9172   let Inst{23} = Acq;
9173   let Inst{22} = Rel;
9174   let Inst{21} = 0b1;
9175   let Inst{20-16} = Rs;
9176   let Inst{15} = 0b1;
9177   let Inst{14-12} = opc;
9178   let Inst{11-10} = 0b00;
9179   let Inst{9-5} = Rn;
9180   let Inst{4-0} = Rt;
9181 }
9182
9183 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
9184   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
9185   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
9186   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
9187   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
9188 }
9189
9190 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9191 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
9192       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
9193           "\t$Rs, $Rt, [$Rn]","",[]> {
9194   bits<2> Sz;
9195   bit Acq;
9196   bit Rel;
9197   bits<5> Rs;
9198   bits<3> opc;
9199   bits<5> Rn;
9200   bits<5> Rt;
9201   let Inst{31-30} = Sz;
9202   let Inst{29-24} = 0b111000;
9203   let Inst{23} = Acq;
9204   let Inst{22} = Rel;
9205   let Inst{21} = 0b1;
9206   let Inst{20-16} = Rs;
9207   let Inst{15} = 0b0;
9208   let Inst{14-12} = opc;
9209   let Inst{11-10} = 0b00;
9210   let Inst{9-5} = Rn;
9211   let Inst{4-0} = Rt;
9212 }
9213
9214 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel, 
9215                         string order> {
9216   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in 
9217     def b : BaseLDOPregister<op, order, "b", GPR32>;
9218   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in 
9219     def h : BaseLDOPregister<op, order, "h", GPR32>;
9220   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in 
9221     def s : BaseLDOPregister<op, order, "", GPR32>;
9222   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in 
9223     def d : BaseLDOPregister<op, order, "", GPR64>;
9224 }
9225
9226 let Predicates = [HasV8_1a] in
9227 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
9228                         Instruction inst> :
9229       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
9230
9231 multiclass STOPregister<string asm, string instr> {
9232   def : BaseSTOPregister<asm # "lb", GPR32, WZR, 
9233                     !cast<Instruction>(instr # "Lb")>;
9234   def : BaseSTOPregister<asm # "lh", GPR32, WZR, 
9235                     !cast<Instruction>(instr # "Lh")>;
9236   def : BaseSTOPregister<asm # "l",  GPR32, WZR, 
9237                     !cast<Instruction>(instr # "Ls")>;
9238   def : BaseSTOPregister<asm # "l",  GPR64, XZR, 
9239                     !cast<Instruction>(instr # "Ld")>;
9240   def : BaseSTOPregister<asm # "b",  GPR32, WZR, 
9241                     !cast<Instruction>(instr # "b")>;
9242   def : BaseSTOPregister<asm # "h",  GPR32, WZR, 
9243                     !cast<Instruction>(instr # "h")>;
9244   def : BaseSTOPregister<asm,        GPR32, WZR, 
9245                     !cast<Instruction>(instr # "s")>;
9246   def : BaseSTOPregister<asm,        GPR64, XZR, 
9247                     !cast<Instruction>(instr # "d")>;
9248 }
9249
9250 //----------------------------------------------------------------------------
9251 // Allow the size specifier tokens to be upper case, not just lower.
9252 def : TokenAlias<".8B", ".8b">;
9253 def : TokenAlias<".4H", ".4h">;
9254 def : TokenAlias<".2S", ".2s">;
9255 def : TokenAlias<".1D", ".1d">;
9256 def : TokenAlias<".16B", ".16b">;
9257 def : TokenAlias<".8H", ".8h">;
9258 def : TokenAlias<".4S", ".4s">;
9259 def : TokenAlias<".2D", ".2d">;
9260 def : TokenAlias<".1Q", ".1q">;
9261 def : TokenAlias<".B", ".b">;
9262 def : TokenAlias<".H", ".h">;
9263 def : TokenAlias<".S", ".s">;
9264 def : TokenAlias<".D", ".d">;
9265 def : TokenAlias<".Q", ".q">;