Fixes the issue of removing manually added fake conditional branches
[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 def PSBHintOperand : AsmOperandClass {
915   let Name = "PSBHint";
916   let ParserMethod = "tryParsePSBHint";
917 }
918 def psbhint_op : Operand<i32> {
919   let ParserMatchClass = PSBHintOperand;
920   let PrintMethod = "printPSBHintOp";
921   let MCOperandPredicate = [{
922     // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
923     // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
924     if (!MCOp.isImm())
925       return false;
926     bool ValidNamed;
927     (void)AArch64PSBHint::PSBHintMapper().toString(MCOp.getImm(),
928       STI.getFeatureBits(), ValidNamed);
929     return ValidNamed;
930   }];
931 }
932
933 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
934                        "mrs", "\t$Rt, $systemreg"> {
935   bits<16> systemreg;
936   let Inst{20-5} = systemreg;
937 }
938
939 // FIXME: Some of these def NZCV, others don't. Best way to model that?
940 // Explicitly modeling each of the system register as a register class
941 // would do it, but feels like overkill at this point.
942 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
943                        "msr", "\t$systemreg, $Rt"> {
944   bits<16> systemreg;
945   let Inst{20-5} = systemreg;
946 }
947
948 def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
949   let Name = "SystemPStateFieldWithImm0_15";
950   let ParserMethod = "tryParseSysReg";
951 }
952 def pstatefield4_op : Operand<i32> {
953   let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
954   let PrintMethod = "printSystemPStateField";
955 }
956
957 let Defs = [NZCV] in
958 class MSRpstateImm0_15
959   : SimpleSystemI<0, (ins pstatefield4_op:$pstatefield, imm0_15:$imm),
960                   "msr", "\t$pstatefield, $imm">,
961     Sched<[WriteSys]> {
962   bits<6> pstatefield;
963   bits<4> imm;
964   let Inst{20-19} = 0b00;
965   let Inst{18-16} = pstatefield{5-3};
966   let Inst{15-12} = 0b0100;
967   let Inst{11-8} = imm;
968   let Inst{7-5} = pstatefield{2-0};
969
970   let DecoderMethod = "DecodeSystemPStateInstruction";
971   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
972   // Fail the decoder should attempt to decode the instruction as MSRI.
973   let hasCompleteDecoder = 0;
974 }
975
976 def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
977   let Name = "SystemPStateFieldWithImm0_1";
978   let ParserMethod = "tryParseSysReg";
979 }
980 def pstatefield1_op : Operand<i32> {
981   let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
982   let PrintMethod = "printSystemPStateField";
983 }
984
985 let Defs = [NZCV] in
986 class MSRpstateImm0_1
987   : SimpleSystemI<0, (ins pstatefield1_op:$pstatefield, imm0_1:$imm),
988                   "msr", "\t$pstatefield, $imm">,
989     Sched<[WriteSys]> {
990   bits<6> pstatefield;
991   bit imm;
992   let Inst{20-19} = 0b00;
993   let Inst{18-16} = pstatefield{5-3};
994   let Inst{15-9} = 0b0100000;
995   let Inst{8} = imm;
996   let Inst{7-5} = pstatefield{2-0};
997
998   let DecoderMethod = "DecodeSystemPStateInstruction";
999   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1000   // Fail the decoder should attempt to decode the instruction as MSRI.
1001   let hasCompleteDecoder = 0;
1002 }
1003
1004 // SYS and SYSL generic system instructions.
1005 def SysCRAsmOperand : AsmOperandClass {
1006   let Name = "SysCR";
1007   let ParserMethod = "tryParseSysCROperand";
1008 }
1009
1010 def sys_cr_op : Operand<i32> {
1011   let PrintMethod = "printSysCROperand";
1012   let ParserMatchClass = SysCRAsmOperand;
1013 }
1014
1015 class SystemXtI<bit L, string asm>
1016   : RtSystemI<L, (outs),
1017        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1018        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1019   bits<3> op1;
1020   bits<4> Cn;
1021   bits<4> Cm;
1022   bits<3> op2;
1023   let Inst{20-19} = 0b01;
1024   let Inst{18-16} = op1;
1025   let Inst{15-12} = Cn;
1026   let Inst{11-8}  = Cm;
1027   let Inst{7-5}   = op2;
1028 }
1029
1030 class SystemLXtI<bit L, string asm>
1031   : RtSystemI<L, (outs),
1032        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1033        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1034   bits<3> op1;
1035   bits<4> Cn;
1036   bits<4> Cm;
1037   bits<3> op2;
1038   let Inst{20-19} = 0b01;
1039   let Inst{18-16} = op1;
1040   let Inst{15-12} = Cn;
1041   let Inst{11-8}  = Cm;
1042   let Inst{7-5}   = op2;
1043 }
1044
1045
1046 // Branch (register) instructions:
1047 //
1048 //  case opc of
1049 //    0001 blr
1050 //    0000 br
1051 //    0101 dret
1052 //    0100 eret
1053 //    0010 ret
1054 //    otherwise UNDEFINED
1055 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1056                     string operands, list<dag> pattern>
1057     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1058   let Inst{31-25} = 0b1101011;
1059   let Inst{24-21} = opc;
1060   let Inst{20-16} = 0b11111;
1061   let Inst{15-10} = 0b000000;
1062   let Inst{4-0}   = 0b00000;
1063 }
1064
1065 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1066     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1067   bits<5> Rn;
1068   let Inst{9-5} = Rn;
1069 }
1070
1071 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1072 class SpecialReturn<bits<4> opc, string asm>
1073     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1074   let Inst{9-5} = 0b11111;
1075 }
1076
1077 //---
1078 // Conditional branch instruction.
1079 //---
1080
1081 // Condition code.
1082 // 4-bit immediate. Pretty-printed as <cc>
1083 def ccode : Operand<i32> {
1084   let PrintMethod = "printCondCode";
1085   let ParserMatchClass = CondCode;
1086 }
1087 def inv_ccode : Operand<i32> {
1088   // AL and NV are invalid in the aliases which use inv_ccode
1089   let PrintMethod = "printInverseCondCode";
1090   let ParserMatchClass = CondCode;
1091   let MCOperandPredicate = [{
1092     return MCOp.isImm() &&
1093            MCOp.getImm() != AArch64CC::AL &&
1094            MCOp.getImm() != AArch64CC::NV;
1095   }];
1096 }
1097
1098 // Conditional branch target. 19-bit immediate. The low two bits of the target
1099 // offset are implied zero and so are not part of the immediate.
1100 def PCRelLabel19Operand : AsmOperandClass {
1101   let Name = "PCRelLabel19";
1102   let DiagnosticType = "InvalidLabel";
1103 }
1104 def am_brcond : Operand<OtherVT> {
1105   let EncoderMethod = "getCondBranchTargetOpValue";
1106   let DecoderMethod = "DecodePCRelLabel19";
1107   let PrintMethod = "printAlignedLabel";
1108   let ParserMatchClass = PCRelLabel19Operand;
1109 }
1110
1111 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1112                      "b", ".$cond\t$target", "",
1113                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1114                    Sched<[WriteBr]> {
1115   let isBranch = 1;
1116   let isTerminator = 1;
1117   let Uses = [NZCV];
1118
1119   bits<4> cond;
1120   bits<19> target;
1121   let Inst{31-24} = 0b01010100;
1122   let Inst{23-5} = target;
1123   let Inst{4} = 0;
1124   let Inst{3-0} = cond;
1125 }
1126
1127 //---
1128 // Compare-and-branch instructions.
1129 //---
1130 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1131     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1132          asm, "\t$Rt, $target", "",
1133          [(node regtype:$Rt, bb:$target)]>,
1134       Sched<[WriteBr]> {
1135   let isBranch = 1;
1136   let isTerminator = 1;
1137
1138   bits<5> Rt;
1139   bits<19> target;
1140   let Inst{30-25} = 0b011010;
1141   let Inst{24}    = op;
1142   let Inst{23-5}  = target;
1143   let Inst{4-0}   = Rt;
1144 }
1145
1146 multiclass CmpBranch<bit op, string asm, SDNode node> {
1147   def W : BaseCmpBranch<GPR32, op, asm, node> {
1148     let Inst{31} = 0;
1149   }
1150   def X : BaseCmpBranch<GPR64, op, asm, node> {
1151     let Inst{31} = 1;
1152   }
1153 }
1154
1155 //---
1156 // Test-bit-and-branch instructions.
1157 //---
1158 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1159 // the target offset are implied zero and so are not part of the immediate.
1160 def BranchTarget14Operand : AsmOperandClass {
1161   let Name = "BranchTarget14";
1162 }
1163 def am_tbrcond : Operand<OtherVT> {
1164   let EncoderMethod = "getTestBranchTargetOpValue";
1165   let PrintMethod = "printAlignedLabel";
1166   let ParserMatchClass = BranchTarget14Operand;
1167 }
1168
1169 // AsmOperand classes to emit (or not) special diagnostics
1170 def TBZImm0_31Operand : AsmOperandClass {
1171   let Name = "TBZImm0_31";
1172   let PredicateMethod = "isImm0_31";
1173   let RenderMethod = "addImm0_31Operands";
1174 }
1175 def TBZImm32_63Operand : AsmOperandClass {
1176   let Name = "Imm32_63";
1177   let DiagnosticType = "InvalidImm0_63";
1178 }
1179
1180 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1181   return (((uint32_t)Imm) < 32);
1182 }]> {
1183   let ParserMatchClass = matcher;
1184 }
1185
1186 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1187 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1188
1189 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1190   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1191 }]> {
1192   let ParserMatchClass = TBZImm32_63Operand;
1193 }
1194
1195 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1196                      bit op, string asm, SDNode node>
1197     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1198        asm, "\t$Rt, $bit_off, $target", "",
1199        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1200       Sched<[WriteBr]> {
1201   let isBranch = 1;
1202   let isTerminator = 1;
1203
1204   bits<5> Rt;
1205   bits<6> bit_off;
1206   bits<14> target;
1207
1208   let Inst{30-25} = 0b011011;
1209   let Inst{24}    = op;
1210   let Inst{23-19} = bit_off{4-0};
1211   let Inst{18-5}  = target;
1212   let Inst{4-0}   = Rt;
1213
1214   let DecoderMethod = "DecodeTestAndBranch";
1215 }
1216
1217 multiclass TestBranch<bit op, string asm, SDNode node> {
1218   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1219     let Inst{31} = 0;
1220   }
1221
1222   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1223     let Inst{31} = 1;
1224   }
1225
1226   // Alias X-reg with 0-31 imm to W-Reg.
1227   def : InstAlias<asm # "\t$Rd, $imm, $target",
1228                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1229                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1230   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1231             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1232             tbz_imm0_31_diag:$imm, bb:$target)>;
1233 }
1234
1235 //---
1236 // Unconditional branch (immediate) instructions.
1237 //---
1238 def BranchTarget26Operand : AsmOperandClass {
1239   let Name = "BranchTarget26";
1240   let DiagnosticType = "InvalidLabel";
1241 }
1242 def am_b_target : Operand<OtherVT> {
1243   let EncoderMethod = "getBranchTargetOpValue";
1244   let PrintMethod = "printAlignedLabel";
1245   let ParserMatchClass = BranchTarget26Operand;
1246 }
1247 def am_bl_target : Operand<i64> {
1248   let EncoderMethod = "getBranchTargetOpValue";
1249   let PrintMethod = "printAlignedLabel";
1250   let ParserMatchClass = BranchTarget26Operand;
1251 }
1252
1253 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1254     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1255   bits<26> addr;
1256   let Inst{31}    = op;
1257   let Inst{30-26} = 0b00101;
1258   let Inst{25-0}  = addr;
1259
1260   let DecoderMethod = "DecodeUnconditionalBranch";
1261 }
1262
1263 class BranchImm<bit op, string asm, list<dag> pattern>
1264     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1265 class CallImm<bit op, string asm, list<dag> pattern>
1266     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1267
1268 //---
1269 // Basic one-operand data processing instructions.
1270 //---
1271
1272 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1273 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1274                          SDPatternOperator node>
1275   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1276       [(set regtype:$Rd, (node regtype:$Rn))]>,
1277     Sched<[WriteI, ReadI]> {
1278   bits<5> Rd;
1279   bits<5> Rn;
1280
1281   let Inst{30-13} = 0b101101011000000000;
1282   let Inst{12-10} = opc;
1283   let Inst{9-5}   = Rn;
1284   let Inst{4-0}   = Rd;
1285 }
1286
1287 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1288 multiclass OneOperandData<bits<3> opc, string asm,
1289                           SDPatternOperator node = null_frag> {
1290   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1291     let Inst{31} = 0;
1292   }
1293
1294   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1295     let Inst{31} = 1;
1296   }
1297 }
1298
1299 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1300     : BaseOneOperandData<opc, GPR32, asm, node> {
1301   let Inst{31} = 0;
1302 }
1303
1304 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1305     : BaseOneOperandData<opc, GPR64, asm, node> {
1306   let Inst{31} = 1;
1307 }
1308
1309 //---
1310 // Basic two-operand data processing instructions.
1311 //---
1312 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1313                           list<dag> pattern>
1314     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1315         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1316       Sched<[WriteI, ReadI, ReadI]> {
1317   let Uses = [NZCV];
1318   bits<5> Rd;
1319   bits<5> Rn;
1320   bits<5> Rm;
1321   let Inst{30}    = isSub;
1322   let Inst{28-21} = 0b11010000;
1323   let Inst{20-16} = Rm;
1324   let Inst{15-10} = 0;
1325   let Inst{9-5}   = Rn;
1326   let Inst{4-0}   = Rd;
1327 }
1328
1329 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1330                       SDNode OpNode>
1331     : BaseBaseAddSubCarry<isSub, regtype, asm,
1332         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1333
1334 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1335                               SDNode OpNode>
1336     : BaseBaseAddSubCarry<isSub, regtype, asm,
1337         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1338          (implicit NZCV)]> {
1339   let Defs = [NZCV];
1340 }
1341
1342 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1343                        SDNode OpNode, SDNode OpNode_setflags> {
1344   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1345     let Inst{31} = 0;
1346     let Inst{29} = 0;
1347   }
1348   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1349     let Inst{31} = 1;
1350     let Inst{29} = 0;
1351   }
1352
1353   // Sets flags.
1354   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1355                                     OpNode_setflags> {
1356     let Inst{31} = 0;
1357     let Inst{29} = 1;
1358   }
1359   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1360                                     OpNode_setflags> {
1361     let Inst{31} = 1;
1362     let Inst{29} = 1;
1363   }
1364 }
1365
1366 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1367                      SDPatternOperator OpNode>
1368   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1369       asm, "\t$Rd, $Rn, $Rm", "",
1370       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1371   bits<5> Rd;
1372   bits<5> Rn;
1373   bits<5> Rm;
1374   let Inst{30-21} = 0b0011010110;
1375   let Inst{20-16} = Rm;
1376   let Inst{15-14} = 0b00;
1377   let Inst{13-10} = opc;
1378   let Inst{9-5}   = Rn;
1379   let Inst{4-0}   = Rd;
1380 }
1381
1382 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1383               SDPatternOperator OpNode>
1384     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1385   let Inst{10}    = isSigned;
1386 }
1387
1388 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1389   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1390            Sched<[WriteID32, ReadID, ReadID]> {
1391     let Inst{31} = 0;
1392   }
1393   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1394            Sched<[WriteID64, ReadID, ReadID]> {
1395     let Inst{31} = 1;
1396   }
1397 }
1398
1399 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1400                 SDPatternOperator OpNode = null_frag>
1401   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1402     Sched<[WriteIS, ReadI]> {
1403   let Inst{11-10} = shift_type;
1404 }
1405
1406 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1407   def Wr : BaseShift<shift_type, GPR32, asm> {
1408     let Inst{31} = 0;
1409   }
1410
1411   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1412     let Inst{31} = 1;
1413   }
1414
1415   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1416             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1417                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1418
1419   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1420             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1421
1422   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1423             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1424
1425   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1426             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1427 }
1428
1429 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1430     : InstAlias<asm#"\t$dst, $src1, $src2",
1431                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1432
1433 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1434                        RegisterClass addtype, string asm,
1435                        list<dag> pattern>
1436   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1437       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1438   bits<5> Rd;
1439   bits<5> Rn;
1440   bits<5> Rm;
1441   bits<5> Ra;
1442   let Inst{30-24} = 0b0011011;
1443   let Inst{23-21} = opc;
1444   let Inst{20-16} = Rm;
1445   let Inst{15}    = isSub;
1446   let Inst{14-10} = Ra;
1447   let Inst{9-5}   = Rn;
1448   let Inst{4-0}   = Rd;
1449 }
1450
1451 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1452   // MADD/MSUB generation is decided by MachineCombiner.cpp
1453   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1454       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1455       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1456     let Inst{31} = 0;
1457   }
1458
1459   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1460       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1461       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1462     let Inst{31} = 1;
1463   }
1464 }
1465
1466 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1467                    SDNode AccNode, SDNode ExtNode>
1468   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1469     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1470                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1471     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1472   let Inst{31} = 1;
1473 }
1474
1475 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1476   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1477       asm, "\t$Rd, $Rn, $Rm", "",
1478       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1479     Sched<[WriteIM64, ReadIM, ReadIM]> {
1480   bits<5> Rd;
1481   bits<5> Rn;
1482   bits<5> Rm;
1483   let Inst{31-24} = 0b10011011;
1484   let Inst{23-21} = opc;
1485   let Inst{20-16} = Rm;
1486   let Inst{15}    = 0;
1487   let Inst{9-5}   = Rn;
1488   let Inst{4-0}   = Rd;
1489
1490   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1491   // (i.e. all bits 1) but is ignored by the processor.
1492   let PostEncoderMethod = "fixMulHigh";
1493 }
1494
1495 class MulAccumWAlias<string asm, Instruction inst>
1496     : InstAlias<asm#"\t$dst, $src1, $src2",
1497                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1498 class MulAccumXAlias<string asm, Instruction inst>
1499     : InstAlias<asm#"\t$dst, $src1, $src2",
1500                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1501 class WideMulAccumAlias<string asm, Instruction inst>
1502     : InstAlias<asm#"\t$dst, $src1, $src2",
1503                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1504
1505 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1506               SDPatternOperator OpNode, string asm>
1507   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1508       asm, "\t$Rd, $Rn, $Rm", "",
1509       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1510     Sched<[WriteISReg, ReadI, ReadISReg]> {
1511   bits<5> Rd;
1512   bits<5> Rn;
1513   bits<5> Rm;
1514
1515   let Inst{31} = sf;
1516   let Inst{30-21} = 0b0011010110;
1517   let Inst{20-16} = Rm;
1518   let Inst{15-13} = 0b010;
1519   let Inst{12} = C;
1520   let Inst{11-10} = sz;
1521   let Inst{9-5} = Rn;
1522   let Inst{4-0} = Rd;
1523   let Predicates = [HasCRC];
1524 }
1525
1526 //---
1527 // Address generation.
1528 //---
1529
1530 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1531     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1532         pattern>,
1533       Sched<[WriteI]> {
1534   bits<5>  Xd;
1535   bits<21> label;
1536   let Inst{31}    = page;
1537   let Inst{30-29} = label{1-0};
1538   let Inst{28-24} = 0b10000;
1539   let Inst{23-5}  = label{20-2};
1540   let Inst{4-0}   = Xd;
1541
1542   let DecoderMethod = "DecodeAdrInstruction";
1543 }
1544
1545 //---
1546 // Move immediate.
1547 //---
1548
1549 def movimm32_imm : Operand<i32> {
1550   let ParserMatchClass = Imm0_65535Operand;
1551   let EncoderMethod = "getMoveWideImmOpValue";
1552   let PrintMethod = "printHexImm";
1553 }
1554 def movimm32_shift : Operand<i32> {
1555   let PrintMethod = "printShifter";
1556   let ParserMatchClass = MovImm32ShifterOperand;
1557 }
1558 def movimm64_shift : Operand<i32> {
1559   let PrintMethod = "printShifter";
1560   let ParserMatchClass = MovImm64ShifterOperand;
1561 }
1562
1563 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1564 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1565                         string asm>
1566   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1567        asm, "\t$Rd, $imm$shift", "", []>,
1568     Sched<[WriteImm]> {
1569   bits<5> Rd;
1570   bits<16> imm;
1571   bits<6> shift;
1572   let Inst{30-29} = opc;
1573   let Inst{28-23} = 0b100101;
1574   let Inst{22-21} = shift{5-4};
1575   let Inst{20-5}  = imm;
1576   let Inst{4-0}   = Rd;
1577
1578   let DecoderMethod = "DecodeMoveImmInstruction";
1579 }
1580
1581 multiclass MoveImmediate<bits<2> opc, string asm> {
1582   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1583     let Inst{31} = 0;
1584   }
1585
1586   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1587     let Inst{31} = 1;
1588   }
1589 }
1590
1591 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1592 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1593                           string asm>
1594   : I<(outs regtype:$Rd),
1595       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1596        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1597     Sched<[WriteI, ReadI]> {
1598   bits<5> Rd;
1599   bits<16> imm;
1600   bits<6> shift;
1601   let Inst{30-29} = opc;
1602   let Inst{28-23} = 0b100101;
1603   let Inst{22-21} = shift{5-4};
1604   let Inst{20-5}  = imm;
1605   let Inst{4-0}   = Rd;
1606
1607   let DecoderMethod = "DecodeMoveImmInstruction";
1608 }
1609
1610 multiclass InsertImmediate<bits<2> opc, string asm> {
1611   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1612     let Inst{31} = 0;
1613   }
1614
1615   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1616     let Inst{31} = 1;
1617   }
1618 }
1619
1620 //---
1621 // Add/Subtract
1622 //---
1623
1624 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1625                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1626                     string asm, SDPatternOperator OpNode>
1627     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1628         asm, "\t$Rd, $Rn, $imm", "",
1629         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1630       Sched<[WriteI, ReadI]>  {
1631   bits<5>  Rd;
1632   bits<5>  Rn;
1633   bits<14> imm;
1634   let Inst{30}    = isSub;
1635   let Inst{29}    = setFlags;
1636   let Inst{28-24} = 0b10001;
1637   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1638   let Inst{21-10} = imm{11-0};
1639   let Inst{9-5}   = Rn;
1640   let Inst{4-0}   = Rd;
1641   let DecoderMethod = "DecodeBaseAddSubImm";
1642 }
1643
1644 class BaseAddSubRegPseudo<RegisterClass regtype,
1645                           SDPatternOperator OpNode>
1646     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1647              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1648       Sched<[WriteI, ReadI, ReadI]>;
1649
1650 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1651                      arith_shifted_reg shifted_regtype, string asm,
1652                      SDPatternOperator OpNode>
1653     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1654         asm, "\t$Rd, $Rn, $Rm", "",
1655         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1656       Sched<[WriteISReg, ReadI, ReadISReg]> {
1657   // The operands are in order to match the 'addr' MI operands, so we
1658   // don't need an encoder method and by-name matching. Just use the default
1659   // in-order handling. Since we're using by-order, make sure the names
1660   // do not match.
1661   bits<5> dst;
1662   bits<5> src1;
1663   bits<5> src2;
1664   bits<8> shift;
1665   let Inst{30}    = isSub;
1666   let Inst{29}    = setFlags;
1667   let Inst{28-24} = 0b01011;
1668   let Inst{23-22} = shift{7-6};
1669   let Inst{21}    = 0;
1670   let Inst{20-16} = src2;
1671   let Inst{15-10} = shift{5-0};
1672   let Inst{9-5}   = src1;
1673   let Inst{4-0}   = dst;
1674
1675   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1676 }
1677
1678 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1679                      RegisterClass src1Regtype, Operand src2Regtype,
1680                      string asm, SDPatternOperator OpNode>
1681     : I<(outs dstRegtype:$R1),
1682         (ins src1Regtype:$R2, src2Regtype:$R3),
1683         asm, "\t$R1, $R2, $R3", "",
1684         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1685       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1686   bits<5> Rd;
1687   bits<5> Rn;
1688   bits<5> Rm;
1689   bits<6> ext;
1690   let Inst{30}    = isSub;
1691   let Inst{29}    = setFlags;
1692   let Inst{28-24} = 0b01011;
1693   let Inst{23-21} = 0b001;
1694   let Inst{20-16} = Rm;
1695   let Inst{15-13} = ext{5-3};
1696   let Inst{12-10} = ext{2-0};
1697   let Inst{9-5}   = Rn;
1698   let Inst{4-0}   = Rd;
1699
1700   let DecoderMethod = "DecodeAddSubERegInstruction";
1701 }
1702
1703 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1704 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1705                        RegisterClass src1Regtype, RegisterClass src2Regtype,
1706                        Operand ext_op, string asm>
1707     : I<(outs dstRegtype:$Rd),
1708         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1709         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1710       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1711   bits<5> Rd;
1712   bits<5> Rn;
1713   bits<5> Rm;
1714   bits<6> ext;
1715   let Inst{30}    = isSub;
1716   let Inst{29}    = setFlags;
1717   let Inst{28-24} = 0b01011;
1718   let Inst{23-21} = 0b001;
1719   let Inst{20-16} = Rm;
1720   let Inst{15}    = ext{5};
1721   let Inst{12-10} = ext{2-0};
1722   let Inst{9-5}   = Rn;
1723   let Inst{4-0}   = Rd;
1724
1725   let DecoderMethod = "DecodeAddSubERegInstruction";
1726 }
1727
1728 // Aliases for register+register add/subtract.
1729 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1730                      RegisterClass src1Regtype, RegisterClass src2Regtype,
1731                      int shiftExt>
1732     : InstAlias<asm#"\t$dst, $src1, $src2",
1733                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1734                       shiftExt)>;
1735
1736 multiclass AddSub<bit isSub, string mnemonic, string alias,
1737                   SDPatternOperator OpNode = null_frag> {
1738   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1739   // Add/Subtract immediate
1740   // Increase the weight of the immediate variant to try to match it before
1741   // the extended register variant.
1742   // We used to match the register variant before the immediate when the
1743   // register argument could be implicitly zero-extended.
1744   let AddedComplexity = 6 in
1745   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1746                            mnemonic, OpNode> {
1747     let Inst{31} = 0;
1748   }
1749   let AddedComplexity = 6 in
1750   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1751                            mnemonic, OpNode> {
1752     let Inst{31} = 1;
1753   }
1754
1755   // Add/Subtract register - Only used for CodeGen
1756   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1757   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1758
1759   // Add/Subtract shifted register
1760   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1761                            OpNode> {
1762     let Inst{31} = 0;
1763   }
1764   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1765                            OpNode> {
1766     let Inst{31} = 1;
1767   }
1768   }
1769
1770   // Add/Subtract extended register
1771   let AddedComplexity = 1, hasSideEffects = 0 in {
1772   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1773                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1774     let Inst{31} = 0;
1775   }
1776   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1777                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1778     let Inst{31} = 1;
1779   }
1780   }
1781
1782   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1783                                arith_extendlsl64, mnemonic> {
1784     // UXTX and SXTX only.
1785     let Inst{14-13} = 0b11;
1786     let Inst{31} = 1;
1787   }
1788
1789   // add Rd, Rb, -imm -> sub Rd, Rn, imm
1790   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1791                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
1792                       addsub_shifted_imm32_neg:$imm), 0>;
1793   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1794                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
1795                        addsub_shifted_imm64_neg:$imm), 0>;
1796
1797   // Register/register aliases with no shift when SP is not used.
1798   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1799                        GPR32, GPR32, GPR32, 0>;
1800   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1801                        GPR64, GPR64, GPR64, 0>;
1802
1803   // Register/register aliases with no shift when either the destination or
1804   // first source register is SP.
1805   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1806                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1807   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1808                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1809   def : AddSubRegAlias<mnemonic,
1810                        !cast<Instruction>(NAME#"Xrx64"),
1811                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1812   def : AddSubRegAlias<mnemonic,
1813                        !cast<Instruction>(NAME#"Xrx64"),
1814                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1815 }
1816
1817 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
1818                    string alias, string cmpAlias> {
1819   let isCompare = 1, Defs = [NZCV] in {
1820   // Add/Subtract immediate
1821   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1822                            mnemonic, OpNode> {
1823     let Inst{31} = 0;
1824   }
1825   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1826                            mnemonic, OpNode> {
1827     let Inst{31} = 1;
1828   }
1829
1830   // Add/Subtract register
1831   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1832   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1833
1834   // Add/Subtract shifted register
1835   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1836                            OpNode> {
1837     let Inst{31} = 0;
1838   }
1839   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1840                            OpNode> {
1841     let Inst{31} = 1;
1842   }
1843
1844   // Add/Subtract extended register
1845   let AddedComplexity = 1 in {
1846   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1847                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1848     let Inst{31} = 0;
1849   }
1850   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1851                            arith_extended_reg32<i64>, mnemonic, OpNode> {
1852     let Inst{31} = 1;
1853   }
1854   }
1855
1856   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1857                                arith_extendlsl64, mnemonic> {
1858     // UXTX and SXTX only.
1859     let Inst{14-13} = 0b11;
1860     let Inst{31} = 1;
1861   }
1862   } // Defs = [NZCV]
1863
1864   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
1865   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1866                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
1867                       addsub_shifted_imm32_neg:$imm), 0>;
1868   def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1869                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
1870                        addsub_shifted_imm64_neg:$imm), 0>;
1871
1872   // Compare aliases
1873   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1874                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1875   def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1876                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1877   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1878                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1879   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1880                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1881   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1882                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1883   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1884                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1885   def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1886                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1887
1888   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
1889   def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1890                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
1891   def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1892                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
1893
1894   // Compare shorthands
1895   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1896                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1897   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1898                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1899   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1900                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1901   def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1902                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1903
1904   // Register/register aliases with no shift when SP is not used.
1905   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1906                        GPR32, GPR32, GPR32, 0>;
1907   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1908                        GPR64, GPR64, GPR64, 0>;
1909
1910   // Register/register aliases with no shift when the first source register
1911   // is SP.
1912   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1913                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1914   def : AddSubRegAlias<mnemonic,
1915                        !cast<Instruction>(NAME#"Xrx64"),
1916                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1917 }
1918
1919 //---
1920 // Extract
1921 //---
1922 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1923                                       SDTCisPtrTy<3>]>;
1924 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1925
1926 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1927                      list<dag> patterns>
1928     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1929          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1930       Sched<[WriteExtr, ReadExtrHi]> {
1931   bits<5> Rd;
1932   bits<5> Rn;
1933   bits<5> Rm;
1934   bits<6> imm;
1935
1936   let Inst{30-23} = 0b00100111;
1937   let Inst{21}    = 0;
1938   let Inst{20-16} = Rm;
1939   let Inst{15-10} = imm;
1940   let Inst{9-5}   = Rn;
1941   let Inst{4-0}   = Rd;
1942 }
1943
1944 multiclass ExtractImm<string asm> {
1945   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1946                       [(set GPR32:$Rd,
1947                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1948     let Inst{31} = 0;
1949     let Inst{22} = 0;
1950     // imm<5> must be zero.
1951     let imm{5}   = 0;
1952   }
1953   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1954                       [(set GPR64:$Rd,
1955                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1956
1957     let Inst{31} = 1;
1958     let Inst{22} = 1;
1959   }
1960 }
1961
1962 //---
1963 // Bitfield
1964 //---
1965
1966 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1967 class BaseBitfieldImm<bits<2> opc,
1968                       RegisterClass regtype, Operand imm_type, string asm>
1969     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1970          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1971       Sched<[WriteIS, ReadI]> {
1972   bits<5> Rd;
1973   bits<5> Rn;
1974   bits<6> immr;
1975   bits<6> imms;
1976
1977   let Inst{30-29} = opc;
1978   let Inst{28-23} = 0b100110;
1979   let Inst{21-16} = immr;
1980   let Inst{15-10} = imms;
1981   let Inst{9-5}   = Rn;
1982   let Inst{4-0}   = Rd;
1983 }
1984
1985 multiclass BitfieldImm<bits<2> opc, string asm> {
1986   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1987     let Inst{31} = 0;
1988     let Inst{22} = 0;
1989     // imms<5> and immr<5> must be zero, else ReservedValue().
1990     let Inst{21} = 0;
1991     let Inst{15} = 0;
1992   }
1993   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1994     let Inst{31} = 1;
1995     let Inst{22} = 1;
1996   }
1997 }
1998
1999 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2000 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2001                       RegisterClass regtype, Operand imm_type, string asm>
2002     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2003                              imm_type:$imms),
2004          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2005       Sched<[WriteIS, ReadI]> {
2006   bits<5> Rd;
2007   bits<5> Rn;
2008   bits<6> immr;
2009   bits<6> imms;
2010
2011   let Inst{30-29} = opc;
2012   let Inst{28-23} = 0b100110;
2013   let Inst{21-16} = immr;
2014   let Inst{15-10} = imms;
2015   let Inst{9-5}   = Rn;
2016   let Inst{4-0}   = Rd;
2017 }
2018
2019 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2020   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2021     let Inst{31} = 0;
2022     let Inst{22} = 0;
2023     // imms<5> and immr<5> must be zero, else ReservedValue().
2024     let Inst{21} = 0;
2025     let Inst{15} = 0;
2026   }
2027   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2028     let Inst{31} = 1;
2029     let Inst{22} = 1;
2030   }
2031 }
2032
2033 //---
2034 // Logical
2035 //---
2036
2037 // Logical (immediate)
2038 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2039                      RegisterClass sregtype, Operand imm_type, string asm,
2040                      list<dag> pattern>
2041     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2042          asm, "\t$Rd, $Rn, $imm", "", pattern>,
2043       Sched<[WriteI, ReadI]> {
2044   bits<5>  Rd;
2045   bits<5>  Rn;
2046   bits<13> imm;
2047   let Inst{30-29} = opc;
2048   let Inst{28-23} = 0b100100;
2049   let Inst{22}    = imm{12};
2050   let Inst{21-16} = imm{11-6};
2051   let Inst{15-10} = imm{5-0};
2052   let Inst{9-5}   = Rn;
2053   let Inst{4-0}   = Rd;
2054
2055   let DecoderMethod = "DecodeLogicalImmInstruction";
2056 }
2057
2058 // Logical (shifted register)
2059 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2060                       logical_shifted_reg shifted_regtype, string asm,
2061                       list<dag> pattern>
2062     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2063         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2064       Sched<[WriteISReg, ReadI, ReadISReg]> {
2065   // The operands are in order to match the 'addr' MI operands, so we
2066   // don't need an encoder method and by-name matching. Just use the default
2067   // in-order handling. Since we're using by-order, make sure the names
2068   // do not match.
2069   bits<5> dst;
2070   bits<5> src1;
2071   bits<5> src2;
2072   bits<8> shift;
2073   let Inst{30-29} = opc;
2074   let Inst{28-24} = 0b01010;
2075   let Inst{23-22} = shift{7-6};
2076   let Inst{21}    = N;
2077   let Inst{20-16} = src2;
2078   let Inst{15-10} = shift{5-0};
2079   let Inst{9-5}   = src1;
2080   let Inst{4-0}   = dst;
2081
2082   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2083 }
2084
2085 // Aliases for register+register logical instructions.
2086 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2087     : InstAlias<asm#"\t$dst, $src1, $src2",
2088                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2089
2090 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2091                       string Alias> {
2092   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2093   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2094                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2095                                                logical_imm32:$imm))]> {
2096     let Inst{31} = 0;
2097     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2098   }
2099   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2100   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2101                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2102                                                logical_imm64:$imm))]> {
2103     let Inst{31} = 1;
2104   }
2105
2106   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2107                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2108                       logical_imm32_not:$imm), 0>;
2109   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2110                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2111                        logical_imm64_not:$imm), 0>;
2112 }
2113
2114 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2115                        string Alias> {
2116   let isCompare = 1, Defs = [NZCV] in {
2117   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2118       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2119     let Inst{31} = 0;
2120     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2121   }
2122   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2123       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2124     let Inst{31} = 1;
2125   }
2126   } // end Defs = [NZCV]
2127
2128   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2129                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2130                       logical_imm32_not:$imm), 0>;
2131   def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2132                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2133                        logical_imm64_not:$imm), 0>;
2134 }
2135
2136 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2137     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2138              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2139       Sched<[WriteI, ReadI, ReadI]>;
2140
2141 // Split from LogicalImm as not all instructions have both.
2142 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2143                       SDPatternOperator OpNode> {
2144   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2145   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2146   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2147   }
2148
2149   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2150                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2151                                                  logical_shifted_reg32:$Rm))]> {
2152     let Inst{31} = 0;
2153   }
2154   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2155                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2156                                                  logical_shifted_reg64:$Rm))]> {
2157     let Inst{31} = 1;
2158   }
2159
2160   def : LogicalRegAlias<mnemonic,
2161                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2162   def : LogicalRegAlias<mnemonic,
2163                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2164 }
2165
2166 // Split from LogicalReg to allow setting NZCV Defs
2167 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2168                        SDPatternOperator OpNode = null_frag> {
2169   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2170   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2171   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2172
2173   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2174             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2175     let Inst{31} = 0;
2176   }
2177   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2178             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2179     let Inst{31} = 1;
2180   }
2181   } // Defs = [NZCV]
2182
2183   def : LogicalRegAlias<mnemonic,
2184                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2185   def : LogicalRegAlias<mnemonic,
2186                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2187 }
2188
2189 //---
2190 // Conditionally set flags
2191 //---
2192
2193 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2194 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2195                             string mnemonic, SDNode OpNode>
2196     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2197          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2198          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2199                              (i32 imm:$cond), NZCV))]>,
2200       Sched<[WriteI, ReadI]> {
2201   let Uses = [NZCV];
2202   let Defs = [NZCV];
2203
2204   bits<5> Rn;
2205   bits<5> imm;
2206   bits<4> nzcv;
2207   bits<4> cond;
2208
2209   let Inst{30}    = op;
2210   let Inst{29-21} = 0b111010010;
2211   let Inst{20-16} = imm;
2212   let Inst{15-12} = cond;
2213   let Inst{11-10} = 0b10;
2214   let Inst{9-5}   = Rn;
2215   let Inst{4}     = 0b0;
2216   let Inst{3-0}   = nzcv;
2217 }
2218
2219 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2220 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2221                             SDNode OpNode>
2222     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2223          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2224          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2225                              (i32 imm:$cond), NZCV))]>,
2226       Sched<[WriteI, ReadI, ReadI]> {
2227   let Uses = [NZCV];
2228   let Defs = [NZCV];
2229
2230   bits<5> Rn;
2231   bits<5> Rm;
2232   bits<4> nzcv;
2233   bits<4> cond;
2234
2235   let Inst{30}    = op;
2236   let Inst{29-21} = 0b111010010;
2237   let Inst{20-16} = Rm;
2238   let Inst{15-12} = cond;
2239   let Inst{11-10} = 0b00;
2240   let Inst{9-5}   = Rn;
2241   let Inst{4}     = 0b0;
2242   let Inst{3-0}   = nzcv;
2243 }
2244
2245 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2246   // immediate operand variants
2247   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2248     let Inst{31} = 0;
2249   }
2250   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2251     let Inst{31} = 1;
2252   }
2253   // register operand variants
2254   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2255     let Inst{31} = 0;
2256   }
2257   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2258     let Inst{31} = 1;
2259   }
2260 }
2261
2262 //---
2263 // Conditional select
2264 //---
2265
2266 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2267     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2268          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2269          [(set regtype:$Rd,
2270                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2271       Sched<[WriteI, ReadI, ReadI]> {
2272   let Uses = [NZCV];
2273
2274   bits<5> Rd;
2275   bits<5> Rn;
2276   bits<5> Rm;
2277   bits<4> cond;
2278
2279   let Inst{30}    = op;
2280   let Inst{29-21} = 0b011010100;
2281   let Inst{20-16} = Rm;
2282   let Inst{15-12} = cond;
2283   let Inst{11-10} = op2;
2284   let Inst{9-5}   = Rn;
2285   let Inst{4-0}   = Rd;
2286 }
2287
2288 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2289   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2290     let Inst{31} = 0;
2291   }
2292   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2293     let Inst{31} = 1;
2294   }
2295 }
2296
2297 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2298                        PatFrag frag>
2299     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2300          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2301          [(set regtype:$Rd,
2302                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2303                (i32 imm:$cond), NZCV))]>,
2304       Sched<[WriteI, ReadI, ReadI]> {
2305   let Uses = [NZCV];
2306
2307   bits<5> Rd;
2308   bits<5> Rn;
2309   bits<5> Rm;
2310   bits<4> cond;
2311
2312   let Inst{30}    = op;
2313   let Inst{29-21} = 0b011010100;
2314   let Inst{20-16} = Rm;
2315   let Inst{15-12} = cond;
2316   let Inst{11-10} = op2;
2317   let Inst{9-5}   = Rn;
2318   let Inst{4-0}   = Rd;
2319 }
2320
2321 def inv_cond_XFORM : SDNodeXForm<imm, [{
2322   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2323   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2324                                    MVT::i32);
2325 }]>;
2326
2327 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2328   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2329     let Inst{31} = 0;
2330   }
2331   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2332     let Inst{31} = 1;
2333   }
2334
2335   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2336             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2337                                            (inv_cond_XFORM imm:$cond))>;
2338
2339   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2340             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2341                                            (inv_cond_XFORM imm:$cond))>;
2342 }
2343
2344 //---
2345 // Special Mask Value
2346 //---
2347 def maski8_or_more : Operand<i32>,
2348   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2349 }
2350 def maski16_or_more : Operand<i32>,
2351   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2352 }
2353
2354
2355 //---
2356 // Load/store
2357 //---
2358
2359 // (unsigned immediate)
2360 // Indexed for 8-bit registers. offset is in range [0,4095].
2361 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2362 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2363 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2364 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2365 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2366
2367 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2368   let Name = "UImm12Offset" # Scale;
2369   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2370   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2371   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2372 }
2373
2374 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2375 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2376 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2377 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2378 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2379
2380 class uimm12_scaled<int Scale> : Operand<i64> {
2381   let ParserMatchClass
2382    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2383   let EncoderMethod
2384    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2385   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2386 }
2387
2388 def uimm12s1 : uimm12_scaled<1>;
2389 def uimm12s2 : uimm12_scaled<2>;
2390 def uimm12s4 : uimm12_scaled<4>;
2391 def uimm12s8 : uimm12_scaled<8>;
2392 def uimm12s16 : uimm12_scaled<16>;
2393
2394 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2395                       string asm, list<dag> pattern>
2396     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2397   bits<5> Rt;
2398
2399   bits<5> Rn;
2400   bits<12> offset;
2401
2402   let Inst{31-30} = sz;
2403   let Inst{29-27} = 0b111;
2404   let Inst{26}    = V;
2405   let Inst{25-24} = 0b01;
2406   let Inst{23-22} = opc;
2407   let Inst{21-10} = offset;
2408   let Inst{9-5}   = Rn;
2409   let Inst{4-0}   = Rt;
2410
2411   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2412 }
2413
2414 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2415                   Operand indextype, string asm, list<dag> pattern> {
2416   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2417   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2418                            (ins GPR64sp:$Rn, indextype:$offset),
2419                            asm, pattern>,
2420            Sched<[WriteLD]>;
2421
2422   def : InstAlias<asm # "\t$Rt, [$Rn]",
2423                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2424 }
2425
2426 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2427              Operand indextype, string asm, list<dag> pattern> {
2428   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2429   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2430                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2431                            asm, pattern>,
2432            Sched<[WriteST]>;
2433
2434   def : InstAlias<asm # "\t$Rt, [$Rn]",
2435                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2436 }
2437
2438 def PrefetchOperand : AsmOperandClass {
2439   let Name = "Prefetch";
2440   let ParserMethod = "tryParsePrefetch";
2441 }
2442 def prfop : Operand<i32> {
2443   let PrintMethod = "printPrefetchOp";
2444   let ParserMatchClass = PrefetchOperand;
2445 }
2446
2447 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2448 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2449     : BaseLoadStoreUI<sz, V, opc,
2450                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2451                       asm, pat>,
2452       Sched<[WriteLD]>;
2453
2454 //---
2455 // Load literal
2456 //---
2457
2458 // Load literal address: 19-bit immediate. The low two bits of the target
2459 // offset are implied zero and so are not part of the immediate.
2460 def am_ldrlit : Operand<OtherVT> {
2461   let EncoderMethod = "getLoadLiteralOpValue";
2462   let DecoderMethod = "DecodePCRelLabel19";
2463   let PrintMethod = "printAlignedLabel";
2464   let ParserMatchClass = PCRelLabel19Operand;
2465 }
2466
2467 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2468 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2469     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2470         asm, "\t$Rt, $label", "", []>,
2471       Sched<[WriteLD]> {
2472   bits<5> Rt;
2473   bits<19> label;
2474   let Inst{31-30} = opc;
2475   let Inst{29-27} = 0b011;
2476   let Inst{26}    = V;
2477   let Inst{25-24} = 0b00;
2478   let Inst{23-5}  = label;
2479   let Inst{4-0}   = Rt;
2480 }
2481
2482 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2483 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2484     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2485         asm, "\t$Rt, $label", "", pat>,
2486       Sched<[WriteLD]> {
2487   bits<5> Rt;
2488   bits<19> label;
2489   let Inst{31-30} = opc;
2490   let Inst{29-27} = 0b011;
2491   let Inst{26}    = V;
2492   let Inst{25-24} = 0b00;
2493   let Inst{23-5}  = label;
2494   let Inst{4-0}   = Rt;
2495 }
2496
2497 //---
2498 // Load/store register offset
2499 //---
2500
2501 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2502 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2503 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2504 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2505 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2506
2507 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2508 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2509 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2510 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2511 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2512
2513 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2514   let Name = "Mem" # Reg # "Extend" # Width;
2515   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2516   let RenderMethod = "addMemExtendOperands";
2517   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2518 }
2519
2520 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2521   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2522   // the trivial shift.
2523   let RenderMethod = "addMemExtend8Operands";
2524 }
2525 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2526 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2527 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2528 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2529
2530 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2531   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2532   // the trivial shift.
2533   let RenderMethod = "addMemExtend8Operands";
2534 }
2535 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2536 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2537 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2538 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2539
2540 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2541         : Operand<i32> {
2542   let ParserMatchClass = ParserClass;
2543   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2544   let DecoderMethod = "DecodeMemExtend";
2545   let EncoderMethod = "getMemExtendOpValue";
2546   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2547 }
2548
2549 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2550 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2551 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2552 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2553 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2554
2555 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2556 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2557 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2558 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2559 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2560
2561 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2562                   Operand wextend, Operand xextend>  {
2563   // CodeGen-level pattern covering the entire addressing mode.
2564   ComplexPattern Wpat = windex;
2565   ComplexPattern Xpat = xindex;
2566
2567   // Asm-level Operand covering the valid "uxtw #3" style syntax.
2568   Operand Wext = wextend;
2569   Operand Xext = xextend;
2570 }
2571
2572 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2573 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2574 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2575 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2576 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2577                        ro_Xextend128>;
2578
2579 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2580                       string asm, dag ins, dag outs, list<dag> pat>
2581     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2582   bits<5> Rt;
2583   bits<5> Rn;
2584   bits<5> Rm;
2585   bits<2> extend;
2586   let Inst{31-30} = sz;
2587   let Inst{29-27} = 0b111;
2588   let Inst{26}    = V;
2589   let Inst{25-24} = 0b00;
2590   let Inst{23-22} = opc;
2591   let Inst{21}    = 1;
2592   let Inst{20-16} = Rm;
2593   let Inst{15}    = extend{1}; // sign extend Rm?
2594   let Inst{14}    = 1;
2595   let Inst{12}    = extend{0}; // do shift?
2596   let Inst{11-10} = 0b10;
2597   let Inst{9-5}   = Rn;
2598   let Inst{4-0}   = Rt;
2599 }
2600
2601 class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2602   : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
2603               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2604
2605 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2606                    string asm, ValueType Ty, SDPatternOperator loadop> {
2607   let AddedComplexity = 10 in
2608   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2609                  (outs regtype:$Rt),
2610                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2611                  [(set (Ty regtype:$Rt),
2612                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2613                                              ro_Wextend8:$extend)))]>,
2614            Sched<[WriteLDIdx, ReadAdrBase]> {
2615     let Inst{13} = 0b0;
2616   }
2617
2618   let AddedComplexity = 10 in
2619   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2620                  (outs regtype:$Rt),
2621                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2622                  [(set (Ty regtype:$Rt),
2623                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2624                                              ro_Xextend8:$extend)))]>,
2625            Sched<[WriteLDIdx, ReadAdrBase]> {
2626     let Inst{13} = 0b1;
2627   }
2628
2629   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2630 }
2631
2632 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2633                     string asm, ValueType Ty, SDPatternOperator storeop> {
2634   let AddedComplexity = 10 in
2635   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2636                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2637                  [(storeop (Ty regtype:$Rt),
2638                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2639                                          ro_Wextend8:$extend))]>,
2640             Sched<[WriteSTIdx, ReadAdrBase]> {
2641     let Inst{13} = 0b0;
2642   }
2643
2644   let AddedComplexity = 10 in
2645   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2646                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2647                  [(storeop (Ty regtype:$Rt),
2648                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2649                                          ro_Xextend8:$extend))]>,
2650             Sched<[WriteSTIdx, ReadAdrBase]> {
2651     let Inst{13} = 0b1;
2652   }
2653
2654   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2655 }
2656
2657 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2658                       string asm, dag ins, dag outs, list<dag> pat>
2659     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2660   bits<5> Rt;
2661   bits<5> Rn;
2662   bits<5> Rm;
2663   bits<2> extend;
2664   let Inst{31-30} = sz;
2665   let Inst{29-27} = 0b111;
2666   let Inst{26}    = V;
2667   let Inst{25-24} = 0b00;
2668   let Inst{23-22} = opc;
2669   let Inst{21}    = 1;
2670   let Inst{20-16} = Rm;
2671   let Inst{15}    = extend{1}; // sign extend Rm?
2672   let Inst{14}    = 1;
2673   let Inst{12}    = extend{0}; // do shift?
2674   let Inst{11-10} = 0b10;
2675   let Inst{9-5}   = Rn;
2676   let Inst{4-0}   = Rt;
2677 }
2678
2679 multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2680                     string asm, ValueType Ty, SDPatternOperator loadop> {
2681   let AddedComplexity = 10 in
2682   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2683                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2684                  [(set (Ty regtype:$Rt),
2685                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2686                                               ro_Wextend16:$extend)))]>,
2687             Sched<[WriteLDIdx, ReadAdrBase]> {
2688     let Inst{13} = 0b0;
2689   }
2690
2691   let AddedComplexity = 10 in
2692   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2693                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2694                  [(set (Ty regtype:$Rt),
2695                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2696                                              ro_Xextend16:$extend)))]>,
2697             Sched<[WriteLDIdx, ReadAdrBase]> {
2698     let Inst{13} = 0b1;
2699   }
2700
2701   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2702 }
2703
2704 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2705                      string asm, ValueType Ty, SDPatternOperator storeop> {
2706   let AddedComplexity = 10 in
2707   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2708                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2709                 [(storeop (Ty regtype:$Rt),
2710                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2711                                          ro_Wextend16:$extend))]>,
2712            Sched<[WriteSTIdx, ReadAdrBase]> {
2713     let Inst{13} = 0b0;
2714   }
2715
2716   let AddedComplexity = 10 in
2717   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2718                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2719                 [(storeop (Ty regtype:$Rt),
2720                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2721                                          ro_Xextend16:$extend))]>,
2722            Sched<[WriteSTIdx, ReadAdrBase]> {
2723     let Inst{13} = 0b1;
2724   }
2725
2726   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2727 }
2728
2729 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2730                       string asm, dag ins, dag outs, list<dag> pat>
2731     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2732   bits<5> Rt;
2733   bits<5> Rn;
2734   bits<5> Rm;
2735   bits<2> extend;
2736   let Inst{31-30} = sz;
2737   let Inst{29-27} = 0b111;
2738   let Inst{26}    = V;
2739   let Inst{25-24} = 0b00;
2740   let Inst{23-22} = opc;
2741   let Inst{21}    = 1;
2742   let Inst{20-16} = Rm;
2743   let Inst{15}    = extend{1}; // sign extend Rm?
2744   let Inst{14}    = 1;
2745   let Inst{12}    = extend{0}; // do shift?
2746   let Inst{11-10} = 0b10;
2747   let Inst{9-5}   = Rn;
2748   let Inst{4-0}   = Rt;
2749 }
2750
2751 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2752                     string asm, ValueType Ty, SDPatternOperator loadop> {
2753   let AddedComplexity = 10 in
2754   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2755                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2756                  [(set (Ty regtype:$Rt),
2757                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2758                                               ro_Wextend32:$extend)))]>,
2759            Sched<[WriteLDIdx, ReadAdrBase]> {
2760     let Inst{13} = 0b0;
2761   }
2762
2763   let AddedComplexity = 10 in
2764   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2765                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2766                  [(set (Ty regtype:$Rt),
2767                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2768                                               ro_Xextend32:$extend)))]>,
2769            Sched<[WriteLDIdx, ReadAdrBase]> {
2770     let Inst{13} = 0b1;
2771   }
2772
2773   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2774 }
2775
2776 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2777                      string asm, ValueType Ty, SDPatternOperator storeop> {
2778   let AddedComplexity = 10 in
2779   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2780                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2781                 [(storeop (Ty regtype:$Rt),
2782                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2783                                          ro_Wextend32:$extend))]>,
2784             Sched<[WriteSTIdx, ReadAdrBase]> {
2785     let Inst{13} = 0b0;
2786   }
2787
2788   let AddedComplexity = 10 in
2789   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2790                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2791                 [(storeop (Ty regtype:$Rt),
2792                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2793                                         ro_Xextend32:$extend))]>,
2794             Sched<[WriteSTIdx, ReadAdrBase]> {
2795     let Inst{13} = 0b1;
2796   }
2797
2798   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2799 }
2800
2801 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2802                       string asm, dag ins, dag outs, list<dag> pat>
2803     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2804   bits<5> Rt;
2805   bits<5> Rn;
2806   bits<5> Rm;
2807   bits<2> extend;
2808   let Inst{31-30} = sz;
2809   let Inst{29-27} = 0b111;
2810   let Inst{26}    = V;
2811   let Inst{25-24} = 0b00;
2812   let Inst{23-22} = opc;
2813   let Inst{21}    = 1;
2814   let Inst{20-16} = Rm;
2815   let Inst{15}    = extend{1}; // sign extend Rm?
2816   let Inst{14}    = 1;
2817   let Inst{12}    = extend{0}; // do shift?
2818   let Inst{11-10} = 0b10;
2819   let Inst{9-5}   = Rn;
2820   let Inst{4-0}   = Rt;
2821 }
2822
2823 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2824                     string asm, ValueType Ty, SDPatternOperator loadop> {
2825   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2826   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2827                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2828                 [(set (Ty regtype:$Rt),
2829                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2830                                              ro_Wextend64:$extend)))]>,
2831            Sched<[WriteLDIdx, ReadAdrBase]> {
2832     let Inst{13} = 0b0;
2833   }
2834
2835   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2836   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2837                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2838                  [(set (Ty regtype:$Rt),
2839                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2840                                               ro_Xextend64:$extend)))]>,
2841            Sched<[WriteLDIdx, ReadAdrBase]> {
2842     let Inst{13} = 0b1;
2843   }
2844
2845   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2846 }
2847
2848 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2849                      string asm, ValueType Ty, SDPatternOperator storeop> {
2850   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2851   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2852                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2853                 [(storeop (Ty regtype:$Rt),
2854                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2855                                          ro_Wextend64:$extend))]>,
2856             Sched<[WriteSTIdx, ReadAdrBase]> {
2857     let Inst{13} = 0b0;
2858   }
2859
2860   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2861   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2862                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2863                 [(storeop (Ty regtype:$Rt),
2864                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2865                                          ro_Xextend64:$extend))]>,
2866             Sched<[WriteSTIdx, ReadAdrBase]> {
2867     let Inst{13} = 0b1;
2868   }
2869
2870   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2871 }
2872
2873 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2874                       string asm, dag ins, dag outs, list<dag> pat>
2875     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2876   bits<5> Rt;
2877   bits<5> Rn;
2878   bits<5> Rm;
2879   bits<2> extend;
2880   let Inst{31-30} = sz;
2881   let Inst{29-27} = 0b111;
2882   let Inst{26}    = V;
2883   let Inst{25-24} = 0b00;
2884   let Inst{23-22} = opc;
2885   let Inst{21}    = 1;
2886   let Inst{20-16} = Rm;
2887   let Inst{15}    = extend{1}; // sign extend Rm?
2888   let Inst{14}    = 1;
2889   let Inst{12}    = extend{0}; // do shift?
2890   let Inst{11-10} = 0b10;
2891   let Inst{9-5}   = Rn;
2892   let Inst{4-0}   = Rt;
2893 }
2894
2895 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2896                      string asm, ValueType Ty, SDPatternOperator loadop> {
2897   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2898   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2899                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2900                  [(set (Ty regtype:$Rt),
2901                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2902                                                ro_Wextend128:$extend)))]>,
2903             Sched<[WriteLDIdx, ReadAdrBase]> {
2904     let Inst{13} = 0b0;
2905   }
2906
2907   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2908   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2909                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2910                  [(set (Ty regtype:$Rt),
2911                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2912                                                ro_Xextend128:$extend)))]>,
2913             Sched<[WriteLDIdx, ReadAdrBase]> {
2914     let Inst{13} = 0b1;
2915   }
2916
2917   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2918 }
2919
2920 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2921                       string asm, ValueType Ty, SDPatternOperator storeop> {
2922   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2923   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2924                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2925                 [(storeop (Ty regtype:$Rt),
2926                           (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2927                                           ro_Wextend128:$extend))]>,
2928             Sched<[WriteSTIdx, ReadAdrBase]> {
2929     let Inst{13} = 0b0;
2930   }
2931
2932   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2933   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2934                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2935                 [(storeop (Ty regtype:$Rt),
2936                           (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2937                                           ro_Xextend128:$extend))]>,
2938             Sched<[WriteSTIdx, ReadAdrBase]> {
2939     let Inst{13} = 0b1;
2940   }
2941
2942   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2943 }
2944
2945 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2946 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2947                      string asm, list<dag> pat>
2948     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2949       Sched<[WriteLD]> {
2950   bits<5> Rt;
2951   bits<5> Rn;
2952   bits<5> Rm;
2953   bits<2> extend;
2954   let Inst{31-30} = sz;
2955   let Inst{29-27} = 0b111;
2956   let Inst{26}    = V;
2957   let Inst{25-24} = 0b00;
2958   let Inst{23-22} = opc;
2959   let Inst{21}    = 1;
2960   let Inst{20-16} = Rm;
2961   let Inst{15}    = extend{1}; // sign extend Rm?
2962   let Inst{14}    = 1;
2963   let Inst{12}    = extend{0}; // do shift?
2964   let Inst{11-10} = 0b10;
2965   let Inst{9-5}   = Rn;
2966   let Inst{4-0}   = Rt;
2967 }
2968
2969 multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2970   def roW : BasePrefetchRO<sz, V, opc, (outs),
2971                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2972                 asm, [(AArch64Prefetch imm:$Rt,
2973                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2974                                                     ro_Wextend64:$extend))]> {
2975     let Inst{13} = 0b0;
2976   }
2977
2978   def roX : BasePrefetchRO<sz, V, opc, (outs),
2979                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2980                 asm,  [(AArch64Prefetch imm:$Rt,
2981                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2982                                                      ro_Xextend64:$extend))]> {
2983     let Inst{13} = 0b1;
2984   }
2985
2986   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2987                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2988                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2989 }
2990
2991 //---
2992 // Load/store unscaled immediate
2993 //---
2994
2995 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2996 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2997 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2998 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2999 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3000
3001 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3002                            string asm, list<dag> pattern>
3003     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3004   bits<5> Rt;
3005   bits<5> Rn;
3006   bits<9> offset;
3007   let Inst{31-30} = sz;
3008   let Inst{29-27} = 0b111;
3009   let Inst{26}    = V;
3010   let Inst{25-24} = 0b00;
3011   let Inst{23-22} = opc;
3012   let Inst{21}    = 0;
3013   let Inst{20-12} = offset;
3014   let Inst{11-10} = 0b00;
3015   let Inst{9-5}   = Rn;
3016   let Inst{4-0}   = Rt;
3017
3018   let DecoderMethod = "DecodeSignedLdStInstruction";
3019 }
3020
3021 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3022                    string asm, list<dag> pattern> {
3023   let AddedComplexity = 1 in // try this before LoadUI
3024   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3025                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3026           Sched<[WriteLD]>;
3027
3028   def : InstAlias<asm # "\t$Rt, [$Rn]",
3029                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3030 }
3031
3032 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3033                          string asm, list<dag> pattern> {
3034   let AddedComplexity = 1 in // try this before StoreUI
3035   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3036                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3037                                asm, pattern>,
3038           Sched<[WriteST]>;
3039
3040   def : InstAlias<asm # "\t$Rt, [$Rn]",
3041                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3042 }
3043
3044 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3045                             list<dag> pat> {
3046   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3047   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3048                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3049                                asm, pat>,
3050           Sched<[WriteLD]>;
3051
3052   def : InstAlias<asm # "\t$Rt, [$Rn]",
3053                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3054 }
3055
3056 //---
3057 // Load/store unscaled immediate, unprivileged
3058 //---
3059
3060 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3061                                 dag oops, dag iops, string asm>
3062     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3063   bits<5> Rt;
3064   bits<5> Rn;
3065   bits<9> offset;
3066   let Inst{31-30} = sz;
3067   let Inst{29-27} = 0b111;
3068   let Inst{26}    = V;
3069   let Inst{25-24} = 0b00;
3070   let Inst{23-22} = opc;
3071   let Inst{21}    = 0;
3072   let Inst{20-12} = offset;
3073   let Inst{11-10} = 0b10;
3074   let Inst{9-5}   = Rn;
3075   let Inst{4-0}   = Rt;
3076
3077   let DecoderMethod = "DecodeSignedLdStInstruction";
3078 }
3079
3080 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3081                             RegisterClass regtype, string asm> {
3082   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3083   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3084                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
3085           Sched<[WriteLD]>;
3086
3087   def : InstAlias<asm # "\t$Rt, [$Rn]",
3088                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3089 }
3090
3091 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3092                              RegisterClass regtype, string asm> {
3093   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3094   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3095                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3096                                  asm>,
3097           Sched<[WriteST]>;
3098
3099   def : InstAlias<asm # "\t$Rt, [$Rn]",
3100                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3101 }
3102
3103 //---
3104 // Load/store pre-indexed
3105 //---
3106
3107 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3108                           string asm, string cstr, list<dag> pat>
3109     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3110   bits<5> Rt;
3111   bits<5> Rn;
3112   bits<9> offset;
3113   let Inst{31-30} = sz;
3114   let Inst{29-27} = 0b111;
3115   let Inst{26}    = V;
3116   let Inst{25-24} = 0;
3117   let Inst{23-22} = opc;
3118   let Inst{21}    = 0;
3119   let Inst{20-12} = offset;
3120   let Inst{11-10} = 0b11;
3121   let Inst{9-5}   = Rn;
3122   let Inst{4-0}   = Rt;
3123
3124   let DecoderMethod = "DecodeSignedLdStInstruction";
3125 }
3126
3127 let hasSideEffects = 0 in {
3128 let mayStore = 0, mayLoad = 1 in
3129 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3130              string asm>
3131     : BaseLoadStorePreIdx<sz, V, opc,
3132                      (outs GPR64sp:$wback, regtype:$Rt),
3133                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3134                      "$Rn = $wback,@earlyclobber $wback", []>,
3135       Sched<[WriteLD, WriteAdr]>;
3136
3137 let mayStore = 1, mayLoad = 0 in
3138 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3139                   string asm, SDPatternOperator storeop, ValueType Ty>
3140     : BaseLoadStorePreIdx<sz, V, opc,
3141                       (outs GPR64sp:$wback),
3142                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3143                       asm, "$Rn = $wback,@earlyclobber $wback",
3144       [(set GPR64sp:$wback,
3145             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3146       Sched<[WriteAdr, WriteST]>;
3147 } // hasSideEffects = 0
3148
3149 //---
3150 // Load/store post-indexed
3151 //---
3152
3153 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3154                           string asm, string cstr, list<dag> pat>
3155     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3156   bits<5> Rt;
3157   bits<5> Rn;
3158   bits<9> offset;
3159   let Inst{31-30} = sz;
3160   let Inst{29-27} = 0b111;
3161   let Inst{26}    = V;
3162   let Inst{25-24} = 0b00;
3163   let Inst{23-22} = opc;
3164   let Inst{21}    = 0b0;
3165   let Inst{20-12} = offset;
3166   let Inst{11-10} = 0b01;
3167   let Inst{9-5}   = Rn;
3168   let Inst{4-0}   = Rt;
3169
3170   let DecoderMethod = "DecodeSignedLdStInstruction";
3171 }
3172
3173 let hasSideEffects = 0 in {
3174 let mayStore = 0, mayLoad = 1 in
3175 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3176              string asm>
3177     : BaseLoadStorePostIdx<sz, V, opc,
3178                       (outs GPR64sp:$wback, regtype:$Rt),
3179                       (ins GPR64sp:$Rn, simm9:$offset),
3180                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3181       Sched<[WriteLD, WriteI]>;
3182
3183 let mayStore = 1, mayLoad = 0 in
3184 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3185                    string asm, SDPatternOperator storeop, ValueType Ty>
3186     : BaseLoadStorePostIdx<sz, V, opc,
3187                       (outs GPR64sp:$wback),
3188                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3189                        asm, "$Rn = $wback,@earlyclobber $wback",
3190       [(set GPR64sp:$wback,
3191             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3192     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3193 } // hasSideEffects = 0
3194
3195
3196 //---
3197 // Load/store pair
3198 //---
3199
3200 // (indexed, offset)
3201
3202 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3203                               string asm>
3204     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3205   bits<5> Rt;
3206   bits<5> Rt2;
3207   bits<5> Rn;
3208   bits<7> offset;
3209   let Inst{31-30} = opc;
3210   let Inst{29-27} = 0b101;
3211   let Inst{26}    = V;
3212   let Inst{25-23} = 0b010;
3213   let Inst{22}    = L;
3214   let Inst{21-15} = offset;
3215   let Inst{14-10} = Rt2;
3216   let Inst{9-5}   = Rn;
3217   let Inst{4-0}   = Rt;
3218
3219   let DecoderMethod = "DecodePairLdStInstruction";
3220 }
3221
3222 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3223                           Operand indextype, string asm> {
3224   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3225   def i : BaseLoadStorePairOffset<opc, V, 1,
3226                                   (outs regtype:$Rt, regtype:$Rt2),
3227                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3228           Sched<[WriteLD, WriteLDHi]>;
3229
3230   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3231                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3232                                                   GPR64sp:$Rn, 0)>;
3233 }
3234
3235
3236 multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3237                            Operand indextype, string asm> {
3238   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3239   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3240                                   (ins regtype:$Rt, regtype:$Rt2,
3241                                        GPR64sp:$Rn, indextype:$offset),
3242                                   asm>,
3243           Sched<[WriteSTP]>;
3244
3245   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3246                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3247                                                   GPR64sp:$Rn, 0)>;
3248 }
3249
3250 // (pre-indexed)
3251 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3252                               string asm>
3253     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3254   bits<5> Rt;
3255   bits<5> Rt2;
3256   bits<5> Rn;
3257   bits<7> offset;
3258   let Inst{31-30} = opc;
3259   let Inst{29-27} = 0b101;
3260   let Inst{26}    = V;
3261   let Inst{25-23} = 0b011;
3262   let Inst{22}    = L;
3263   let Inst{21-15} = offset;
3264   let Inst{14-10} = Rt2;
3265   let Inst{9-5}   = Rn;
3266   let Inst{4-0}   = Rt;
3267
3268   let DecoderMethod = "DecodePairLdStInstruction";
3269 }
3270
3271 let hasSideEffects = 0 in {
3272 let mayStore = 0, mayLoad = 1 in
3273 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3274                      Operand indextype, string asm>
3275     : BaseLoadStorePairPreIdx<opc, V, 1,
3276                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3277                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3278       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3279
3280 let mayStore = 1, mayLoad = 0 in
3281 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3282                       Operand indextype, string asm>
3283     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3284                              (ins regtype:$Rt, regtype:$Rt2,
3285                                   GPR64sp:$Rn, indextype:$offset),
3286                              asm>,
3287       Sched<[WriteAdr, WriteSTP]>;
3288 } // hasSideEffects = 0
3289
3290 // (post-indexed)
3291
3292 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3293                               string asm>
3294     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3295   bits<5> Rt;
3296   bits<5> Rt2;
3297   bits<5> Rn;
3298   bits<7> offset;
3299   let Inst{31-30} = opc;
3300   let Inst{29-27} = 0b101;
3301   let Inst{26}    = V;
3302   let Inst{25-23} = 0b001;
3303   let Inst{22}    = L;
3304   let Inst{21-15} = offset;
3305   let Inst{14-10} = Rt2;
3306   let Inst{9-5}   = Rn;
3307   let Inst{4-0}   = Rt;
3308
3309   let DecoderMethod = "DecodePairLdStInstruction";
3310 }
3311
3312 let hasSideEffects = 0 in {
3313 let mayStore = 0, mayLoad = 1 in
3314 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3315                       Operand idxtype, string asm>
3316     : BaseLoadStorePairPostIdx<opc, V, 1,
3317                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3318                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3319       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3320
3321 let mayStore = 1, mayLoad = 0 in
3322 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3323                        Operand idxtype, string asm>
3324     : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3325                              (ins regtype:$Rt, regtype:$Rt2,
3326                                   GPR64sp:$Rn, idxtype:$offset),
3327                              asm>,
3328       Sched<[WriteAdr, WriteSTP]>;
3329 } // hasSideEffects = 0
3330
3331 //  (no-allocate)
3332
3333 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3334                               string asm>
3335     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3336   bits<5> Rt;
3337   bits<5> Rt2;
3338   bits<5> Rn;
3339   bits<7> offset;
3340   let Inst{31-30} = opc;
3341   let Inst{29-27} = 0b101;
3342   let Inst{26}    = V;
3343   let Inst{25-23} = 0b000;
3344   let Inst{22}    = L;
3345   let Inst{21-15} = offset;
3346   let Inst{14-10} = Rt2;
3347   let Inst{9-5}   = Rn;
3348   let Inst{4-0}   = Rt;
3349
3350   let DecoderMethod = "DecodePairLdStInstruction";
3351 }
3352
3353 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3354                            Operand indextype, string asm> {
3355   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3356   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3357                                    (outs regtype:$Rt, regtype:$Rt2),
3358                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3359           Sched<[WriteLD, WriteLDHi]>;
3360
3361
3362   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3363                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3364                                                   GPR64sp:$Rn, 0)>;
3365 }
3366
3367 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3368                       Operand indextype, string asm> {
3369   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3370   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3371                                    (ins regtype:$Rt, regtype:$Rt2,
3372                                         GPR64sp:$Rn, indextype:$offset),
3373                                    asm>,
3374           Sched<[WriteSTP]>;
3375
3376   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3377                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3378                                                   GPR64sp:$Rn, 0)>;
3379 }
3380
3381 //---
3382 // Load/store exclusive
3383 //---
3384
3385 // True exclusive operations write to and/or read from the system's exclusive
3386 // monitors, which as far as a compiler is concerned can be modelled as a
3387 // random shared memory address. Hence LoadExclusive mayStore.
3388 //
3389 // Since these instructions have the undefined register bits set to 1 in
3390 // their canonical form, we need a post encoder method to set those bits
3391 // to 1 when encoding these instructions. We do this using the
3392 // fixLoadStoreExclusive function. This function has template parameters:
3393 //
3394 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3395 //
3396 // hasRs indicates that the instruction uses the Rs field, so we won't set
3397 // it to 1 (and the same for Rt2). We don't need template parameters for
3398 // the other register fields since Rt and Rn are always used.
3399 //
3400 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3401 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3402                              dag oops, dag iops, string asm, string operands>
3403     : I<oops, iops, asm, operands, "", []> {
3404   let Inst{31-30} = sz;
3405   let Inst{29-24} = 0b001000;
3406   let Inst{23}    = o2;
3407   let Inst{22}    = L;
3408   let Inst{21}    = o1;
3409   let Inst{15}    = o0;
3410
3411   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3412 }
3413
3414 // Neither Rs nor Rt2 operands.
3415 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3416                                dag oops, dag iops, string asm, string operands>
3417     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3418   bits<5> Rt;
3419   bits<5> Rn;
3420   let Inst{20-16} = 0b11111;
3421   let Unpredictable{20-16} = 0b11111;
3422   let Inst{14-10} = 0b11111;
3423   let Unpredictable{14-10} = 0b11111;
3424   let Inst{9-5} = Rn;
3425   let Inst{4-0} = Rt;
3426
3427   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3428 }
3429
3430 // Simple load acquires don't set the exclusive monitor
3431 let mayLoad = 1, mayStore = 0 in
3432 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3433                   RegisterClass regtype, string asm>
3434     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3435                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3436       Sched<[WriteLD]>;
3437
3438 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3439                     RegisterClass regtype, string asm>
3440     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3441                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3442       Sched<[WriteLD]>;
3443
3444 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3445                        RegisterClass regtype, string asm>
3446     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3447                              (outs regtype:$Rt, regtype:$Rt2),
3448                              (ins GPR64sp0:$Rn), asm,
3449                              "\t$Rt, $Rt2, [$Rn]">,
3450       Sched<[WriteLD, WriteLDHi]> {
3451   bits<5> Rt;
3452   bits<5> Rt2;
3453   bits<5> Rn;
3454   let Inst{14-10} = Rt2;
3455   let Inst{9-5} = Rn;
3456   let Inst{4-0} = Rt;
3457
3458   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3459 }
3460
3461 // Simple store release operations do not check the exclusive monitor.
3462 let mayLoad = 0, mayStore = 1 in
3463 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3464                    RegisterClass regtype, string asm>
3465     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3466                                (ins regtype:$Rt, GPR64sp0:$Rn),
3467                                asm, "\t$Rt, [$Rn]">,
3468       Sched<[WriteST]>;
3469
3470 let mayLoad = 1, mayStore = 1 in
3471 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3472                      RegisterClass regtype, string asm>
3473     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3474                              (ins regtype:$Rt, GPR64sp0:$Rn),
3475                              asm, "\t$Ws, $Rt, [$Rn]">,
3476       Sched<[WriteSTX]> {
3477   bits<5> Ws;
3478   bits<5> Rt;
3479   bits<5> Rn;
3480   let Inst{20-16} = Ws;
3481   let Inst{9-5} = Rn;
3482   let Inst{4-0} = Rt;
3483
3484   let Constraints = "@earlyclobber $Ws";
3485   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3486 }
3487
3488 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3489                          RegisterClass regtype, string asm>
3490     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3491                              (outs GPR32:$Ws),
3492                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3493                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3494       Sched<[WriteSTX]> {
3495   bits<5> Ws;
3496   bits<5> Rt;
3497   bits<5> Rt2;
3498   bits<5> Rn;
3499   let Inst{20-16} = Ws;
3500   let Inst{14-10} = Rt2;
3501   let Inst{9-5} = Rn;
3502   let Inst{4-0} = Rt;
3503
3504   let Constraints = "@earlyclobber $Ws";
3505 }
3506
3507 //---
3508 // Exception generation
3509 //---
3510
3511 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3512 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3513     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3514       Sched<[WriteSys]> {
3515   bits<16> imm;
3516   let Inst{31-24} = 0b11010100;
3517   let Inst{23-21} = op1;
3518   let Inst{20-5}  = imm;
3519   let Inst{4-2}   = 0b000;
3520   let Inst{1-0}   = ll;
3521 }
3522
3523 let Predicates = [HasFPARMv8] in {
3524
3525 //---
3526 // Floating point to integer conversion
3527 //---
3528
3529 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3530                       RegisterClass srcType, RegisterClass dstType,
3531                       string asm, list<dag> pattern>
3532     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3533          asm, "\t$Rd, $Rn", "", pattern>,
3534       Sched<[WriteFCvt]> {
3535   bits<5> Rd;
3536   bits<5> Rn;
3537   let Inst{30-29} = 0b00;
3538   let Inst{28-24} = 0b11110;
3539   let Inst{23-22} = type;
3540   let Inst{21}    = 1;
3541   let Inst{20-19} = rmode;
3542   let Inst{18-16} = opcode;
3543   let Inst{15-10} = 0;
3544   let Inst{9-5}   = Rn;
3545   let Inst{4-0}   = Rd;
3546 }
3547
3548 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3549 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3550                       RegisterClass srcType, RegisterClass dstType,
3551                       Operand immType, string asm, list<dag> pattern>
3552     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3553          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3554       Sched<[WriteFCvt]> {
3555   bits<5> Rd;
3556   bits<5> Rn;
3557   bits<6> scale;
3558   let Inst{30-29} = 0b00;
3559   let Inst{28-24} = 0b11110;
3560   let Inst{23-22} = type;
3561   let Inst{21}    = 0;
3562   let Inst{20-19} = rmode;
3563   let Inst{18-16} = opcode;
3564   let Inst{15-10} = scale;
3565   let Inst{9-5}   = Rn;
3566   let Inst{4-0}   = Rd;
3567 }
3568
3569 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3570            SDPatternOperator OpN> {
3571   // Unscaled half-precision to 32-bit
3572   def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
3573                                      [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
3574     let Inst{31} = 0; // 32-bit GPR flag
3575     let Predicates = [HasFullFP16];
3576   }
3577
3578   // Unscaled half-precision to 64-bit
3579   def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
3580                                      [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
3581     let Inst{31} = 1; // 64-bit GPR flag
3582     let Predicates = [HasFullFP16];
3583   }
3584
3585   // Unscaled single-precision to 32-bit
3586   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3587                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3588     let Inst{31} = 0; // 32-bit GPR flag
3589   }
3590
3591   // Unscaled single-precision to 64-bit
3592   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3593                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3594     let Inst{31} = 1; // 64-bit GPR flag
3595   }
3596
3597   // Unscaled double-precision to 32-bit
3598   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3599                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3600     let Inst{31} = 0; // 32-bit GPR flag
3601   }
3602
3603   // Unscaled double-precision to 64-bit
3604   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3605                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3606     let Inst{31} = 1; // 64-bit GPR flag
3607   }
3608 }
3609
3610 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3611                              SDPatternOperator OpN> {
3612   // Scaled half-precision to 32-bit
3613   def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
3614                               fixedpoint_f16_i32, asm,
3615               [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
3616                                           fixedpoint_f16_i32:$scale)))]> {
3617     let Inst{31} = 0; // 32-bit GPR flag
3618     let scale{5} = 1;
3619     let Predicates = [HasFullFP16];
3620   }
3621
3622   // Scaled half-precision to 64-bit
3623   def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
3624                               fixedpoint_f16_i64, asm,
3625               [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
3626                                           fixedpoint_f16_i64:$scale)))]> {
3627     let Inst{31} = 1; // 64-bit GPR flag
3628     let Predicates = [HasFullFP16];
3629   }
3630
3631   // Scaled single-precision to 32-bit
3632   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3633                               fixedpoint_f32_i32, asm,
3634               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3635                                           fixedpoint_f32_i32:$scale)))]> {
3636     let Inst{31} = 0; // 32-bit GPR flag
3637     let scale{5} = 1;
3638   }
3639
3640   // Scaled single-precision to 64-bit
3641   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3642                               fixedpoint_f32_i64, asm,
3643               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3644                                           fixedpoint_f32_i64:$scale)))]> {
3645     let Inst{31} = 1; // 64-bit GPR flag
3646   }
3647
3648   // Scaled double-precision to 32-bit
3649   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3650                               fixedpoint_f64_i32, asm,
3651               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3652                                           fixedpoint_f64_i32:$scale)))]> {
3653     let Inst{31} = 0; // 32-bit GPR flag
3654     let scale{5} = 1;
3655   }
3656
3657   // Scaled double-precision to 64-bit
3658   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3659                               fixedpoint_f64_i64, asm,
3660               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3661                                           fixedpoint_f64_i64:$scale)))]> {
3662     let Inst{31} = 1; // 64-bit GPR flag
3663   }
3664 }
3665
3666 //---
3667 // Integer to floating point conversion
3668 //---
3669
3670 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3671 class BaseIntegerToFP<bit isUnsigned,
3672                       RegisterClass srcType, RegisterClass dstType,
3673                       Operand immType, string asm, list<dag> pattern>
3674     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3675          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3676       Sched<[WriteFCvt]> {
3677   bits<5> Rd;
3678   bits<5> Rn;
3679   bits<6> scale;
3680   let Inst{30-24} = 0b0011110;
3681   let Inst{21-17} = 0b00001;
3682   let Inst{16}    = isUnsigned;
3683   let Inst{15-10} = scale;
3684   let Inst{9-5}   = Rn;
3685   let Inst{4-0}   = Rd;
3686 }
3687
3688 class BaseIntegerToFPUnscaled<bit isUnsigned,
3689                       RegisterClass srcType, RegisterClass dstType,
3690                       ValueType dvt, string asm, SDNode node>
3691     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3692          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3693       Sched<[WriteFCvt]> {
3694   bits<5> Rd;
3695   bits<5> Rn;
3696   bits<6> scale;
3697   let Inst{30-24} = 0b0011110;
3698   let Inst{21-17} = 0b10001;
3699   let Inst{16}    = isUnsigned;
3700   let Inst{15-10} = 0b000000;
3701   let Inst{9-5}   = Rn;
3702   let Inst{4-0}   = Rd;
3703 }
3704
3705 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3706   // Unscaled
3707   def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
3708     let Inst{31} = 0; // 32-bit GPR flag
3709     let Inst{23-22} = 0b11; // 16-bit FPR flag
3710     let Predicates = [HasFullFP16];
3711   }
3712
3713   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3714     let Inst{31} = 0; // 32-bit GPR flag
3715     let Inst{23-22} = 0b00; // 32-bit FPR flag
3716   }
3717
3718   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3719     let Inst{31} = 0; // 32-bit GPR flag
3720     let Inst{23-22} = 0b01; // 64-bit FPR flag
3721   }
3722
3723   def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
3724     let Inst{31} = 1; // 64-bit GPR flag
3725     let Inst{23-22} = 0b11; // 16-bit FPR flag
3726     let Predicates = [HasFullFP16];
3727   }
3728
3729   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3730     let Inst{31} = 1; // 64-bit GPR flag
3731     let Inst{23-22} = 0b00; // 32-bit FPR flag
3732   }
3733
3734   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3735     let Inst{31} = 1; // 64-bit GPR flag
3736     let Inst{23-22} = 0b01; // 64-bit FPR flag
3737   }
3738
3739   // Scaled
3740   def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
3741                              [(set FPR16:$Rd,
3742                                    (fdiv (node GPR32:$Rn),
3743                                          fixedpoint_f16_i32:$scale))]> {
3744     let Inst{31} = 0; // 32-bit GPR flag
3745     let Inst{23-22} = 0b11; // 16-bit FPR flag
3746     let scale{5} = 1;
3747     let Predicates = [HasFullFP16];
3748   }
3749
3750   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3751                              [(set FPR32:$Rd,
3752                                    (fdiv (node GPR32:$Rn),
3753                                          fixedpoint_f32_i32:$scale))]> {
3754     let Inst{31} = 0; // 32-bit GPR flag
3755     let Inst{23-22} = 0b00; // 32-bit FPR flag
3756     let scale{5} = 1;
3757   }
3758
3759   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3760                              [(set FPR64:$Rd,
3761                                    (fdiv (node GPR32:$Rn),
3762                                          fixedpoint_f64_i32:$scale))]> {
3763     let Inst{31} = 0; // 32-bit GPR flag
3764     let Inst{23-22} = 0b01; // 64-bit FPR flag
3765     let scale{5} = 1;
3766   }
3767
3768   def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
3769                              [(set FPR16:$Rd,
3770                                    (fdiv (node GPR64:$Rn),
3771                                          fixedpoint_f16_i64:$scale))]> {
3772     let Inst{31} = 1; // 64-bit GPR flag
3773     let Inst{23-22} = 0b11; // 16-bit FPR flag
3774     let Predicates = [HasFullFP16];
3775   }
3776
3777   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3778                              [(set FPR32:$Rd,
3779                                    (fdiv (node GPR64:$Rn),
3780                                          fixedpoint_f32_i64:$scale))]> {
3781     let Inst{31} = 1; // 64-bit GPR flag
3782     let Inst{23-22} = 0b00; // 32-bit FPR flag
3783   }
3784
3785   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3786                              [(set FPR64:$Rd,
3787                                    (fdiv (node GPR64:$Rn),
3788                                          fixedpoint_f64_i64:$scale))]> {
3789     let Inst{31} = 1; // 64-bit GPR flag
3790     let Inst{23-22} = 0b01; // 64-bit FPR flag
3791   }
3792 }
3793
3794 //---
3795 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3796 //---
3797
3798 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3799 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3800                       RegisterClass srcType, RegisterClass dstType,
3801                       string asm>
3802     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3803         // We use COPY_TO_REGCLASS for these bitconvert operations.
3804         // copyPhysReg() expands the resultant COPY instructions after
3805         // regalloc is done. This gives greater freedom for the allocator
3806         // and related passes (coalescing, copy propagation, et. al.) to
3807         // be more effective.
3808         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3809       Sched<[WriteFCopy]> {
3810   bits<5> Rd;
3811   bits<5> Rn;
3812   let Inst{30-24} = 0b0011110;
3813   let Inst{21}    = 1;
3814   let Inst{20-19} = rmode;
3815   let Inst{18-16} = opcode;
3816   let Inst{15-10} = 0b000000;
3817   let Inst{9-5}   = Rn;
3818   let Inst{4-0}   = Rd;
3819 }
3820
3821 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3822 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3823                      RegisterClass srcType, RegisterOperand dstType, string asm,
3824                      string kind>
3825     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3826         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3827       Sched<[WriteFCopy]> {
3828   bits<5> Rd;
3829   bits<5> Rn;
3830   let Inst{30-23} = 0b00111101;
3831   let Inst{21}    = 1;
3832   let Inst{20-19} = rmode;
3833   let Inst{18-16} = opcode;
3834   let Inst{15-10} = 0b000000;
3835   let Inst{9-5}   = Rn;
3836   let Inst{4-0}   = Rd;
3837
3838   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3839 }
3840
3841 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3842 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3843                      RegisterOperand srcType, RegisterClass dstType, string asm,
3844                      string kind>
3845     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3846         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3847       Sched<[WriteFCopy]> {
3848   bits<5> Rd;
3849   bits<5> Rn;
3850   let Inst{30-23} = 0b00111101;
3851   let Inst{21}    = 1;
3852   let Inst{20-19} = rmode;
3853   let Inst{18-16} = opcode;
3854   let Inst{15-10} = 0b000000;
3855   let Inst{9-5}   = Rn;
3856   let Inst{4-0}   = Rd;
3857
3858   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3859 }
3860
3861
3862 multiclass UnscaledConversion<string asm> {
3863   def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
3864     let Inst{31} = 0; // 32-bit GPR flag
3865     let Inst{23-22} = 0b11; // 16-bit FPR flag
3866     let Predicates = [HasFullFP16];
3867   }
3868
3869   def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
3870     let Inst{31} = 1; // 64-bit GPR flag
3871     let Inst{23-22} = 0b11; // 16-bit FPR flag
3872     let Predicates = [HasFullFP16];
3873   }
3874
3875   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3876     let Inst{31} = 0; // 32-bit GPR flag
3877     let Inst{23-22} = 0b00; // 32-bit FPR flag
3878   }
3879
3880   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3881     let Inst{31} = 1; // 64-bit GPR flag
3882     let Inst{23-22} = 0b01; // 64-bit FPR flag
3883   }
3884
3885   def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
3886     let Inst{31} = 0; // 32-bit GPR flag
3887     let Inst{23-22} = 0b11; // 16-bit FPR flag
3888     let Predicates = [HasFullFP16];
3889   }
3890
3891   def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
3892     let Inst{31} = 1; // 64-bit GPR flag
3893     let Inst{23-22} = 0b11; // 16-bit FPR flag
3894     let Predicates = [HasFullFP16];
3895   }
3896
3897   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3898     let Inst{31} = 0; // 32-bit GPR flag
3899     let Inst{23-22} = 0b00; // 32-bit FPR flag
3900   }
3901
3902   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3903     let Inst{31} = 1; // 64-bit GPR flag
3904     let Inst{23-22} = 0b01; // 64-bit FPR flag
3905   }
3906
3907   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3908                                              asm, ".d"> {
3909     let Inst{31} = 1;
3910     let Inst{22} = 0;
3911   }
3912
3913   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3914                                                asm, ".d"> {
3915     let Inst{31} = 1;
3916     let Inst{22} = 0;
3917   }
3918 }
3919
3920 //---
3921 // Floating point conversion
3922 //---
3923
3924 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3925                        RegisterClass srcType, string asm, list<dag> pattern>
3926     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3927       Sched<[WriteFCvt]> {
3928   bits<5> Rd;
3929   bits<5> Rn;
3930   let Inst{31-24} = 0b00011110;
3931   let Inst{23-22} = type;
3932   let Inst{21-17} = 0b10001;
3933   let Inst{16-15} = opcode;
3934   let Inst{14-10} = 0b10000;
3935   let Inst{9-5}   = Rn;
3936   let Inst{4-0}   = Rd;
3937 }
3938
3939 multiclass FPConversion<string asm> {
3940   // Double-precision to Half-precision
3941   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3942                              [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3943
3944   // Double-precision to Single-precision
3945   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3946                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3947
3948   // Half-precision to Double-precision
3949   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3950                              [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3951
3952   // Half-precision to Single-precision
3953   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3954                              [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3955
3956   // Single-precision to Double-precision
3957   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3958                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3959
3960   // Single-precision to Half-precision
3961   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3962                              [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3963 }
3964
3965 //---
3966 // Single operand floating point data processing
3967 //---
3968
3969 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3970 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3971                               ValueType vt, string asm, SDPatternOperator node>
3972     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3973          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3974       Sched<[WriteF]> {
3975   bits<5> Rd;
3976   bits<5> Rn;
3977   let Inst{31-24} = 0b00011110;
3978   let Inst{21-19} = 0b100;
3979   let Inst{18-15} = opcode;
3980   let Inst{14-10} = 0b10000;
3981   let Inst{9-5}   = Rn;
3982   let Inst{4-0}   = Rd;
3983 }
3984
3985 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3986                                SDPatternOperator node = null_frag> {
3987   def Hr : BaseSingleOperandFPData<opcode, FPR16, f16, asm, node> {
3988     let Inst{23-22} = 0b11; // 16-bit size flag
3989     let Predicates = [HasFullFP16];
3990   }
3991
3992   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3993     let Inst{23-22} = 0b00; // 32-bit size flag
3994   }
3995
3996   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3997     let Inst{23-22} = 0b01; // 64-bit size flag
3998   }
3999 }
4000
4001 //---
4002 // Two operand floating point data processing
4003 //---
4004
4005 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4006 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4007                            string asm, list<dag> pat>
4008     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4009          asm, "\t$Rd, $Rn, $Rm", "", pat>,
4010       Sched<[WriteF]> {
4011   bits<5> Rd;
4012   bits<5> Rn;
4013   bits<5> Rm;
4014   let Inst{31-24} = 0b00011110;
4015   let Inst{21}    = 1;
4016   let Inst{20-16} = Rm;
4017   let Inst{15-12} = opcode;
4018   let Inst{11-10} = 0b10;
4019   let Inst{9-5}   = Rn;
4020   let Inst{4-0}   = Rd;
4021 }
4022
4023 multiclass TwoOperandFPData<bits<4> opcode, string asm,
4024                             SDPatternOperator node = null_frag> {
4025   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4026                          [(set (f16 FPR16:$Rd),
4027                                (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4028     let Inst{23-22} = 0b11; // 16-bit size flag
4029     let Predicates = [HasFullFP16];
4030   }
4031
4032   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4033                          [(set (f32 FPR32:$Rd),
4034                                (node (f32 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 (f64 FPR64:$Rd),
4040                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4041     let Inst{23-22} = 0b01; // 64-bit size flag
4042   }
4043 }
4044
4045 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4046   def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4047                   [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4048     let Inst{23-22} = 0b11; // 16-bit size flag
4049     let Predicates = [HasFullFP16];
4050   }
4051
4052   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4053                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4054     let Inst{23-22} = 0b00; // 32-bit size flag
4055   }
4056
4057   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4058                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4059     let Inst{23-22} = 0b01; // 64-bit size flag
4060   }
4061 }
4062
4063
4064 //---
4065 // Three operand floating point data processing
4066 //---
4067
4068 class BaseThreeOperandFPData<bit isNegated, bit isSub,
4069                              RegisterClass regtype, string asm, list<dag> pat>
4070     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4071          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4072       Sched<[WriteFMul]> {
4073   bits<5> Rd;
4074   bits<5> Rn;
4075   bits<5> Rm;
4076   bits<5> Ra;
4077   let Inst{31-24} = 0b00011111;
4078   let Inst{21}    = isNegated;
4079   let Inst{20-16} = Rm;
4080   let Inst{15}    = isSub;
4081   let Inst{14-10} = Ra;
4082   let Inst{9-5}   = Rn;
4083   let Inst{4-0}   = Rd;
4084 }
4085
4086 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4087                               SDPatternOperator node> {
4088   def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4089             [(set FPR16:$Rd,
4090                   (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4091     let Inst{23-22} = 0b11; // 16-bit size flag
4092     let Predicates = [HasFullFP16];
4093   }
4094
4095   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4096             [(set FPR32:$Rd,
4097                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4098     let Inst{23-22} = 0b00; // 32-bit size flag
4099   }
4100
4101   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4102             [(set FPR64:$Rd,
4103                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4104     let Inst{23-22} = 0b01; // 64-bit size flag
4105   }
4106 }
4107
4108 //---
4109 // Floating point data comparisons
4110 //---
4111
4112 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4113 class BaseOneOperandFPComparison<bit signalAllNans,
4114                                  RegisterClass regtype, string asm,
4115                                  list<dag> pat>
4116     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4117       Sched<[WriteFCmp]> {
4118   bits<5> Rn;
4119   let Inst{31-24} = 0b00011110;
4120   let Inst{21}    = 1;
4121
4122   let Inst{15-10} = 0b001000;
4123   let Inst{9-5}   = Rn;
4124   let Inst{4}     = signalAllNans;
4125   let Inst{3-0}   = 0b1000;
4126
4127   // Rm should be 0b00000 canonically, but we need to accept any value.
4128   let PostEncoderMethod = "fixOneOperandFPComparison";
4129 }
4130
4131 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4132 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4133                                 string asm, list<dag> pat>
4134     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4135       Sched<[WriteFCmp]> {
4136   bits<5> Rm;
4137   bits<5> Rn;
4138   let Inst{31-24} = 0b00011110;
4139   let Inst{21}    = 1;
4140   let Inst{20-16} = Rm;
4141   let Inst{15-10} = 0b001000;
4142   let Inst{9-5}   = Rn;
4143   let Inst{4}     = signalAllNans;
4144   let Inst{3-0}   = 0b0000;
4145 }
4146
4147 multiclass FPComparison<bit signalAllNans, string asm,
4148                         SDPatternOperator OpNode = null_frag> {
4149   let Defs = [NZCV] in {
4150   def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4151       [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4152     let Inst{23-22} = 0b11;
4153     let Predicates = [HasFullFP16];
4154   }
4155
4156   def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4157       [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4158     let Inst{23-22} = 0b11;
4159     let Predicates = [HasFullFP16];
4160   }
4161
4162   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4163       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4164     let Inst{23-22} = 0b00;
4165   }
4166
4167   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4168       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4169     let Inst{23-22} = 0b00;
4170   }
4171
4172   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4173       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4174     let Inst{23-22} = 0b01;
4175   }
4176
4177   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4178       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4179     let Inst{23-22} = 0b01;
4180   }
4181   } // Defs = [NZCV]
4182 }
4183
4184 //---
4185 // Floating point conditional comparisons
4186 //---
4187
4188 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4189 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4190                            string mnemonic, list<dag> pat>
4191     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4192          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4193       Sched<[WriteFCmp]> {
4194   let Uses = [NZCV];
4195   let Defs = [NZCV];
4196
4197   bits<5> Rn;
4198   bits<5> Rm;
4199   bits<4> nzcv;
4200   bits<4> cond;
4201
4202   let Inst{31-24} = 0b00011110;
4203   let Inst{21}    = 1;
4204   let Inst{20-16} = Rm;
4205   let Inst{15-12} = cond;
4206   let Inst{11-10} = 0b01;
4207   let Inst{9-5}   = Rn;
4208   let Inst{4}     = signalAllNans;
4209   let Inst{3-0}   = nzcv;
4210 }
4211
4212 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4213                             SDPatternOperator OpNode = null_frag> {
4214   def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic, []> {
4215     let Inst{23-22} = 0b11;
4216     let Predicates = [HasFullFP16];
4217   }
4218
4219   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4220       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4221                           (i32 imm:$cond), NZCV))]> {
4222     let Inst{23-22} = 0b00;
4223   }
4224
4225   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4226       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4227                           (i32 imm:$cond), NZCV))]> {
4228     let Inst{23-22} = 0b01;
4229   }
4230 }
4231
4232 //---
4233 // Floating point conditional select
4234 //---
4235
4236 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4237     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4238          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4239          [(set regtype:$Rd,
4240                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4241                           (i32 imm:$cond), NZCV))]>,
4242       Sched<[WriteF]> {
4243   bits<5> Rd;
4244   bits<5> Rn;
4245   bits<5> Rm;
4246   bits<4> cond;
4247
4248   let Inst{31-24} = 0b00011110;
4249   let Inst{21}    = 1;
4250   let Inst{20-16} = Rm;
4251   let Inst{15-12} = cond;
4252   let Inst{11-10} = 0b11;
4253   let Inst{9-5}   = Rn;
4254   let Inst{4-0}   = Rd;
4255 }
4256
4257 multiclass FPCondSelect<string asm> {
4258   let Uses = [NZCV] in {
4259   def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4260     let Inst{23-22} = 0b11;
4261     let Predicates = [HasFullFP16];
4262   }
4263
4264   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4265     let Inst{23-22} = 0b00;
4266   }
4267
4268   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4269     let Inst{23-22} = 0b01;
4270   }
4271   } // Uses = [NZCV]
4272 }
4273
4274 //---
4275 // Floating move immediate
4276 //---
4277
4278 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4279   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4280       [(set regtype:$Rd, fpimmtype:$imm)]>,
4281     Sched<[WriteFImm]> {
4282   bits<5> Rd;
4283   bits<8> imm;
4284   let Inst{31-24} = 0b00011110;
4285   let Inst{21}    = 1;
4286   let Inst{20-13} = imm;
4287   let Inst{12-5}  = 0b10000000;
4288   let Inst{4-0}   = Rd;
4289 }
4290
4291 multiclass FPMoveImmediate<string asm> {
4292   def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4293     let Inst{23-22} = 0b11;
4294     let Predicates = [HasFullFP16];
4295   }
4296
4297   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4298     let Inst{23-22} = 0b00;
4299   }
4300
4301   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4302     let Inst{23-22} = 0b01;
4303   }
4304 }
4305 } // end of 'let Predicates = [HasFPARMv8]'
4306
4307 //----------------------------------------------------------------------------
4308 // AdvSIMD
4309 //----------------------------------------------------------------------------
4310
4311 let Predicates = [HasNEON] in {
4312
4313 //----------------------------------------------------------------------------
4314 // AdvSIMD three register vector instructions
4315 //----------------------------------------------------------------------------
4316
4317 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4318 class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4319                         RegisterOperand regtype, string asm, string kind,
4320                         list<dag> pattern>
4321   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4322       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4323       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4324     Sched<[WriteV]> {
4325   bits<5> Rd;
4326   bits<5> Rn;
4327   bits<5> Rm;
4328   let Inst{31}    = 0;
4329   let Inst{30}    = Q;
4330   let Inst{29}    = U;
4331   let Inst{28-24} = 0b01110;
4332   let Inst{23-21} = size;
4333   let Inst{20-16} = Rm;
4334   let Inst{15-11} = opcode;
4335   let Inst{10}    = 1;
4336   let Inst{9-5}   = Rn;
4337   let Inst{4-0}   = Rd;
4338 }
4339
4340 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4341 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
4342                         RegisterOperand regtype, string asm, string kind,
4343                         list<dag> pattern>
4344   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4345       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4346       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4347     Sched<[WriteV]> {
4348   bits<5> Rd;
4349   bits<5> Rn;
4350   bits<5> Rm;
4351   let Inst{31}    = 0;
4352   let Inst{30}    = Q;
4353   let Inst{29}    = U;
4354   let Inst{28-24} = 0b01110;
4355   let Inst{23-21} = size;
4356   let Inst{20-16} = Rm;
4357   let Inst{15-11} = opcode;
4358   let Inst{10}    = 1;
4359   let Inst{9-5}   = Rn;
4360   let Inst{4-0}   = Rd;
4361 }
4362
4363 // All operand sizes distinguished in the encoding.
4364 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4365                                SDPatternOperator OpNode> {
4366   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4367                                       asm, ".8b",
4368          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4369   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4370                                       asm, ".16b",
4371          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4372   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4373                                       asm, ".4h",
4374          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4375   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4376                                       asm, ".8h",
4377          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4378   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4379                                       asm, ".2s",
4380          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4381   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4382                                       asm, ".4s",
4383          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4384   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
4385                                       asm, ".2d",
4386          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4387 }
4388
4389 // As above, but D sized elements unsupported.
4390 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4391                                   SDPatternOperator OpNode> {
4392   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4393                                       asm, ".8b",
4394         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4395   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4396                                       asm, ".16b",
4397         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4398   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4399                                       asm, ".4h",
4400         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4401   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4402                                       asm, ".8h",
4403         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4404   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4405                                       asm, ".2s",
4406         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4407   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4408                                       asm, ".4s",
4409         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4410 }
4411
4412 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4413                                   SDPatternOperator OpNode> {
4414   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
4415                                       asm, ".8b",
4416       [(set (v8i8 V64:$dst),
4417             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4418   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
4419                                       asm, ".16b",
4420       [(set (v16i8 V128:$dst),
4421             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4422   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
4423                                       asm, ".4h",
4424       [(set (v4i16 V64:$dst),
4425             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4426   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
4427                                       asm, ".8h",
4428       [(set (v8i16 V128:$dst),
4429             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4430   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
4431                                       asm, ".2s",
4432       [(set (v2i32 V64:$dst),
4433             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4434   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
4435                                       asm, ".4s",
4436       [(set (v4i32 V128:$dst),
4437             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4438 }
4439
4440 // As above, but only B sized elements supported.
4441 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4442                                 SDPatternOperator OpNode> {
4443   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4444                                       asm, ".8b",
4445     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4446   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4447                                       asm, ".16b",
4448     [(set (v16i8 V128:$Rd),
4449           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4450 }
4451
4452 // As above, but only floating point elements supported.
4453 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
4454                                  string asm, SDPatternOperator OpNode> {
4455   let Predicates = [HasNEON, HasFullFP16] in {
4456   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4457                                       asm, ".4h",
4458         [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4459   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4460                                       asm, ".8h",
4461         [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4462   } // Predicates = [HasNEON, HasFullFP16]
4463   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4464                                       asm, ".2s",
4465         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4466   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4467                                       asm, ".4s",
4468         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4469   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4470                                       asm, ".2d",
4471         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4472 }
4473
4474 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
4475                                     string asm,
4476                                     SDPatternOperator OpNode> {
4477   let Predicates = [HasNEON, HasFullFP16] in {
4478   def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4479                                       asm, ".4h",
4480         [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4481   def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4482                                       asm, ".8h",
4483         [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4484   } // Predicates = [HasNEON, HasFullFP16]
4485   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4486                                       asm, ".2s",
4487         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4488   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4489                                       asm, ".4s",
4490         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4491   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4492                                       asm, ".2d",
4493         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4494 }
4495
4496 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
4497                                  string asm, SDPatternOperator OpNode> {
4498   let Predicates = [HasNEON, HasFullFP16] in {
4499   def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
4500                                       asm, ".4h",
4501      [(set (v4f16 V64:$dst),
4502            (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4503   def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
4504                                       asm, ".8h",
4505      [(set (v8f16 V128:$dst),
4506            (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4507   } // Predicates = [HasNEON, HasFullFP16]
4508   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
4509                                       asm, ".2s",
4510      [(set (v2f32 V64:$dst),
4511            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4512   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
4513                                       asm, ".4s",
4514      [(set (v4f32 V128:$dst),
4515            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4516   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
4517                                       asm, ".2d",
4518      [(set (v2f64 V128:$dst),
4519            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4520 }
4521
4522 // As above, but D and B sized elements unsupported.
4523 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4524                                 SDPatternOperator OpNode> {
4525   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4526                                       asm, ".4h",
4527         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4528   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4529                                       asm, ".8h",
4530         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4531   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4532                                       asm, ".2s",
4533         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4534   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4535                                       asm, ".4s",
4536         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4537 }
4538
4539 // Logical three vector ops share opcode bits, and only use B sized elements.
4540 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4541                                   SDPatternOperator OpNode = null_frag> {
4542   def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
4543                                      asm, ".8b",
4544                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4545   def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
4546                                      asm, ".16b",
4547                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4548
4549   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4550           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4551   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4552           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4553   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4554           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4555
4556   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4557       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4558   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4559       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4560   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4561       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4562 }
4563
4564 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4565                                   string asm, SDPatternOperator OpNode> {
4566   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
4567                                      asm, ".8b",
4568              [(set (v8i8 V64:$dst),
4569                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4570   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
4571                                      asm, ".16b",
4572              [(set (v16i8 V128:$dst),
4573                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4574                            (v16i8 V128:$Rm)))]>;
4575
4576   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4577                            (v4i16 V64:$RHS))),
4578           (!cast<Instruction>(NAME#"v8i8")
4579             V64:$LHS, V64:$MHS, V64:$RHS)>;
4580   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4581                            (v2i32 V64:$RHS))),
4582           (!cast<Instruction>(NAME#"v8i8")
4583             V64:$LHS, V64:$MHS, V64:$RHS)>;
4584   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4585                            (v1i64 V64:$RHS))),
4586           (!cast<Instruction>(NAME#"v8i8")
4587             V64:$LHS, V64:$MHS, V64:$RHS)>;
4588
4589   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4590                            (v8i16 V128:$RHS))),
4591       (!cast<Instruction>(NAME#"v16i8")
4592         V128:$LHS, V128:$MHS, V128:$RHS)>;
4593   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4594                            (v4i32 V128:$RHS))),
4595       (!cast<Instruction>(NAME#"v16i8")
4596         V128:$LHS, V128:$MHS, V128:$RHS)>;
4597   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4598                            (v2i64 V128:$RHS))),
4599       (!cast<Instruction>(NAME#"v16i8")
4600         V128:$LHS, V128:$MHS, V128:$RHS)>;
4601 }
4602
4603
4604 //----------------------------------------------------------------------------
4605 // AdvSIMD two register vector instructions.
4606 //----------------------------------------------------------------------------
4607
4608 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4609 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4610                             bits<2> size2, RegisterOperand regtype, string asm,
4611                             string dstkind, string srckind, list<dag> pattern>
4612   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4613       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4614       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4615     Sched<[WriteV]> {
4616   bits<5> Rd;
4617   bits<5> Rn;
4618   let Inst{31}    = 0;
4619   let Inst{30}    = Q;
4620   let Inst{29}    = U;
4621   let Inst{28-24} = 0b01110;
4622   let Inst{23-22} = size;
4623   let Inst{21} = 0b1;
4624   let Inst{20-19} = size2;
4625   let Inst{18-17} = 0b00;
4626   let Inst{16-12} = opcode;
4627   let Inst{11-10} = 0b10;
4628   let Inst{9-5}   = Rn;
4629   let Inst{4-0}   = Rd;
4630 }
4631
4632 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4633 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4634                                 bits<2> size2, RegisterOperand regtype,
4635                                 string asm, string dstkind, string srckind,
4636                                 list<dag> pattern>
4637   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4638       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4639       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4640     Sched<[WriteV]> {
4641   bits<5> Rd;
4642   bits<5> Rn;
4643   let Inst{31}    = 0;
4644   let Inst{30}    = Q;
4645   let Inst{29}    = U;
4646   let Inst{28-24} = 0b01110;
4647   let Inst{23-22} = size;
4648   let Inst{21} = 0b1;
4649   let Inst{20-19} = size2;
4650   let Inst{18-17} = 0b00;
4651   let Inst{16-12} = opcode;
4652   let Inst{11-10} = 0b10;
4653   let Inst{9-5}   = Rn;
4654   let Inst{4-0}   = Rd;
4655 }
4656
4657 // Supports B, H, and S element sizes.
4658 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4659                             SDPatternOperator OpNode> {
4660   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4661                                       asm, ".8b", ".8b",
4662                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4663   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4664                                       asm, ".16b", ".16b",
4665                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4666   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4667                                       asm, ".4h", ".4h",
4668                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4669   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4670                                       asm, ".8h", ".8h",
4671                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4672   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
4673                                       asm, ".2s", ".2s",
4674                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4675   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
4676                                       asm, ".4s", ".4s",
4677                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4678 }
4679
4680 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4681                             RegisterOperand regtype, string asm, string dstkind,
4682                             string srckind, string amount>
4683   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4684       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4685       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4686     Sched<[WriteV]> {
4687   bits<5> Rd;
4688   bits<5> Rn;
4689   let Inst{31}    = 0;
4690   let Inst{30}    = Q;
4691   let Inst{29-24} = 0b101110;
4692   let Inst{23-22} = size;
4693   let Inst{21-10} = 0b100001001110;
4694   let Inst{9-5}   = Rn;
4695   let Inst{4-0}   = Rd;
4696 }
4697
4698 multiclass SIMDVectorLShiftLongBySizeBHS {
4699   let hasSideEffects = 0 in {
4700   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4701                                              "shll", ".8h",  ".8b", "8">;
4702   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4703                                              "shll2", ".8h", ".16b", "8">;
4704   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4705                                              "shll", ".4s",  ".4h", "16">;
4706   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4707                                              "shll2", ".4s", ".8h", "16">;
4708   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4709                                              "shll", ".2d",  ".2s", "32">;
4710   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4711                                              "shll2", ".2d", ".4s", "32">;
4712   }
4713 }
4714
4715 // Supports all element sizes.
4716 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4717                              SDPatternOperator OpNode> {
4718   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4719                                       asm, ".4h", ".8b",
4720                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4721   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4722                                       asm, ".8h", ".16b",
4723                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4724   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4725                                       asm, ".2s", ".4h",
4726                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4727   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4728                                       asm, ".4s", ".8h",
4729                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4730   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
4731                                       asm, ".1d", ".2s",
4732                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4733   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
4734                                       asm, ".2d", ".4s",
4735                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4736 }
4737
4738 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4739                                  SDPatternOperator OpNode> {
4740   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
4741                                           asm, ".4h", ".8b",
4742       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4743                                       (v8i8 V64:$Rn)))]>;
4744   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
4745                                           asm, ".8h", ".16b",
4746       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4747                                       (v16i8 V128:$Rn)))]>;
4748   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
4749                                           asm, ".2s", ".4h",
4750       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4751                                       (v4i16 V64:$Rn)))]>;
4752   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
4753                                           asm, ".4s", ".8h",
4754       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4755                                       (v8i16 V128:$Rn)))]>;
4756   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
4757                                           asm, ".1d", ".2s",
4758       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4759                                       (v2i32 V64:$Rn)))]>;
4760   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
4761                                           asm, ".2d", ".4s",
4762       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4763                                       (v4i32 V128:$Rn)))]>;
4764 }
4765
4766 // Supports all element sizes, except 1xD.
4767 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4768                                   SDPatternOperator OpNode> {
4769   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
4770                                     asm, ".8b", ".8b",
4771     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4772   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
4773                                     asm, ".16b", ".16b",
4774     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4775   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
4776                                     asm, ".4h", ".4h",
4777     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4778   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
4779                                     asm, ".8h", ".8h",
4780     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4781   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
4782                                     asm, ".2s", ".2s",
4783     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4784   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
4785                                     asm, ".4s", ".4s",
4786     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4787   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
4788                                     asm, ".2d", ".2d",
4789     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4790 }
4791
4792 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4793                              SDPatternOperator OpNode = null_frag> {
4794   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4795                                 asm, ".8b", ".8b",
4796     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4797   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4798                                 asm, ".16b", ".16b",
4799     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4800   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4801                                 asm, ".4h", ".4h",
4802     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4803   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4804                                 asm, ".8h", ".8h",
4805     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4806   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
4807                                 asm, ".2s", ".2s",
4808     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4809   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
4810                                 asm, ".4s", ".4s",
4811     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4812   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
4813                                 asm, ".2d", ".2d",
4814     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4815 }
4816
4817
4818 // Supports only B element sizes.
4819 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4820                           SDPatternOperator OpNode> {
4821   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
4822                                 asm, ".8b", ".8b",
4823                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4824   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
4825                                 asm, ".16b", ".16b",
4826                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4827
4828 }
4829
4830 // Supports only B and H element sizes.
4831 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4832                                 SDPatternOperator OpNode> {
4833   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4834                                 asm, ".8b", ".8b",
4835                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4836   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4837                                 asm, ".16b", ".16b",
4838                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4839   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4840                                 asm, ".4h", ".4h",
4841                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4842   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4843                                 asm, ".8h", ".8h",
4844                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4845 }
4846
4847 // Supports only S and D element sizes, uses high bit of the size field
4848 // as an extra opcode bit.
4849 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4850                            SDPatternOperator OpNode> {
4851   let Predicates = [HasNEON, HasFullFP16] in {
4852   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
4853                                 asm, ".4h", ".4h",
4854                           [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
4855   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
4856                                 asm, ".8h", ".8h",
4857                           [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
4858   } // Predicates = [HasNEON, HasFullFP16]
4859   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4860                                 asm, ".2s", ".2s",
4861                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4862   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4863                                 asm, ".4s", ".4s",
4864                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4865   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
4866                                 asm, ".2d", ".2d",
4867                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4868 }
4869
4870 // Supports only S element size.
4871 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4872                            SDPatternOperator OpNode> {
4873   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4874                                 asm, ".2s", ".2s",
4875                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4876   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4877                                 asm, ".4s", ".4s",
4878                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4879 }
4880
4881
4882 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4883                            SDPatternOperator OpNode> {
4884   let Predicates = [HasNEON, HasFullFP16] in {
4885   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
4886                                 asm, ".4h", ".4h",
4887                           [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
4888   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
4889                                 asm, ".8h", ".8h",
4890                           [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
4891   } // Predicates = [HasNEON, HasFullFP16]
4892   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4893                                 asm, ".2s", ".2s",
4894                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4895   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4896                                 asm, ".4s", ".4s",
4897                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4898   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
4899                                 asm, ".2d", ".2d",
4900                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4901 }
4902
4903 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4904                            SDPatternOperator OpNode> {
4905   let Predicates = [HasNEON, HasFullFP16] in {
4906   def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
4907                                 asm, ".4h", ".4h",
4908                           [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4909   def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
4910                                 asm, ".8h", ".8h",
4911                           [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4912   } // Predicates = [HasNEON, HasFullFP16]
4913   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4914                                 asm, ".2s", ".2s",
4915                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4916   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4917                                 asm, ".4s", ".4s",
4918                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4919   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
4920                                 asm, ".2d", ".2d",
4921                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4922 }
4923
4924
4925 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4926                            RegisterOperand inreg, RegisterOperand outreg,
4927                            string asm, string outkind, string inkind,
4928                            list<dag> pattern>
4929   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4930       "{\t$Rd" # outkind # ", $Rn" # inkind #
4931       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4932     Sched<[WriteV]> {
4933   bits<5> Rd;
4934   bits<5> Rn;
4935   let Inst{31}    = 0;
4936   let Inst{30}    = Q;
4937   let Inst{29}    = U;
4938   let Inst{28-24} = 0b01110;
4939   let Inst{23-22} = size;
4940   let Inst{21-17} = 0b10000;
4941   let Inst{16-12} = opcode;
4942   let Inst{11-10} = 0b10;
4943   let Inst{9-5}   = Rn;
4944   let Inst{4-0}   = Rd;
4945 }
4946
4947 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4948                            RegisterOperand inreg, RegisterOperand outreg,
4949                            string asm, string outkind, string inkind,
4950                            list<dag> pattern>
4951   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4952       "{\t$Rd" # outkind # ", $Rn" # inkind #
4953       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4954     Sched<[WriteV]> {
4955   bits<5> Rd;
4956   bits<5> Rn;
4957   let Inst{31}    = 0;
4958   let Inst{30}    = Q;
4959   let Inst{29}    = U;
4960   let Inst{28-24} = 0b01110;
4961   let Inst{23-22} = size;
4962   let Inst{21-17} = 0b10000;
4963   let Inst{16-12} = opcode;
4964   let Inst{11-10} = 0b10;
4965   let Inst{9-5}   = Rn;
4966   let Inst{4-0}   = Rd;
4967 }
4968
4969 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4970                               SDPatternOperator OpNode> {
4971   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4972                                       asm, ".8b", ".8h",
4973         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4974   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4975                                       asm#"2", ".16b", ".8h", []>;
4976   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4977                                       asm, ".4h", ".4s",
4978         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4979   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4980                                       asm#"2", ".8h", ".4s", []>;
4981   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4982                                       asm, ".2s", ".2d",
4983         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4984   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4985                                       asm#"2", ".4s", ".2d", []>;
4986
4987   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4988             (!cast<Instruction>(NAME # "v16i8")
4989                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4990   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4991             (!cast<Instruction>(NAME # "v8i16")
4992                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4993   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4994             (!cast<Instruction>(NAME # "v4i32")
4995                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4996 }
4997
4998 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
4999                            bits<5> opcode, RegisterOperand regtype, string asm,
5000                            string kind, string zero, ValueType dty,
5001                            ValueType sty, SDNode OpNode>
5002   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5003       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5004       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5005       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5006     Sched<[WriteV]> {
5007   bits<5> Rd;
5008   bits<5> Rn;
5009   let Inst{31}    = 0;
5010   let Inst{30}    = Q;
5011   let Inst{29}    = U;
5012   let Inst{28-24} = 0b01110;
5013   let Inst{23-22} = size;
5014   let Inst{21} = 0b1;
5015   let Inst{20-19} = size2;
5016   let Inst{18-17} = 0b00;
5017   let Inst{16-12} = opcode;
5018   let Inst{11-10} = 0b10;
5019   let Inst{9-5}   = Rn;
5020   let Inst{4-0}   = Rd;
5021 }
5022
5023 // Comparisons support all element sizes, except 1xD.
5024 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5025                             SDNode OpNode> {
5026   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5027                                      asm, ".8b", "0",
5028                                      v8i8, v8i8, OpNode>;
5029   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5030                                      asm, ".16b", "0",
5031                                      v16i8, v16i8, OpNode>;
5032   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5033                                      asm, ".4h", "0",
5034                                      v4i16, v4i16, OpNode>;
5035   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5036                                      asm, ".8h", "0",
5037                                      v8i16, v8i16, OpNode>;
5038   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5039                                      asm, ".2s", "0",
5040                                      v2i32, v2i32, OpNode>;
5041   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5042                                      asm, ".4s", "0",
5043                                      v4i32, v4i32, OpNode>;
5044   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5045                                      asm, ".2d", "0",
5046                                      v2i64, v2i64, OpNode>;
5047 }
5048
5049 // FP Comparisons support only S and D element sizes (and H for v8.2a).
5050 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5051                               string asm, SDNode OpNode> {
5052
5053   let Predicates = [HasNEON, HasFullFP16] in {
5054   def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5055                                      asm, ".4h", "0.0",
5056                                      v4i16, v4f16, OpNode>;
5057   def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5058                                      asm, ".8h", "0.0",
5059                                      v8i16, v8f16, OpNode>;
5060   } // Predicates = [HasNEON, HasFullFP16]
5061   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5062                                      asm, ".2s", "0.0",
5063                                      v2i32, v2f32, OpNode>;
5064   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5065                                      asm, ".4s", "0.0",
5066                                      v4i32, v4f32, OpNode>;
5067   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5068                                      asm, ".2d", "0.0",
5069                                      v2i64, v2f64, OpNode>;
5070
5071   let Predicates = [HasNEON, HasFullFP16] in {
5072   def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5073                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5074   def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5075                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5076   }
5077   def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5078                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5079   def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5080                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5081   def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5082                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5083   let Predicates = [HasNEON, HasFullFP16] in {
5084   def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5085                   (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5086   def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5087                   (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5088   }
5089   def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5090                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5091   def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5092                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5093   def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5094                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5095 }
5096
5097 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5098 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5099                              RegisterOperand outtype, RegisterOperand intype,
5100                              string asm, string VdTy, string VnTy,
5101                              list<dag> pattern>
5102   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5103       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5104     Sched<[WriteV]> {
5105   bits<5> Rd;
5106   bits<5> Rn;
5107   let Inst{31}    = 0;
5108   let Inst{30}    = Q;
5109   let Inst{29}    = U;
5110   let Inst{28-24} = 0b01110;
5111   let Inst{23-22} = size;
5112   let Inst{21-17} = 0b10000;
5113   let Inst{16-12} = opcode;
5114   let Inst{11-10} = 0b10;
5115   let Inst{9-5}   = Rn;
5116   let Inst{4-0}   = Rd;
5117 }
5118
5119 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5120                              RegisterOperand outtype, RegisterOperand intype,
5121                              string asm, string VdTy, string VnTy,
5122                              list<dag> pattern>
5123   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5124       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5125     Sched<[WriteV]> {
5126   bits<5> Rd;
5127   bits<5> Rn;
5128   let Inst{31}    = 0;
5129   let Inst{30}    = Q;
5130   let Inst{29}    = U;
5131   let Inst{28-24} = 0b01110;
5132   let Inst{23-22} = size;
5133   let Inst{21-17} = 0b10000;
5134   let Inst{16-12} = opcode;
5135   let Inst{11-10} = 0b10;
5136   let Inst{9-5}   = Rn;
5137   let Inst{4-0}   = Rd;
5138 }
5139
5140 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5141   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5142                                     asm, ".4s", ".4h", []>;
5143   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5144                                     asm#"2", ".4s", ".8h", []>;
5145   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5146                                     asm, ".2d", ".2s", []>;
5147   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5148                                     asm#"2", ".2d", ".4s", []>;
5149 }
5150
5151 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5152   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5153                                     asm, ".4h", ".4s", []>;
5154   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5155                                     asm#"2", ".8h", ".4s", []>;
5156   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5157                                     asm, ".2s", ".2d", []>;
5158   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5159                                     asm#"2", ".4s", ".2d", []>;
5160 }
5161
5162 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5163                                      Intrinsic OpNode> {
5164   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5165                                      asm, ".2s", ".2d",
5166                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5167   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5168                                     asm#"2", ".4s", ".2d", []>;
5169
5170   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5171             (!cast<Instruction>(NAME # "v4f32")
5172                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5173 }
5174
5175 //----------------------------------------------------------------------------
5176 // AdvSIMD three register different-size vector instructions.
5177 //----------------------------------------------------------------------------
5178
5179 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5180 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5181                       RegisterOperand outtype, RegisterOperand intype1,
5182                       RegisterOperand intype2, string asm,
5183                       string outkind, string inkind1, string inkind2,
5184                       list<dag> pattern>
5185   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5186       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5187       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5188     Sched<[WriteV]> {
5189   bits<5> Rd;
5190   bits<5> Rn;
5191   bits<5> Rm;
5192   let Inst{31}    = 0;
5193   let Inst{30}    = size{0};
5194   let Inst{29}    = U;
5195   let Inst{28-24} = 0b01110;
5196   let Inst{23-22} = size{2-1};
5197   let Inst{21}    = 1;
5198   let Inst{20-16} = Rm;
5199   let Inst{15-12} = opcode;
5200   let Inst{11-10} = 0b00;
5201   let Inst{9-5}   = Rn;
5202   let Inst{4-0}   = Rd;
5203 }
5204
5205 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5206 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5207                       RegisterOperand outtype, RegisterOperand intype1,
5208                       RegisterOperand intype2, string asm,
5209                       string outkind, string inkind1, string inkind2,
5210                       list<dag> pattern>
5211   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5212       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5213       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5214     Sched<[WriteV]> {
5215   bits<5> Rd;
5216   bits<5> Rn;
5217   bits<5> Rm;
5218   let Inst{31}    = 0;
5219   let Inst{30}    = size{0};
5220   let Inst{29}    = U;
5221   let Inst{28-24} = 0b01110;
5222   let Inst{23-22} = size{2-1};
5223   let Inst{21}    = 1;
5224   let Inst{20-16} = Rm;
5225   let Inst{15-12} = opcode;
5226   let Inst{11-10} = 0b00;
5227   let Inst{9-5}   = Rn;
5228   let Inst{4-0}   = Rd;
5229 }
5230
5231 // FIXME: TableGen doesn't know how to deal with expanded types that also
5232 //        change the element count (in this case, placing the results in
5233 //        the high elements of the result register rather than the low
5234 //        elements). Until that's fixed, we can't code-gen those.
5235 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5236                                     Intrinsic IntOp> {
5237   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5238                                                   V64, V128, V128,
5239                                                   asm, ".8b", ".8h", ".8h",
5240      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5241   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5242                                                   V128, V128, V128,
5243                                                   asm#"2", ".16b", ".8h", ".8h",
5244      []>;
5245   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5246                                                   V64, V128, V128,
5247                                                   asm, ".4h", ".4s", ".4s",
5248      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5249   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5250                                                   V128, V128, V128,
5251                                                   asm#"2", ".8h", ".4s", ".4s",
5252      []>;
5253   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5254                                                   V64, V128, V128,
5255                                                   asm, ".2s", ".2d", ".2d",
5256      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5257   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5258                                                   V128, V128, V128,
5259                                                   asm#"2", ".4s", ".2d", ".2d",
5260      []>;
5261
5262
5263   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5264   // a version attached to an instruction.
5265   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5266                                                    (v8i16 V128:$Rm))),
5267             (!cast<Instruction>(NAME # "v8i16_v16i8")
5268                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5269                 V128:$Rn, V128:$Rm)>;
5270   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5271                                                     (v4i32 V128:$Rm))),
5272             (!cast<Instruction>(NAME # "v4i32_v8i16")
5273                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5274                 V128:$Rn, V128:$Rm)>;
5275   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5276                                                     (v2i64 V128:$Rm))),
5277             (!cast<Instruction>(NAME # "v2i64_v4i32")
5278                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5279                 V128:$Rn, V128:$Rm)>;
5280 }
5281
5282 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5283                                       Intrinsic IntOp> {
5284   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5285                                             V128, V64, V64,
5286                                             asm, ".8h", ".8b", ".8b",
5287       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5288   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5289                                             V128, V128, V128,
5290                                             asm#"2", ".8h", ".16b", ".16b", []>;
5291   let Predicates = [HasCrypto] in {
5292     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5293                                               V128, V64, V64,
5294                                               asm, ".1q", ".1d", ".1d", []>;
5295     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5296                                               V128, V128, V128,
5297                                               asm#"2", ".1q", ".2d", ".2d", []>;
5298   }
5299
5300   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5301                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
5302       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5303 }
5304
5305 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5306                                  SDPatternOperator OpNode> {
5307   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5308                                                   V128, V64, V64,
5309                                                   asm, ".4s", ".4h", ".4h",
5310       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5311   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5312                                                   V128, V128, V128,
5313                                                   asm#"2", ".4s", ".8h", ".8h",
5314       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5315                                       (extract_high_v8i16 V128:$Rm)))]>;
5316   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5317                                                   V128, V64, V64,
5318                                                   asm, ".2d", ".2s", ".2s",
5319       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5320   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5321                                                   V128, V128, V128,
5322                                                   asm#"2", ".2d", ".4s", ".4s",
5323       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5324                                       (extract_high_v4i32 V128:$Rm)))]>;
5325 }
5326
5327 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5328                                   SDPatternOperator OpNode = null_frag> {
5329   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5330                                                   V128, V64, V64,
5331                                                   asm, ".8h", ".8b", ".8b",
5332       [(set (v8i16 V128:$Rd),
5333             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5334   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5335                                                  V128, V128, V128,
5336                                                  asm#"2", ".8h", ".16b", ".16b",
5337       [(set (v8i16 V128:$Rd),
5338             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5339                                 (extract_high_v16i8 V128:$Rm)))))]>;
5340   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5341                                                   V128, V64, V64,
5342                                                   asm, ".4s", ".4h", ".4h",
5343       [(set (v4i32 V128:$Rd),
5344             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5345   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5346                                                   V128, V128, V128,
5347                                                   asm#"2", ".4s", ".8h", ".8h",
5348       [(set (v4i32 V128:$Rd),
5349             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5350                                   (extract_high_v8i16 V128:$Rm)))))]>;
5351   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5352                                                   V128, V64, V64,
5353                                                   asm, ".2d", ".2s", ".2s",
5354       [(set (v2i64 V128:$Rd),
5355             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5356   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5357                                                   V128, V128, V128,
5358                                                   asm#"2", ".2d", ".4s", ".4s",
5359       [(set (v2i64 V128:$Rd),
5360             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5361                                  (extract_high_v4i32 V128:$Rm)))))]>;
5362 }
5363
5364 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5365                                           string asm,
5366                                           SDPatternOperator OpNode> {
5367   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5368                                                   V128, V64, V64,
5369                                                   asm, ".8h", ".8b", ".8b",
5370     [(set (v8i16 V128:$dst),
5371           (add (v8i16 V128:$Rd),
5372                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5373   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5374                                                  V128, V128, V128,
5375                                                  asm#"2", ".8h", ".16b", ".16b",
5376     [(set (v8i16 V128:$dst),
5377           (add (v8i16 V128:$Rd),
5378                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5379                                    (extract_high_v16i8 V128:$Rm))))))]>;
5380   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5381                                                   V128, V64, V64,
5382                                                   asm, ".4s", ".4h", ".4h",
5383     [(set (v4i32 V128:$dst),
5384           (add (v4i32 V128:$Rd),
5385                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5386   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5387                                                   V128, V128, V128,
5388                                                   asm#"2", ".4s", ".8h", ".8h",
5389     [(set (v4i32 V128:$dst),
5390           (add (v4i32 V128:$Rd),
5391                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5392                                     (extract_high_v8i16 V128:$Rm))))))]>;
5393   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5394                                                   V128, V64, V64,
5395                                                   asm, ".2d", ".2s", ".2s",
5396     [(set (v2i64 V128:$dst),
5397           (add (v2i64 V128:$Rd),
5398                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5399   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5400                                                   V128, V128, V128,
5401                                                   asm#"2", ".2d", ".4s", ".4s",
5402     [(set (v2i64 V128:$dst),
5403           (add (v2i64 V128:$Rd),
5404                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5405                                     (extract_high_v4i32 V128:$Rm))))))]>;
5406 }
5407
5408 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5409                                   SDPatternOperator OpNode = null_frag> {
5410   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5411                                                   V128, V64, V64,
5412                                                   asm, ".8h", ".8b", ".8b",
5413       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5414   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5415                                                  V128, V128, V128,
5416                                                  asm#"2", ".8h", ".16b", ".16b",
5417       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5418                                       (extract_high_v16i8 V128:$Rm)))]>;
5419   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5420                                                   V128, V64, V64,
5421                                                   asm, ".4s", ".4h", ".4h",
5422       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5423   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5424                                                   V128, V128, V128,
5425                                                   asm#"2", ".4s", ".8h", ".8h",
5426       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5427                                       (extract_high_v8i16 V128:$Rm)))]>;
5428   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5429                                                   V128, V64, V64,
5430                                                   asm, ".2d", ".2s", ".2s",
5431       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5432   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5433                                                   V128, V128, V128,
5434                                                   asm#"2", ".2d", ".4s", ".4s",
5435       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5436                                       (extract_high_v4i32 V128:$Rm)))]>;
5437 }
5438
5439 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5440                                       string asm,
5441                                       SDPatternOperator OpNode> {
5442   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5443                                                   V128, V64, V64,
5444                                                   asm, ".8h", ".8b", ".8b",
5445     [(set (v8i16 V128:$dst),
5446           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5447   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5448                                                  V128, V128, V128,
5449                                                  asm#"2", ".8h", ".16b", ".16b",
5450     [(set (v8i16 V128:$dst),
5451           (OpNode (v8i16 V128:$Rd),
5452                   (extract_high_v16i8 V128:$Rn),
5453                   (extract_high_v16i8 V128:$Rm)))]>;
5454   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5455                                                   V128, V64, V64,
5456                                                   asm, ".4s", ".4h", ".4h",
5457     [(set (v4i32 V128:$dst),
5458           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5459   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5460                                                   V128, V128, V128,
5461                                                   asm#"2", ".4s", ".8h", ".8h",
5462     [(set (v4i32 V128:$dst),
5463           (OpNode (v4i32 V128:$Rd),
5464                   (extract_high_v8i16 V128:$Rn),
5465                   (extract_high_v8i16 V128:$Rm)))]>;
5466   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5467                                                   V128, V64, V64,
5468                                                   asm, ".2d", ".2s", ".2s",
5469     [(set (v2i64 V128:$dst),
5470           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5471   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5472                                                   V128, V128, V128,
5473                                                   asm#"2", ".2d", ".4s", ".4s",
5474     [(set (v2i64 V128:$dst),
5475           (OpNode (v2i64 V128:$Rd),
5476                   (extract_high_v4i32 V128:$Rn),
5477                   (extract_high_v4i32 V128:$Rm)))]>;
5478 }
5479
5480 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5481                                            SDPatternOperator Accum> {
5482   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5483                                                   V128, V64, V64,
5484                                                   asm, ".4s", ".4h", ".4h",
5485     [(set (v4i32 V128:$dst),
5486           (Accum (v4i32 V128:$Rd),
5487                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5488                                                 (v4i16 V64:$Rm)))))]>;
5489   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5490                                                   V128, V128, V128,
5491                                                   asm#"2", ".4s", ".8h", ".8h",
5492     [(set (v4i32 V128:$dst),
5493           (Accum (v4i32 V128:$Rd),
5494                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5495                                             (extract_high_v8i16 V128:$Rm)))))]>;
5496   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5497                                                   V128, V64, V64,
5498                                                   asm, ".2d", ".2s", ".2s",
5499     [(set (v2i64 V128:$dst),
5500           (Accum (v2i64 V128:$Rd),
5501                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5502                                                 (v2i32 V64:$Rm)))))]>;
5503   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5504                                                   V128, V128, V128,
5505                                                   asm#"2", ".2d", ".4s", ".4s",
5506     [(set (v2i64 V128:$dst),
5507           (Accum (v2i64 V128:$Rd),
5508                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5509                                             (extract_high_v4i32 V128:$Rm)))))]>;
5510 }
5511
5512 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5513                                   SDPatternOperator OpNode> {
5514   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5515                                                   V128, V128, V64,
5516                                                   asm, ".8h", ".8h", ".8b",
5517        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5518   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5519                                                   V128, V128, V128,
5520                                                   asm#"2", ".8h", ".8h", ".16b",
5521        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5522                                        (extract_high_v16i8 V128:$Rm)))]>;
5523   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5524                                                   V128, V128, V64,
5525                                                   asm, ".4s", ".4s", ".4h",
5526        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5527   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5528                                                   V128, V128, V128,
5529                                                   asm#"2", ".4s", ".4s", ".8h",
5530        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5531                                        (extract_high_v8i16 V128:$Rm)))]>;
5532   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5533                                                   V128, V128, V64,
5534                                                   asm, ".2d", ".2d", ".2s",
5535        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5536   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5537                                                   V128, V128, V128,
5538                                                   asm#"2", ".2d", ".2d", ".4s",
5539        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5540                                        (extract_high_v4i32 V128:$Rm)))]>;
5541 }
5542
5543 //----------------------------------------------------------------------------
5544 // AdvSIMD bitwise extract from vector
5545 //----------------------------------------------------------------------------
5546
5547 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5548                              string asm, string kind>
5549   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5550       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5551       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5552       [(set (vty regtype:$Rd),
5553             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5554     Sched<[WriteV]> {
5555   bits<5> Rd;
5556   bits<5> Rn;
5557   bits<5> Rm;
5558   bits<4> imm;
5559   let Inst{31}    = 0;
5560   let Inst{30}    = size;
5561   let Inst{29-21} = 0b101110000;
5562   let Inst{20-16} = Rm;
5563   let Inst{15}    = 0;
5564   let Inst{14-11} = imm;
5565   let Inst{10}    = 0;
5566   let Inst{9-5}   = Rn;
5567   let Inst{4-0}   = Rd;
5568 }
5569
5570
5571 multiclass SIMDBitwiseExtract<string asm> {
5572   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5573     let imm{3} = 0;
5574   }
5575   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5576 }
5577
5578 //----------------------------------------------------------------------------
5579 // AdvSIMD zip vector
5580 //----------------------------------------------------------------------------
5581
5582 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5583                         string asm, string kind, SDNode OpNode, ValueType valty>
5584   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5585       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5586       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5587       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5588     Sched<[WriteV]> {
5589   bits<5> Rd;
5590   bits<5> Rn;
5591   bits<5> Rm;
5592   let Inst{31}    = 0;
5593   let Inst{30}    = size{0};
5594   let Inst{29-24} = 0b001110;
5595   let Inst{23-22} = size{2-1};
5596   let Inst{21}    = 0;
5597   let Inst{20-16} = Rm;
5598   let Inst{15}    = 0;
5599   let Inst{14-12} = opc;
5600   let Inst{11-10} = 0b10;
5601   let Inst{9-5}   = Rn;
5602   let Inst{4-0}   = Rd;
5603 }
5604
5605 multiclass SIMDZipVector<bits<3>opc, string asm,
5606                          SDNode OpNode> {
5607   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5608       asm, ".8b", OpNode, v8i8>;
5609   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5610       asm, ".16b", OpNode, v16i8>;
5611   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5612       asm, ".4h", OpNode, v4i16>;
5613   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5614       asm, ".8h", OpNode, v8i16>;
5615   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5616       asm, ".2s", OpNode, v2i32>;
5617   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5618       asm, ".4s", OpNode, v4i32>;
5619   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5620       asm, ".2d", OpNode, v2i64>;
5621
5622   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5623         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5624   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5625         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5626   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5627         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5628   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5629         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5630   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5631         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5632 }
5633
5634 //----------------------------------------------------------------------------
5635 // AdvSIMD three register scalar instructions
5636 //----------------------------------------------------------------------------
5637
5638 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5639 class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
5640                         RegisterClass regtype, string asm,
5641                         list<dag> pattern>
5642   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5643       "\t$Rd, $Rn, $Rm", "", pattern>,
5644     Sched<[WriteV]> {
5645   bits<5> Rd;
5646   bits<5> Rn;
5647   bits<5> Rm;
5648   let Inst{31-30} = 0b01;
5649   let Inst{29}    = U;
5650   let Inst{28-24} = 0b11110;
5651   let Inst{23-21} = size;
5652   let Inst{20-16} = Rm;
5653   let Inst{15-11} = opcode;
5654   let Inst{10}    = 1;
5655   let Inst{9-5}   = Rn;
5656   let Inst{4-0}   = Rd;
5657 }
5658
5659 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5660 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5661                         dag oops, dag iops, string asm,
5662             list<dag> pattern>
5663   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5664     Sched<[WriteV]> {
5665   bits<5> Rd;
5666   bits<5> Rn;
5667   bits<5> Rm;
5668   let Inst{31-30} = 0b01;
5669   let Inst{29}    = U;
5670   let Inst{28-24} = 0b11110;
5671   let Inst{23-22} = size;
5672   let Inst{21}    = R;
5673   let Inst{20-16} = Rm;
5674   let Inst{15-11} = opcode;
5675   let Inst{10}    = 1;
5676   let Inst{9-5}   = Rn;
5677   let Inst{4-0}   = Rd;
5678 }
5679
5680 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5681                             SDPatternOperator OpNode> {
5682   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
5683     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5684 }
5685
5686 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5687                                SDPatternOperator OpNode> {
5688   def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
5689     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5690   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
5691   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
5692   def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
5693
5694   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5695             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5696   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5697             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5698 }
5699
5700 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5701                              SDPatternOperator OpNode> {
5702   def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
5703                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5704   def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
5705 }
5706
5707 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5708                                  SDPatternOperator OpNode = null_frag> {
5709   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5710                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm), 
5711                                      asm, []>;
5712   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5713                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm), 
5714                                      asm, []>;
5715 }
5716
5717 multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
5718                              SDPatternOperator OpNode = null_frag> {
5719   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5720     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
5721       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5722     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
5723       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5724     let Predicates = [HasNEON, HasFullFP16] in {
5725     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
5726       [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
5727     } // Predicates = [HasNEON, HasFullFP16]
5728   }
5729
5730   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5731             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5732 }
5733
5734 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
5735                                 SDPatternOperator OpNode = null_frag> {
5736   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5737     def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
5738       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5739     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
5740       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5741     let Predicates = [HasNEON, HasFullFP16] in {
5742     def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
5743       []>;
5744     } // Predicates = [HasNEON, HasFullFP16]
5745   }
5746
5747   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5748             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5749 }
5750
5751 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5752               dag oops, dag iops, string asm, string cstr, list<dag> pat>
5753   : I<oops, iops, asm,
5754       "\t$Rd, $Rn, $Rm", cstr, pat>,
5755     Sched<[WriteV]> {
5756   bits<5> Rd;
5757   bits<5> Rn;
5758   bits<5> Rm;
5759   let Inst{31-30} = 0b01;
5760   let Inst{29}    = U;
5761   let Inst{28-24} = 0b11110;
5762   let Inst{23-22} = size;
5763   let Inst{21}    = 1;
5764   let Inst{20-16} = Rm;
5765   let Inst{15-11} = opcode;
5766   let Inst{10}    = 0;
5767   let Inst{9-5}   = Rn;
5768   let Inst{4-0}   = Rd;
5769 }
5770
5771 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5772 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5773                                   SDPatternOperator OpNode = null_frag> {
5774   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5775                                       (outs FPR32:$Rd),
5776                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5777   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5778                                       (outs FPR64:$Rd),
5779                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5780             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5781 }
5782
5783 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5784 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5785                                   SDPatternOperator OpNode = null_frag> {
5786   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5787                                       (outs FPR32:$dst),
5788                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5789                                       asm, "$Rd = $dst", []>;
5790   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5791                                       (outs FPR64:$dst),
5792                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5793                                       asm, "$Rd = $dst",
5794             [(set (i64 FPR64:$dst),
5795                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5796 }
5797
5798 //----------------------------------------------------------------------------
5799 // AdvSIMD two register scalar instructions
5800 //----------------------------------------------------------------------------
5801
5802 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5803 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
5804                         RegisterClass regtype, RegisterClass regtype2,
5805                         string asm, list<dag> pat>
5806   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5807       "\t$Rd, $Rn", "", pat>,
5808     Sched<[WriteV]> {
5809   bits<5> Rd;
5810   bits<5> Rn;
5811   let Inst{31-30} = 0b01;
5812   let Inst{29}    = U;
5813   let Inst{28-24} = 0b11110;
5814   let Inst{23-22} = size;
5815   let Inst{21} = 0b1;
5816   let Inst{20-19} = size2;
5817   let Inst{18-17} = 0b00;
5818   let Inst{16-12} = opcode;
5819   let Inst{11-10} = 0b10;
5820   let Inst{9-5}   = Rn;
5821   let Inst{4-0}   = Rd;
5822 }
5823
5824 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5825 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5826                         RegisterClass regtype, RegisterClass regtype2,
5827                         string asm, list<dag> pat>
5828   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5829       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5830     Sched<[WriteV]> {
5831   bits<5> Rd;
5832   bits<5> Rn;
5833   let Inst{31-30} = 0b01;
5834   let Inst{29}    = U;
5835   let Inst{28-24} = 0b11110;
5836   let Inst{23-22} = size;
5837   let Inst{21-17} = 0b10000;
5838   let Inst{16-12} = opcode;
5839   let Inst{11-10} = 0b10;
5840   let Inst{9-5}   = Rn;
5841   let Inst{4-0}   = Rd;
5842 }
5843
5844
5845 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5846 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
5847                         RegisterClass regtype, string asm, string zero>
5848   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5849       "\t$Rd, $Rn, #" # zero, "", []>,
5850     Sched<[WriteV]> {
5851   bits<5> Rd;
5852   bits<5> Rn;
5853   let Inst{31-30} = 0b01;
5854   let Inst{29}    = U;
5855   let Inst{28-24} = 0b11110;
5856   let Inst{23-22} = size;
5857   let Inst{21} = 0b1;
5858   let Inst{20-19} = size2;
5859   let Inst{18-17} = 0b00;
5860   let Inst{16-12} = opcode;
5861   let Inst{11-10} = 0b10;
5862   let Inst{9-5}   = Rn;
5863   let Inst{4-0}   = Rd;
5864 }
5865
5866 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5867   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5868      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5869     Sched<[WriteV]> {
5870   bits<5> Rd;
5871   bits<5> Rn;
5872   let Inst{31-17} = 0b011111100110000;
5873   let Inst{16-12} = opcode;
5874   let Inst{11-10} = 0b10;
5875   let Inst{9-5}   = Rn;
5876   let Inst{4-0}   = Rd;
5877 }
5878
5879 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5880                              SDPatternOperator OpNode> {
5881   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
5882
5883   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5884             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5885 }
5886
5887 multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
5888                               SDPatternOperator OpNode> {
5889   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
5890   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
5891   let Predicates = [HasNEON, HasFullFP16] in {
5892   def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
5893   }
5894
5895   def : InstAlias<asm # "\t$Rd, $Rn, #0",
5896                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5897   def : InstAlias<asm # "\t$Rd, $Rn, #0",
5898                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5899   let Predicates = [HasNEON, HasFullFP16] in {
5900   def : InstAlias<asm # "\t$Rd, $Rn, #0",
5901                   (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
5902   }
5903
5904   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5905             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5906 }
5907
5908 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5909                           SDPatternOperator OpNode = null_frag> {
5910   def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
5911     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5912
5913   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5914             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5915 }
5916
5917 multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
5918   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
5919   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
5920   let Predicates = [HasNEON, HasFullFP16] in {
5921   def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
5922   }
5923 }
5924
5925 multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
5926                               SDPatternOperator OpNode> {
5927   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
5928                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5929   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
5930                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5931   let Predicates = [HasNEON, HasFullFP16] in {
5932   def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
5933                                 [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
5934   }
5935 }
5936
5937 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5938                              SDPatternOperator OpNode = null_frag> {
5939   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5940     def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
5941            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5942     def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
5943            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5944     def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
5945     def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
5946   }
5947
5948   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5949             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5950 }
5951
5952 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5953                                  Intrinsic OpNode> {
5954   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5955     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5956         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5957     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5958         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5959     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5960     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5961   }
5962
5963   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5964             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5965 }
5966
5967
5968
5969 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5970 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5971                                  SDPatternOperator OpNode = null_frag> {
5972   def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
5973         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5974   def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
5975   def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
5976 }
5977
5978 //----------------------------------------------------------------------------
5979 // AdvSIMD scalar pairwise instructions
5980 //----------------------------------------------------------------------------
5981
5982 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5983 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5984                         RegisterOperand regtype, RegisterOperand vectype,
5985                         string asm, string kind>
5986   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5987       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5988     Sched<[WriteV]> {
5989   bits<5> Rd;
5990   bits<5> Rn;
5991   let Inst{31-30} = 0b01;
5992   let Inst{29}    = U;
5993   let Inst{28-24} = 0b11110;
5994   let Inst{23-22} = size;
5995   let Inst{21-17} = 0b11000;
5996   let Inst{16-12} = opcode;
5997   let Inst{11-10} = 0b10;
5998   let Inst{9-5}   = Rn;
5999   let Inst{4-0}   = Rd;
6000 }
6001
6002 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6003   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6004                                       asm, ".2d">;
6005 }
6006
6007 multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6008   let Predicates = [HasNEON, HasFullFP16] in {
6009   def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6010                                       asm, ".2h">;
6011   }
6012   def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6013                                       asm, ".2s">;
6014   def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6015                                       asm, ".2d">;
6016 }
6017
6018 //----------------------------------------------------------------------------
6019 // AdvSIMD across lanes instructions
6020 //----------------------------------------------------------------------------
6021
6022 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6023 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6024                           RegisterClass regtype, RegisterOperand vectype,
6025                           string asm, string kind, list<dag> pattern>
6026   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6027       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6028     Sched<[WriteV]> {
6029   bits<5> Rd;
6030   bits<5> Rn;
6031   let Inst{31}    = 0;
6032   let Inst{30}    = Q;
6033   let Inst{29}    = U;
6034   let Inst{28-24} = 0b01110;
6035   let Inst{23-22} = size;
6036   let Inst{21-17} = 0b11000;
6037   let Inst{16-12} = opcode;
6038   let Inst{11-10} = 0b10;
6039   let Inst{9-5}   = Rn;
6040   let Inst{4-0}   = Rd;
6041 }
6042
6043 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6044                               string asm> {
6045   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
6046                                    asm, ".8b", []>;
6047   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
6048                                    asm, ".16b", []>;
6049   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6050                                    asm, ".4h", []>;
6051   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6052                                    asm, ".8h", []>;
6053   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6054                                    asm, ".4s", []>;
6055 }
6056
6057 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6058   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6059                                    asm, ".8b", []>;
6060   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6061                                    asm, ".16b", []>;
6062   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6063                                    asm, ".4h", []>;
6064   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6065                                    asm, ".8h", []>;
6066   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6067                                    asm, ".4s", []>;
6068 }
6069
6070 multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6071                             Intrinsic intOp> {
6072   let Predicates = [HasNEON, HasFullFP16] in {
6073   def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6074                                    asm, ".4h",
6075         [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6076   def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6077                                    asm, ".8h",
6078         [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6079   } // Predicates = [HasNEON, HasFullFP16]
6080   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6081                                    asm, ".4s",
6082         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6083 }
6084
6085 //----------------------------------------------------------------------------
6086 // AdvSIMD INS/DUP instructions
6087 //----------------------------------------------------------------------------
6088
6089 // FIXME: There has got to be a better way to factor these. ugh.
6090
6091 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6092                      string operands, string constraints, list<dag> pattern>
6093   : I<outs, ins, asm, operands, constraints, pattern>,
6094     Sched<[WriteV]> {
6095   bits<5> Rd;
6096   bits<5> Rn;
6097   let Inst{31} = 0;
6098   let Inst{30} = Q;
6099   let Inst{29} = op;
6100   let Inst{28-21} = 0b01110000;
6101   let Inst{15} = 0;
6102   let Inst{10} = 1;
6103   let Inst{9-5} = Rn;
6104   let Inst{4-0} = Rd;
6105 }
6106
6107 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6108                       RegisterOperand vecreg, RegisterClass regtype>
6109   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6110                    "{\t$Rd" # size # ", $Rn" #
6111                    "|" # size # "\t$Rd, $Rn}", "",
6112                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6113   let Inst{20-16} = imm5;
6114   let Inst{14-11} = 0b0001;
6115 }
6116
6117 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6118                          ValueType vectype, ValueType insreg,
6119                          RegisterOperand vecreg, Operand idxtype,
6120                          ValueType elttype, SDNode OpNode>
6121   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6122                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6123                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6124                  [(set (vectype vecreg:$Rd),
6125                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6126   let Inst{14-11} = 0b0000;
6127 }
6128
6129 class SIMDDup64FromElement
6130   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6131                        VectorIndexD, i64, AArch64duplane64> {
6132   bits<1> idx;
6133   let Inst{20} = idx;
6134   let Inst{19-16} = 0b1000;
6135 }
6136
6137 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6138                            RegisterOperand vecreg>
6139   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6140                        VectorIndexS, i64, AArch64duplane32> {
6141   bits<2> idx;
6142   let Inst{20-19} = idx;
6143   let Inst{18-16} = 0b100;
6144 }
6145
6146 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6147                            RegisterOperand vecreg>
6148   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6149                        VectorIndexH, i64, AArch64duplane16> {
6150   bits<3> idx;
6151   let Inst{20-18} = idx;
6152   let Inst{17-16} = 0b10;
6153 }
6154
6155 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6156                           RegisterOperand vecreg>
6157   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6158                        VectorIndexB, i64, AArch64duplane8> {
6159   bits<4> idx;
6160   let Inst{20-17} = idx;
6161   let Inst{16} = 1;
6162 }
6163
6164 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6165                   Operand idxtype, string asm, list<dag> pattern>
6166   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6167                    "{\t$Rd, $Rn" # size # "$idx" #
6168                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6169   let Inst{14-11} = imm4;
6170 }
6171
6172 class SIMDSMov<bit Q, string size, RegisterClass regtype,
6173                Operand idxtype>
6174   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6175 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6176                Operand idxtype>
6177   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6178       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6179
6180 class SIMDMovAlias<string asm, string size, Instruction inst,
6181                    RegisterClass regtype, Operand idxtype>
6182     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6183                     "|" # size # "\t$dst, $src$idx}",
6184                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6185
6186 multiclass SMov {
6187   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6188     bits<4> idx;
6189     let Inst{20-17} = idx;
6190     let Inst{16} = 1;
6191   }
6192   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6193     bits<4> idx;
6194     let Inst{20-17} = idx;
6195     let Inst{16} = 1;
6196   }
6197   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6198     bits<3> idx;
6199     let Inst{20-18} = idx;
6200     let Inst{17-16} = 0b10;
6201   }
6202   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6203     bits<3> idx;
6204     let Inst{20-18} = idx;
6205     let Inst{17-16} = 0b10;
6206   }
6207   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6208     bits<2> idx;
6209     let Inst{20-19} = idx;
6210     let Inst{18-16} = 0b100;
6211   }
6212 }
6213
6214 multiclass UMov {
6215   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6216     bits<4> idx;
6217     let Inst{20-17} = idx;
6218     let Inst{16} = 1;
6219   }
6220   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6221     bits<3> idx;
6222     let Inst{20-18} = idx;
6223     let Inst{17-16} = 0b10;
6224   }
6225   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6226     bits<2> idx;
6227     let Inst{20-19} = idx;
6228     let Inst{18-16} = 0b100;
6229   }
6230   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6231     bits<1> idx;
6232     let Inst{20} = idx;
6233     let Inst{19-16} = 0b1000;
6234   }
6235   def : SIMDMovAlias<"mov", ".s",
6236                      !cast<Instruction>(NAME#"vi32"),
6237                      GPR32, VectorIndexS>;
6238   def : SIMDMovAlias<"mov", ".d",
6239                      !cast<Instruction>(NAME#"vi64"),
6240                      GPR64, VectorIndexD>;
6241 }
6242
6243 class SIMDInsFromMain<string size, ValueType vectype,
6244                       RegisterClass regtype, Operand idxtype>
6245   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6246                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6247                    "{\t$Rd" # size # "$idx, $Rn" #
6248                    "|" # size # "\t$Rd$idx, $Rn}",
6249                    "$Rd = $dst",
6250             [(set V128:$dst,
6251               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6252   let Inst{14-11} = 0b0011;
6253 }
6254
6255 class SIMDInsFromElement<string size, ValueType vectype,
6256                          ValueType elttype, Operand idxtype>
6257   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6258                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6259                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6260                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
6261                    "$Rd = $dst",
6262          [(set V128:$dst,
6263                (vector_insert
6264                  (vectype V128:$Rd),
6265                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6266                  idxtype:$idx))]>;
6267
6268 class SIMDInsMainMovAlias<string size, Instruction inst,
6269                           RegisterClass regtype, Operand idxtype>
6270     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6271                         "|" # size #"\t$dst$idx, $src}",
6272                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6273 class SIMDInsElementMovAlias<string size, Instruction inst,
6274                              Operand idxtype>
6275     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6276                       # "|" # size #"\t$dst$idx, $src$idx2}",
6277                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6278
6279
6280 multiclass SIMDIns {
6281   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6282     bits<4> idx;
6283     let Inst{20-17} = idx;
6284     let Inst{16} = 1;
6285   }
6286   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6287     bits<3> idx;
6288     let Inst{20-18} = idx;
6289     let Inst{17-16} = 0b10;
6290   }
6291   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6292     bits<2> idx;
6293     let Inst{20-19} = idx;
6294     let Inst{18-16} = 0b100;
6295   }
6296   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6297     bits<1> idx;
6298     let Inst{20} = idx;
6299     let Inst{19-16} = 0b1000;
6300   }
6301
6302   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6303     bits<4> idx;
6304     bits<4> idx2;
6305     let Inst{20-17} = idx;
6306     let Inst{16} = 1;
6307     let Inst{14-11} = idx2;
6308   }
6309   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6310     bits<3> idx;
6311     bits<3> idx2;
6312     let Inst{20-18} = idx;
6313     let Inst{17-16} = 0b10;
6314     let Inst{14-12} = idx2;
6315     let Inst{11} = {?};
6316   }
6317   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6318     bits<2> idx;
6319     bits<2> idx2;
6320     let Inst{20-19} = idx;
6321     let Inst{18-16} = 0b100;
6322     let Inst{14-13} = idx2;
6323     let Inst{12-11} = {?,?};
6324   }
6325   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6326     bits<1> idx;
6327     bits<1> idx2;
6328     let Inst{20} = idx;
6329     let Inst{19-16} = 0b1000;
6330     let Inst{14} = idx2;
6331     let Inst{13-11} = {?,?,?};
6332   }
6333
6334   // For all forms of the INS instruction, the "mov" mnemonic is the
6335   // preferred alias. Why they didn't just call the instruction "mov" in
6336   // the first place is a very good question indeed...
6337   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6338                          GPR32, VectorIndexB>;
6339   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6340                          GPR32, VectorIndexH>;
6341   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6342                          GPR32, VectorIndexS>;
6343   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6344                          GPR64, VectorIndexD>;
6345
6346   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6347                          VectorIndexB>;
6348   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6349                          VectorIndexH>;
6350   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6351                          VectorIndexS>;
6352   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6353                          VectorIndexD>;
6354 }
6355
6356 //----------------------------------------------------------------------------
6357 // AdvSIMD TBL/TBX
6358 //----------------------------------------------------------------------------
6359
6360 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6361 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6362                           RegisterOperand listtype, string asm, string kind>
6363   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6364        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6365     Sched<[WriteV]> {
6366   bits<5> Vd;
6367   bits<5> Vn;
6368   bits<5> Vm;
6369   let Inst{31}    = 0;
6370   let Inst{30}    = Q;
6371   let Inst{29-21} = 0b001110000;
6372   let Inst{20-16} = Vm;
6373   let Inst{15}    = 0;
6374   let Inst{14-13} = len;
6375   let Inst{12}    = op;
6376   let Inst{11-10} = 0b00;
6377   let Inst{9-5}   = Vn;
6378   let Inst{4-0}   = Vd;
6379 }
6380
6381 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6382 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6383                           RegisterOperand listtype, string asm, string kind>
6384   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6385        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6386     Sched<[WriteV]> {
6387   bits<5> Vd;
6388   bits<5> Vn;
6389   bits<5> Vm;
6390   let Inst{31}    = 0;
6391   let Inst{30}    = Q;
6392   let Inst{29-21} = 0b001110000;
6393   let Inst{20-16} = Vm;
6394   let Inst{15}    = 0;
6395   let Inst{14-13} = len;
6396   let Inst{12}    = op;
6397   let Inst{11-10} = 0b00;
6398   let Inst{9-5}   = Vn;
6399   let Inst{4-0}   = Vd;
6400 }
6401
6402 class SIMDTableLookupAlias<string asm, Instruction inst,
6403                           RegisterOperand vectype, RegisterOperand listtype>
6404     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6405                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6406
6407 multiclass SIMDTableLookup<bit op, string asm> {
6408   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6409                                       asm, ".8b">;
6410   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6411                                       asm, ".8b">;
6412   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6413                                       asm, ".8b">;
6414   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6415                                       asm, ".8b">;
6416   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6417                                       asm, ".16b">;
6418   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6419                                       asm, ".16b">;
6420   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6421                                       asm, ".16b">;
6422   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6423                                       asm, ".16b">;
6424
6425   def : SIMDTableLookupAlias<asm # ".8b",
6426                          !cast<Instruction>(NAME#"v8i8One"),
6427                          V64, VecListOne128>;
6428   def : SIMDTableLookupAlias<asm # ".8b",
6429                          !cast<Instruction>(NAME#"v8i8Two"),
6430                          V64, VecListTwo128>;
6431   def : SIMDTableLookupAlias<asm # ".8b",
6432                          !cast<Instruction>(NAME#"v8i8Three"),
6433                          V64, VecListThree128>;
6434   def : SIMDTableLookupAlias<asm # ".8b",
6435                          !cast<Instruction>(NAME#"v8i8Four"),
6436                          V64, VecListFour128>;
6437   def : SIMDTableLookupAlias<asm # ".16b",
6438                          !cast<Instruction>(NAME#"v16i8One"),
6439                          V128, VecListOne128>;
6440   def : SIMDTableLookupAlias<asm # ".16b",
6441                          !cast<Instruction>(NAME#"v16i8Two"),
6442                          V128, VecListTwo128>;
6443   def : SIMDTableLookupAlias<asm # ".16b",
6444                          !cast<Instruction>(NAME#"v16i8Three"),
6445                          V128, VecListThree128>;
6446   def : SIMDTableLookupAlias<asm # ".16b",
6447                          !cast<Instruction>(NAME#"v16i8Four"),
6448                          V128, VecListFour128>;
6449 }
6450
6451 multiclass SIMDTableLookupTied<bit op, string asm> {
6452   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6453                                       asm, ".8b">;
6454   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6455                                       asm, ".8b">;
6456   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6457                                       asm, ".8b">;
6458   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6459                                       asm, ".8b">;
6460   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6461                                       asm, ".16b">;
6462   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6463                                       asm, ".16b">;
6464   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6465                                       asm, ".16b">;
6466   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6467                                       asm, ".16b">;
6468
6469   def : SIMDTableLookupAlias<asm # ".8b",
6470                          !cast<Instruction>(NAME#"v8i8One"),
6471                          V64, VecListOne128>;
6472   def : SIMDTableLookupAlias<asm # ".8b",
6473                          !cast<Instruction>(NAME#"v8i8Two"),
6474                          V64, VecListTwo128>;
6475   def : SIMDTableLookupAlias<asm # ".8b",
6476                          !cast<Instruction>(NAME#"v8i8Three"),
6477                          V64, VecListThree128>;
6478   def : SIMDTableLookupAlias<asm # ".8b",
6479                          !cast<Instruction>(NAME#"v8i8Four"),
6480                          V64, VecListFour128>;
6481   def : SIMDTableLookupAlias<asm # ".16b",
6482                          !cast<Instruction>(NAME#"v16i8One"),
6483                          V128, VecListOne128>;
6484   def : SIMDTableLookupAlias<asm # ".16b",
6485                          !cast<Instruction>(NAME#"v16i8Two"),
6486                          V128, VecListTwo128>;
6487   def : SIMDTableLookupAlias<asm # ".16b",
6488                          !cast<Instruction>(NAME#"v16i8Three"),
6489                          V128, VecListThree128>;
6490   def : SIMDTableLookupAlias<asm # ".16b",
6491                          !cast<Instruction>(NAME#"v16i8Four"),
6492                          V128, VecListFour128>;
6493 }
6494
6495
6496 //----------------------------------------------------------------------------
6497 // AdvSIMD scalar CPY
6498 //----------------------------------------------------------------------------
6499 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6500 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6501                         string kind, Operand idxtype>
6502   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6503        "{\t$dst, $src" # kind # "$idx" #
6504        "|\t$dst, $src$idx}", "", []>,
6505     Sched<[WriteV]> {
6506   bits<5> dst;
6507   bits<5> src;
6508   let Inst{31-21} = 0b01011110000;
6509   let Inst{15-10} = 0b000001;
6510   let Inst{9-5}   = src;
6511   let Inst{4-0}   = dst;
6512 }
6513
6514 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6515       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6516     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6517                     # "|\t$dst, $src$index}",
6518                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6519
6520
6521 multiclass SIMDScalarCPY<string asm> {
6522   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6523     bits<4> idx;
6524     let Inst{20-17} = idx;
6525     let Inst{16} = 1;
6526   }
6527   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6528     bits<3> idx;
6529     let Inst{20-18} = idx;
6530     let Inst{17-16} = 0b10;
6531   }
6532   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6533     bits<2> idx;
6534     let Inst{20-19} = idx;
6535     let Inst{18-16} = 0b100;
6536   }
6537   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6538     bits<1> idx;
6539     let Inst{20} = idx;
6540     let Inst{19-16} = 0b1000;
6541   }
6542
6543   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6544                                                           VectorIndexD:$idx)))),
6545             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6546
6547   // 'DUP' mnemonic aliases.
6548   def : SIMDScalarCPYAlias<"dup", ".b",
6549                            !cast<Instruction>(NAME#"i8"),
6550                            FPR8, V128, VectorIndexB>;
6551   def : SIMDScalarCPYAlias<"dup", ".h",
6552                            !cast<Instruction>(NAME#"i16"),
6553                            FPR16, V128, VectorIndexH>;
6554   def : SIMDScalarCPYAlias<"dup", ".s",
6555                            !cast<Instruction>(NAME#"i32"),
6556                            FPR32, V128, VectorIndexS>;
6557   def : SIMDScalarCPYAlias<"dup", ".d",
6558                            !cast<Instruction>(NAME#"i64"),
6559                            FPR64, V128, VectorIndexD>;
6560 }
6561
6562 //----------------------------------------------------------------------------
6563 // AdvSIMD modified immediate instructions
6564 //----------------------------------------------------------------------------
6565
6566 class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
6567                           string asm, string op_string,
6568                           string cstr, list<dag> pattern>
6569   : I<oops, iops, asm, op_string, cstr, pattern>,
6570     Sched<[WriteV]> {
6571   bits<5> Rd;
6572   bits<8> imm8;
6573   let Inst{31}    = 0;
6574   let Inst{30}    = Q;
6575   let Inst{29}    = op;
6576   let Inst{28-19} = 0b0111100000;
6577   let Inst{18-16} = imm8{7-5};
6578   let Inst{11} = op2;
6579   let Inst{10} = 1;
6580   let Inst{9-5}   = imm8{4-0};
6581   let Inst{4-0}   = Rd;
6582 }
6583
6584 class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
6585                                 Operand immtype, dag opt_shift_iop,
6586                                 string opt_shift, string asm, string kind,
6587                                 list<dag> pattern>
6588   : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
6589                         !con((ins immtype:$imm8), opt_shift_iop), asm,
6590                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
6591                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6592                         "", pattern> {
6593   let DecoderMethod = "DecodeModImmInstruction";
6594 }
6595
6596 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6597                                 Operand immtype, dag opt_shift_iop,
6598                                 string opt_shift, string asm, string kind,
6599                                 list<dag> pattern>
6600   : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
6601                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6602                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6603                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6604                         "$Rd = $dst", pattern> {
6605   let DecoderMethod = "DecodeModImmTiedInstruction";
6606 }
6607
6608 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6609                                      RegisterOperand vectype, string asm,
6610                                      string kind, list<dag> pattern>
6611   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
6612                               (ins logical_vec_shift:$shift),
6613                               "$shift", asm, kind, pattern> {
6614   bits<2> shift;
6615   let Inst{15}    = b15_b12{1};
6616   let Inst{14-13} = shift;
6617   let Inst{12}    = b15_b12{0};
6618 }
6619
6620 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6621                                      RegisterOperand vectype, string asm,
6622                                      string kind, list<dag> pattern>
6623   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6624                               (ins logical_vec_shift:$shift),
6625                               "$shift", asm, kind, pattern> {
6626   bits<2> shift;
6627   let Inst{15}    = b15_b12{1};
6628   let Inst{14-13} = shift;
6629   let Inst{12}    = b15_b12{0};
6630 }
6631
6632
6633 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6634                                          RegisterOperand vectype, string asm,
6635                                          string kind, list<dag> pattern>
6636   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
6637                               (ins logical_vec_hw_shift:$shift),
6638                               "$shift", asm, kind, pattern> {
6639   bits<2> shift;
6640   let Inst{15} = b15_b12{1};
6641   let Inst{14} = 0;
6642   let Inst{13} = shift{0};
6643   let Inst{12} = b15_b12{0};
6644 }
6645
6646 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6647                                          RegisterOperand vectype, string asm,
6648                                          string kind, list<dag> pattern>
6649   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6650                               (ins logical_vec_hw_shift:$shift),
6651                               "$shift", asm, kind, pattern> {
6652   bits<2> shift;
6653   let Inst{15} = b15_b12{1};
6654   let Inst{14} = 0;
6655   let Inst{13} = shift{0};
6656   let Inst{12} = b15_b12{0};
6657 }
6658
6659 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6660                                       string asm> {
6661   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6662                                                  asm, ".4h", []>;
6663   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6664                                                  asm, ".8h", []>;
6665
6666   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6667                                              asm, ".2s", []>;
6668   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6669                                              asm, ".4s", []>;
6670 }
6671
6672 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6673                                       bits<2> w_cmode, string asm,
6674                                       SDNode OpNode> {
6675   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6676                                                  asm, ".4h",
6677              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6678                                              imm0_255:$imm8,
6679                                              (i32 imm:$shift)))]>;
6680   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6681                                                  asm, ".8h",
6682              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6683                                               imm0_255:$imm8,
6684                                               (i32 imm:$shift)))]>;
6685
6686   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6687                                              asm, ".2s",
6688              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6689                                              imm0_255:$imm8,
6690                                              (i32 imm:$shift)))]>;
6691   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6692                                              asm, ".4s",
6693              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6694                                               imm0_255:$imm8,
6695                                               (i32 imm:$shift)))]>;
6696 }
6697
6698 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6699                              RegisterOperand vectype, string asm,
6700                              string kind, list<dag> pattern>
6701   : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
6702                               (ins move_vec_shift:$shift),
6703                               "$shift", asm, kind, pattern> {
6704   bits<1> shift;
6705   let Inst{15-13} = cmode{3-1};
6706   let Inst{12}    = shift;
6707 }
6708
6709 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
6710                                    RegisterOperand vectype,
6711                                    Operand imm_type, string asm,
6712                                    string kind, list<dag> pattern>
6713   : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
6714                               asm, kind, pattern> {
6715   let Inst{15-12} = cmode;
6716 }
6717
6718 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6719                                    list<dag> pattern>
6720   : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6721                         "\t$Rd, $imm8", "", pattern> {
6722   let Inst{15-12} = cmode;
6723   let DecoderMethod = "DecodeModImmInstruction";
6724 }
6725
6726 //----------------------------------------------------------------------------
6727 // AdvSIMD indexed element
6728 //----------------------------------------------------------------------------
6729
6730 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6731 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6732                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6733                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6734                       string apple_kind, string dst_kind, string lhs_kind,
6735                       string rhs_kind, list<dag> pattern>
6736   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6737       asm,
6738       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6739       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6740     Sched<[WriteV]> {
6741   bits<5> Rd;
6742   bits<5> Rn;
6743   bits<5> Rm;
6744
6745   let Inst{31}    = 0;
6746   let Inst{30}    = Q;
6747   let Inst{29}    = U;
6748   let Inst{28}    = Scalar;
6749   let Inst{27-24} = 0b1111;
6750   let Inst{23-22} = size;
6751   // Bit 21 must be set by the derived class.
6752   let Inst{20-16} = Rm;
6753   let Inst{15-12} = opc;
6754   // Bit 11 must be set by the derived class.
6755   let Inst{10}    = 0;
6756   let Inst{9-5}   = Rn;
6757   let Inst{4-0}   = Rd;
6758 }
6759
6760 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6761 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6762                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6763                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6764                       string apple_kind, string dst_kind, string lhs_kind,
6765                       string rhs_kind, list<dag> pattern>
6766   : I<(outs dst_reg:$dst),
6767       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6768       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6769       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6770     Sched<[WriteV]> {
6771   bits<5> Rd;
6772   bits<5> Rn;
6773   bits<5> Rm;
6774
6775   let Inst{31}    = 0;
6776   let Inst{30}    = Q;
6777   let Inst{29}    = U;
6778   let Inst{28}    = Scalar;
6779   let Inst{27-24} = 0b1111;
6780   let Inst{23-22} = size;
6781   // Bit 21 must be set by the derived class.
6782   let Inst{20-16} = Rm;
6783   let Inst{15-12} = opc;
6784   // Bit 11 must be set by the derived class.
6785   let Inst{10}    = 0;
6786   let Inst{9-5}   = Rn;
6787   let Inst{4-0}   = Rd;
6788 }
6789
6790 multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
6791                          SDPatternOperator OpNode> {
6792   let Predicates = [HasNEON, HasFullFP16] in {
6793   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
6794                                       V64, V64,
6795                                       V128_lo, VectorIndexH,
6796                                       asm, ".4h", ".4h", ".4h", ".h",
6797     [(set (v4f16 V64:$Rd),
6798         (OpNode (v4f16 V64:$Rn),
6799          (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6800     bits<3> idx;
6801     let Inst{11} = idx{2};
6802     let Inst{21} = idx{1};
6803     let Inst{20} = idx{0};
6804   }
6805
6806   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
6807                                       V128, V128,
6808                                       V128_lo, VectorIndexH,
6809                                       asm, ".8h", ".8h", ".8h", ".h",
6810     [(set (v8f16 V128:$Rd),
6811         (OpNode (v8f16 V128:$Rn),
6812          (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6813     bits<3> idx;
6814     let Inst{11} = idx{2};
6815     let Inst{21} = idx{1};
6816     let Inst{20} = idx{0};
6817   }
6818   } // Predicates = [HasNEON, HasFullFP16]
6819
6820   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6821                                       V64, V64,
6822                                       V128, VectorIndexS,
6823                                       asm, ".2s", ".2s", ".2s", ".s",
6824     [(set (v2f32 V64:$Rd),
6825         (OpNode (v2f32 V64:$Rn),
6826          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6827     bits<2> idx;
6828     let Inst{11} = idx{1};
6829     let Inst{21} = idx{0};
6830   }
6831
6832   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6833                                       V128, V128,
6834                                       V128, VectorIndexS,
6835                                       asm, ".4s", ".4s", ".4s", ".s",
6836     [(set (v4f32 V128:$Rd),
6837         (OpNode (v4f32 V128:$Rn),
6838          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6839     bits<2> idx;
6840     let Inst{11} = idx{1};
6841     let Inst{21} = idx{0};
6842   }
6843
6844   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6845                                       V128, V128,
6846                                       V128, VectorIndexD,
6847                                       asm, ".2d", ".2d", ".2d", ".d",
6848     [(set (v2f64 V128:$Rd),
6849         (OpNode (v2f64 V128:$Rn),
6850          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6851     bits<1> idx;
6852     let Inst{11} = idx{0};
6853     let Inst{21} = 0;
6854   }
6855
6856   let Predicates = [HasNEON, HasFullFP16] in {
6857   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
6858                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6859                                       asm, ".h", "", "", ".h",
6860     [(set (f16 FPR16Op:$Rd),
6861           (OpNode (f16 FPR16Op:$Rn),
6862                   (f16 (vector_extract (v8f16 V128_lo:$Rm),
6863                                        VectorIndexH:$idx))))]> {
6864     bits<3> idx;
6865     let Inst{11} = idx{2};
6866     let Inst{21} = idx{1};
6867     let Inst{20} = idx{0};
6868   }
6869   } // Predicates = [HasNEON, HasFullFP16]
6870
6871   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6872                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6873                                       asm, ".s", "", "", ".s",
6874     [(set (f32 FPR32Op:$Rd),
6875           (OpNode (f32 FPR32Op:$Rn),
6876                   (f32 (vector_extract (v4f32 V128:$Rm),
6877                                        VectorIndexS:$idx))))]> {
6878     bits<2> idx;
6879     let Inst{11} = idx{1};
6880     let Inst{21} = idx{0};
6881   }
6882
6883   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6884                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6885                                       asm, ".d", "", "", ".d",
6886     [(set (f64 FPR64Op:$Rd),
6887           (OpNode (f64 FPR64Op:$Rn),
6888                   (f64 (vector_extract (v2f64 V128:$Rm),
6889                                        VectorIndexD:$idx))))]> {
6890     bits<1> idx;
6891     let Inst{11} = idx{0};
6892     let Inst{21} = 0;
6893   }
6894 }
6895
6896 multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
6897   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6898   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6899                            (AArch64duplane32 (v4f32 V128:$Rm),
6900                                            VectorIndexS:$idx))),
6901             (!cast<Instruction>(INST # v2i32_indexed)
6902                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6903   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6904                            (AArch64dup (f32 FPR32Op:$Rm)))),
6905             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6906                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6907
6908
6909   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6910   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6911                            (AArch64duplane32 (v4f32 V128:$Rm),
6912                                            VectorIndexS:$idx))),
6913             (!cast<Instruction>(INST # "v4i32_indexed")
6914                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6915   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6916                            (AArch64dup (f32 FPR32Op:$Rm)))),
6917             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6918                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6919
6920   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6921   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6922                            (AArch64duplane64 (v2f64 V128:$Rm),
6923                                            VectorIndexD:$idx))),
6924             (!cast<Instruction>(INST # "v2i64_indexed")
6925                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6926   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6927                            (AArch64dup (f64 FPR64Op:$Rm)))),
6928             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6929                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6930
6931   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6932   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6933                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6934             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6935                 V128:$Rm, VectorIndexS:$idx)>;
6936   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6937                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6938             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6939                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6940
6941   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6942   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6943                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6944             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6945                 V128:$Rm, VectorIndexD:$idx)>;
6946 }
6947
6948 multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
6949   let Predicates = [HasNEON, HasFullFP16] in {
6950   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
6951                                           V128_lo, VectorIndexH,
6952                                           asm, ".4h", ".4h", ".4h", ".h", []> {
6953     bits<3> idx;
6954     let Inst{11} = idx{2};
6955     let Inst{21} = idx{1};
6956     let Inst{20} = idx{0};
6957   }
6958
6959   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
6960                                           V128, V128,
6961                                           V128_lo, VectorIndexH,
6962                                           asm, ".8h", ".8h", ".8h", ".h", []> {
6963     bits<3> idx;
6964     let Inst{11} = idx{2};
6965     let Inst{21} = idx{1};
6966     let Inst{20} = idx{0};
6967   }
6968   } // Predicates = [HasNEON, HasFullFP16]
6969
6970   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6971                                           V128, VectorIndexS,
6972                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6973     bits<2> idx;
6974     let Inst{11} = idx{1};
6975     let Inst{21} = idx{0};
6976   }
6977
6978   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6979                                       V128, V128,
6980                                       V128, VectorIndexS,
6981                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6982     bits<2> idx;
6983     let Inst{11} = idx{1};
6984     let Inst{21} = idx{0};
6985   }
6986
6987   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6988                                       V128, V128,
6989                                       V128, VectorIndexD,
6990                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6991     bits<1> idx;
6992     let Inst{11} = idx{0};
6993     let Inst{21} = 0;
6994   }
6995
6996   let Predicates = [HasNEON, HasFullFP16] in {
6997   def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
6998                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6999                                       asm, ".h", "", "", ".h", []> {
7000     bits<3> idx;
7001     let Inst{11} = idx{2};
7002     let Inst{21} = idx{1};
7003     let Inst{20} = idx{0};
7004   }
7005   } // Predicates = [HasNEON, HasFullFP16]
7006
7007   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7008                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7009                                       asm, ".s", "", "", ".s", []> {
7010     bits<2> idx;
7011     let Inst{11} = idx{1};
7012     let Inst{21} = idx{0};
7013   }
7014
7015   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7016                                       FPR64Op, FPR64Op, V128, VectorIndexD,
7017                                       asm, ".d", "", "", ".d", []> {
7018     bits<1> idx;
7019     let Inst{11} = idx{0};
7020     let Inst{21} = 0;
7021   }
7022 }
7023
7024 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7025                          SDPatternOperator OpNode> {
7026   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7027                                       V128_lo, VectorIndexH,
7028                                       asm, ".4h", ".4h", ".4h", ".h",
7029     [(set (v4i16 V64:$Rd),
7030         (OpNode (v4i16 V64:$Rn),
7031          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7032     bits<3> idx;
7033     let Inst{11} = idx{2};
7034     let Inst{21} = idx{1};
7035     let Inst{20} = idx{0};
7036   }
7037
7038   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7039                                       V128, V128,
7040                                       V128_lo, VectorIndexH,
7041                                       asm, ".8h", ".8h", ".8h", ".h",
7042     [(set (v8i16 V128:$Rd),
7043        (OpNode (v8i16 V128:$Rn),
7044          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7045     bits<3> idx;
7046     let Inst{11} = idx{2};
7047     let Inst{21} = idx{1};
7048     let Inst{20} = idx{0};
7049   }
7050
7051   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7052                                       V64, V64,
7053                                       V128, VectorIndexS,
7054                                       asm, ".2s", ".2s", ".2s",  ".s",
7055     [(set (v2i32 V64:$Rd),
7056        (OpNode (v2i32 V64:$Rn),
7057           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7058     bits<2> idx;
7059     let Inst{11} = idx{1};
7060     let Inst{21} = idx{0};
7061   }
7062
7063   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7064                                       V128, V128,
7065                                       V128, VectorIndexS,
7066                                       asm, ".4s", ".4s", ".4s", ".s",
7067     [(set (v4i32 V128:$Rd),
7068        (OpNode (v4i32 V128:$Rn),
7069           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7070     bits<2> idx;
7071     let Inst{11} = idx{1};
7072     let Inst{21} = idx{0};
7073   }
7074
7075   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7076                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7077                                       asm, ".h", "", "", ".h", []> {
7078     bits<3> idx;
7079     let Inst{11} = idx{2};
7080     let Inst{21} = idx{1};
7081     let Inst{20} = idx{0};
7082   }
7083
7084   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7085                                       FPR32Op, FPR32Op, V128, VectorIndexS,
7086                                       asm, ".s", "", "", ".s",
7087       [(set (i32 FPR32Op:$Rd),
7088             (OpNode FPR32Op:$Rn,
7089                     (i32 (vector_extract (v4i32 V128:$Rm),
7090                                          VectorIndexS:$idx))))]> {
7091     bits<2> idx;
7092     let Inst{11} = idx{1};
7093     let Inst{21} = idx{0};
7094   }
7095 }
7096
7097 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7098                                SDPatternOperator OpNode> {
7099   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7100                                       V64, V64,
7101                                       V128_lo, VectorIndexH,
7102                                       asm, ".4h", ".4h", ".4h", ".h",
7103     [(set (v4i16 V64:$Rd),
7104         (OpNode (v4i16 V64:$Rn),
7105          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7106     bits<3> idx;
7107     let Inst{11} = idx{2};
7108     let Inst{21} = idx{1};
7109     let Inst{20} = idx{0};
7110   }
7111
7112   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7113                                       V128, V128,
7114                                       V128_lo, VectorIndexH,
7115                                       asm, ".8h", ".8h", ".8h", ".h",
7116     [(set (v8i16 V128:$Rd),
7117        (OpNode (v8i16 V128:$Rn),
7118          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7119     bits<3> idx;
7120     let Inst{11} = idx{2};
7121     let Inst{21} = idx{1};
7122     let Inst{20} = idx{0};
7123   }
7124
7125   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7126                                       V64, V64,
7127                                       V128, VectorIndexS,
7128                                       asm, ".2s", ".2s", ".2s", ".s",
7129     [(set (v2i32 V64:$Rd),
7130        (OpNode (v2i32 V64:$Rn),
7131           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7132     bits<2> idx;
7133     let Inst{11} = idx{1};
7134     let Inst{21} = idx{0};
7135   }
7136
7137   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7138                                       V128, V128,
7139                                       V128, VectorIndexS,
7140                                       asm, ".4s", ".4s", ".4s", ".s",
7141     [(set (v4i32 V128:$Rd),
7142        (OpNode (v4i32 V128:$Rn),
7143           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7144     bits<2> idx;
7145     let Inst{11} = idx{1};
7146     let Inst{21} = idx{0};
7147   }
7148 }
7149
7150 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7151                                    SDPatternOperator OpNode> {
7152   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7153                                           V128_lo, VectorIndexH,
7154                                           asm, ".4h", ".4h", ".4h", ".h",
7155     [(set (v4i16 V64:$dst),
7156         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7157          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7158     bits<3> idx;
7159     let Inst{11} = idx{2};
7160     let Inst{21} = idx{1};
7161     let Inst{20} = idx{0};
7162   }
7163
7164   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7165                                       V128, V128,
7166                                       V128_lo, VectorIndexH,
7167                                       asm, ".8h", ".8h", ".8h", ".h",
7168     [(set (v8i16 V128:$dst),
7169        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7170          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7171     bits<3> idx;
7172     let Inst{11} = idx{2};
7173     let Inst{21} = idx{1};
7174     let Inst{20} = idx{0};
7175   }
7176
7177   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7178                                       V64, V64,
7179                                       V128, VectorIndexS,
7180                                       asm, ".2s", ".2s", ".2s", ".s",
7181     [(set (v2i32 V64:$dst),
7182        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7183           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7184     bits<2> idx;
7185     let Inst{11} = idx{1};
7186     let Inst{21} = idx{0};
7187   }
7188
7189   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7190                                       V128, V128,
7191                                       V128, VectorIndexS,
7192                                       asm, ".4s", ".4s", ".4s", ".s",
7193     [(set (v4i32 V128:$dst),
7194        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7195           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7196     bits<2> idx;
7197     let Inst{11} = idx{1};
7198     let Inst{21} = idx{0};
7199   }
7200 }
7201
7202 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
7203                              SDPatternOperator OpNode> {
7204   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7205                                       V128, V64,
7206                                       V128_lo, VectorIndexH,
7207                                       asm, ".4s", ".4s", ".4h", ".h",
7208     [(set (v4i32 V128:$Rd),
7209         (OpNode (v4i16 V64:$Rn),
7210          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7211     bits<3> idx;
7212     let Inst{11} = idx{2};
7213     let Inst{21} = idx{1};
7214     let Inst{20} = idx{0};
7215   }
7216
7217   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7218                                       V128, V128,
7219                                       V128_lo, VectorIndexH,
7220                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7221     [(set (v4i32 V128:$Rd),
7222           (OpNode (extract_high_v8i16 V128:$Rn),
7223                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7224                                                       VectorIndexH:$idx))))]> {
7225
7226     bits<3> idx;
7227     let Inst{11} = idx{2};
7228     let Inst{21} = idx{1};
7229     let Inst{20} = idx{0};
7230   }
7231
7232   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7233                                       V128, V64,
7234                                       V128, VectorIndexS,
7235                                       asm, ".2d", ".2d", ".2s", ".s",
7236     [(set (v2i64 V128:$Rd),
7237         (OpNode (v2i32 V64:$Rn),
7238          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7239     bits<2> idx;
7240     let Inst{11} = idx{1};
7241     let Inst{21} = idx{0};
7242   }
7243
7244   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7245                                       V128, V128,
7246                                       V128, VectorIndexS,
7247                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7248     [(set (v2i64 V128:$Rd),
7249           (OpNode (extract_high_v4i32 V128:$Rn),
7250                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7251                                                       VectorIndexS:$idx))))]> {
7252     bits<2> idx;
7253     let Inst{11} = idx{1};
7254     let Inst{21} = idx{0};
7255   }
7256
7257   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7258                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7259                                       asm, ".h", "", "", ".h", []> {
7260     bits<3> idx;
7261     let Inst{11} = idx{2};
7262     let Inst{21} = idx{1};
7263     let Inst{20} = idx{0};
7264   }
7265
7266   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7267                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7268                                       asm, ".s", "", "", ".s", []> {
7269     bits<2> idx;
7270     let Inst{11} = idx{1};
7271     let Inst{21} = idx{0};
7272   }
7273 }
7274
7275 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
7276                                        SDPatternOperator Accum> {
7277   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7278                                       V128, V64,
7279                                       V128_lo, VectorIndexH,
7280                                       asm, ".4s", ".4s", ".4h", ".h",
7281     [(set (v4i32 V128:$dst),
7282           (Accum (v4i32 V128:$Rd),
7283                  (v4i32 (int_aarch64_neon_sqdmull
7284                              (v4i16 V64:$Rn),
7285                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7286                                                     VectorIndexH:$idx))))))]> {
7287     bits<3> idx;
7288     let Inst{11} = idx{2};
7289     let Inst{21} = idx{1};
7290     let Inst{20} = idx{0};
7291   }
7292
7293   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
7294   // intermediate EXTRACT_SUBREG would be untyped.
7295   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
7296                 (i32 (vector_extract (v4i32
7297                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7298                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7299                                                     VectorIndexH:$idx)))),
7300                          (i64 0))))),
7301             (EXTRACT_SUBREG
7302                 (!cast<Instruction>(NAME # v4i16_indexed)
7303                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
7304                     V128_lo:$Rm, VectorIndexH:$idx),
7305                 ssub)>;
7306
7307   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7308                                       V128, V128,
7309                                       V128_lo, VectorIndexH,
7310                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7311     [(set (v4i32 V128:$dst),
7312           (Accum (v4i32 V128:$Rd),
7313                  (v4i32 (int_aarch64_neon_sqdmull
7314                             (extract_high_v8i16 V128:$Rn),
7315                             (extract_high_v8i16
7316                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7317                                                 VectorIndexH:$idx))))))]> {
7318     bits<3> idx;
7319     let Inst{11} = idx{2};
7320     let Inst{21} = idx{1};
7321     let Inst{20} = idx{0};
7322   }
7323
7324   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7325                                       V128, V64,
7326                                       V128, VectorIndexS,
7327                                       asm, ".2d", ".2d", ".2s", ".s",
7328     [(set (v2i64 V128:$dst),
7329         (Accum (v2i64 V128:$Rd),
7330                (v2i64 (int_aarch64_neon_sqdmull
7331                           (v2i32 V64:$Rn),
7332                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
7333                                                  VectorIndexS:$idx))))))]> {
7334     bits<2> idx;
7335     let Inst{11} = idx{1};
7336     let Inst{21} = idx{0};
7337   }
7338
7339   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7340                                       V128, V128,
7341                                       V128, VectorIndexS,
7342                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7343     [(set (v2i64 V128:$dst),
7344           (Accum (v2i64 V128:$Rd),
7345                  (v2i64 (int_aarch64_neon_sqdmull
7346                             (extract_high_v4i32 V128:$Rn),
7347                             (extract_high_v4i32
7348                                 (AArch64duplane32 (v4i32 V128:$Rm),
7349                                                 VectorIndexS:$idx))))))]> {
7350     bits<2> idx;
7351     let Inst{11} = idx{1};
7352     let Inst{21} = idx{0};
7353   }
7354
7355   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
7356                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7357                                       asm, ".h", "", "", ".h", []> {
7358     bits<3> idx;
7359     let Inst{11} = idx{2};
7360     let Inst{21} = idx{1};
7361     let Inst{20} = idx{0};
7362   }
7363
7364
7365   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7366                                       FPR64Op, FPR32Op, V128, VectorIndexS,
7367                                       asm, ".s", "", "", ".s",
7368     [(set (i64 FPR64Op:$dst),
7369           (Accum (i64 FPR64Op:$Rd),
7370                  (i64 (int_aarch64_neon_sqdmulls_scalar
7371                             (i32 FPR32Op:$Rn),
7372                             (i32 (vector_extract (v4i32 V128:$Rm),
7373                                                  VectorIndexS:$idx))))))]> {
7374
7375     bits<2> idx;
7376     let Inst{11} = idx{1};
7377     let Inst{21} = idx{0};
7378   }
7379 }
7380
7381 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
7382                                    SDPatternOperator OpNode> {
7383   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7384   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7385                                       V128, V64,
7386                                       V128_lo, VectorIndexH,
7387                                       asm, ".4s", ".4s", ".4h", ".h",
7388     [(set (v4i32 V128:$Rd),
7389         (OpNode (v4i16 V64:$Rn),
7390          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7391     bits<3> idx;
7392     let Inst{11} = idx{2};
7393     let Inst{21} = idx{1};
7394     let Inst{20} = idx{0};
7395   }
7396
7397   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7398                                       V128, V128,
7399                                       V128_lo, VectorIndexH,
7400                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7401     [(set (v4i32 V128:$Rd),
7402           (OpNode (extract_high_v8i16 V128:$Rn),
7403                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7404                                                       VectorIndexH:$idx))))]> {
7405
7406     bits<3> idx;
7407     let Inst{11} = idx{2};
7408     let Inst{21} = idx{1};
7409     let Inst{20} = idx{0};
7410   }
7411
7412   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7413                                       V128, V64,
7414                                       V128, VectorIndexS,
7415                                       asm, ".2d", ".2d", ".2s", ".s",
7416     [(set (v2i64 V128:$Rd),
7417         (OpNode (v2i32 V64:$Rn),
7418          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7419     bits<2> idx;
7420     let Inst{11} = idx{1};
7421     let Inst{21} = idx{0};
7422   }
7423
7424   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7425                                       V128, V128,
7426                                       V128, VectorIndexS,
7427                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7428     [(set (v2i64 V128:$Rd),
7429           (OpNode (extract_high_v4i32 V128:$Rn),
7430                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7431                                                       VectorIndexS:$idx))))]> {
7432     bits<2> idx;
7433     let Inst{11} = idx{1};
7434     let Inst{21} = idx{0};
7435   }
7436   }
7437 }
7438
7439 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7440                                        SDPatternOperator OpNode> {
7441   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7442   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7443                                       V128, V64,
7444                                       V128_lo, VectorIndexH,
7445                                       asm, ".4s", ".4s", ".4h", ".h",
7446     [(set (v4i32 V128:$dst),
7447         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7448          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7449     bits<3> idx;
7450     let Inst{11} = idx{2};
7451     let Inst{21} = idx{1};
7452     let Inst{20} = idx{0};
7453   }
7454
7455   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7456                                       V128, V128,
7457                                       V128_lo, VectorIndexH,
7458                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7459     [(set (v4i32 V128:$dst),
7460           (OpNode (v4i32 V128:$Rd),
7461                   (extract_high_v8i16 V128:$Rn),
7462                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7463                                                       VectorIndexH:$idx))))]> {
7464     bits<3> idx;
7465     let Inst{11} = idx{2};
7466     let Inst{21} = idx{1};
7467     let Inst{20} = idx{0};
7468   }
7469
7470   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7471                                       V128, V64,
7472                                       V128, VectorIndexS,
7473                                       asm, ".2d", ".2d", ".2s", ".s",
7474     [(set (v2i64 V128:$dst),
7475         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7476          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7477     bits<2> idx;
7478     let Inst{11} = idx{1};
7479     let Inst{21} = idx{0};
7480   }
7481
7482   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7483                                       V128, V128,
7484                                       V128, VectorIndexS,
7485                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7486     [(set (v2i64 V128:$dst),
7487           (OpNode (v2i64 V128:$Rd),
7488                   (extract_high_v4i32 V128:$Rn),
7489                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7490                                                       VectorIndexS:$idx))))]> {
7491     bits<2> idx;
7492     let Inst{11} = idx{1};
7493     let Inst{21} = idx{0};
7494   }
7495   }
7496 }
7497
7498 //----------------------------------------------------------------------------
7499 // AdvSIMD scalar shift by immediate
7500 //----------------------------------------------------------------------------
7501
7502 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7503 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7504                      RegisterClass regtype1, RegisterClass regtype2,
7505                      Operand immtype, string asm, list<dag> pattern>
7506   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7507       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7508     Sched<[WriteV]> {
7509   bits<5> Rd;
7510   bits<5> Rn;
7511   bits<7> imm;
7512   let Inst{31-30} = 0b01;
7513   let Inst{29}    = U;
7514   let Inst{28-23} = 0b111110;
7515   let Inst{22-16} = fixed_imm;
7516   let Inst{15-11} = opc;
7517   let Inst{10}    = 1;
7518   let Inst{9-5} = Rn;
7519   let Inst{4-0} = Rd;
7520 }
7521
7522 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7523 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7524                      RegisterClass regtype1, RegisterClass regtype2,
7525                      Operand immtype, string asm, list<dag> pattern>
7526   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7527       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7528     Sched<[WriteV]> {
7529   bits<5> Rd;
7530   bits<5> Rn;
7531   bits<7> imm;
7532   let Inst{31-30} = 0b01;
7533   let Inst{29}    = U;
7534   let Inst{28-23} = 0b111110;
7535   let Inst{22-16} = fixed_imm;
7536   let Inst{15-11} = opc;
7537   let Inst{10}    = 1;
7538   let Inst{9-5} = Rn;
7539   let Inst{4-0} = Rd;
7540 }
7541
7542
7543 multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
7544   let Predicates = [HasNEON, HasFullFP16] in {
7545   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7546                               FPR16, FPR16, vecshiftR16, asm, []> {
7547     let Inst{19-16} = imm{3-0};
7548   }
7549   } // Predicates = [HasNEON, HasFullFP16]
7550   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7551                               FPR32, FPR32, vecshiftR32, asm, []> {
7552     let Inst{20-16} = imm{4-0};
7553   }
7554
7555   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7556                               FPR64, FPR64, vecshiftR64, asm, []> {
7557     let Inst{21-16} = imm{5-0};
7558   }
7559 }
7560
7561 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7562                              SDPatternOperator OpNode> {
7563   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7564                               FPR64, FPR64, vecshiftR64, asm,
7565   [(set (i64 FPR64:$Rd),
7566      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7567     let Inst{21-16} = imm{5-0};
7568   }
7569
7570   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7571             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7572 }
7573
7574 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7575                                  SDPatternOperator OpNode = null_frag> {
7576   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7577                               FPR64, FPR64, vecshiftR64, asm,
7578   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7579                                                    (i32 vecshiftR64:$imm)))]> {
7580     let Inst{21-16} = imm{5-0};
7581   }
7582
7583   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7584                            (i32 vecshiftR64:$imm))),
7585             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7586                                             vecshiftR64:$imm)>;
7587 }
7588
7589 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7590                              SDPatternOperator OpNode> {
7591   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7592                               FPR64, FPR64, vecshiftL64, asm,
7593     [(set (v1i64 FPR64:$Rd),
7594        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7595     let Inst{21-16} = imm{5-0};
7596   }
7597 }
7598
7599 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7600 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7601   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7602                               FPR64, FPR64, vecshiftL64, asm, []> {
7603     let Inst{21-16} = imm{5-0};
7604   }
7605 }
7606
7607 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7608 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7609                                SDPatternOperator OpNode = null_frag> {
7610   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7611                               FPR8, FPR16, vecshiftR8, asm, []> {
7612     let Inst{18-16} = imm{2-0};
7613   }
7614
7615   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7616                               FPR16, FPR32, vecshiftR16, asm, []> {
7617     let Inst{19-16} = imm{3-0};
7618   }
7619
7620   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7621                               FPR32, FPR64, vecshiftR32, asm,
7622     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7623     let Inst{20-16} = imm{4-0};
7624   }
7625 }
7626
7627 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7628                                 SDPatternOperator OpNode> {
7629   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7630                               FPR8, FPR8, vecshiftL8, asm, []> {
7631     let Inst{18-16} = imm{2-0};
7632   }
7633
7634   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7635                               FPR16, FPR16, vecshiftL16, asm, []> {
7636     let Inst{19-16} = imm{3-0};
7637   }
7638
7639   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7640                               FPR32, FPR32, vecshiftL32, asm,
7641     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7642     let Inst{20-16} = imm{4-0};
7643   }
7644
7645   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7646                               FPR64, FPR64, vecshiftL64, asm,
7647     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7648     let Inst{21-16} = imm{5-0};
7649   }
7650
7651   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7652             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7653 }
7654
7655 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7656   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7657                               FPR8, FPR8, vecshiftR8, asm, []> {
7658     let Inst{18-16} = imm{2-0};
7659   }
7660
7661   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7662                               FPR16, FPR16, vecshiftR16, asm, []> {
7663     let Inst{19-16} = imm{3-0};
7664   }
7665
7666   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7667                               FPR32, FPR32, vecshiftR32, asm, []> {
7668     let Inst{20-16} = imm{4-0};
7669   }
7670
7671   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7672                               FPR64, FPR64, vecshiftR64, asm, []> {
7673     let Inst{21-16} = imm{5-0};
7674   }
7675 }
7676
7677 //----------------------------------------------------------------------------
7678 // AdvSIMD vector x indexed element
7679 //----------------------------------------------------------------------------
7680
7681 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7682 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7683                      RegisterOperand dst_reg, RegisterOperand src_reg,
7684                      Operand immtype,
7685                      string asm, string dst_kind, string src_kind,
7686                      list<dag> pattern>
7687   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7688       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7689            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7690     Sched<[WriteV]> {
7691   bits<5> Rd;
7692   bits<5> Rn;
7693   let Inst{31}    = 0;
7694   let Inst{30}    = Q;
7695   let Inst{29}    = U;
7696   let Inst{28-23} = 0b011110;
7697   let Inst{22-16} = fixed_imm;
7698   let Inst{15-11} = opc;
7699   let Inst{10}    = 1;
7700   let Inst{9-5}   = Rn;
7701   let Inst{4-0}   = Rd;
7702 }
7703
7704 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7705 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7706                      RegisterOperand vectype1, RegisterOperand vectype2,
7707                      Operand immtype,
7708                      string asm, string dst_kind, string src_kind,
7709                      list<dag> pattern>
7710   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7711       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7712            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7713     Sched<[WriteV]> {
7714   bits<5> Rd;
7715   bits<5> Rn;
7716   let Inst{31}    = 0;
7717   let Inst{30}    = Q;
7718   let Inst{29}    = U;
7719   let Inst{28-23} = 0b011110;
7720   let Inst{22-16} = fixed_imm;
7721   let Inst{15-11} = opc;
7722   let Inst{10}    = 1;
7723   let Inst{9-5}   = Rn;
7724   let Inst{4-0}   = Rd;
7725 }
7726
7727 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7728                               Intrinsic OpNode> {
7729   let Predicates = [HasNEON, HasFullFP16] in {
7730   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7731                                   V64, V64, vecshiftR16,
7732                                   asm, ".4h", ".4h",
7733       [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
7734     bits<4> imm;
7735     let Inst{19-16} = imm;
7736   }
7737
7738   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7739                                   V128, V128, vecshiftR16,
7740                                   asm, ".8h", ".8h",
7741       [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
7742     bits<4> imm;
7743     let Inst{19-16} = imm;
7744   }
7745   } // Predicates = [HasNEON, HasFullFP16]
7746   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7747                                   V64, V64, vecshiftR32,
7748                                   asm, ".2s", ".2s",
7749       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$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 (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7758     bits<5> imm;
7759     let Inst{20-16} = imm;
7760   }
7761
7762   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7763                                   V128, V128, vecshiftR64,
7764                                   asm, ".2d", ".2d",
7765       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7766     bits<6> imm;
7767     let Inst{21-16} = imm;
7768   }
7769 }
7770
7771 multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
7772                                   Intrinsic OpNode> {
7773   let Predicates = [HasNEON, HasFullFP16] in {
7774   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7775                                   V64, V64, vecshiftR16,
7776                                   asm, ".4h", ".4h",
7777       [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
7778     bits<4> imm;
7779     let Inst{19-16} = imm;
7780   }
7781
7782   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7783                                   V128, V128, vecshiftR16,
7784                                   asm, ".8h", ".8h",
7785       [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
7786     bits<4> imm;
7787     let Inst{19-16} = imm;
7788   }
7789   } // Predicates = [HasNEON, HasFullFP16]
7790
7791   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7792                                   V64, V64, vecshiftR32,
7793                                   asm, ".2s", ".2s",
7794       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7795     bits<5> imm;
7796     let Inst{20-16} = imm;
7797   }
7798
7799   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7800                                   V128, V128, vecshiftR32,
7801                                   asm, ".4s", ".4s",
7802       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7803     bits<5> imm;
7804     let Inst{20-16} = imm;
7805   }
7806
7807   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7808                                   V128, V128, vecshiftR64,
7809                                   asm, ".2d", ".2d",
7810       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7811     bits<6> imm;
7812     let Inst{21-16} = imm;
7813   }
7814 }
7815
7816 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7817                                      SDPatternOperator OpNode> {
7818   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7819                                   V64, V128, vecshiftR16Narrow,
7820                                   asm, ".8b", ".8h",
7821       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7822     bits<3> imm;
7823     let Inst{18-16} = imm;
7824   }
7825
7826   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7827                                   V128, V128, vecshiftR16Narrow,
7828                                   asm#"2", ".16b", ".8h", []> {
7829     bits<3> imm;
7830     let Inst{18-16} = imm;
7831     let hasSideEffects = 0;
7832   }
7833
7834   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7835                                   V64, V128, vecshiftR32Narrow,
7836                                   asm, ".4h", ".4s",
7837       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7838     bits<4> imm;
7839     let Inst{19-16} = imm;
7840   }
7841
7842   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7843                                   V128, V128, vecshiftR32Narrow,
7844                                   asm#"2", ".8h", ".4s", []> {
7845     bits<4> imm;
7846     let Inst{19-16} = imm;
7847     let hasSideEffects = 0;
7848   }
7849
7850   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7851                                   V64, V128, vecshiftR64Narrow,
7852                                   asm, ".2s", ".2d",
7853       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7854     bits<5> imm;
7855     let Inst{20-16} = imm;
7856   }
7857
7858   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7859                                   V128, V128, vecshiftR64Narrow,
7860                                   asm#"2", ".4s", ".2d", []> {
7861     bits<5> imm;
7862     let Inst{20-16} = imm;
7863     let hasSideEffects = 0;
7864   }
7865
7866   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7867   // themselves, so put them here instead.
7868
7869   // Patterns involving what's effectively an insert high and a normal
7870   // intrinsic, represented by CONCAT_VECTORS.
7871   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7872                                                    vecshiftR16Narrow:$imm)),
7873             (!cast<Instruction>(NAME # "v16i8_shift")
7874                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7875                 V128:$Rn, vecshiftR16Narrow:$imm)>;
7876   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7877                                                      vecshiftR32Narrow:$imm)),
7878             (!cast<Instruction>(NAME # "v8i16_shift")
7879                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7880                 V128:$Rn, vecshiftR32Narrow:$imm)>;
7881   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7882                                                      vecshiftR64Narrow:$imm)),
7883             (!cast<Instruction>(NAME # "v4i32_shift")
7884                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7885                 V128:$Rn, vecshiftR64Narrow:$imm)>;
7886 }
7887
7888 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7889                                 SDPatternOperator OpNode> {
7890   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7891                                   V64, V64, vecshiftL8,
7892                                   asm, ".8b", ".8b",
7893                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7894                        (i32 vecshiftL8:$imm)))]> {
7895     bits<3> imm;
7896     let Inst{18-16} = imm;
7897   }
7898
7899   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7900                                   V128, V128, vecshiftL8,
7901                                   asm, ".16b", ".16b",
7902              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7903                    (i32 vecshiftL8:$imm)))]> {
7904     bits<3> imm;
7905     let Inst{18-16} = imm;
7906   }
7907
7908   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7909                                   V64, V64, vecshiftL16,
7910                                   asm, ".4h", ".4h",
7911               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7912                     (i32 vecshiftL16:$imm)))]> {
7913     bits<4> imm;
7914     let Inst{19-16} = imm;
7915   }
7916
7917   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7918                                   V128, V128, vecshiftL16,
7919                                   asm, ".8h", ".8h",
7920             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7921                   (i32 vecshiftL16:$imm)))]> {
7922     bits<4> imm;
7923     let Inst{19-16} = imm;
7924   }
7925
7926   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7927                                   V64, V64, vecshiftL32,
7928                                   asm, ".2s", ".2s",
7929               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7930                     (i32 vecshiftL32:$imm)))]> {
7931     bits<5> imm;
7932     let Inst{20-16} = imm;
7933   }
7934
7935   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7936                                   V128, V128, vecshiftL32,
7937                                   asm, ".4s", ".4s",
7938             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7939                   (i32 vecshiftL32:$imm)))]> {
7940     bits<5> imm;
7941     let Inst{20-16} = imm;
7942   }
7943
7944   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7945                                   V128, V128, vecshiftL64,
7946                                   asm, ".2d", ".2d",
7947             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7948                   (i32 vecshiftL64:$imm)))]> {
7949     bits<6> imm;
7950     let Inst{21-16} = imm;
7951   }
7952 }
7953
7954 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7955                                 SDPatternOperator OpNode> {
7956   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7957                                   V64, V64, vecshiftR8,
7958                                   asm, ".8b", ".8b",
7959                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7960                        (i32 vecshiftR8:$imm)))]> {
7961     bits<3> imm;
7962     let Inst{18-16} = imm;
7963   }
7964
7965   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7966                                   V128, V128, vecshiftR8,
7967                                   asm, ".16b", ".16b",
7968              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7969                    (i32 vecshiftR8:$imm)))]> {
7970     bits<3> imm;
7971     let Inst{18-16} = imm;
7972   }
7973
7974   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7975                                   V64, V64, vecshiftR16,
7976                                   asm, ".4h", ".4h",
7977               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7978                     (i32 vecshiftR16:$imm)))]> {
7979     bits<4> imm;
7980     let Inst{19-16} = imm;
7981   }
7982
7983   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7984                                   V128, V128, vecshiftR16,
7985                                   asm, ".8h", ".8h",
7986             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7987                   (i32 vecshiftR16:$imm)))]> {
7988     bits<4> imm;
7989     let Inst{19-16} = imm;
7990   }
7991
7992   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7993                                   V64, V64, vecshiftR32,
7994                                   asm, ".2s", ".2s",
7995               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7996                     (i32 vecshiftR32:$imm)))]> {
7997     bits<5> imm;
7998     let Inst{20-16} = imm;
7999   }
8000
8001   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8002                                   V128, V128, vecshiftR32,
8003                                   asm, ".4s", ".4s",
8004             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8005                   (i32 vecshiftR32:$imm)))]> {
8006     bits<5> imm;
8007     let Inst{20-16} = imm;
8008   }
8009
8010   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8011                                   V128, V128, vecshiftR64,
8012                                   asm, ".2d", ".2d",
8013             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8014                   (i32 vecshiftR64:$imm)))]> {
8015     bits<6> imm;
8016     let Inst{21-16} = imm;
8017   }
8018 }
8019
8020 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8021 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8022                                     SDPatternOperator OpNode = null_frag> {
8023   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8024                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
8025                  [(set (v8i8 V64:$dst),
8026                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8027                            (i32 vecshiftR8:$imm)))]> {
8028     bits<3> imm;
8029     let Inst{18-16} = imm;
8030   }
8031
8032   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8033                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
8034              [(set (v16i8 V128:$dst),
8035                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8036                        (i32 vecshiftR8:$imm)))]> {
8037     bits<3> imm;
8038     let Inst{18-16} = imm;
8039   }
8040
8041   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8042                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
8043               [(set (v4i16 V64:$dst),
8044                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8045                         (i32 vecshiftR16:$imm)))]> {
8046     bits<4> imm;
8047     let Inst{19-16} = imm;
8048   }
8049
8050   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8051                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
8052             [(set (v8i16 V128:$dst),
8053               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8054                       (i32 vecshiftR16:$imm)))]> {
8055     bits<4> imm;
8056     let Inst{19-16} = imm;
8057   }
8058
8059   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8060                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
8061               [(set (v2i32 V64:$dst),
8062                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8063                         (i32 vecshiftR32:$imm)))]> {
8064     bits<5> imm;
8065     let Inst{20-16} = imm;
8066   }
8067
8068   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8069                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
8070             [(set (v4i32 V128:$dst),
8071               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8072                       (i32 vecshiftR32:$imm)))]> {
8073     bits<5> imm;
8074     let Inst{20-16} = imm;
8075   }
8076
8077   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8078                                   V128, V128, vecshiftR64,
8079                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8080               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8081                       (i32 vecshiftR64:$imm)))]> {
8082     bits<6> imm;
8083     let Inst{21-16} = imm;
8084   }
8085 }
8086
8087 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8088                                     SDPatternOperator OpNode = null_frag> {
8089   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8090                                   V64, V64, vecshiftL8,
8091                                   asm, ".8b", ".8b",
8092                     [(set (v8i8 V64:$dst),
8093                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8094                                   (i32 vecshiftL8:$imm)))]> {
8095     bits<3> imm;
8096     let Inst{18-16} = imm;
8097   }
8098
8099   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8100                                   V128, V128, vecshiftL8,
8101                                   asm, ".16b", ".16b",
8102                     [(set (v16i8 V128:$dst),
8103                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8104                                   (i32 vecshiftL8:$imm)))]> {
8105     bits<3> imm;
8106     let Inst{18-16} = imm;
8107   }
8108
8109   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8110                                   V64, V64, vecshiftL16,
8111                                   asm, ".4h", ".4h",
8112                     [(set (v4i16 V64:$dst),
8113                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8114                                    (i32 vecshiftL16:$imm)))]> {
8115     bits<4> imm;
8116     let Inst{19-16} = imm;
8117   }
8118
8119   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8120                                   V128, V128, vecshiftL16,
8121                                   asm, ".8h", ".8h",
8122                     [(set (v8i16 V128:$dst),
8123                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8124                                   (i32 vecshiftL16:$imm)))]> {
8125     bits<4> imm;
8126     let Inst{19-16} = imm;
8127   }
8128
8129   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8130                                   V64, V64, vecshiftL32,
8131                                   asm, ".2s", ".2s",
8132                     [(set (v2i32 V64:$dst),
8133                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8134                                   (i32 vecshiftL32:$imm)))]> {
8135     bits<5> imm;
8136     let Inst{20-16} = imm;
8137   }
8138
8139   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8140                                   V128, V128, vecshiftL32,
8141                                   asm, ".4s", ".4s",
8142                     [(set (v4i32 V128:$dst),
8143                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8144                                   (i32 vecshiftL32:$imm)))]> {
8145     bits<5> imm;
8146     let Inst{20-16} = imm;
8147   }
8148
8149   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8150                                   V128, V128, vecshiftL64,
8151                                   asm, ".2d", ".2d",
8152                     [(set (v2i64 V128:$dst),
8153                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8154                                   (i32 vecshiftL64:$imm)))]> {
8155     bits<6> imm;
8156     let Inst{21-16} = imm;
8157   }
8158 }
8159
8160 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8161                                    SDPatternOperator OpNode> {
8162   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8163                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
8164       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8165     bits<3> imm;
8166     let Inst{18-16} = imm;
8167   }
8168
8169   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8170                                   V128, V128, vecshiftL8,
8171                                   asm#"2", ".8h", ".16b",
8172       [(set (v8i16 V128:$Rd),
8173             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8174     bits<3> imm;
8175     let Inst{18-16} = imm;
8176   }
8177
8178   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8179                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
8180       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8181     bits<4> imm;
8182     let Inst{19-16} = imm;
8183   }
8184
8185   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8186                                   V128, V128, vecshiftL16,
8187                                   asm#"2", ".4s", ".8h",
8188       [(set (v4i32 V128:$Rd),
8189             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8190
8191     bits<4> imm;
8192     let Inst{19-16} = imm;
8193   }
8194
8195   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8196                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
8197       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8198     bits<5> imm;
8199     let Inst{20-16} = imm;
8200   }
8201
8202   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8203                                   V128, V128, vecshiftL32,
8204                                   asm#"2", ".2d", ".4s",
8205       [(set (v2i64 V128:$Rd),
8206             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
8207     bits<5> imm;
8208     let Inst{20-16} = imm;
8209   }
8210 }
8211
8212
8213 //---
8214 // Vector load/store
8215 //---
8216 // SIMD ldX/stX no-index memory references don't allow the optional
8217 // ", #0" constant and handle post-indexing explicitly, so we use
8218 // a more specialized parse method for them. Otherwise, it's the same as
8219 // the general GPR64sp handling.
8220
8221 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
8222                    string asm, dag oops, dag iops, list<dag> pattern>
8223   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
8224   bits<5> Vt;
8225   bits<5> Rn;
8226   let Inst{31} = 0;
8227   let Inst{30} = Q;
8228   let Inst{29-23} = 0b0011000;
8229   let Inst{22} = L;
8230   let Inst{21-16} = 0b000000;
8231   let Inst{15-12} = opcode;
8232   let Inst{11-10} = size;
8233   let Inst{9-5} = Rn;
8234   let Inst{4-0} = Vt;
8235 }
8236
8237 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
8238                        string asm, dag oops, dag iops>
8239   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
8240   bits<5> Vt;
8241   bits<5> Rn;
8242   bits<5> Xm;
8243   let Inst{31} = 0;
8244   let Inst{30} = Q;
8245   let Inst{29-23} = 0b0011001;
8246   let Inst{22} = L;
8247   let Inst{21} = 0;
8248   let Inst{20-16} = Xm;
8249   let Inst{15-12} = opcode;
8250   let Inst{11-10} = size;
8251   let Inst{9-5} = Rn;
8252   let Inst{4-0} = Vt;
8253 }
8254
8255 // The immediate form of AdvSIMD post-indexed addressing is encoded with
8256 // register post-index addressing from the zero register.
8257 multiclass SIMDLdStAliases<string asm, string layout, string Count,
8258                            int Offset, int Size> {
8259   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8260   //      "ld1\t$Vt, [$Rn], #16"
8261   // may get mapped to
8262   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8263   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8264                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8265                       GPR64sp:$Rn,
8266                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8267                       XZR), 1>;
8268
8269   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8270   //      "ld1.8b\t$Vt, [$Rn], #16"
8271   // may get mapped to
8272   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8273   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8274                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8275                       GPR64sp:$Rn,
8276                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8277                       XZR), 0>;
8278
8279   // E.g. "ld1.8b { v0, v1 }, [x1]"
8280   //      "ld1\t$Vt, [$Rn]"
8281   // may get mapped to
8282   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
8283   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8284                   (!cast<Instruction>(NAME # Count # "v" # layout)
8285                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8286                       GPR64sp:$Rn), 0>;
8287
8288   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
8289   //      "ld1\t$Vt, [$Rn], $Xm"
8290   // may get mapped to
8291   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
8292   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8293                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8294                       GPR64sp:$Rn,
8295                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8296                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8297 }
8298
8299 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
8300                        int Offset64, bits<4> opcode> {
8301   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8302     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
8303                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
8304                            (ins GPR64sp:$Rn), []>;
8305     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
8306                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
8307                            (ins GPR64sp:$Rn), []>;
8308     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
8309                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
8310                            (ins GPR64sp:$Rn), []>;
8311     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
8312                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
8313                            (ins GPR64sp:$Rn), []>;
8314     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
8315                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
8316                            (ins GPR64sp:$Rn), []>;
8317     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
8318                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
8319                            (ins GPR64sp:$Rn), []>;
8320     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
8321                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
8322                            (ins GPR64sp:$Rn), []>;
8323
8324
8325     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
8326                        (outs GPR64sp:$wback,
8327                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
8328                        (ins GPR64sp:$Rn,
8329                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8330     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
8331                        (outs GPR64sp:$wback,
8332                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
8333                        (ins GPR64sp:$Rn,
8334                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8335     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
8336                        (outs GPR64sp:$wback,
8337                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
8338                        (ins GPR64sp:$Rn,
8339                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8340     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
8341                        (outs GPR64sp:$wback,
8342                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
8343                        (ins GPR64sp:$Rn,
8344                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8345     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
8346                        (outs GPR64sp:$wback,
8347                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
8348                        (ins GPR64sp:$Rn,
8349                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8350     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
8351                        (outs GPR64sp:$wback,
8352                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
8353                        (ins GPR64sp:$Rn,
8354                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8355     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
8356                        (outs GPR64sp:$wback,
8357                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
8358                        (ins GPR64sp:$Rn,
8359                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8360   }
8361
8362   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8363   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8364   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8365   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8366   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8367   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8368   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8369 }
8370
8371 // Only ld1/st1 has a v1d version.
8372 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
8373                        int Offset64, bits<4> opcode> {
8374   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
8375     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
8376                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8377                                  GPR64sp:$Rn), []>;
8378     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
8379                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8380                                 GPR64sp:$Rn), []>;
8381     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
8382                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8383                                 GPR64sp:$Rn), []>;
8384     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
8385                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8386                                 GPR64sp:$Rn), []>;
8387     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
8388                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8389                                 GPR64sp:$Rn), []>;
8390     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
8391                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8392                                 GPR64sp:$Rn), []>;
8393     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
8394                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8395                                 GPR64sp:$Rn), []>;
8396
8397     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
8398                        (outs GPR64sp:$wback),
8399                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8400                             GPR64sp:$Rn,
8401                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8402     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
8403                        (outs GPR64sp:$wback),
8404                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8405                             GPR64sp:$Rn,
8406                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8407     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
8408                        (outs GPR64sp:$wback),
8409                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8410                             GPR64sp:$Rn,
8411                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8412     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
8413                        (outs GPR64sp:$wback),
8414                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8415                             GPR64sp:$Rn,
8416                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8417     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
8418                        (outs GPR64sp:$wback),
8419                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8420                             GPR64sp:$Rn,
8421                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8422     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
8423                        (outs GPR64sp:$wback),
8424                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8425                             GPR64sp:$Rn,
8426                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8427     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
8428                        (outs GPR64sp:$wback),
8429                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8430                             GPR64sp:$Rn,
8431                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8432   }
8433
8434   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8435   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8436   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8437   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8438   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8439   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8440   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8441 }
8442
8443 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
8444                        int Offset128, int Offset64, bits<4> opcode>
8445   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
8446
8447   // LD1 instructions have extra "1d" variants.
8448   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8449     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8450                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8451                            (ins GPR64sp:$Rn), []>;
8452
8453     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8454                        (outs GPR64sp:$wback,
8455                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
8456                        (ins GPR64sp:$Rn,
8457                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8458   }
8459
8460   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8461 }
8462
8463 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
8464                        int Offset128, int Offset64, bits<4> opcode>
8465   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
8466
8467   // ST1 instructions have extra "1d" variants.
8468   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8469     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8470                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8471                                 GPR64sp:$Rn), []>;
8472
8473     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8474                        (outs GPR64sp:$wback),
8475                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8476                             GPR64sp:$Rn,
8477                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8478   }
8479
8480   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8481 }
8482
8483 multiclass SIMDLd1Multiple<string asm> {
8484   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8485   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8486   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8487   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8488 }
8489
8490 multiclass SIMDSt1Multiple<string asm> {
8491   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8492   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8493   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8494   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8495 }
8496
8497 multiclass SIMDLd2Multiple<string asm> {
8498   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8499 }
8500
8501 multiclass SIMDSt2Multiple<string asm> {
8502   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8503 }
8504
8505 multiclass SIMDLd3Multiple<string asm> {
8506   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8507 }
8508
8509 multiclass SIMDSt3Multiple<string asm> {
8510   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8511 }
8512
8513 multiclass SIMDLd4Multiple<string asm> {
8514   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8515 }
8516
8517 multiclass SIMDSt4Multiple<string asm> {
8518   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8519 }
8520
8521 //---
8522 // AdvSIMD Load/store single-element
8523 //---
8524
8525 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8526                          string asm, string operands, string cst,
8527                          dag oops, dag iops, list<dag> pattern>
8528   : I<oops, iops, asm, operands, cst, pattern> {
8529   bits<5> Vt;
8530   bits<5> Rn;
8531   let Inst{31} = 0;
8532   let Inst{29-24} = 0b001101;
8533   let Inst{22} = L;
8534   let Inst{21} = R;
8535   let Inst{15-13} = opcode;
8536   let Inst{9-5} = Rn;
8537   let Inst{4-0} = Vt;
8538 }
8539
8540 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8541                          string asm, string operands, string cst,
8542                          dag oops, dag iops, list<dag> pattern>
8543   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8544   bits<5> Vt;
8545   bits<5> Rn;
8546   let Inst{31} = 0;
8547   let Inst{29-24} = 0b001101;
8548   let Inst{22} = L;
8549   let Inst{21} = R;
8550   let Inst{15-13} = opcode;
8551   let Inst{9-5} = Rn;
8552   let Inst{4-0} = Vt;
8553 }
8554
8555
8556 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8557 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8558                   Operand listtype>
8559   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8560                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
8561                        []> {
8562   let Inst{30} = Q;
8563   let Inst{23} = 0;
8564   let Inst{20-16} = 0b00000;
8565   let Inst{12} = S;
8566   let Inst{11-10} = size;
8567 }
8568 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8569 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8570                       string asm, Operand listtype, Operand GPR64pi>
8571   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8572                        "$Rn = $wback",
8573                        (outs GPR64sp:$wback, listtype:$Vt),
8574                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8575   bits<5> Xm;
8576   let Inst{30} = Q;
8577   let Inst{23} = 1;
8578   let Inst{20-16} = Xm;
8579   let Inst{12} = S;
8580   let Inst{11-10} = size;
8581 }
8582
8583 multiclass SIMDLdrAliases<string asm, string layout, string Count,
8584                           int Offset, int Size> {
8585   // E.g. "ld1r { v0.8b }, [x1], #1"
8586   //      "ld1r.8b\t$Vt, [$Rn], #1"
8587   // may get mapped to
8588   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8589   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8590                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8591                       GPR64sp:$Rn,
8592                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8593                       XZR), 1>;
8594
8595   // E.g. "ld1r.8b { v0 }, [x1], #1"
8596   //      "ld1r.8b\t$Vt, [$Rn], #1"
8597   // may get mapped to
8598   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8599   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8600                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8601                       GPR64sp:$Rn,
8602                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8603                       XZR), 0>;
8604
8605   // E.g. "ld1r.8b { v0 }, [x1]"
8606   //      "ld1r.8b\t$Vt, [$Rn]"
8607   // may get mapped to
8608   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8609   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8610                   (!cast<Instruction>(NAME # "v" # layout)
8611                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8612                       GPR64sp:$Rn), 0>;
8613
8614   // E.g. "ld1r.8b { v0 }, [x1], x2"
8615   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
8616   // may get mapped to
8617   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8618   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8619                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8620                       GPR64sp:$Rn,
8621                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8622                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8623 }
8624
8625 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8626   int Offset1, int Offset2, int Offset4, int Offset8> {
8627   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8628                         !cast<Operand>("VecList" # Count # "8b")>;
8629   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8630                         !cast<Operand>("VecList" # Count #"16b")>;
8631   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8632                         !cast<Operand>("VecList" # Count #"4h")>;
8633   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8634                         !cast<Operand>("VecList" # Count #"8h")>;
8635   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8636                         !cast<Operand>("VecList" # Count #"2s")>;
8637   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8638                         !cast<Operand>("VecList" # Count #"4s")>;
8639   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8640                         !cast<Operand>("VecList" # Count #"1d")>;
8641   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8642                         !cast<Operand>("VecList" # Count #"2d")>;
8643
8644   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8645                                  !cast<Operand>("VecList" # Count # "8b"),
8646                                  !cast<Operand>("GPR64pi" # Offset1)>;
8647   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8648                                  !cast<Operand>("VecList" # Count # "16b"),
8649                                  !cast<Operand>("GPR64pi" # Offset1)>;
8650   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8651                                  !cast<Operand>("VecList" # Count # "4h"),
8652                                  !cast<Operand>("GPR64pi" # Offset2)>;
8653   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8654                                  !cast<Operand>("VecList" # Count # "8h"),
8655                                  !cast<Operand>("GPR64pi" # Offset2)>;
8656   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8657                                  !cast<Operand>("VecList" # Count # "2s"),
8658                                  !cast<Operand>("GPR64pi" # Offset4)>;
8659   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8660                                  !cast<Operand>("VecList" # Count # "4s"),
8661                                  !cast<Operand>("GPR64pi" # Offset4)>;
8662   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8663                                  !cast<Operand>("VecList" # Count # "1d"),
8664                                  !cast<Operand>("GPR64pi" # Offset8)>;
8665   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8666                                  !cast<Operand>("VecList" # Count # "2d"),
8667                                  !cast<Operand>("GPR64pi" # Offset8)>;
8668
8669   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
8670   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8671   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
8672   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
8673   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
8674   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
8675   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
8676   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
8677 }
8678
8679 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8680                       dag oops, dag iops, list<dag> pattern>
8681   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8682                        pattern> {
8683   // idx encoded in Q:S:size fields.
8684   bits<4> idx;
8685   let Inst{30} = idx{3};
8686   let Inst{23} = 0;
8687   let Inst{20-16} = 0b00000;
8688   let Inst{12} = idx{2};
8689   let Inst{11-10} = idx{1-0};
8690 }
8691 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8692                       dag oops, dag iops, list<dag> pattern>
8693   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8694                            oops, iops, pattern> {
8695   // idx encoded in Q:S:size fields.
8696   bits<4> idx;
8697   let Inst{30} = idx{3};
8698   let Inst{23} = 0;
8699   let Inst{20-16} = 0b00000;
8700   let Inst{12} = idx{2};
8701   let Inst{11-10} = idx{1-0};
8702 }
8703 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8704                           dag oops, dag iops>
8705   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8706                        "$Rn = $wback", oops, iops, []> {
8707   // idx encoded in Q:S:size fields.
8708   bits<4> idx;
8709   bits<5> Xm;
8710   let Inst{30} = idx{3};
8711   let Inst{23} = 1;
8712   let Inst{20-16} = Xm;
8713   let Inst{12} = idx{2};
8714   let Inst{11-10} = idx{1-0};
8715 }
8716 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8717                           dag oops, dag iops>
8718   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8719                            "$Rn = $wback", oops, iops, []> {
8720   // idx encoded in Q:S:size fields.
8721   bits<4> idx;
8722   bits<5> Xm;
8723   let Inst{30} = idx{3};
8724   let Inst{23} = 1;
8725   let Inst{20-16} = Xm;
8726   let Inst{12} = idx{2};
8727   let Inst{11-10} = idx{1-0};
8728 }
8729
8730 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8731                       dag oops, dag iops, list<dag> pattern>
8732   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8733                        pattern> {
8734   // idx encoded in Q:S:size<1> fields.
8735   bits<3> idx;
8736   let Inst{30} = idx{2};
8737   let Inst{23} = 0;
8738   let Inst{20-16} = 0b00000;
8739   let Inst{12} = idx{1};
8740   let Inst{11} = idx{0};
8741   let Inst{10} = size;
8742 }
8743 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8744                       dag oops, dag iops, list<dag> pattern>
8745   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8746                            oops, iops, pattern> {
8747   // idx encoded in Q:S:size<1> fields.
8748   bits<3> idx;
8749   let Inst{30} = idx{2};
8750   let Inst{23} = 0;
8751   let Inst{20-16} = 0b00000;
8752   let Inst{12} = idx{1};
8753   let Inst{11} = idx{0};
8754   let Inst{10} = size;
8755 }
8756
8757 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8758                           dag oops, dag iops>
8759   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8760                        "$Rn = $wback", oops, iops, []> {
8761   // idx encoded in Q:S:size<1> fields.
8762   bits<3> idx;
8763   bits<5> Xm;
8764   let Inst{30} = idx{2};
8765   let Inst{23} = 1;
8766   let Inst{20-16} = Xm;
8767   let Inst{12} = idx{1};
8768   let Inst{11} = idx{0};
8769   let Inst{10} = size;
8770 }
8771 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8772                           dag oops, dag iops>
8773   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8774                            "$Rn = $wback", oops, iops, []> {
8775   // idx encoded in Q:S:size<1> fields.
8776   bits<3> idx;
8777   bits<5> Xm;
8778   let Inst{30} = idx{2};
8779   let Inst{23} = 1;
8780   let Inst{20-16} = Xm;
8781   let Inst{12} = idx{1};
8782   let Inst{11} = idx{0};
8783   let Inst{10} = size;
8784 }
8785 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8786                       dag oops, dag iops, list<dag> pattern>
8787   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8788                        pattern> {
8789   // idx encoded in Q:S fields.
8790   bits<2> idx;
8791   let Inst{30} = idx{1};
8792   let Inst{23} = 0;
8793   let Inst{20-16} = 0b00000;
8794   let Inst{12} = idx{0};
8795   let Inst{11-10} = size;
8796 }
8797 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8798                       dag oops, dag iops, list<dag> pattern>
8799   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8800                            oops, iops, pattern> {
8801   // idx encoded in Q:S fields.
8802   bits<2> idx;
8803   let Inst{30} = idx{1};
8804   let Inst{23} = 0;
8805   let Inst{20-16} = 0b00000;
8806   let Inst{12} = idx{0};
8807   let Inst{11-10} = size;
8808 }
8809 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8810                           string asm, dag oops, dag iops>
8811   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8812                        "$Rn = $wback", oops, iops, []> {
8813   // idx encoded in Q:S fields.
8814   bits<2> idx;
8815   bits<5> Xm;
8816   let Inst{30} = idx{1};
8817   let Inst{23} = 1;
8818   let Inst{20-16} = Xm;
8819   let Inst{12} = idx{0};
8820   let Inst{11-10} = size;
8821 }
8822 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8823                           string asm, dag oops, dag iops>
8824   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8825                            "$Rn = $wback", oops, iops, []> {
8826   // idx encoded in Q:S fields.
8827   bits<2> idx;
8828   bits<5> Xm;
8829   let Inst{30} = idx{1};
8830   let Inst{23} = 1;
8831   let Inst{20-16} = Xm;
8832   let Inst{12} = idx{0};
8833   let Inst{11-10} = size;
8834 }
8835 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8836                       dag oops, dag iops, list<dag> pattern>
8837   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8838                        pattern> {
8839   // idx encoded in Q field.
8840   bits<1> idx;
8841   let Inst{30} = idx;
8842   let Inst{23} = 0;
8843   let Inst{20-16} = 0b00000;
8844   let Inst{12} = 0;
8845   let Inst{11-10} = size;
8846 }
8847 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8848                       dag oops, dag iops, list<dag> pattern>
8849   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8850                            oops, iops, pattern> {
8851   // idx encoded in Q field.
8852   bits<1> idx;
8853   let Inst{30} = idx;
8854   let Inst{23} = 0;
8855   let Inst{20-16} = 0b00000;
8856   let Inst{12} = 0;
8857   let Inst{11-10} = size;
8858 }
8859 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8860                           string asm, dag oops, dag iops>
8861   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8862                        "$Rn = $wback", oops, iops, []> {
8863   // idx encoded in Q field.
8864   bits<1> idx;
8865   bits<5> Xm;
8866   let Inst{30} = idx;
8867   let Inst{23} = 1;
8868   let Inst{20-16} = Xm;
8869   let Inst{12} = 0;
8870   let Inst{11-10} = size;
8871 }
8872 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8873                           string asm, dag oops, dag iops>
8874   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8875                            "$Rn = $wback", oops, iops, []> {
8876   // idx encoded in Q field.
8877   bits<1> idx;
8878   bits<5> Xm;
8879   let Inst{30} = idx;
8880   let Inst{23} = 1;
8881   let Inst{20-16} = Xm;
8882   let Inst{12} = 0;
8883   let Inst{11-10} = size;
8884 }
8885
8886 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8887 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8888                          RegisterOperand listtype,
8889                          RegisterOperand GPR64pi> {
8890   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8891                            (outs listtype:$dst),
8892                            (ins listtype:$Vt, VectorIndexB:$idx,
8893                                 GPR64sp:$Rn), []>;
8894
8895   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8896                             (outs GPR64sp:$wback, listtype:$dst),
8897                             (ins listtype:$Vt, VectorIndexB:$idx,
8898                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8899 }
8900 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8901 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8902                          RegisterOperand listtype,
8903                          RegisterOperand GPR64pi> {
8904   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8905                             (outs listtype:$dst),
8906                             (ins listtype:$Vt, VectorIndexH:$idx,
8907                                  GPR64sp:$Rn), []>;
8908
8909   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8910                             (outs GPR64sp:$wback, listtype:$dst),
8911                             (ins listtype:$Vt, VectorIndexH:$idx,
8912                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8913 }
8914 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8915 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8916                          RegisterOperand listtype,
8917                          RegisterOperand GPR64pi> {
8918   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8919                             (outs listtype:$dst),
8920                             (ins listtype:$Vt, VectorIndexS:$idx,
8921                                  GPR64sp:$Rn), []>;
8922
8923   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8924                             (outs GPR64sp:$wback, listtype:$dst),
8925                             (ins listtype:$Vt, VectorIndexS:$idx,
8926                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8927 }
8928 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8929 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8930                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8931   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8932                             (outs listtype:$dst),
8933                             (ins listtype:$Vt, VectorIndexD:$idx,
8934                                  GPR64sp:$Rn), []>;
8935
8936   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8937                             (outs GPR64sp:$wback, listtype:$dst),
8938                             (ins listtype:$Vt, VectorIndexD:$idx,
8939                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8940 }
8941 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8942 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8943                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8944   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8945                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8946                                         GPR64sp:$Rn), []>;
8947
8948   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8949                                     (outs GPR64sp:$wback),
8950                                     (ins listtype:$Vt, VectorIndexB:$idx,
8951                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
8952 }
8953 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8954 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8955                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8956   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8957                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8958                                          GPR64sp:$Rn), []>;
8959
8960   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8961                             (outs GPR64sp:$wback),
8962                             (ins listtype:$Vt, VectorIndexH:$idx,
8963                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8964 }
8965 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8966 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8967                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8968   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8969                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8970                                          GPR64sp:$Rn), []>;
8971
8972   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8973                             (outs GPR64sp:$wback),
8974                             (ins listtype:$Vt, VectorIndexS:$idx,
8975                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8976 }
8977 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8978 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8979                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8980   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8981                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8982                                          GPR64sp:$Rn), []>;
8983
8984   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8985                             (outs GPR64sp:$wback),
8986                             (ins listtype:$Vt, VectorIndexD:$idx,
8987                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8988 }
8989
8990 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8991                                  string Count, int Offset, Operand idxtype> {
8992   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8993   //      "ld1\t$Vt, [$Rn], #1"
8994   // may get mapped to
8995   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8996   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8997                   (!cast<Instruction>(NAME # Type  # "_POST")
8998                       GPR64sp:$Rn,
8999                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9000                       idxtype:$idx, XZR), 1>;
9001
9002   // E.g. "ld1.8b { v0 }[0], [x1], #1"
9003   //      "ld1.8b\t$Vt, [$Rn], #1"
9004   // may get mapped to
9005   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9006   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9007                   (!cast<Instruction>(NAME # Type # "_POST")
9008                       GPR64sp:$Rn,
9009                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9010                       idxtype:$idx, XZR), 0>;
9011
9012   // E.g. "ld1.8b { v0 }[0], [x1]"
9013   //      "ld1.8b\t$Vt, [$Rn]"
9014   // may get mapped to
9015   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9016   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9017                       (!cast<Instruction>(NAME # Type)
9018                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9019                          idxtype:$idx, GPR64sp:$Rn), 0>;
9020
9021   // E.g. "ld1.8b { v0 }[0], [x1], x2"
9022   //      "ld1.8b\t$Vt, [$Rn], $Xm"
9023   // may get mapped to
9024   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9025   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9026                       (!cast<Instruction>(NAME # Type # "_POST")
9027                          GPR64sp:$Rn,
9028                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9029                          idxtype:$idx,
9030                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9031 }
9032
9033 multiclass SIMDLdSt1SingleAliases<string asm> {
9034   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
9035   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9036   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9037   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9038 }
9039
9040 multiclass SIMDLdSt2SingleAliases<string asm> {
9041   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
9042   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
9043   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
9044   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9045 }
9046
9047 multiclass SIMDLdSt3SingleAliases<string asm> {
9048   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
9049   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
9050   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9051   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9052 }
9053
9054 multiclass SIMDLdSt4SingleAliases<string asm> {
9055   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
9056   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
9057   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9058   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9059 }
9060 } // end of 'let Predicates = [HasNEON]'
9061
9062 //----------------------------------------------------------------------------
9063 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9064 //----------------------------------------------------------------------------
9065
9066 let Predicates = [HasNEON, HasV8_1a] in {
9067
9068 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9069                                     RegisterOperand regtype, string asm, 
9070                                     string kind, list<dag> pattern>
9071   : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind, 
9072                                 pattern> {
9073 }
9074 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9075                                              SDPatternOperator Accum> {
9076   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9077     [(set (v4i16 V64:$dst),
9078           (Accum (v4i16 V64:$Rd),
9079                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9080                                                    (v4i16 V64:$Rm)))))]>;         
9081   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9082     [(set (v8i16 V128:$dst),
9083           (Accum (v8i16 V128:$Rd),
9084                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9085                                                    (v8i16 V128:$Rm)))))]>;
9086   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9087     [(set (v2i32 V64:$dst),
9088           (Accum (v2i32 V64:$Rd),
9089                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9090                                                    (v2i32 V64:$Rm)))))]>;
9091   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9092     [(set (v4i32 V128:$dst),
9093           (Accum (v4i32 V128:$Rd),
9094                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9095                                                    (v4i32 V128:$Rm)))))]>;
9096 }
9097
9098 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9099                                      SDPatternOperator Accum> {
9100   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9101                                           V64, V64, V128_lo, VectorIndexH,
9102                                           asm, ".4h", ".4h", ".4h", ".h",
9103     [(set (v4i16 V64:$dst),
9104           (Accum (v4i16 V64:$Rd),
9105                  (v4i16 (int_aarch64_neon_sqrdmulh
9106                           (v4i16 V64:$Rn),
9107                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9108                                                     VectorIndexH:$idx))))))]> {
9109     bits<3> idx;
9110     let Inst{11} = idx{2};
9111     let Inst{21} = idx{1};
9112     let Inst{20} = idx{0};
9113   }
9114
9115   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9116                                           V128, V128, V128_lo, VectorIndexH,
9117                                           asm, ".8h", ".8h", ".8h", ".h",
9118     [(set (v8i16 V128:$dst),
9119           (Accum (v8i16 V128:$Rd),
9120                  (v8i16 (int_aarch64_neon_sqrdmulh
9121                           (v8i16 V128:$Rn),
9122                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9123                                                    VectorIndexH:$idx))))))]> {
9124     bits<3> idx;
9125     let Inst{11} = idx{2};
9126     let Inst{21} = idx{1};
9127     let Inst{20} = idx{0};
9128   }
9129
9130   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9131                                           V64, V64, V128, VectorIndexS,
9132                                           asm, ".2s", ".2s", ".2s", ".s",
9133     [(set (v2i32 V64:$dst),
9134         (Accum (v2i32 V64:$Rd),
9135                (v2i32 (int_aarch64_neon_sqrdmulh
9136                         (v2i32 V64:$Rn),
9137                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9138                                                  VectorIndexS:$idx))))))]> {
9139     bits<2> idx;
9140     let Inst{11} = idx{1};
9141     let Inst{21} = idx{0};
9142   }
9143
9144   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but 
9145   // an intermediate EXTRACT_SUBREG would be untyped.
9146   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we 
9147   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9148   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9149                        (i32 (vector_extract 
9150                                (v4i32 (insert_subvector
9151                                        (undef), 
9152                                         (v2i32 (int_aarch64_neon_sqrdmulh 
9153                                                  (v2i32 V64:$Rn),
9154                                                  (v2i32 (AArch64duplane32 
9155                                                           (v4i32 V128:$Rm),
9156                                                           VectorIndexS:$idx)))),
9157                                       (i32 0))),
9158                                (i64 0))))),
9159             (EXTRACT_SUBREG
9160                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9161                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), 
9162                                                 FPR32Op:$Rd, 
9163                                                 ssub)), 
9164                           V64:$Rn,
9165                           V128:$Rm, 
9166                           VectorIndexS:$idx)),
9167                 ssub)>;
9168
9169   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9170                                           V128, V128, V128, VectorIndexS,
9171                                           asm, ".4s", ".4s", ".4s", ".s",
9172     [(set (v4i32 V128:$dst),
9173           (Accum (v4i32 V128:$Rd),
9174                  (v4i32 (int_aarch64_neon_sqrdmulh
9175                           (v4i32 V128:$Rn),
9176                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9177                                                    VectorIndexS:$idx))))))]> {
9178     bits<2> idx;
9179     let Inst{11} = idx{1};
9180     let Inst{21} = idx{0};
9181   }
9182
9183   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9184   // an intermediate EXTRACT_SUBREG would be untyped.
9185   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9186                         (i32 (vector_extract 
9187                                (v4i32 (int_aarch64_neon_sqrdmulh 
9188                                         (v4i32 V128:$Rn),
9189                                         (v4i32 (AArch64duplane32 
9190                                                  (v4i32 V128:$Rm),
9191                                                  VectorIndexS:$idx)))),
9192                                (i64 0))))),
9193             (EXTRACT_SUBREG
9194                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9195                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), 
9196                                                FPR32Op:$Rd, 
9197                                                ssub)), 
9198                          V128:$Rn,
9199                          V128:$Rm, 
9200                          VectorIndexS:$idx)),
9201                 ssub)>;
9202
9203   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9204                                         FPR16Op, FPR16Op, V128_lo,
9205                                         VectorIndexH, asm, ".h", "", "", ".h", 
9206                                         []> {
9207     bits<3> idx;
9208     let Inst{11} = idx{2};
9209     let Inst{21} = idx{1};
9210     let Inst{20} = idx{0};
9211   }
9212
9213   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9214                                         FPR32Op, FPR32Op, V128, VectorIndexS,
9215                                         asm, ".s", "", "", ".s",
9216     [(set (i32 FPR32Op:$dst),
9217           (Accum (i32 FPR32Op:$Rd),
9218                  (i32 (int_aarch64_neon_sqrdmulh
9219                         (i32 FPR32Op:$Rn),
9220                         (i32 (vector_extract (v4i32 V128:$Rm),
9221                                              VectorIndexS:$idx))))))]> {
9222     bits<2> idx;
9223     let Inst{11} = idx{1};
9224     let Inst{21} = idx{0};
9225   }
9226 }
9227 } // let Predicates = [HasNeon, HasV8_1a]
9228
9229 //----------------------------------------------------------------------------
9230 // Crypto extensions
9231 //----------------------------------------------------------------------------
9232
9233 let Predicates = [HasCrypto] in {
9234 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9235 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
9236               list<dag> pat>
9237   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
9238     Sched<[WriteV]>{
9239   bits<5> Rd;
9240   bits<5> Rn;
9241   let Inst{31-16} = 0b0100111000101000;
9242   let Inst{15-12} = opc;
9243   let Inst{11-10} = 0b10;
9244   let Inst{9-5}   = Rn;
9245   let Inst{4-0}   = Rd;
9246 }
9247
9248 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
9249   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
9250             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
9251
9252 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
9253   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
9254             "$Rd = $dst",
9255             [(set (v16i8 V128:$dst),
9256                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
9257
9258 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9259 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
9260                      dag oops, dag iops, list<dag> pat>
9261   : I<oops, iops, asm,
9262       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
9263       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
9264     Sched<[WriteV]>{
9265   bits<5> Rd;
9266   bits<5> Rn;
9267   bits<5> Rm;
9268   let Inst{31-21} = 0b01011110000;
9269   let Inst{20-16} = Rm;
9270   let Inst{15}    = 0;
9271   let Inst{14-12} = opc;
9272   let Inst{11-10} = 0b00;
9273   let Inst{9-5}   = Rn;
9274   let Inst{4-0}   = Rd;
9275 }
9276
9277 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
9278   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9279                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
9280                    [(set (v4i32 FPR128:$dst),
9281                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
9282                                  (v4i32 V128:$Rm)))]>;
9283
9284 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
9285   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
9286                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
9287                    [(set (v4i32 V128:$dst),
9288                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9289                                  (v4i32 V128:$Rm)))]>;
9290
9291 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
9292   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9293                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
9294                    [(set (v4i32 FPR128:$dst),
9295                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
9296                                  (v4i32 V128:$Rm)))]>;
9297
9298 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9299 class SHA2OpInst<bits<4> opc, string asm, string kind,
9300                  string cstr, dag oops, dag iops,
9301                  list<dag> pat>
9302   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
9303                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
9304     Sched<[WriteV]>{
9305   bits<5> Rd;
9306   bits<5> Rn;
9307   let Inst{31-16} = 0b0101111000101000;
9308   let Inst{15-12} = opc;
9309   let Inst{11-10} = 0b10;
9310   let Inst{9-5}   = Rn;
9311   let Inst{4-0}   = Rd;
9312 }
9313
9314 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
9315   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
9316                (ins V128:$Rd, V128:$Rn),
9317                [(set (v4i32 V128:$dst),
9318                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
9319
9320 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
9321   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
9322                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
9323 } // end of 'let Predicates = [HasCrypto]'
9324
9325 //----------------------------------------------------------------------------
9326 // v8.1 atomic instructions extension:
9327 // * CAS
9328 // * CASP
9329 // * SWP
9330 // * LDOPregister<OP>, and aliases STOPregister<OP>
9331
9332 // Instruction encodings:
9333 //
9334 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
9335 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
9336 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
9337 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
9338 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
9339 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
9340
9341 // Instruction syntax:
9342 //
9343 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9344 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
9345 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
9346 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
9347 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9348 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
9349 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9350 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
9351 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
9352 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
9353
9354 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9355 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
9356                       string cstr, list<dag> pattern>
9357       : I<oops, iops, asm, operands, cstr, pattern> {
9358   bits<2> Sz;
9359   bit NP;
9360   bit Acq;
9361   bit Rel;
9362   bits<5> Rs;
9363   bits<5> Rn;
9364   bits<5> Rt;
9365   let Inst{31-30} = Sz;
9366   let Inst{29-24} = 0b001000;
9367   let Inst{23} = NP;
9368   let Inst{22} = Acq;
9369   let Inst{21} = 0b1;
9370   let Inst{20-16} = Rs;
9371   let Inst{15} = Rel;
9372   let Inst{14-10} = 0b11111;
9373   let Inst{9-5} = Rn;
9374   let Inst{4-0} = Rt;
9375 }
9376
9377 class BaseCAS<string order, string size, RegisterClass RC>
9378       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9379                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
9380                         "$out = $Rs",[]> {
9381   let NP = 1;
9382 }
9383
9384 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
9385   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
9386   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
9387   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
9388   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
9389 }
9390
9391 class BaseCASP<string order, string size, RegisterOperand RC>
9392       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9393                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
9394                         "$out = $Rs",[]> {
9395   let NP = 0;
9396 }
9397
9398 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
9399   let Sz = 0b00, Acq = Acq, Rel = Rel in 
9400     def s : BaseCASP<order, "", WSeqPairClassOperand>;
9401   let Sz = 0b01, Acq = Acq, Rel = Rel in 
9402     def d : BaseCASP<order, "", XSeqPairClassOperand>;
9403 }
9404
9405 let Predicates = [HasV8_1a] in
9406 class BaseSWP<string order, string size, RegisterClass RC>
9407       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
9408           "\t$Rs, $Rt, [$Rn]","",[]> {
9409   bits<2> Sz;
9410   bit Acq;
9411   bit Rel;
9412   bits<5> Rs;
9413   bits<3> opc = 0b000;
9414   bits<5> Rn;
9415   bits<5> Rt;
9416   let Inst{31-30} = Sz;
9417   let Inst{29-24} = 0b111000;
9418   let Inst{23} = Acq;
9419   let Inst{22} = Rel;
9420   let Inst{21} = 0b1;
9421   let Inst{20-16} = Rs;
9422   let Inst{15} = 0b1;
9423   let Inst{14-12} = opc;
9424   let Inst{11-10} = 0b00;
9425   let Inst{9-5} = Rn;
9426   let Inst{4-0} = Rt;
9427 }
9428
9429 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
9430   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
9431   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
9432   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
9433   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
9434 }
9435
9436 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9437 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
9438       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
9439           "\t$Rs, $Rt, [$Rn]","",[]> {
9440   bits<2> Sz;
9441   bit Acq;
9442   bit Rel;
9443   bits<5> Rs;
9444   bits<3> opc;
9445   bits<5> Rn;
9446   bits<5> Rt;
9447   let Inst{31-30} = Sz;
9448   let Inst{29-24} = 0b111000;
9449   let Inst{23} = Acq;
9450   let Inst{22} = Rel;
9451   let Inst{21} = 0b1;
9452   let Inst{20-16} = Rs;
9453   let Inst{15} = 0b0;
9454   let Inst{14-12} = opc;
9455   let Inst{11-10} = 0b00;
9456   let Inst{9-5} = Rn;
9457   let Inst{4-0} = Rt;
9458 }
9459
9460 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel, 
9461                         string order> {
9462   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in 
9463     def b : BaseLDOPregister<op, order, "b", GPR32>;
9464   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in 
9465     def h : BaseLDOPregister<op, order, "h", GPR32>;
9466   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in 
9467     def s : BaseLDOPregister<op, order, "", GPR32>;
9468   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in 
9469     def d : BaseLDOPregister<op, order, "", GPR64>;
9470 }
9471
9472 let Predicates = [HasV8_1a] in
9473 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
9474                         Instruction inst> :
9475       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
9476
9477 multiclass STOPregister<string asm, string instr> {
9478   def : BaseSTOPregister<asm # "lb", GPR32, WZR, 
9479                     !cast<Instruction>(instr # "Lb")>;
9480   def : BaseSTOPregister<asm # "lh", GPR32, WZR, 
9481                     !cast<Instruction>(instr # "Lh")>;
9482   def : BaseSTOPregister<asm # "l",  GPR32, WZR, 
9483                     !cast<Instruction>(instr # "Ls")>;
9484   def : BaseSTOPregister<asm # "l",  GPR64, XZR, 
9485                     !cast<Instruction>(instr # "Ld")>;
9486   def : BaseSTOPregister<asm # "b",  GPR32, WZR, 
9487                     !cast<Instruction>(instr # "b")>;
9488   def : BaseSTOPregister<asm # "h",  GPR32, WZR, 
9489                     !cast<Instruction>(instr # "h")>;
9490   def : BaseSTOPregister<asm,        GPR32, WZR, 
9491                     !cast<Instruction>(instr # "s")>;
9492   def : BaseSTOPregister<asm,        GPR64, XZR, 
9493                     !cast<Instruction>(instr # "d")>;
9494 }
9495
9496 //----------------------------------------------------------------------------
9497 // Allow the size specifier tokens to be upper case, not just lower.
9498 def : TokenAlias<".8B", ".8b">;
9499 def : TokenAlias<".4H", ".4h">;
9500 def : TokenAlias<".2S", ".2s">;
9501 def : TokenAlias<".1D", ".1d">;
9502 def : TokenAlias<".16B", ".16b">;
9503 def : TokenAlias<".8H", ".8h">;
9504 def : TokenAlias<".4S", ".4s">;
9505 def : TokenAlias<".2D", ".2d">;
9506 def : TokenAlias<".1Q", ".1q">;
9507 def : TokenAlias<".2H", ".2h">;
9508 def : TokenAlias<".B", ".b">;
9509 def : TokenAlias<".H", ".h">;
9510 def : TokenAlias<".S", ".s">;
9511 def : TokenAlias<".D", ".d">;
9512 def : TokenAlias<".Q", ".q">;