Fix comment typo (test commit). NFC
[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 class AsmImmRange<int Low, int High> : AsmOperandClass {
252   let Name = "Imm" # Low # "_" # High;
253   let DiagnosticType = "InvalidImm" # Low # "_" # High;
254 }
255
256 def Imm1_8Operand : AsmImmRange<1, 8>;
257 def Imm1_16Operand : AsmImmRange<1, 16>;
258 def Imm1_32Operand : AsmImmRange<1, 32>;
259 def Imm1_64Operand : AsmImmRange<1, 64>;
260
261 def MovZSymbolG3AsmOperand : AsmOperandClass {
262   let Name = "MovZSymbolG3";
263   let RenderMethod = "addImmOperands";
264 }
265
266 def movz_symbol_g3 : Operand<i32> {
267   let ParserMatchClass = MovZSymbolG3AsmOperand;
268 }
269
270 def MovZSymbolG2AsmOperand : AsmOperandClass {
271   let Name = "MovZSymbolG2";
272   let RenderMethod = "addImmOperands";
273 }
274
275 def movz_symbol_g2 : Operand<i32> {
276   let ParserMatchClass = MovZSymbolG2AsmOperand;
277 }
278
279 def MovZSymbolG1AsmOperand : AsmOperandClass {
280   let Name = "MovZSymbolG1";
281   let RenderMethod = "addImmOperands";
282 }
283
284 def movz_symbol_g1 : Operand<i32> {
285   let ParserMatchClass = MovZSymbolG1AsmOperand;
286 }
287
288 def MovZSymbolG0AsmOperand : AsmOperandClass {
289   let Name = "MovZSymbolG0";
290   let RenderMethod = "addImmOperands";
291 }
292
293 def movz_symbol_g0 : Operand<i32> {
294   let ParserMatchClass = MovZSymbolG0AsmOperand;
295 }
296
297 def MovKSymbolG3AsmOperand : AsmOperandClass {
298   let Name = "MovKSymbolG3";
299   let RenderMethod = "addImmOperands";
300 }
301
302 def movk_symbol_g3 : Operand<i32> {
303   let ParserMatchClass = MovKSymbolG3AsmOperand;
304 }
305
306 def MovKSymbolG2AsmOperand : AsmOperandClass {
307   let Name = "MovKSymbolG2";
308   let RenderMethod = "addImmOperands";
309 }
310
311 def movk_symbol_g2 : Operand<i32> {
312   let ParserMatchClass = MovKSymbolG2AsmOperand;
313 }
314
315 def MovKSymbolG1AsmOperand : AsmOperandClass {
316   let Name = "MovKSymbolG1";
317   let RenderMethod = "addImmOperands";
318 }
319
320 def movk_symbol_g1 : Operand<i32> {
321   let ParserMatchClass = MovKSymbolG1AsmOperand;
322 }
323
324 def MovKSymbolG0AsmOperand : AsmOperandClass {
325   let Name = "MovKSymbolG0";
326   let RenderMethod = "addImmOperands";
327 }
328
329 def movk_symbol_g0 : Operand<i32> {
330   let ParserMatchClass = MovKSymbolG0AsmOperand;
331 }
332
333 class fixedpoint_i32<ValueType FloatVT>
334   : Operand<FloatVT>,
335     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
336   let EncoderMethod = "getFixedPointScaleOpValue";
337   let DecoderMethod = "DecodeFixedPointScaleImm32";
338   let ParserMatchClass = Imm1_32Operand;
339 }
340
341 class fixedpoint_i64<ValueType FloatVT>
342   : Operand<FloatVT>,
343     ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
344   let EncoderMethod = "getFixedPointScaleOpValue";
345   let DecoderMethod = "DecodeFixedPointScaleImm64";
346   let ParserMatchClass = Imm1_64Operand;
347 }
348
349 def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
350 def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
351
352 def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
353 def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
354
355 def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
356   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
357 }]> {
358   let EncoderMethod = "getVecShiftR8OpValue";
359   let DecoderMethod = "DecodeVecShiftR8Imm";
360   let ParserMatchClass = Imm1_8Operand;
361 }
362 def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
363   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
364 }]> {
365   let EncoderMethod = "getVecShiftR16OpValue";
366   let DecoderMethod = "DecodeVecShiftR16Imm";
367   let ParserMatchClass = Imm1_16Operand;
368 }
369 def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
370   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
371 }]> {
372   let EncoderMethod = "getVecShiftR16OpValue";
373   let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
374   let ParserMatchClass = Imm1_8Operand;
375 }
376 def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
377   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
378 }]> {
379   let EncoderMethod = "getVecShiftR32OpValue";
380   let DecoderMethod = "DecodeVecShiftR32Imm";
381   let ParserMatchClass = Imm1_32Operand;
382 }
383 def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
384   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
385 }]> {
386   let EncoderMethod = "getVecShiftR32OpValue";
387   let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
388   let ParserMatchClass = Imm1_16Operand;
389 }
390 def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
391   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
392 }]> {
393   let EncoderMethod = "getVecShiftR64OpValue";
394   let DecoderMethod = "DecodeVecShiftR64Imm";
395   let ParserMatchClass = Imm1_64Operand;
396 }
397 def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
398   return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
399 }]> {
400   let EncoderMethod = "getVecShiftR64OpValue";
401   let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
402   let ParserMatchClass = Imm1_32Operand;
403 }
404
405 def Imm0_7Operand : AsmImmRange<0, 7>;
406 def Imm0_15Operand : AsmImmRange<0, 15>;
407 def Imm0_31Operand : AsmImmRange<0, 31>;
408 def Imm0_63Operand : AsmImmRange<0, 63>;
409
410 def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
411   return (((uint32_t)Imm) < 8);
412 }]> {
413   let EncoderMethod = "getVecShiftL8OpValue";
414   let DecoderMethod = "DecodeVecShiftL8Imm";
415   let ParserMatchClass = Imm0_7Operand;
416 }
417 def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
418   return (((uint32_t)Imm) < 16);
419 }]> {
420   let EncoderMethod = "getVecShiftL16OpValue";
421   let DecoderMethod = "DecodeVecShiftL16Imm";
422   let ParserMatchClass = Imm0_15Operand;
423 }
424 def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
425   return (((uint32_t)Imm) < 32);
426 }]> {
427   let EncoderMethod = "getVecShiftL32OpValue";
428   let DecoderMethod = "DecodeVecShiftL32Imm";
429   let ParserMatchClass = Imm0_31Operand;
430 }
431 def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
432   return (((uint32_t)Imm) < 64);
433 }]> {
434   let EncoderMethod = "getVecShiftL64OpValue";
435   let DecoderMethod = "DecodeVecShiftL64Imm";
436   let ParserMatchClass = Imm0_63Operand;
437 }
438
439
440 // Crazy immediate formats used by 32-bit and 64-bit logical immediate
441 // instructions for splatting repeating bit patterns across the immediate.
442 def logical_imm32_XFORM : SDNodeXForm<imm, [{
443   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
444   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
445 }]>;
446 def logical_imm64_XFORM : SDNodeXForm<imm, [{
447   uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
448   return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
449 }]>;
450
451 let DiagnosticType = "LogicalSecondSource" in {
452   def LogicalImm32Operand : AsmOperandClass {
453     let Name = "LogicalImm32";
454   }
455   def LogicalImm64Operand : AsmOperandClass {
456     let Name = "LogicalImm64";
457   }
458   def LogicalImm32NotOperand : AsmOperandClass {
459     let Name = "LogicalImm32Not";
460   }
461   def LogicalImm64NotOperand : AsmOperandClass {
462     let Name = "LogicalImm64Not";
463   }
464 }
465 def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
466   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
467 }], logical_imm32_XFORM> {
468   let PrintMethod = "printLogicalImm32";
469   let ParserMatchClass = LogicalImm32Operand;
470 }
471 def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
472   return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
473 }], logical_imm64_XFORM> {
474   let PrintMethod = "printLogicalImm64";
475   let ParserMatchClass = LogicalImm64Operand;
476 }
477 def logical_imm32_not : Operand<i32> {
478   let ParserMatchClass = LogicalImm32NotOperand;
479 }
480 def logical_imm64_not : Operand<i64> {
481   let ParserMatchClass = LogicalImm64NotOperand;
482 }
483
484 // imm0_65535 predicate - True if the immediate is in the range [0,65535].
485 def Imm0_65535Operand : AsmImmRange<0, 65535>;
486 def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
487   return ((uint32_t)Imm) < 65536;
488 }]> {
489   let ParserMatchClass = Imm0_65535Operand;
490   let PrintMethod = "printHexImm";
491 }
492
493 // imm0_255 predicate - True if the immediate is in the range [0,255].
494 def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
495 def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
496   return ((uint32_t)Imm) < 256;
497 }]> {
498   let ParserMatchClass = Imm0_255Operand;
499   let PrintMethod = "printHexImm";
500 }
501
502 // imm0_127 predicate - True if the immediate is in the range [0,127]
503 def Imm0_127Operand : AsmImmRange<0, 127>;
504 def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
505   return ((uint32_t)Imm) < 128;
506 }]> {
507   let ParserMatchClass = Imm0_127Operand;
508   let PrintMethod = "printHexImm";
509 }
510
511 // NOTE: These imm0_N operands have to be of type i64 because i64 is the size
512 // for all shift-amounts.
513
514 // imm0_63 predicate - True if the immediate is in the range [0,63]
515 def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
516   return ((uint64_t)Imm) < 64;
517 }]> {
518   let ParserMatchClass = Imm0_63Operand;
519 }
520
521 // imm0_31 predicate - True if the immediate is in the range [0,31]
522 def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
523   return ((uint64_t)Imm) < 32;
524 }]> {
525   let ParserMatchClass = Imm0_31Operand;
526 }
527
528 // True if the 32-bit immediate is in the range [0,31]
529 def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
530   return ((uint64_t)Imm) < 32;
531 }]> {
532   let ParserMatchClass = Imm0_31Operand;
533 }
534
535 // imm0_15 predicate - True if the immediate is in the range [0,15]
536 def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
537   return ((uint64_t)Imm) < 16;
538 }]> {
539   let ParserMatchClass = Imm0_15Operand;
540 }
541
542 // imm0_7 predicate - True if the immediate is in the range [0,7]
543 def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
544   return ((uint64_t)Imm) < 8;
545 }]> {
546   let ParserMatchClass = Imm0_7Operand;
547 }
548
549 // imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
550 def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
551   return ((uint32_t)Imm) < 16;
552 }]> {
553   let ParserMatchClass = Imm0_15Operand;
554 }
555
556 // An arithmetic shifter operand:
557 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
558 //  {5-0} - imm6
559 class arith_shift<ValueType Ty, int width> : Operand<Ty> {
560   let PrintMethod = "printShifter";
561   let ParserMatchClass = !cast<AsmOperandClass>(
562                          "ArithmeticShifterOperand" # width);
563 }
564
565 def arith_shift32 : arith_shift<i32, 32>;
566 def arith_shift64 : arith_shift<i64, 64>;
567
568 class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
569     : Operand<Ty>,
570       ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
571   let PrintMethod = "printShiftedRegister";
572   let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
573 }
574
575 def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
576 def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
577
578 // An arithmetic shifter operand:
579 //  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
580 //  {5-0} - imm6
581 class logical_shift<int width> : Operand<i32> {
582   let PrintMethod = "printShifter";
583   let ParserMatchClass = !cast<AsmOperandClass>(
584                          "LogicalShifterOperand" # width);
585 }
586
587 def logical_shift32 : logical_shift<32>;
588 def logical_shift64 : logical_shift<64>;
589
590 class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
591     : Operand<Ty>,
592       ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
593   let PrintMethod = "printShiftedRegister";
594   let MIOperandInfo = (ops regclass, shiftop);
595 }
596
597 def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
598 def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
599
600 // A logical vector shifter operand:
601 //  {7-6} - shift type: 00 = lsl
602 //  {5-0} - imm6: #0, #8, #16, or #24
603 def logical_vec_shift : Operand<i32> {
604   let PrintMethod = "printShifter";
605   let EncoderMethod = "getVecShifterOpValue";
606   let ParserMatchClass = LogicalVecShifterOperand;
607 }
608
609 // A logical vector half-word shifter operand:
610 //  {7-6} - shift type: 00 = lsl
611 //  {5-0} - imm6: #0 or #8
612 def logical_vec_hw_shift : Operand<i32> {
613   let PrintMethod = "printShifter";
614   let EncoderMethod = "getVecShifterOpValue";
615   let ParserMatchClass = LogicalVecHalfWordShifterOperand;
616 }
617
618 // A vector move shifter operand:
619 //  {0} - imm1: #8 or #16
620 def move_vec_shift : Operand<i32> {
621   let PrintMethod = "printShifter";
622   let EncoderMethod = "getMoveVecShifterOpValue";
623   let ParserMatchClass = MoveVecShifterOperand;
624 }
625
626 let DiagnosticType = "AddSubSecondSource" in {
627   def AddSubImmOperand : AsmOperandClass {
628     let Name = "AddSubImm";
629     let ParserMethod = "tryParseAddSubImm";
630   }
631   def AddSubImmNegOperand : AsmOperandClass {
632     let Name = "AddSubImmNeg";
633     let ParserMethod = "tryParseAddSubImm";
634   }
635 }
636 // An ADD/SUB immediate shifter operand:
637 //  second operand:
638 //  {7-6} - shift type: 00 = lsl
639 //  {5-0} - imm6: #0 or #12
640 class addsub_shifted_imm<ValueType Ty>
641     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
642   let PrintMethod = "printAddSubImm";
643   let EncoderMethod = "getAddSubImmOpValue";
644   let ParserMatchClass = AddSubImmOperand;
645   let MIOperandInfo = (ops i32imm, i32imm);
646 }
647
648 class addsub_shifted_imm_neg<ValueType Ty>
649     : Operand<Ty> {
650   let EncoderMethod = "getAddSubImmOpValue";
651   let ParserMatchClass = AddSubImmNegOperand;
652   let MIOperandInfo = (ops i32imm, i32imm);
653 }
654
655 def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
656 def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
657 def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
658 def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
659
660 class neg_addsub_shifted_imm<ValueType Ty>
661     : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
662   let PrintMethod = "printAddSubImm";
663   let EncoderMethod = "getAddSubImmOpValue";
664   let ParserMatchClass = AddSubImmOperand;
665   let MIOperandInfo = (ops i32imm, i32imm);
666 }
667
668 def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
669 def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
670
671 // An extend operand:
672 //  {5-3} - extend type
673 //  {2-0} - imm3
674 def arith_extend : Operand<i32> {
675   let PrintMethod = "printArithExtend";
676   let ParserMatchClass = ExtendOperand;
677 }
678 def arith_extend64 : Operand<i32> {
679   let PrintMethod = "printArithExtend";
680   let ParserMatchClass = ExtendOperand64;
681 }
682
683 // 'extend' that's a lsl of a 64-bit register.
684 def arith_extendlsl64 : Operand<i32> {
685   let PrintMethod = "printArithExtend";
686   let ParserMatchClass = ExtendOperandLSL64;
687 }
688
689 class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
690                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
691   let PrintMethod = "printExtendedRegister";
692   let MIOperandInfo = (ops GPR32, arith_extend);
693 }
694
695 class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
696                     ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
697   let PrintMethod = "printExtendedRegister";
698   let MIOperandInfo = (ops GPR32, arith_extend64);
699 }
700
701 // Floating-point immediate.
702 def fpimm32 : Operand<f32>,
703               PatLeaf<(f32 fpimm), [{
704       return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
705     }], SDNodeXForm<fpimm, [{
706       APFloat InVal = N->getValueAPF();
707       uint32_t enc = AArch64_AM::getFP32Imm(InVal);
708       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
709     }]>> {
710   let ParserMatchClass = FPImmOperand;
711   let PrintMethod = "printFPImmOperand";
712 }
713 def fpimm64 : Operand<f64>,
714               PatLeaf<(f64 fpimm), [{
715       return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
716     }], SDNodeXForm<fpimm, [{
717       APFloat InVal = N->getValueAPF();
718       uint32_t enc = AArch64_AM::getFP64Imm(InVal);
719       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
720     }]>> {
721   let ParserMatchClass = FPImmOperand;
722   let PrintMethod = "printFPImmOperand";
723 }
724
725 def fpimm8 : Operand<i32> {
726   let ParserMatchClass = FPImmOperand;
727   let PrintMethod = "printFPImmOperand";
728 }
729
730 def fpimm0 : PatLeaf<(fpimm), [{
731   return N->isExactlyValue(+0.0);
732 }]>;
733
734 // Vector lane operands
735 class AsmVectorIndex<string Suffix> : AsmOperandClass {
736   let Name = "VectorIndex" # Suffix;
737   let DiagnosticType = "InvalidIndex" # Suffix;
738 }
739 def VectorIndex1Operand : AsmVectorIndex<"1">;
740 def VectorIndexBOperand : AsmVectorIndex<"B">;
741 def VectorIndexHOperand : AsmVectorIndex<"H">;
742 def VectorIndexSOperand : AsmVectorIndex<"S">;
743 def VectorIndexDOperand : AsmVectorIndex<"D">;
744
745 def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
746   return ((uint64_t)Imm) == 1;
747 }]> {
748   let ParserMatchClass = VectorIndex1Operand;
749   let PrintMethod = "printVectorIndex";
750   let MIOperandInfo = (ops i64imm);
751 }
752 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
753   return ((uint64_t)Imm) < 16;
754 }]> {
755   let ParserMatchClass = VectorIndexBOperand;
756   let PrintMethod = "printVectorIndex";
757   let MIOperandInfo = (ops i64imm);
758 }
759 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
760   return ((uint64_t)Imm) < 8;
761 }]> {
762   let ParserMatchClass = VectorIndexHOperand;
763   let PrintMethod = "printVectorIndex";
764   let MIOperandInfo = (ops i64imm);
765 }
766 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
767   return ((uint64_t)Imm) < 4;
768 }]> {
769   let ParserMatchClass = VectorIndexSOperand;
770   let PrintMethod = "printVectorIndex";
771   let MIOperandInfo = (ops i64imm);
772 }
773 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
774   return ((uint64_t)Imm) < 2;
775 }]> {
776   let ParserMatchClass = VectorIndexDOperand;
777   let PrintMethod = "printVectorIndex";
778   let MIOperandInfo = (ops i64imm);
779 }
780
781 // 8-bit immediate for AdvSIMD where 64-bit values of the form:
782 // aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
783 // are encoded as the eight bit value 'abcdefgh'.
784 def simdimmtype10 : Operand<i32>,
785                     PatLeaf<(f64 fpimm), [{
786       return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
787                                                .bitcastToAPInt()
788                                                .getZExtValue());
789     }], SDNodeXForm<fpimm, [{
790       APFloat InVal = N->getValueAPF();
791       uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
792                                                            .bitcastToAPInt()
793                                                            .getZExtValue());
794       return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
795     }]>> {
796   let ParserMatchClass = SIMDImmType10Operand;
797   let PrintMethod = "printSIMDType10Operand";
798 }
799
800
801 //---
802 // System management
803 //---
804
805 // Base encoding for system instruction operands.
806 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
807 class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
808                   list<dag> pattern = []>
809     : I<oops, iops, asm, operands, "", pattern> {
810   let Inst{31-22} = 0b1101010100;
811   let Inst{21}    = L;
812 }
813
814 // System instructions which do not have an Rt register.
815 class SimpleSystemI<bit L, dag iops, string asm, string operands,
816                     list<dag> pattern = []>
817     : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
818   let Inst{4-0} = 0b11111;
819 }
820
821 // System instructions which have an Rt register.
822 class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
823     : BaseSystemI<L, oops, iops, asm, operands>,
824       Sched<[WriteSys]> {
825   bits<5> Rt;
826   let Inst{4-0} = Rt;
827 }
828
829 // Hint instructions that take both a CRm and a 3-bit immediate.
830 // NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
831 // model patterns with sufficiently fine granularity
832 let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
833   class HintI<string mnemonic>
834       : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#" $imm", "",
835                       [(int_aarch64_hint imm0_127:$imm)]>,
836         Sched<[WriteHint]> {
837     bits <7> imm;
838     let Inst{20-12} = 0b000110010;
839     let Inst{11-5} = imm;
840   }
841
842 // System instructions taking a single literal operand which encodes into
843 // CRm. op2 differentiates the opcodes.
844 def BarrierAsmOperand : AsmOperandClass {
845   let Name = "Barrier";
846   let ParserMethod = "tryParseBarrierOperand";
847 }
848 def barrier_op : Operand<i32> {
849   let PrintMethod = "printBarrierOption";
850   let ParserMatchClass = BarrierAsmOperand;
851 }
852 class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
853                  list<dag> pattern = []>
854     : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
855       Sched<[WriteBarrier]> {
856   bits<4> CRm;
857   let Inst{20-12} = 0b000110011;
858   let Inst{11-8} = CRm;
859   let Inst{7-5} = opc;
860 }
861
862 // MRS/MSR system instructions. These have different operand classes because
863 // a different subset of registers can be accessed through each instruction.
864 def MRSSystemRegisterOperand : AsmOperandClass {
865   let Name = "MRSSystemRegister";
866   let ParserMethod = "tryParseSysReg";
867   let DiagnosticType = "MRS";
868 }
869 // concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
870 def mrs_sysreg_op : Operand<i32> {
871   let ParserMatchClass = MRSSystemRegisterOperand;
872   let DecoderMethod = "DecodeMRSSystemRegister";
873   let PrintMethod = "printMRSSystemRegister";
874 }
875
876 def MSRSystemRegisterOperand : AsmOperandClass {
877   let Name = "MSRSystemRegister";
878   let ParserMethod = "tryParseSysReg";
879   let DiagnosticType = "MSR";
880 }
881 def msr_sysreg_op : Operand<i32> {
882   let ParserMatchClass = MSRSystemRegisterOperand;
883   let DecoderMethod = "DecodeMSRSystemRegister";
884   let PrintMethod = "printMSRSystemRegister";
885 }
886
887 class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
888                        "mrs", "\t$Rt, $systemreg"> {
889   bits<16> systemreg;
890   let Inst{20-5} = systemreg;
891 }
892
893 // FIXME: Some of these def NZCV, others don't. Best way to model that?
894 // Explicitly modeling each of the system register as a register class
895 // would do it, but feels like overkill at this point.
896 class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
897                        "msr", "\t$systemreg, $Rt"> {
898   bits<16> systemreg;
899   let Inst{20-5} = systemreg;
900 }
901
902 def SystemPStateFieldOperand : AsmOperandClass {
903   let Name = "SystemPStateField";
904   let ParserMethod = "tryParseSysReg";
905 }
906 def pstatefield_op : Operand<i32> {
907   let ParserMatchClass = SystemPStateFieldOperand;
908   let PrintMethod = "printSystemPStateField";
909 }
910
911 let Defs = [NZCV] in
912 class MSRpstateI
913   : SimpleSystemI<0, (ins pstatefield_op:$pstate_field, imm0_15:$imm),
914                   "msr", "\t$pstate_field, $imm">,
915     Sched<[WriteSys]> {
916   bits<6> pstatefield;
917   bits<4> imm;
918   let Inst{20-19} = 0b00;
919   let Inst{18-16} = pstatefield{5-3};
920   let Inst{15-12} = 0b0100;
921   let Inst{11-8} = imm;
922   let Inst{7-5} = pstatefield{2-0};
923
924   let DecoderMethod = "DecodeSystemPStateInstruction";
925   // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
926   // Fail the decoder should attempt to decode the instruction as MSRI.
927   let hasCompleteDecoder = 0;
928 }
929
930 // SYS and SYSL generic system instructions.
931 def SysCRAsmOperand : AsmOperandClass {
932   let Name = "SysCR";
933   let ParserMethod = "tryParseSysCROperand";
934 }
935
936 def sys_cr_op : Operand<i32> {
937   let PrintMethod = "printSysCROperand";
938   let ParserMatchClass = SysCRAsmOperand;
939 }
940
941 class SystemXtI<bit L, string asm>
942   : RtSystemI<L, (outs),
943        (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
944        asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
945   bits<3> op1;
946   bits<4> Cn;
947   bits<4> Cm;
948   bits<3> op2;
949   let Inst{20-19} = 0b01;
950   let Inst{18-16} = op1;
951   let Inst{15-12} = Cn;
952   let Inst{11-8}  = Cm;
953   let Inst{7-5}   = op2;
954 }
955
956 class SystemLXtI<bit L, string asm>
957   : RtSystemI<L, (outs),
958        (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
959        asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
960   bits<3> op1;
961   bits<4> Cn;
962   bits<4> Cm;
963   bits<3> op2;
964   let Inst{20-19} = 0b01;
965   let Inst{18-16} = op1;
966   let Inst{15-12} = Cn;
967   let Inst{11-8}  = Cm;
968   let Inst{7-5}   = op2;
969 }
970
971
972 // Branch (register) instructions:
973 //
974 //  case opc of
975 //    0001 blr
976 //    0000 br
977 //    0101 dret
978 //    0100 eret
979 //    0010 ret
980 //    otherwise UNDEFINED
981 class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
982                     string operands, list<dag> pattern>
983     : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
984   let Inst{31-25} = 0b1101011;
985   let Inst{24-21} = opc;
986   let Inst{20-16} = 0b11111;
987   let Inst{15-10} = 0b000000;
988   let Inst{4-0}   = 0b00000;
989 }
990
991 class BranchReg<bits<4> opc, string asm, list<dag> pattern>
992     : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
993   bits<5> Rn;
994   let Inst{9-5} = Rn;
995 }
996
997 let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
998 class SpecialReturn<bits<4> opc, string asm>
999     : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1000   let Inst{9-5} = 0b11111;
1001 }
1002
1003 //---
1004 // Conditional branch instruction.
1005 //---
1006
1007 // Condition code.
1008 // 4-bit immediate. Pretty-printed as <cc>
1009 def ccode : Operand<i32> {
1010   let PrintMethod = "printCondCode";
1011   let ParserMatchClass = CondCode;
1012 }
1013 def inv_ccode : Operand<i32> {
1014   // AL and NV are invalid in the aliases which use inv_ccode
1015   let PrintMethod = "printInverseCondCode";
1016   let ParserMatchClass = CondCode;
1017   let MCOperandPredicate = [{
1018     return MCOp.isImm() &&
1019            MCOp.getImm() != AArch64CC::AL &&
1020            MCOp.getImm() != AArch64CC::NV;
1021   }];
1022 }
1023
1024 // Conditional branch target. 19-bit immediate. The low two bits of the target
1025 // offset are implied zero and so are not part of the immediate.
1026 def PCRelLabel19Operand : AsmOperandClass {
1027   let Name = "PCRelLabel19";
1028   let DiagnosticType = "InvalidLabel";
1029 }
1030 def am_brcond : Operand<OtherVT> {
1031   let EncoderMethod = "getCondBranchTargetOpValue";
1032   let DecoderMethod = "DecodePCRelLabel19";
1033   let PrintMethod = "printAlignedLabel";
1034   let ParserMatchClass = PCRelLabel19Operand;
1035 }
1036
1037 class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1038                      "b", ".$cond\t$target", "",
1039                      [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1040                    Sched<[WriteBr]> {
1041   let isBranch = 1;
1042   let isTerminator = 1;
1043   let Uses = [NZCV];
1044
1045   bits<4> cond;
1046   bits<19> target;
1047   let Inst{31-24} = 0b01010100;
1048   let Inst{23-5} = target;
1049   let Inst{4} = 0;
1050   let Inst{3-0} = cond;
1051 }
1052
1053 //---
1054 // Compare-and-branch instructions.
1055 //---
1056 class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1057     : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1058          asm, "\t$Rt, $target", "",
1059          [(node regtype:$Rt, bb:$target)]>,
1060       Sched<[WriteBr]> {
1061   let isBranch = 1;
1062   let isTerminator = 1;
1063
1064   bits<5> Rt;
1065   bits<19> target;
1066   let Inst{30-25} = 0b011010;
1067   let Inst{24}    = op;
1068   let Inst{23-5}  = target;
1069   let Inst{4-0}   = Rt;
1070 }
1071
1072 multiclass CmpBranch<bit op, string asm, SDNode node> {
1073   def W : BaseCmpBranch<GPR32, op, asm, node> {
1074     let Inst{31} = 0;
1075   }
1076   def X : BaseCmpBranch<GPR64, op, asm, node> {
1077     let Inst{31} = 1;
1078   }
1079 }
1080
1081 //---
1082 // Test-bit-and-branch instructions.
1083 //---
1084 // Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1085 // the target offset are implied zero and so are not part of the immediate.
1086 def BranchTarget14Operand : AsmOperandClass {
1087   let Name = "BranchTarget14";
1088 }
1089 def am_tbrcond : Operand<OtherVT> {
1090   let EncoderMethod = "getTestBranchTargetOpValue";
1091   let PrintMethod = "printAlignedLabel";
1092   let ParserMatchClass = BranchTarget14Operand;
1093 }
1094
1095 // AsmOperand classes to emit (or not) special diagnostics
1096 def TBZImm0_31Operand : AsmOperandClass {
1097   let Name = "TBZImm0_31";
1098   let PredicateMethod = "isImm0_31";
1099   let RenderMethod = "addImm0_31Operands";
1100 }
1101 def TBZImm32_63Operand : AsmOperandClass {
1102   let Name = "Imm32_63";
1103   let DiagnosticType = "InvalidImm0_63";
1104 }
1105
1106 class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1107   return (((uint32_t)Imm) < 32);
1108 }]> {
1109   let ParserMatchClass = matcher;
1110 }
1111
1112 def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1113 def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1114
1115 def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1116   return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1117 }]> {
1118   let ParserMatchClass = TBZImm32_63Operand;
1119 }
1120
1121 class BaseTestBranch<RegisterClass regtype, Operand immtype,
1122                      bit op, string asm, SDNode node>
1123     : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1124        asm, "\t$Rt, $bit_off, $target", "",
1125        [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1126       Sched<[WriteBr]> {
1127   let isBranch = 1;
1128   let isTerminator = 1;
1129
1130   bits<5> Rt;
1131   bits<6> bit_off;
1132   bits<14> target;
1133
1134   let Inst{30-25} = 0b011011;
1135   let Inst{24}    = op;
1136   let Inst{23-19} = bit_off{4-0};
1137   let Inst{18-5}  = target;
1138   let Inst{4-0}   = Rt;
1139
1140   let DecoderMethod = "DecodeTestAndBranch";
1141 }
1142
1143 multiclass TestBranch<bit op, string asm, SDNode node> {
1144   def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1145     let Inst{31} = 0;
1146   }
1147
1148   def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1149     let Inst{31} = 1;
1150   }
1151
1152   // Alias X-reg with 0-31 imm to W-Reg.
1153   def : InstAlias<asm # "\t$Rd, $imm, $target",
1154                   (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1155                   tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1156   def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1157             (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1158             tbz_imm0_31_diag:$imm, bb:$target)>;
1159 }
1160
1161 //---
1162 // Unconditional branch (immediate) instructions.
1163 //---
1164 def BranchTarget26Operand : AsmOperandClass {
1165   let Name = "BranchTarget26";
1166   let DiagnosticType = "InvalidLabel";
1167 }
1168 def am_b_target : Operand<OtherVT> {
1169   let EncoderMethod = "getBranchTargetOpValue";
1170   let PrintMethod = "printAlignedLabel";
1171   let ParserMatchClass = BranchTarget26Operand;
1172 }
1173 def am_bl_target : Operand<i64> {
1174   let EncoderMethod = "getBranchTargetOpValue";
1175   let PrintMethod = "printAlignedLabel";
1176   let ParserMatchClass = BranchTarget26Operand;
1177 }
1178
1179 class BImm<bit op, dag iops, string asm, list<dag> pattern>
1180     : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1181   bits<26> addr;
1182   let Inst{31}    = op;
1183   let Inst{30-26} = 0b00101;
1184   let Inst{25-0}  = addr;
1185
1186   let DecoderMethod = "DecodeUnconditionalBranch";
1187 }
1188
1189 class BranchImm<bit op, string asm, list<dag> pattern>
1190     : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1191 class CallImm<bit op, string asm, list<dag> pattern>
1192     : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1193
1194 //---
1195 // Basic one-operand data processing instructions.
1196 //---
1197
1198 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1199 class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1200                          SDPatternOperator node>
1201   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1202       [(set regtype:$Rd, (node regtype:$Rn))]>,
1203     Sched<[WriteI, ReadI]> {
1204   bits<5> Rd;
1205   bits<5> Rn;
1206
1207   let Inst{30-13} = 0b101101011000000000;
1208   let Inst{12-10} = opc;
1209   let Inst{9-5}   = Rn;
1210   let Inst{4-0}   = Rd;
1211 }
1212
1213 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1214 multiclass OneOperandData<bits<3> opc, string asm,
1215                           SDPatternOperator node = null_frag> {
1216   def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1217     let Inst{31} = 0;
1218   }
1219
1220   def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1221     let Inst{31} = 1;
1222   }
1223 }
1224
1225 class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1226     : BaseOneOperandData<opc, GPR32, asm, node> {
1227   let Inst{31} = 0;
1228 }
1229
1230 class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1231     : BaseOneOperandData<opc, GPR64, asm, node> {
1232   let Inst{31} = 1;
1233 }
1234
1235 //---
1236 // Basic two-operand data processing instructions.
1237 //---
1238 class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1239                           list<dag> pattern>
1240     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1241         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1242       Sched<[WriteI, ReadI, ReadI]> {
1243   let Uses = [NZCV];
1244   bits<5> Rd;
1245   bits<5> Rn;
1246   bits<5> Rm;
1247   let Inst{30}    = isSub;
1248   let Inst{28-21} = 0b11010000;
1249   let Inst{20-16} = Rm;
1250   let Inst{15-10} = 0;
1251   let Inst{9-5}   = Rn;
1252   let Inst{4-0}   = Rd;
1253 }
1254
1255 class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1256                       SDNode OpNode>
1257     : BaseBaseAddSubCarry<isSub, regtype, asm,
1258         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1259
1260 class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1261                               SDNode OpNode>
1262     : BaseBaseAddSubCarry<isSub, regtype, asm,
1263         [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1264          (implicit NZCV)]> {
1265   let Defs = [NZCV];
1266 }
1267
1268 multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1269                        SDNode OpNode, SDNode OpNode_setflags> {
1270   def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1271     let Inst{31} = 0;
1272     let Inst{29} = 0;
1273   }
1274   def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1275     let Inst{31} = 1;
1276     let Inst{29} = 0;
1277   }
1278
1279   // Sets flags.
1280   def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1281                                     OpNode_setflags> {
1282     let Inst{31} = 0;
1283     let Inst{29} = 1;
1284   }
1285   def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1286                                     OpNode_setflags> {
1287     let Inst{31} = 1;
1288     let Inst{29} = 1;
1289   }
1290 }
1291
1292 class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1293                      SDPatternOperator OpNode>
1294   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1295       asm, "\t$Rd, $Rn, $Rm", "",
1296       [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1297   bits<5> Rd;
1298   bits<5> Rn;
1299   bits<5> Rm;
1300   let Inst{30-21} = 0b0011010110;
1301   let Inst{20-16} = Rm;
1302   let Inst{15-14} = 0b00;
1303   let Inst{13-10} = opc;
1304   let Inst{9-5}   = Rn;
1305   let Inst{4-0}   = Rd;
1306 }
1307
1308 class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1309               SDPatternOperator OpNode>
1310     : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1311   let Inst{10}    = isSigned;
1312 }
1313
1314 multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1315   def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1316            Sched<[WriteID32, ReadID, ReadID]> {
1317     let Inst{31} = 0;
1318   }
1319   def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1320            Sched<[WriteID64, ReadID, ReadID]> {
1321     let Inst{31} = 1;
1322   }
1323 }
1324
1325 class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1326                 SDPatternOperator OpNode = null_frag>
1327   : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1328     Sched<[WriteIS, ReadI]> {
1329   let Inst{11-10} = shift_type;
1330 }
1331
1332 multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1333   def Wr : BaseShift<shift_type, GPR32, asm> {
1334     let Inst{31} = 0;
1335   }
1336
1337   def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1338     let Inst{31} = 1;
1339   }
1340
1341   def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1342             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1343                                              (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1344
1345   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1346             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1347
1348   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1349             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1350
1351   def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1352             (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1353 }
1354
1355 class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1356     : InstAlias<asm#" $dst, $src1, $src2",
1357                 (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1358
1359 class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1360                        RegisterClass addtype, string asm,
1361                        list<dag> pattern>
1362   : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1363       asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1364   bits<5> Rd;
1365   bits<5> Rn;
1366   bits<5> Rm;
1367   bits<5> Ra;
1368   let Inst{30-24} = 0b0011011;
1369   let Inst{23-21} = opc;
1370   let Inst{20-16} = Rm;
1371   let Inst{15}    = isSub;
1372   let Inst{14-10} = Ra;
1373   let Inst{9-5}   = Rn;
1374   let Inst{4-0}   = Rd;
1375 }
1376
1377 multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1378   // MADD/MSUB generation is decided by MachineCombiner.cpp
1379   def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1380       [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1381       Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1382     let Inst{31} = 0;
1383   }
1384
1385   def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1386       [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1387       Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1388     let Inst{31} = 1;
1389   }
1390 }
1391
1392 class WideMulAccum<bit isSub, bits<3> opc, string asm,
1393                    SDNode AccNode, SDNode ExtNode>
1394   : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1395     [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1396                             (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1397     Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1398   let Inst{31} = 1;
1399 }
1400
1401 class MulHi<bits<3> opc, string asm, SDNode OpNode>
1402   : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1403       asm, "\t$Rd, $Rn, $Rm", "",
1404       [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1405     Sched<[WriteIM64, ReadIM, ReadIM]> {
1406   bits<5> Rd;
1407   bits<5> Rn;
1408   bits<5> Rm;
1409   let Inst{31-24} = 0b10011011;
1410   let Inst{23-21} = opc;
1411   let Inst{20-16} = Rm;
1412   let Inst{15}    = 0;
1413   let Inst{9-5}   = Rn;
1414   let Inst{4-0}   = Rd;
1415
1416   // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1417   // (i.e. all bits 1) but is ignored by the processor.
1418   let PostEncoderMethod = "fixMulHigh";
1419 }
1420
1421 class MulAccumWAlias<string asm, Instruction inst>
1422     : InstAlias<asm#" $dst, $src1, $src2",
1423                 (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1424 class MulAccumXAlias<string asm, Instruction inst>
1425     : InstAlias<asm#" $dst, $src1, $src2",
1426                 (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1427 class WideMulAccumAlias<string asm, Instruction inst>
1428     : InstAlias<asm#" $dst, $src1, $src2",
1429                 (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1430
1431 class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1432               SDPatternOperator OpNode, string asm>
1433   : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1434       asm, "\t$Rd, $Rn, $Rm", "",
1435       [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1436     Sched<[WriteISReg, ReadI, ReadISReg]> {
1437   bits<5> Rd;
1438   bits<5> Rn;
1439   bits<5> Rm;
1440
1441   let Inst{31} = sf;
1442   let Inst{30-21} = 0b0011010110;
1443   let Inst{20-16} = Rm;
1444   let Inst{15-13} = 0b010;
1445   let Inst{12} = C;
1446   let Inst{11-10} = sz;
1447   let Inst{9-5} = Rn;
1448   let Inst{4-0} = Rd;
1449   let Predicates = [HasCRC];
1450 }
1451
1452 //---
1453 // Address generation.
1454 //---
1455
1456 class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1457     : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1458         pattern>,
1459       Sched<[WriteI]> {
1460   bits<5>  Xd;
1461   bits<21> label;
1462   let Inst{31}    = page;
1463   let Inst{30-29} = label{1-0};
1464   let Inst{28-24} = 0b10000;
1465   let Inst{23-5}  = label{20-2};
1466   let Inst{4-0}   = Xd;
1467
1468   let DecoderMethod = "DecodeAdrInstruction";
1469 }
1470
1471 //---
1472 // Move immediate.
1473 //---
1474
1475 def movimm32_imm : Operand<i32> {
1476   let ParserMatchClass = Imm0_65535Operand;
1477   let EncoderMethod = "getMoveWideImmOpValue";
1478   let PrintMethod = "printHexImm";
1479 }
1480 def movimm32_shift : Operand<i32> {
1481   let PrintMethod = "printShifter";
1482   let ParserMatchClass = MovImm32ShifterOperand;
1483 }
1484 def movimm64_shift : Operand<i32> {
1485   let PrintMethod = "printShifter";
1486   let ParserMatchClass = MovImm64ShifterOperand;
1487 }
1488
1489 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1490 class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1491                         string asm>
1492   : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1493        asm, "\t$Rd, $imm$shift", "", []>,
1494     Sched<[WriteImm]> {
1495   bits<5> Rd;
1496   bits<16> imm;
1497   bits<6> shift;
1498   let Inst{30-29} = opc;
1499   let Inst{28-23} = 0b100101;
1500   let Inst{22-21} = shift{5-4};
1501   let Inst{20-5}  = imm;
1502   let Inst{4-0}   = Rd;
1503
1504   let DecoderMethod = "DecodeMoveImmInstruction";
1505 }
1506
1507 multiclass MoveImmediate<bits<2> opc, string asm> {
1508   def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1509     let Inst{31} = 0;
1510   }
1511
1512   def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1513     let Inst{31} = 1;
1514   }
1515 }
1516
1517 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1518 class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1519                           string asm>
1520   : I<(outs regtype:$Rd),
1521       (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1522        asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1523     Sched<[WriteI, ReadI]> {
1524   bits<5> Rd;
1525   bits<16> imm;
1526   bits<6> shift;
1527   let Inst{30-29} = opc;
1528   let Inst{28-23} = 0b100101;
1529   let Inst{22-21} = shift{5-4};
1530   let Inst{20-5}  = imm;
1531   let Inst{4-0}   = Rd;
1532
1533   let DecoderMethod = "DecodeMoveImmInstruction";
1534 }
1535
1536 multiclass InsertImmediate<bits<2> opc, string asm> {
1537   def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1538     let Inst{31} = 0;
1539   }
1540
1541   def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1542     let Inst{31} = 1;
1543   }
1544 }
1545
1546 //---
1547 // Add/Subtract
1548 //---
1549
1550 class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1551                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
1552                     string asm, SDPatternOperator OpNode>
1553     : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1554         asm, "\t$Rd, $Rn, $imm", "",
1555         [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1556       Sched<[WriteI, ReadI]>  {
1557   bits<5>  Rd;
1558   bits<5>  Rn;
1559   bits<14> imm;
1560   let Inst{30}    = isSub;
1561   let Inst{29}    = setFlags;
1562   let Inst{28-24} = 0b10001;
1563   let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1564   let Inst{21-10} = imm{11-0};
1565   let Inst{9-5}   = Rn;
1566   let Inst{4-0}   = Rd;
1567   let DecoderMethod = "DecodeBaseAddSubImm";
1568 }
1569
1570 class BaseAddSubRegPseudo<RegisterClass regtype,
1571                           SDPatternOperator OpNode>
1572     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1573              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1574       Sched<[WriteI, ReadI, ReadI]>;
1575
1576 class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1577                      arith_shifted_reg shifted_regtype, string asm,
1578                      SDPatternOperator OpNode>
1579     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1580         asm, "\t$Rd, $Rn, $Rm", "",
1581         [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1582       Sched<[WriteISReg, ReadI, ReadISReg]> {
1583   // The operands are in order to match the 'addr' MI operands, so we
1584   // don't need an encoder method and by-name matching. Just use the default
1585   // in-order handling. Since we're using by-order, make sure the names
1586   // do not match.
1587   bits<5> dst;
1588   bits<5> src1;
1589   bits<5> src2;
1590   bits<8> shift;
1591   let Inst{30}    = isSub;
1592   let Inst{29}    = setFlags;
1593   let Inst{28-24} = 0b01011;
1594   let Inst{23-22} = shift{7-6};
1595   let Inst{21}    = 0;
1596   let Inst{20-16} = src2;
1597   let Inst{15-10} = shift{5-0};
1598   let Inst{9-5}   = src1;
1599   let Inst{4-0}   = dst;
1600
1601   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1602 }
1603
1604 class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1605                      RegisterClass src1Regtype, Operand src2Regtype,
1606                      string asm, SDPatternOperator OpNode>
1607     : I<(outs dstRegtype:$R1),
1608         (ins src1Regtype:$R2, src2Regtype:$R3),
1609         asm, "\t$R1, $R2, $R3", "",
1610         [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1611       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1612   bits<5> Rd;
1613   bits<5> Rn;
1614   bits<5> Rm;
1615   bits<6> ext;
1616   let Inst{30}    = isSub;
1617   let Inst{29}    = setFlags;
1618   let Inst{28-24} = 0b01011;
1619   let Inst{23-21} = 0b001;
1620   let Inst{20-16} = Rm;
1621   let Inst{15-13} = ext{5-3};
1622   let Inst{12-10} = ext{2-0};
1623   let Inst{9-5}   = Rn;
1624   let Inst{4-0}   = Rd;
1625
1626   let DecoderMethod = "DecodeAddSubERegInstruction";
1627 }
1628
1629 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1630 class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1631                        RegisterClass src1Regtype, RegisterClass src2Regtype,
1632                        Operand ext_op, string asm>
1633     : I<(outs dstRegtype:$Rd),
1634         (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1635         asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1636       Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1637   bits<5> Rd;
1638   bits<5> Rn;
1639   bits<5> Rm;
1640   bits<6> ext;
1641   let Inst{30}    = isSub;
1642   let Inst{29}    = setFlags;
1643   let Inst{28-24} = 0b01011;
1644   let Inst{23-21} = 0b001;
1645   let Inst{20-16} = Rm;
1646   let Inst{15}    = ext{5};
1647   let Inst{12-10} = ext{2-0};
1648   let Inst{9-5}   = Rn;
1649   let Inst{4-0}   = Rd;
1650
1651   let DecoderMethod = "DecodeAddSubERegInstruction";
1652 }
1653
1654 // Aliases for register+register add/subtract.
1655 class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1656                      RegisterClass src1Regtype, RegisterClass src2Regtype,
1657                      int shiftExt>
1658     : InstAlias<asm#" $dst, $src1, $src2",
1659                 (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1660                       shiftExt)>;
1661
1662 multiclass AddSub<bit isSub, string mnemonic, string alias,
1663                   SDPatternOperator OpNode = null_frag> {
1664   let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1665   // Add/Subtract immediate
1666   // Increase the weight of the immediate variant to try to match it before
1667   // the extended register variant.
1668   // We used to match the register variant before the immediate when the
1669   // register argument could be implicitly zero-extended.
1670   let AddedComplexity = 6 in
1671   def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1672                            mnemonic, OpNode> {
1673     let Inst{31} = 0;
1674   }
1675   let AddedComplexity = 6 in
1676   def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1677                            mnemonic, OpNode> {
1678     let Inst{31} = 1;
1679   }
1680
1681   // Add/Subtract register - Only used for CodeGen
1682   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1683   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1684
1685   // Add/Subtract shifted register
1686   def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1687                            OpNode> {
1688     let Inst{31} = 0;
1689   }
1690   def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1691                            OpNode> {
1692     let Inst{31} = 1;
1693   }
1694   }
1695
1696   // Add/Subtract extended register
1697   let AddedComplexity = 1, hasSideEffects = 0 in {
1698   def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1699                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1700     let Inst{31} = 0;
1701   }
1702   def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1703                            arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1704     let Inst{31} = 1;
1705   }
1706   }
1707
1708   def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1709                                arith_extendlsl64, mnemonic> {
1710     // UXTX and SXTX only.
1711     let Inst{14-13} = 0b11;
1712     let Inst{31} = 1;
1713   }
1714
1715   // add Rd, Rb, -imm -> sub Rd, Rn, imm
1716   def : InstAlias<alias#" $Rd, $Rn, $imm",
1717                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
1718                       addsub_shifted_imm32_neg:$imm), 0>;
1719   def : InstAlias<alias#" $Rd, $Rn, $imm",
1720                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
1721                        addsub_shifted_imm64_neg:$imm), 0>;
1722
1723   // Register/register aliases with no shift when SP is not used.
1724   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1725                        GPR32, GPR32, GPR32, 0>;
1726   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1727                        GPR64, GPR64, GPR64, 0>;
1728
1729   // Register/register aliases with no shift when either the destination or
1730   // first source register is SP.
1731   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1732                        GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1733   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1734                        GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1735   def : AddSubRegAlias<mnemonic,
1736                        !cast<Instruction>(NAME#"Xrx64"),
1737                        GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1738   def : AddSubRegAlias<mnemonic,
1739                        !cast<Instruction>(NAME#"Xrx64"),
1740                        GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1741 }
1742
1743 multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
1744                    string alias, string cmpAlias> {
1745   let isCompare = 1, Defs = [NZCV] in {
1746   // Add/Subtract immediate
1747   def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1748                            mnemonic, OpNode> {
1749     let Inst{31} = 0;
1750   }
1751   def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1752                            mnemonic, OpNode> {
1753     let Inst{31} = 1;
1754   }
1755
1756   // Add/Subtract register
1757   def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1758   def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1759
1760   // Add/Subtract shifted register
1761   def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1762                            OpNode> {
1763     let Inst{31} = 0;
1764   }
1765   def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1766                            OpNode> {
1767     let Inst{31} = 1;
1768   }
1769
1770   // Add/Subtract extended register
1771   let AddedComplexity = 1 in {
1772   def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1773                            arith_extended_reg32<i32>, mnemonic, OpNode> {
1774     let Inst{31} = 0;
1775   }
1776   def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1777                            arith_extended_reg32<i64>, mnemonic, OpNode> {
1778     let Inst{31} = 1;
1779   }
1780   }
1781
1782   def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1783                                arith_extendlsl64, mnemonic> {
1784     // UXTX and SXTX only.
1785     let Inst{14-13} = 0b11;
1786     let Inst{31} = 1;
1787   }
1788   } // Defs = [NZCV]
1789
1790   // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
1791   def : InstAlias<alias#" $Rd, $Rn, $imm",
1792                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
1793                       addsub_shifted_imm32_neg:$imm), 0>;
1794   def : InstAlias<alias#" $Rd, $Rn, $imm",
1795                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
1796                        addsub_shifted_imm64_neg:$imm), 0>;
1797
1798   // Compare aliases
1799   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Wri")
1800                   WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1801   def : InstAlias<cmp#" $src, $imm", (!cast<Instruction>(NAME#"Xri")
1802                   XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1803   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1804                   WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1805   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1806                   XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1807   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1808                   XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1809   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1810                   WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1811   def : InstAlias<cmp#" $src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1812                   XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1813
1814   // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
1815   def : InstAlias<cmpAlias#" $src, $imm", (!cast<Instruction>(NAME#"Wri")
1816                   WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
1817   def : InstAlias<cmpAlias#" $src, $imm", (!cast<Instruction>(NAME#"Xri")
1818                   XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
1819
1820   // Compare shorthands
1821   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1822                   WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1823   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1824                   XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1825   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1826                   WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1827   def : InstAlias<cmp#" $src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1828                   XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1829
1830   // Register/register aliases with no shift when SP is not used.
1831   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1832                        GPR32, GPR32, GPR32, 0>;
1833   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1834                        GPR64, GPR64, GPR64, 0>;
1835
1836   // Register/register aliases with no shift when the first source register
1837   // is SP.
1838   def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1839                        GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1840   def : AddSubRegAlias<mnemonic,
1841                        !cast<Instruction>(NAME#"Xrx64"),
1842                        GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1843 }
1844
1845 //---
1846 // Extract
1847 //---
1848 def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1849                                       SDTCisPtrTy<3>]>;
1850 def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1851
1852 class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1853                      list<dag> patterns>
1854     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1855          asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1856       Sched<[WriteExtr, ReadExtrHi]> {
1857   bits<5> Rd;
1858   bits<5> Rn;
1859   bits<5> Rm;
1860   bits<6> imm;
1861
1862   let Inst{30-23} = 0b00100111;
1863   let Inst{21}    = 0;
1864   let Inst{20-16} = Rm;
1865   let Inst{15-10} = imm;
1866   let Inst{9-5}   = Rn;
1867   let Inst{4-0}   = Rd;
1868 }
1869
1870 multiclass ExtractImm<string asm> {
1871   def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1872                       [(set GPR32:$Rd,
1873                         (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1874     let Inst{31} = 0;
1875     let Inst{22} = 0;
1876     // imm<5> must be zero.
1877     let imm{5}   = 0;
1878   }
1879   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1880                       [(set GPR64:$Rd,
1881                         (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1882
1883     let Inst{31} = 1;
1884     let Inst{22} = 1;
1885   }
1886 }
1887
1888 //---
1889 // Bitfield
1890 //---
1891
1892 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1893 class BaseBitfieldImm<bits<2> opc,
1894                       RegisterClass regtype, Operand imm_type, string asm>
1895     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1896          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1897       Sched<[WriteIS, ReadI]> {
1898   bits<5> Rd;
1899   bits<5> Rn;
1900   bits<6> immr;
1901   bits<6> imms;
1902
1903   let Inst{30-29} = opc;
1904   let Inst{28-23} = 0b100110;
1905   let Inst{21-16} = immr;
1906   let Inst{15-10} = imms;
1907   let Inst{9-5}   = Rn;
1908   let Inst{4-0}   = Rd;
1909 }
1910
1911 multiclass BitfieldImm<bits<2> opc, string asm> {
1912   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1913     let Inst{31} = 0;
1914     let Inst{22} = 0;
1915     // imms<5> and immr<5> must be zero, else ReservedValue().
1916     let Inst{21} = 0;
1917     let Inst{15} = 0;
1918   }
1919   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1920     let Inst{31} = 1;
1921     let Inst{22} = 1;
1922   }
1923 }
1924
1925 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1926 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1927                       RegisterClass regtype, Operand imm_type, string asm>
1928     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1929                              imm_type:$imms),
1930          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1931       Sched<[WriteIS, ReadI]> {
1932   bits<5> Rd;
1933   bits<5> Rn;
1934   bits<6> immr;
1935   bits<6> imms;
1936
1937   let Inst{30-29} = opc;
1938   let Inst{28-23} = 0b100110;
1939   let Inst{21-16} = immr;
1940   let Inst{15-10} = imms;
1941   let Inst{9-5}   = Rn;
1942   let Inst{4-0}   = Rd;
1943 }
1944
1945 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1946   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1947     let Inst{31} = 0;
1948     let Inst{22} = 0;
1949     // imms<5> and immr<5> must be zero, else ReservedValue().
1950     let Inst{21} = 0;
1951     let Inst{15} = 0;
1952   }
1953   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1954     let Inst{31} = 1;
1955     let Inst{22} = 1;
1956   }
1957 }
1958
1959 //---
1960 // Logical
1961 //---
1962
1963 // Logical (immediate)
1964 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1965                      RegisterClass sregtype, Operand imm_type, string asm,
1966                      list<dag> pattern>
1967     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1968          asm, "\t$Rd, $Rn, $imm", "", pattern>,
1969       Sched<[WriteI, ReadI]> {
1970   bits<5>  Rd;
1971   bits<5>  Rn;
1972   bits<13> imm;
1973   let Inst{30-29} = opc;
1974   let Inst{28-23} = 0b100100;
1975   let Inst{22}    = imm{12};
1976   let Inst{21-16} = imm{11-6};
1977   let Inst{15-10} = imm{5-0};
1978   let Inst{9-5}   = Rn;
1979   let Inst{4-0}   = Rd;
1980
1981   let DecoderMethod = "DecodeLogicalImmInstruction";
1982 }
1983
1984 // Logical (shifted register)
1985 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1986                       logical_shifted_reg shifted_regtype, string asm,
1987                       list<dag> pattern>
1988     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1989         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1990       Sched<[WriteISReg, ReadI, ReadISReg]> {
1991   // The operands are in order to match the 'addr' MI operands, so we
1992   // don't need an encoder method and by-name matching. Just use the default
1993   // in-order handling. Since we're using by-order, make sure the names
1994   // do not match.
1995   bits<5> dst;
1996   bits<5> src1;
1997   bits<5> src2;
1998   bits<8> shift;
1999   let Inst{30-29} = opc;
2000   let Inst{28-24} = 0b01010;
2001   let Inst{23-22} = shift{7-6};
2002   let Inst{21}    = N;
2003   let Inst{20-16} = src2;
2004   let Inst{15-10} = shift{5-0};
2005   let Inst{9-5}   = src1;
2006   let Inst{4-0}   = dst;
2007
2008   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2009 }
2010
2011 // Aliases for register+register logical instructions.
2012 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2013     : InstAlias<asm#" $dst, $src1, $src2",
2014                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2015
2016 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2017                       string Alias> {
2018   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2019   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2020                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2021                                                logical_imm32:$imm))]> {
2022     let Inst{31} = 0;
2023     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2024   }
2025   let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2026   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2027                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2028                                                logical_imm64:$imm))]> {
2029     let Inst{31} = 1;
2030   }
2031
2032   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2033                   (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2034                       logical_imm32_not:$imm), 0>;
2035   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2036                   (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2037                        logical_imm64_not:$imm), 0>;
2038 }
2039
2040 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2041                        string Alias> {
2042   let isCompare = 1, Defs = [NZCV] in {
2043   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2044       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2045     let Inst{31} = 0;
2046     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2047   }
2048   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2049       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2050     let Inst{31} = 1;
2051   }
2052   } // end Defs = [NZCV]
2053
2054   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2055                   (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2056                       logical_imm32_not:$imm), 0>;
2057   def : InstAlias<Alias # " $Rd, $Rn, $imm",
2058                   (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2059                        logical_imm64_not:$imm), 0>;
2060 }
2061
2062 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2063     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2064              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2065       Sched<[WriteI, ReadI, ReadI]>;
2066
2067 // Split from LogicalImm as not all instructions have both.
2068 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2069                       SDPatternOperator OpNode> {
2070   let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2071   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2072   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2073   }
2074
2075   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2076                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2077                                                  logical_shifted_reg32:$Rm))]> {
2078     let Inst{31} = 0;
2079   }
2080   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2081                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2082                                                  logical_shifted_reg64:$Rm))]> {
2083     let Inst{31} = 1;
2084   }
2085
2086   def : LogicalRegAlias<mnemonic,
2087                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2088   def : LogicalRegAlias<mnemonic,
2089                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2090 }
2091
2092 // Split from LogicalReg to allow setting NZCV Defs
2093 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2094                        SDPatternOperator OpNode = null_frag> {
2095   let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2096   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2097   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2098
2099   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2100             [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2101     let Inst{31} = 0;
2102   }
2103   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2104             [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2105     let Inst{31} = 1;
2106   }
2107   } // Defs = [NZCV]
2108
2109   def : LogicalRegAlias<mnemonic,
2110                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
2111   def : LogicalRegAlias<mnemonic,
2112                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
2113 }
2114
2115 //---
2116 // Conditionally set flags
2117 //---
2118
2119 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2120 class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2121                             string mnemonic, SDNode OpNode>
2122     : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2123          mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2124          [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2125                              (i32 imm:$cond), NZCV))]>,
2126       Sched<[WriteI, ReadI]> {
2127   let Uses = [NZCV];
2128   let Defs = [NZCV];
2129
2130   bits<5> Rn;
2131   bits<5> imm;
2132   bits<4> nzcv;
2133   bits<4> cond;
2134
2135   let Inst{30}    = op;
2136   let Inst{29-21} = 0b111010010;
2137   let Inst{20-16} = imm;
2138   let Inst{15-12} = cond;
2139   let Inst{11-10} = 0b10;
2140   let Inst{9-5}   = Rn;
2141   let Inst{4}     = 0b0;
2142   let Inst{3-0}   = nzcv;
2143 }
2144
2145 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2146 class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2147                             SDNode OpNode>
2148     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2149          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2150          [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2151                              (i32 imm:$cond), NZCV))]>,
2152       Sched<[WriteI, ReadI, ReadI]> {
2153   let Uses = [NZCV];
2154   let Defs = [NZCV];
2155
2156   bits<5> Rn;
2157   bits<5> Rm;
2158   bits<4> nzcv;
2159   bits<4> cond;
2160
2161   let Inst{30}    = op;
2162   let Inst{29-21} = 0b111010010;
2163   let Inst{20-16} = Rm;
2164   let Inst{15-12} = cond;
2165   let Inst{11-10} = 0b00;
2166   let Inst{9-5}   = Rn;
2167   let Inst{4}     = 0b0;
2168   let Inst{3-0}   = nzcv;
2169 }
2170
2171 multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2172   // immediate operand variants
2173   def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2174     let Inst{31} = 0;
2175   }
2176   def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2177     let Inst{31} = 1;
2178   }
2179   // register operand variants
2180   def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2181     let Inst{31} = 0;
2182   }
2183   def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2184     let Inst{31} = 1;
2185   }
2186 }
2187
2188 //---
2189 // Conditional select
2190 //---
2191
2192 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2193     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2194          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2195          [(set regtype:$Rd,
2196                (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2197       Sched<[WriteI, ReadI, ReadI]> {
2198   let Uses = [NZCV];
2199
2200   bits<5> Rd;
2201   bits<5> Rn;
2202   bits<5> Rm;
2203   bits<4> cond;
2204
2205   let Inst{30}    = op;
2206   let Inst{29-21} = 0b011010100;
2207   let Inst{20-16} = Rm;
2208   let Inst{15-12} = cond;
2209   let Inst{11-10} = op2;
2210   let Inst{9-5}   = Rn;
2211   let Inst{4-0}   = Rd;
2212 }
2213
2214 multiclass CondSelect<bit op, bits<2> op2, string asm> {
2215   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2216     let Inst{31} = 0;
2217   }
2218   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2219     let Inst{31} = 1;
2220   }
2221 }
2222
2223 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2224                        PatFrag frag>
2225     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2226          asm, "\t$Rd, $Rn, $Rm, $cond", "",
2227          [(set regtype:$Rd,
2228                (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2229                (i32 imm:$cond), NZCV))]>,
2230       Sched<[WriteI, ReadI, ReadI]> {
2231   let Uses = [NZCV];
2232
2233   bits<5> Rd;
2234   bits<5> Rn;
2235   bits<5> Rm;
2236   bits<4> cond;
2237
2238   let Inst{30}    = op;
2239   let Inst{29-21} = 0b011010100;
2240   let Inst{20-16} = Rm;
2241   let Inst{15-12} = cond;
2242   let Inst{11-10} = op2;
2243   let Inst{9-5}   = Rn;
2244   let Inst{4-0}   = Rd;
2245 }
2246
2247 def inv_cond_XFORM : SDNodeXForm<imm, [{
2248   AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2249   return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2250                                    MVT::i32);
2251 }]>;
2252
2253 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2254   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2255     let Inst{31} = 0;
2256   }
2257   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2258     let Inst{31} = 1;
2259   }
2260
2261   def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2262             (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2263                                            (inv_cond_XFORM imm:$cond))>;
2264
2265   def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2266             (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2267                                            (inv_cond_XFORM imm:$cond))>;
2268 }
2269
2270 //---
2271 // Special Mask Value
2272 //---
2273 def maski8_or_more : Operand<i32>,
2274   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2275 }
2276 def maski16_or_more : Operand<i32>,
2277   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2278 }
2279
2280
2281 //---
2282 // Load/store
2283 //---
2284
2285 // (unsigned immediate)
2286 // Indexed for 8-bit registers. offset is in range [0,4095].
2287 def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2288 def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2289 def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2290 def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2291 def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2292
2293 class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2294   let Name = "UImm12Offset" # Scale;
2295   let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2296   let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2297   let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2298 }
2299
2300 def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2301 def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2302 def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2303 def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2304 def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2305
2306 class uimm12_scaled<int Scale> : Operand<i64> {
2307   let ParserMatchClass
2308    = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2309   let EncoderMethod
2310    = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2311   let PrintMethod = "printUImm12Offset<" # Scale # ">";
2312 }
2313
2314 def uimm12s1 : uimm12_scaled<1>;
2315 def uimm12s2 : uimm12_scaled<2>;
2316 def uimm12s4 : uimm12_scaled<4>;
2317 def uimm12s8 : uimm12_scaled<8>;
2318 def uimm12s16 : uimm12_scaled<16>;
2319
2320 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2321                       string asm, list<dag> pattern>
2322     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2323   bits<5> Rt;
2324
2325   bits<5> Rn;
2326   bits<12> offset;
2327
2328   let Inst{31-30} = sz;
2329   let Inst{29-27} = 0b111;
2330   let Inst{26}    = V;
2331   let Inst{25-24} = 0b01;
2332   let Inst{23-22} = opc;
2333   let Inst{21-10} = offset;
2334   let Inst{9-5}   = Rn;
2335   let Inst{4-0}   = Rt;
2336
2337   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2338 }
2339
2340 multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2341                   Operand indextype, string asm, list<dag> pattern> {
2342   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2343   def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2344                            (ins GPR64sp:$Rn, indextype:$offset),
2345                            asm, pattern>,
2346            Sched<[WriteLD]>;
2347
2348   def : InstAlias<asm # " $Rt, [$Rn]",
2349                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2350 }
2351
2352 multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2353              Operand indextype, string asm, list<dag> pattern> {
2354   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2355   def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2356                            (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2357                            asm, pattern>,
2358            Sched<[WriteST]>;
2359
2360   def : InstAlias<asm # " $Rt, [$Rn]",
2361                   (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2362 }
2363
2364 def PrefetchOperand : AsmOperandClass {
2365   let Name = "Prefetch";
2366   let ParserMethod = "tryParsePrefetch";
2367 }
2368 def prfop : Operand<i32> {
2369   let PrintMethod = "printPrefetchOp";
2370   let ParserMatchClass = PrefetchOperand;
2371 }
2372
2373 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2374 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2375     : BaseLoadStoreUI<sz, V, opc,
2376                       (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2377                       asm, pat>,
2378       Sched<[WriteLD]>;
2379
2380 //---
2381 // Load literal
2382 //---
2383
2384 // Load literal address: 19-bit immediate. The low two bits of the target
2385 // offset are implied zero and so are not part of the immediate.
2386 def am_ldrlit : Operand<OtherVT> {
2387   let EncoderMethod = "getLoadLiteralOpValue";
2388   let DecoderMethod = "DecodePCRelLabel19";
2389   let PrintMethod = "printAlignedLabel";
2390   let ParserMatchClass = PCRelLabel19Operand;
2391 }
2392
2393 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2394 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2395     : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2396         asm, "\t$Rt, $label", "", []>,
2397       Sched<[WriteLD]> {
2398   bits<5> Rt;
2399   bits<19> label;
2400   let Inst{31-30} = opc;
2401   let Inst{29-27} = 0b011;
2402   let Inst{26}    = V;
2403   let Inst{25-24} = 0b00;
2404   let Inst{23-5}  = label;
2405   let Inst{4-0}   = Rt;
2406 }
2407
2408 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2409 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2410     : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2411         asm, "\t$Rt, $label", "", pat>,
2412       Sched<[WriteLD]> {
2413   bits<5> Rt;
2414   bits<19> label;
2415   let Inst{31-30} = opc;
2416   let Inst{29-27} = 0b011;
2417   let Inst{26}    = V;
2418   let Inst{25-24} = 0b00;
2419   let Inst{23-5}  = label;
2420   let Inst{4-0}   = Rt;
2421 }
2422
2423 //---
2424 // Load/store register offset
2425 //---
2426
2427 def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2428 def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2429 def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2430 def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2431 def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2432
2433 def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2434 def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2435 def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2436 def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2437 def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2438
2439 class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2440   let Name = "Mem" # Reg # "Extend" # Width;
2441   let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2442   let RenderMethod = "addMemExtendOperands";
2443   let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2444 }
2445
2446 def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2447   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2448   // the trivial shift.
2449   let RenderMethod = "addMemExtend8Operands";
2450 }
2451 def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2452 def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2453 def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2454 def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2455
2456 def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2457   // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2458   // the trivial shift.
2459   let RenderMethod = "addMemExtend8Operands";
2460 }
2461 def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2462 def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2463 def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2464 def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2465
2466 class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2467         : Operand<i32> {
2468   let ParserMatchClass = ParserClass;
2469   let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2470   let DecoderMethod = "DecodeMemExtend";
2471   let EncoderMethod = "getMemExtendOpValue";
2472   let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2473 }
2474
2475 def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2476 def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2477 def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2478 def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2479 def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2480
2481 def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2482 def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2483 def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2484 def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2485 def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2486
2487 class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2488                   Operand wextend, Operand xextend>  {
2489   // CodeGen-level pattern covering the entire addressing mode.
2490   ComplexPattern Wpat = windex;
2491   ComplexPattern Xpat = xindex;
2492
2493   // Asm-level Operand covering the valid "uxtw #3" style syntax.
2494   Operand Wext = wextend;
2495   Operand Xext = xextend;
2496 }
2497
2498 def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2499 def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2500 def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2501 def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2502 def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2503                        ro_Xextend128>;
2504
2505 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2506                       string asm, dag ins, dag outs, list<dag> pat>
2507     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2508   bits<5> Rt;
2509   bits<5> Rn;
2510   bits<5> Rm;
2511   bits<2> extend;
2512   let Inst{31-30} = sz;
2513   let Inst{29-27} = 0b111;
2514   let Inst{26}    = V;
2515   let Inst{25-24} = 0b00;
2516   let Inst{23-22} = opc;
2517   let Inst{21}    = 1;
2518   let Inst{20-16} = Rm;
2519   let Inst{15}    = extend{1}; // sign extend Rm?
2520   let Inst{14}    = 1;
2521   let Inst{12}    = extend{0}; // do shift?
2522   let Inst{11-10} = 0b10;
2523   let Inst{9-5}   = Rn;
2524   let Inst{4-0}   = Rt;
2525 }
2526
2527 class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2528   : InstAlias<asm # " $Rt, [$Rn, $Rm]",
2529               (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2530
2531 multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2532                    string asm, ValueType Ty, SDPatternOperator loadop> {
2533   let AddedComplexity = 10 in
2534   def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2535                  (outs regtype:$Rt),
2536                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2537                  [(set (Ty regtype:$Rt),
2538                        (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2539                                              ro_Wextend8:$extend)))]>,
2540            Sched<[WriteLDIdx, ReadAdrBase]> {
2541     let Inst{13} = 0b0;
2542   }
2543
2544   let AddedComplexity = 10 in
2545   def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2546                  (outs regtype:$Rt),
2547                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2548                  [(set (Ty regtype:$Rt),
2549                        (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2550                                              ro_Xextend8:$extend)))]>,
2551            Sched<[WriteLDIdx, ReadAdrBase]> {
2552     let Inst{13} = 0b1;
2553   }
2554
2555   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2556 }
2557
2558 multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2559                     string asm, ValueType Ty, SDPatternOperator storeop> {
2560   let AddedComplexity = 10 in
2561   def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2562                  (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2563                  [(storeop (Ty regtype:$Rt),
2564                            (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2565                                          ro_Wextend8:$extend))]>,
2566             Sched<[WriteSTIdx, ReadAdrBase]> {
2567     let Inst{13} = 0b0;
2568   }
2569
2570   let AddedComplexity = 10 in
2571   def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2572                  (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2573                  [(storeop (Ty regtype:$Rt),
2574                            (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2575                                          ro_Xextend8:$extend))]>,
2576             Sched<[WriteSTIdx, ReadAdrBase]> {
2577     let Inst{13} = 0b1;
2578   }
2579
2580   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2581 }
2582
2583 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2584                       string asm, dag ins, dag outs, list<dag> pat>
2585     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2586   bits<5> Rt;
2587   bits<5> Rn;
2588   bits<5> Rm;
2589   bits<2> extend;
2590   let Inst{31-30} = sz;
2591   let Inst{29-27} = 0b111;
2592   let Inst{26}    = V;
2593   let Inst{25-24} = 0b00;
2594   let Inst{23-22} = opc;
2595   let Inst{21}    = 1;
2596   let Inst{20-16} = Rm;
2597   let Inst{15}    = extend{1}; // sign extend Rm?
2598   let Inst{14}    = 1;
2599   let Inst{12}    = extend{0}; // do shift?
2600   let Inst{11-10} = 0b10;
2601   let Inst{9-5}   = Rn;
2602   let Inst{4-0}   = Rt;
2603 }
2604
2605 multiclass Load16RO<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 : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2609                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2610                  [(set (Ty regtype:$Rt),
2611                        (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2612                                               ro_Wextend16:$extend)))]>,
2613             Sched<[WriteLDIdx, ReadAdrBase]> {
2614     let Inst{13} = 0b0;
2615   }
2616
2617   let AddedComplexity = 10 in
2618   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2619                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2620                  [(set (Ty regtype:$Rt),
2621                        (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2622                                              ro_Xextend16:$extend)))]>,
2623             Sched<[WriteLDIdx, ReadAdrBase]> {
2624     let Inst{13} = 0b1;
2625   }
2626
2627   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2628 }
2629
2630 multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2631                      string asm, ValueType Ty, SDPatternOperator storeop> {
2632   let AddedComplexity = 10 in
2633   def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2634                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2635                 [(storeop (Ty regtype:$Rt),
2636                           (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2637                                          ro_Wextend16:$extend))]>,
2638            Sched<[WriteSTIdx, ReadAdrBase]> {
2639     let Inst{13} = 0b0;
2640   }
2641
2642   let AddedComplexity = 10 in
2643   def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2644                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2645                 [(storeop (Ty regtype:$Rt),
2646                           (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2647                                          ro_Xextend16:$extend))]>,
2648            Sched<[WriteSTIdx, ReadAdrBase]> {
2649     let Inst{13} = 0b1;
2650   }
2651
2652   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2653 }
2654
2655 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2656                       string asm, dag ins, dag outs, list<dag> pat>
2657     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2658   bits<5> Rt;
2659   bits<5> Rn;
2660   bits<5> Rm;
2661   bits<2> extend;
2662   let Inst{31-30} = sz;
2663   let Inst{29-27} = 0b111;
2664   let Inst{26}    = V;
2665   let Inst{25-24} = 0b00;
2666   let Inst{23-22} = opc;
2667   let Inst{21}    = 1;
2668   let Inst{20-16} = Rm;
2669   let Inst{15}    = extend{1}; // sign extend Rm?
2670   let Inst{14}    = 1;
2671   let Inst{12}    = extend{0}; // do shift?
2672   let Inst{11-10} = 0b10;
2673   let Inst{9-5}   = Rn;
2674   let Inst{4-0}   = Rt;
2675 }
2676
2677 multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2678                     string asm, ValueType Ty, SDPatternOperator loadop> {
2679   let AddedComplexity = 10 in
2680   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2681                  (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2682                  [(set (Ty regtype:$Rt),
2683                        (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2684                                               ro_Wextend32:$extend)))]>,
2685            Sched<[WriteLDIdx, ReadAdrBase]> {
2686     let Inst{13} = 0b0;
2687   }
2688
2689   let AddedComplexity = 10 in
2690   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2691                  (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2692                  [(set (Ty regtype:$Rt),
2693                        (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2694                                               ro_Xextend32:$extend)))]>,
2695            Sched<[WriteLDIdx, ReadAdrBase]> {
2696     let Inst{13} = 0b1;
2697   }
2698
2699   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2700 }
2701
2702 multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2703                      string asm, ValueType Ty, SDPatternOperator storeop> {
2704   let AddedComplexity = 10 in
2705   def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2706                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2707                 [(storeop (Ty regtype:$Rt),
2708                           (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2709                                          ro_Wextend32:$extend))]>,
2710             Sched<[WriteSTIdx, ReadAdrBase]> {
2711     let Inst{13} = 0b0;
2712   }
2713
2714   let AddedComplexity = 10 in
2715   def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2716                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2717                 [(storeop (Ty regtype:$Rt),
2718                           (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2719                                         ro_Xextend32:$extend))]>,
2720             Sched<[WriteSTIdx, ReadAdrBase]> {
2721     let Inst{13} = 0b1;
2722   }
2723
2724   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2725 }
2726
2727 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2728                       string asm, dag ins, dag outs, list<dag> pat>
2729     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2730   bits<5> Rt;
2731   bits<5> Rn;
2732   bits<5> Rm;
2733   bits<2> extend;
2734   let Inst{31-30} = sz;
2735   let Inst{29-27} = 0b111;
2736   let Inst{26}    = V;
2737   let Inst{25-24} = 0b00;
2738   let Inst{23-22} = opc;
2739   let Inst{21}    = 1;
2740   let Inst{20-16} = Rm;
2741   let Inst{15}    = extend{1}; // sign extend Rm?
2742   let Inst{14}    = 1;
2743   let Inst{12}    = extend{0}; // do shift?
2744   let Inst{11-10} = 0b10;
2745   let Inst{9-5}   = Rn;
2746   let Inst{4-0}   = Rt;
2747 }
2748
2749 multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2750                     string asm, ValueType Ty, SDPatternOperator loadop> {
2751   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2752   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2753                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2754                 [(set (Ty regtype:$Rt),
2755                       (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2756                                              ro_Wextend64:$extend)))]>,
2757            Sched<[WriteLDIdx, ReadAdrBase]> {
2758     let Inst{13} = 0b0;
2759   }
2760
2761   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2762   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2763                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2764                  [(set (Ty regtype:$Rt),
2765                        (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2766                                               ro_Xextend64:$extend)))]>,
2767            Sched<[WriteLDIdx, ReadAdrBase]> {
2768     let Inst{13} = 0b1;
2769   }
2770
2771   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2772 }
2773
2774 multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2775                      string asm, ValueType Ty, SDPatternOperator storeop> {
2776   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2777   def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2778                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2779                 [(storeop (Ty regtype:$Rt),
2780                           (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2781                                          ro_Wextend64:$extend))]>,
2782             Sched<[WriteSTIdx, ReadAdrBase]> {
2783     let Inst{13} = 0b0;
2784   }
2785
2786   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2787   def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2788                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2789                 [(storeop (Ty regtype:$Rt),
2790                           (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2791                                          ro_Xextend64:$extend))]>,
2792             Sched<[WriteSTIdx, ReadAdrBase]> {
2793     let Inst{13} = 0b1;
2794   }
2795
2796   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2797 }
2798
2799 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2800                       string asm, dag ins, dag outs, list<dag> pat>
2801     : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2802   bits<5> Rt;
2803   bits<5> Rn;
2804   bits<5> Rm;
2805   bits<2> extend;
2806   let Inst{31-30} = sz;
2807   let Inst{29-27} = 0b111;
2808   let Inst{26}    = V;
2809   let Inst{25-24} = 0b00;
2810   let Inst{23-22} = opc;
2811   let Inst{21}    = 1;
2812   let Inst{20-16} = Rm;
2813   let Inst{15}    = extend{1}; // sign extend Rm?
2814   let Inst{14}    = 1;
2815   let Inst{12}    = extend{0}; // do shift?
2816   let Inst{11-10} = 0b10;
2817   let Inst{9-5}   = Rn;
2818   let Inst{4-0}   = Rt;
2819 }
2820
2821 multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2822                      string asm, ValueType Ty, SDPatternOperator loadop> {
2823   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2824   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2825                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2826                  [(set (Ty regtype:$Rt),
2827                        (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2828                                                ro_Wextend128:$extend)))]>,
2829             Sched<[WriteLDIdx, ReadAdrBase]> {
2830     let Inst{13} = 0b0;
2831   }
2832
2833   let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2834   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2835                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2836                  [(set (Ty regtype:$Rt),
2837                        (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2838                                                ro_Xextend128:$extend)))]>,
2839             Sched<[WriteLDIdx, ReadAdrBase]> {
2840     let Inst{13} = 0b1;
2841   }
2842
2843   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2844 }
2845
2846 multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2847                       string asm, ValueType Ty, SDPatternOperator storeop> {
2848   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2849   def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2850                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2851                 [(storeop (Ty regtype:$Rt),
2852                           (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2853                                           ro_Wextend128:$extend))]>,
2854             Sched<[WriteSTIdx, ReadAdrBase]> {
2855     let Inst{13} = 0b0;
2856   }
2857
2858   let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2859   def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2860                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2861                 [(storeop (Ty regtype:$Rt),
2862                           (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2863                                           ro_Xextend128:$extend))]>,
2864             Sched<[WriteSTIdx, ReadAdrBase]> {
2865     let Inst{13} = 0b1;
2866   }
2867
2868   def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2869 }
2870
2871 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2872 class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2873                      string asm, list<dag> pat>
2874     : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2875       Sched<[WriteLD]> {
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 PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2896   def roW : BasePrefetchRO<sz, V, opc, (outs),
2897                 (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2898                 asm, [(AArch64Prefetch imm:$Rt,
2899                                      (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2900                                                     ro_Wextend64:$extend))]> {
2901     let Inst{13} = 0b0;
2902   }
2903
2904   def roX : BasePrefetchRO<sz, V, opc, (outs),
2905                 (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2906                 asm,  [(AArch64Prefetch imm:$Rt,
2907                                       (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2908                                                      ro_Xextend64:$extend))]> {
2909     let Inst{13} = 0b1;
2910   }
2911
2912   def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2913                (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2914                                                  GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2915 }
2916
2917 //---
2918 // Load/store unscaled immediate
2919 //---
2920
2921 def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2922 def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2923 def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2924 def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2925 def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2926
2927 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2928                            string asm, list<dag> pattern>
2929     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2930   bits<5> Rt;
2931   bits<5> Rn;
2932   bits<9> offset;
2933   let Inst{31-30} = sz;
2934   let Inst{29-27} = 0b111;
2935   let Inst{26}    = V;
2936   let Inst{25-24} = 0b00;
2937   let Inst{23-22} = opc;
2938   let Inst{21}    = 0;
2939   let Inst{20-12} = offset;
2940   let Inst{11-10} = 0b00;
2941   let Inst{9-5}   = Rn;
2942   let Inst{4-0}   = Rt;
2943
2944   let DecoderMethod = "DecodeSignedLdStInstruction";
2945 }
2946
2947 multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2948                    string asm, list<dag> pattern> {
2949   let AddedComplexity = 1 in // try this before LoadUI
2950   def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2951                                (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
2952           Sched<[WriteLD]>;
2953
2954   def : InstAlias<asm # " $Rt, [$Rn]",
2955                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2956 }
2957
2958 multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2959                          string asm, list<dag> pattern> {
2960   let AddedComplexity = 1 in // try this before StoreUI
2961   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
2962                                (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
2963                                asm, pattern>,
2964           Sched<[WriteST]>;
2965
2966   def : InstAlias<asm # " $Rt, [$Rn]",
2967                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
2968 }
2969
2970 multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
2971                             list<dag> pat> {
2972   let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2973   def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
2974                                (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
2975                                asm, pat>,
2976           Sched<[WriteLD]>;
2977
2978   def : InstAlias<asm # " $Rt, [$Rn]",
2979                   (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
2980 }
2981
2982 //---
2983 // Load/store unscaled immediate, unprivileged
2984 //---
2985
2986 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2987                                 dag oops, dag iops, string asm>
2988     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
2989   bits<5> Rt;
2990   bits<5> Rn;
2991   bits<9> offset;
2992   let Inst{31-30} = sz;
2993   let Inst{29-27} = 0b111;
2994   let Inst{26}    = V;
2995   let Inst{25-24} = 0b00;
2996   let Inst{23-22} = opc;
2997   let Inst{21}    = 0;
2998   let Inst{20-12} = offset;
2999   let Inst{11-10} = 0b10;
3000   let Inst{9-5}   = Rn;
3001   let Inst{4-0}   = Rt;
3002
3003   let DecoderMethod = "DecodeSignedLdStInstruction";
3004 }
3005
3006 multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3007                             RegisterClass regtype, string asm> {
3008   let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3009   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3010                                     (ins GPR64sp:$Rn, simm9:$offset), asm>,
3011           Sched<[WriteLD]>;
3012
3013   def : InstAlias<asm # " $Rt, [$Rn]",
3014                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3015 }
3016
3017 multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3018                              RegisterClass regtype, string asm> {
3019   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3020   def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3021                                  (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3022                                  asm>,
3023           Sched<[WriteST]>;
3024
3025   def : InstAlias<asm # " $Rt, [$Rn]",
3026                   (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3027 }
3028
3029 //---
3030 // Load/store pre-indexed
3031 //---
3032
3033 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3034                           string asm, string cstr, list<dag> pat>
3035     : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3036   bits<5> Rt;
3037   bits<5> Rn;
3038   bits<9> offset;
3039   let Inst{31-30} = sz;
3040   let Inst{29-27} = 0b111;
3041   let Inst{26}    = V;
3042   let Inst{25-24} = 0;
3043   let Inst{23-22} = opc;
3044   let Inst{21}    = 0;
3045   let Inst{20-12} = offset;
3046   let Inst{11-10} = 0b11;
3047   let Inst{9-5}   = Rn;
3048   let Inst{4-0}   = Rt;
3049
3050   let DecoderMethod = "DecodeSignedLdStInstruction";
3051 }
3052
3053 let hasSideEffects = 0 in {
3054 let mayStore = 0, mayLoad = 1 in
3055 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3056              string asm>
3057     : BaseLoadStorePreIdx<sz, V, opc,
3058                      (outs GPR64sp:$wback, regtype:$Rt),
3059                      (ins GPR64sp:$Rn, simm9:$offset), asm,
3060                      "$Rn = $wback,@earlyclobber $wback", []>,
3061       Sched<[WriteLD, WriteAdr]>;
3062
3063 let mayStore = 1, mayLoad = 0 in
3064 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3065                   string asm, SDPatternOperator storeop, ValueType Ty>
3066     : BaseLoadStorePreIdx<sz, V, opc,
3067                       (outs GPR64sp:$wback),
3068                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3069                       asm, "$Rn = $wback,@earlyclobber $wback",
3070       [(set GPR64sp:$wback,
3071             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3072       Sched<[WriteAdr, WriteST]>;
3073 } // hasSideEffects = 0
3074
3075 //---
3076 // Load/store post-indexed
3077 //---
3078
3079 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3080                           string asm, string cstr, list<dag> pat>
3081     : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3082   bits<5> Rt;
3083   bits<5> Rn;
3084   bits<9> offset;
3085   let Inst{31-30} = sz;
3086   let Inst{29-27} = 0b111;
3087   let Inst{26}    = V;
3088   let Inst{25-24} = 0b00;
3089   let Inst{23-22} = opc;
3090   let Inst{21}    = 0b0;
3091   let Inst{20-12} = offset;
3092   let Inst{11-10} = 0b01;
3093   let Inst{9-5}   = Rn;
3094   let Inst{4-0}   = Rt;
3095
3096   let DecoderMethod = "DecodeSignedLdStInstruction";
3097 }
3098
3099 let hasSideEffects = 0 in {
3100 let mayStore = 0, mayLoad = 1 in
3101 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3102              string asm>
3103     : BaseLoadStorePostIdx<sz, V, opc,
3104                       (outs GPR64sp:$wback, regtype:$Rt),
3105                       (ins GPR64sp:$Rn, simm9:$offset),
3106                       asm, "$Rn = $wback,@earlyclobber $wback", []>,
3107       Sched<[WriteLD, WriteI]>;
3108
3109 let mayStore = 1, mayLoad = 0 in
3110 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3111                    string asm, SDPatternOperator storeop, ValueType Ty>
3112     : BaseLoadStorePostIdx<sz, V, opc,
3113                       (outs GPR64sp:$wback),
3114                       (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3115                        asm, "$Rn = $wback,@earlyclobber $wback",
3116       [(set GPR64sp:$wback,
3117             (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3118     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3119 } // hasSideEffects = 0
3120
3121
3122 //---
3123 // Load/store pair
3124 //---
3125
3126 // (indexed, offset)
3127
3128 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3129                               string asm>
3130     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3131   bits<5> Rt;
3132   bits<5> Rt2;
3133   bits<5> Rn;
3134   bits<7> offset;
3135   let Inst{31-30} = opc;
3136   let Inst{29-27} = 0b101;
3137   let Inst{26}    = V;
3138   let Inst{25-23} = 0b010;
3139   let Inst{22}    = L;
3140   let Inst{21-15} = offset;
3141   let Inst{14-10} = Rt2;
3142   let Inst{9-5}   = Rn;
3143   let Inst{4-0}   = Rt;
3144
3145   let DecoderMethod = "DecodePairLdStInstruction";
3146 }
3147
3148 multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3149                           Operand indextype, string asm> {
3150   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3151   def i : BaseLoadStorePairOffset<opc, V, 1,
3152                                   (outs regtype:$Rt, regtype:$Rt2),
3153                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3154           Sched<[WriteLD, WriteLDHi]>;
3155
3156   def : InstAlias<asm # " $Rt, $Rt2, [$Rn]",
3157                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3158                                                   GPR64sp:$Rn, 0)>;
3159 }
3160
3161
3162 multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3163                            Operand indextype, string asm> {
3164   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3165   def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3166                                   (ins regtype:$Rt, regtype:$Rt2,
3167                                        GPR64sp:$Rn, indextype:$offset),
3168                                   asm>,
3169           Sched<[WriteSTP]>;
3170
3171   def : InstAlias<asm # " $Rt, $Rt2, [$Rn]",
3172                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3173                                                   GPR64sp:$Rn, 0)>;
3174 }
3175
3176 // (pre-indexed)
3177 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3178                               string asm>
3179     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3180   bits<5> Rt;
3181   bits<5> Rt2;
3182   bits<5> Rn;
3183   bits<7> offset;
3184   let Inst{31-30} = opc;
3185   let Inst{29-27} = 0b101;
3186   let Inst{26}    = V;
3187   let Inst{25-23} = 0b011;
3188   let Inst{22}    = L;
3189   let Inst{21-15} = offset;
3190   let Inst{14-10} = Rt2;
3191   let Inst{9-5}   = Rn;
3192   let Inst{4-0}   = Rt;
3193
3194   let DecoderMethod = "DecodePairLdStInstruction";
3195 }
3196
3197 let hasSideEffects = 0 in {
3198 let mayStore = 0, mayLoad = 1 in
3199 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3200                      Operand indextype, string asm>
3201     : BaseLoadStorePairPreIdx<opc, V, 1,
3202                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3203                               (ins GPR64sp:$Rn, indextype:$offset), asm>,
3204       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3205
3206 let mayStore = 1, mayLoad = 0 in
3207 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3208                       Operand indextype, string asm>
3209     : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3210                              (ins regtype:$Rt, regtype:$Rt2,
3211                                   GPR64sp:$Rn, indextype:$offset),
3212                              asm>,
3213       Sched<[WriteAdr, WriteSTP]>;
3214 } // hasSideEffects = 0
3215
3216 // (post-indexed)
3217
3218 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3219                               string asm>
3220     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3221   bits<5> Rt;
3222   bits<5> Rt2;
3223   bits<5> Rn;
3224   bits<7> offset;
3225   let Inst{31-30} = opc;
3226   let Inst{29-27} = 0b101;
3227   let Inst{26}    = V;
3228   let Inst{25-23} = 0b001;
3229   let Inst{22}    = L;
3230   let Inst{21-15} = offset;
3231   let Inst{14-10} = Rt2;
3232   let Inst{9-5}   = Rn;
3233   let Inst{4-0}   = Rt;
3234
3235   let DecoderMethod = "DecodePairLdStInstruction";
3236 }
3237
3238 let hasSideEffects = 0 in {
3239 let mayStore = 0, mayLoad = 1 in
3240 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3241                       Operand idxtype, string asm>
3242     : BaseLoadStorePairPostIdx<opc, V, 1,
3243                               (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3244                               (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3245       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3246
3247 let mayStore = 1, mayLoad = 0 in
3248 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3249                        Operand idxtype, string asm>
3250     : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
3251                              (ins GPR64sp:$wback, regtype:$Rt, regtype:$Rt2,
3252                                   GPR64sp:$Rn, idxtype:$offset),
3253                              asm>,
3254       Sched<[WriteAdr, WriteSTP]>;
3255 } // hasSideEffects = 0
3256
3257 //  (no-allocate)
3258
3259 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3260                               string asm>
3261     : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3262   bits<5> Rt;
3263   bits<5> Rt2;
3264   bits<5> Rn;
3265   bits<7> offset;
3266   let Inst{31-30} = opc;
3267   let Inst{29-27} = 0b101;
3268   let Inst{26}    = V;
3269   let Inst{25-23} = 0b000;
3270   let Inst{22}    = L;
3271   let Inst{21-15} = offset;
3272   let Inst{14-10} = Rt2;
3273   let Inst{9-5}   = Rn;
3274   let Inst{4-0}   = Rt;
3275
3276   let DecoderMethod = "DecodePairLdStInstruction";
3277 }
3278
3279 multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3280                            Operand indextype, string asm> {
3281   let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3282   def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3283                                    (outs regtype:$Rt, regtype:$Rt2),
3284                                    (ins GPR64sp:$Rn, indextype:$offset), asm>,
3285           Sched<[WriteLD, WriteLDHi]>;
3286
3287
3288   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3289                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3290                                                   GPR64sp:$Rn, 0)>;
3291 }
3292
3293 multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3294                       Operand indextype, string asm> {
3295   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3296   def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3297                                    (ins regtype:$Rt, regtype:$Rt2,
3298                                         GPR64sp:$Rn, indextype:$offset),
3299                                    asm>,
3300           Sched<[WriteSTP]>;
3301
3302   def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3303                   (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3304                                                   GPR64sp:$Rn, 0)>;
3305 }
3306
3307 //---
3308 // Load/store exclusive
3309 //---
3310
3311 // True exclusive operations write to and/or read from the system's exclusive
3312 // monitors, which as far as a compiler is concerned can be modelled as a
3313 // random shared memory address. Hence LoadExclusive mayStore.
3314 //
3315 // Since these instructions have the undefined register bits set to 1 in
3316 // their canonical form, we need a post encoder method to set those bits
3317 // to 1 when encoding these instructions. We do this using the
3318 // fixLoadStoreExclusive function. This function has template parameters:
3319 //
3320 // fixLoadStoreExclusive<int hasRs, int hasRt2>
3321 //
3322 // hasRs indicates that the instruction uses the Rs field, so we won't set
3323 // it to 1 (and the same for Rt2). We don't need template parameters for
3324 // the other register fields since Rt and Rn are always used.
3325 //
3326 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3327 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3328                              dag oops, dag iops, string asm, string operands>
3329     : I<oops, iops, asm, operands, "", []> {
3330   let Inst{31-30} = sz;
3331   let Inst{29-24} = 0b001000;
3332   let Inst{23}    = o2;
3333   let Inst{22}    = L;
3334   let Inst{21}    = o1;
3335   let Inst{15}    = o0;
3336
3337   let DecoderMethod = "DecodeExclusiveLdStInstruction";
3338 }
3339
3340 // Neither Rs nor Rt2 operands.
3341 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3342                                dag oops, dag iops, string asm, string operands>
3343     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3344   bits<5> Rt;
3345   bits<5> Rn;
3346   let Inst{20-16} = 0b11111;
3347   let Unpredictable{20-16} = 0b11111;
3348   let Inst{14-10} = 0b11111;
3349   let Unpredictable{14-10} = 0b11111;
3350   let Inst{9-5} = Rn;
3351   let Inst{4-0} = Rt;
3352
3353   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3354 }
3355
3356 // Simple load acquires don't set the exclusive monitor
3357 let mayLoad = 1, mayStore = 0 in
3358 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3359                   RegisterClass regtype, string asm>
3360     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3361                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3362       Sched<[WriteLD]>;
3363
3364 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3365                     RegisterClass regtype, string asm>
3366     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3367                                (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3368       Sched<[WriteLD]>;
3369
3370 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3371                        RegisterClass regtype, string asm>
3372     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3373                              (outs regtype:$Rt, regtype:$Rt2),
3374                              (ins GPR64sp0:$Rn), asm,
3375                              "\t$Rt, $Rt2, [$Rn]">,
3376       Sched<[WriteLD, WriteLDHi]> {
3377   bits<5> Rt;
3378   bits<5> Rt2;
3379   bits<5> Rn;
3380   let Inst{14-10} = Rt2;
3381   let Inst{9-5} = Rn;
3382   let Inst{4-0} = Rt;
3383
3384   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3385 }
3386
3387 // Simple store release operations do not check the exclusive monitor.
3388 let mayLoad = 0, mayStore = 1 in
3389 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3390                    RegisterClass regtype, string asm>
3391     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3392                                (ins regtype:$Rt, GPR64sp0:$Rn),
3393                                asm, "\t$Rt, [$Rn]">,
3394       Sched<[WriteST]>;
3395
3396 let mayLoad = 1, mayStore = 1 in
3397 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3398                      RegisterClass regtype, string asm>
3399     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3400                              (ins regtype:$Rt, GPR64sp0:$Rn),
3401                              asm, "\t$Ws, $Rt, [$Rn]">,
3402       Sched<[WriteSTX]> {
3403   bits<5> Ws;
3404   bits<5> Rt;
3405   bits<5> Rn;
3406   let Inst{20-16} = Ws;
3407   let Inst{9-5} = Rn;
3408   let Inst{4-0} = Rt;
3409
3410   let Constraints = "@earlyclobber $Ws";
3411   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3412 }
3413
3414 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3415                          RegisterClass regtype, string asm>
3416     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3417                              (outs GPR32:$Ws),
3418                              (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3419                               asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3420       Sched<[WriteSTX]> {
3421   bits<5> Ws;
3422   bits<5> Rt;
3423   bits<5> Rt2;
3424   bits<5> Rn;
3425   let Inst{20-16} = Ws;
3426   let Inst{14-10} = Rt2;
3427   let Inst{9-5} = Rn;
3428   let Inst{4-0} = Rt;
3429
3430   let Constraints = "@earlyclobber $Ws";
3431 }
3432
3433 //---
3434 // Exception generation
3435 //---
3436
3437 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3438 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3439     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3440       Sched<[WriteSys]> {
3441   bits<16> imm;
3442   let Inst{31-24} = 0b11010100;
3443   let Inst{23-21} = op1;
3444   let Inst{20-5}  = imm;
3445   let Inst{4-2}   = 0b000;
3446   let Inst{1-0}   = ll;
3447 }
3448
3449 let Predicates = [HasFPARMv8] in {
3450
3451 //---
3452 // Floating point to integer conversion
3453 //---
3454
3455 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3456                       RegisterClass srcType, RegisterClass dstType,
3457                       string asm, list<dag> pattern>
3458     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3459          asm, "\t$Rd, $Rn", "", pattern>,
3460       Sched<[WriteFCvt]> {
3461   bits<5> Rd;
3462   bits<5> Rn;
3463   let Inst{30-29} = 0b00;
3464   let Inst{28-24} = 0b11110;
3465   let Inst{23-22} = type;
3466   let Inst{21}    = 1;
3467   let Inst{20-19} = rmode;
3468   let Inst{18-16} = opcode;
3469   let Inst{15-10} = 0;
3470   let Inst{9-5}   = Rn;
3471   let Inst{4-0}   = Rd;
3472 }
3473
3474 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3475 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3476                       RegisterClass srcType, RegisterClass dstType,
3477                       Operand immType, string asm, list<dag> pattern>
3478     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3479          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3480       Sched<[WriteFCvt]> {
3481   bits<5> Rd;
3482   bits<5> Rn;
3483   bits<6> scale;
3484   let Inst{30-29} = 0b00;
3485   let Inst{28-24} = 0b11110;
3486   let Inst{23-22} = type;
3487   let Inst{21}    = 0;
3488   let Inst{20-19} = rmode;
3489   let Inst{18-16} = opcode;
3490   let Inst{15-10} = scale;
3491   let Inst{9-5}   = Rn;
3492   let Inst{4-0}   = Rd;
3493 }
3494
3495 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3496            SDPatternOperator OpN> {
3497   // Unscaled single-precision to 32-bit
3498   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3499                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3500     let Inst{31} = 0; // 32-bit GPR flag
3501   }
3502
3503   // Unscaled single-precision to 64-bit
3504   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3505                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3506     let Inst{31} = 1; // 64-bit GPR flag
3507   }
3508
3509   // Unscaled double-precision to 32-bit
3510   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3511                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3512     let Inst{31} = 0; // 32-bit GPR flag
3513   }
3514
3515   // Unscaled double-precision to 64-bit
3516   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3517                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3518     let Inst{31} = 1; // 64-bit GPR flag
3519   }
3520 }
3521
3522 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3523                              SDPatternOperator OpN> {
3524   // Scaled single-precision to 32-bit
3525   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3526                               fixedpoint_f32_i32, asm,
3527               [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3528                                           fixedpoint_f32_i32:$scale)))]> {
3529     let Inst{31} = 0; // 32-bit GPR flag
3530     let scale{5} = 1;
3531   }
3532
3533   // Scaled single-precision to 64-bit
3534   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3535                               fixedpoint_f32_i64, asm,
3536               [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3537                                           fixedpoint_f32_i64:$scale)))]> {
3538     let Inst{31} = 1; // 64-bit GPR flag
3539   }
3540
3541   // Scaled double-precision to 32-bit
3542   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3543                               fixedpoint_f64_i32, asm,
3544               [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3545                                           fixedpoint_f64_i32:$scale)))]> {
3546     let Inst{31} = 0; // 32-bit GPR flag
3547     let scale{5} = 1;
3548   }
3549
3550   // Scaled double-precision to 64-bit
3551   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3552                               fixedpoint_f64_i64, asm,
3553               [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3554                                           fixedpoint_f64_i64:$scale)))]> {
3555     let Inst{31} = 1; // 64-bit GPR flag
3556   }
3557 }
3558
3559 //---
3560 // Integer to floating point conversion
3561 //---
3562
3563 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3564 class BaseIntegerToFP<bit isUnsigned,
3565                       RegisterClass srcType, RegisterClass dstType,
3566                       Operand immType, string asm, list<dag> pattern>
3567     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3568          asm, "\t$Rd, $Rn, $scale", "", pattern>,
3569       Sched<[WriteFCvt]> {
3570   bits<5> Rd;
3571   bits<5> Rn;
3572   bits<6> scale;
3573   let Inst{30-23} = 0b00111100;
3574   let Inst{21-17} = 0b00001;
3575   let Inst{16}    = isUnsigned;
3576   let Inst{15-10} = scale;
3577   let Inst{9-5}   = Rn;
3578   let Inst{4-0}   = Rd;
3579 }
3580
3581 class BaseIntegerToFPUnscaled<bit isUnsigned,
3582                       RegisterClass srcType, RegisterClass dstType,
3583                       ValueType dvt, string asm, SDNode node>
3584     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3585          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3586       Sched<[WriteFCvt]> {
3587   bits<5> Rd;
3588   bits<5> Rn;
3589   bits<6> scale;
3590   let Inst{30-23} = 0b00111100;
3591   let Inst{21-17} = 0b10001;
3592   let Inst{16}    = isUnsigned;
3593   let Inst{15-10} = 0b000000;
3594   let Inst{9-5}   = Rn;
3595   let Inst{4-0}   = Rd;
3596 }
3597
3598 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3599   // Unscaled
3600   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3601     let Inst{31} = 0; // 32-bit GPR flag
3602     let Inst{22} = 0; // 32-bit FPR flag
3603   }
3604
3605   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3606     let Inst{31} = 0; // 32-bit GPR flag
3607     let Inst{22} = 1; // 64-bit FPR flag
3608   }
3609
3610   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3611     let Inst{31} = 1; // 64-bit GPR flag
3612     let Inst{22} = 0; // 32-bit FPR flag
3613   }
3614
3615   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3616     let Inst{31} = 1; // 64-bit GPR flag
3617     let Inst{22} = 1; // 64-bit FPR flag
3618   }
3619
3620   // Scaled
3621   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3622                              [(set FPR32:$Rd,
3623                                    (fdiv (node GPR32:$Rn),
3624                                          fixedpoint_f32_i32:$scale))]> {
3625     let Inst{31} = 0; // 32-bit GPR flag
3626     let Inst{22} = 0; // 32-bit FPR flag
3627     let scale{5} = 1;
3628   }
3629
3630   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3631                              [(set FPR64:$Rd,
3632                                    (fdiv (node GPR32:$Rn),
3633                                          fixedpoint_f64_i32:$scale))]> {
3634     let Inst{31} = 0; // 32-bit GPR flag
3635     let Inst{22} = 1; // 64-bit FPR flag
3636     let scale{5} = 1;
3637   }
3638
3639   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3640                              [(set FPR32:$Rd,
3641                                    (fdiv (node GPR64:$Rn),
3642                                          fixedpoint_f32_i64:$scale))]> {
3643     let Inst{31} = 1; // 64-bit GPR flag
3644     let Inst{22} = 0; // 32-bit FPR flag
3645   }
3646
3647   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3648                              [(set FPR64:$Rd,
3649                                    (fdiv (node GPR64:$Rn),
3650                                          fixedpoint_f64_i64:$scale))]> {
3651     let Inst{31} = 1; // 64-bit GPR flag
3652     let Inst{22} = 1; // 64-bit FPR flag
3653   }
3654 }
3655
3656 //---
3657 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3658 //---
3659
3660 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3661 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3662                       RegisterClass srcType, RegisterClass dstType,
3663                       string asm>
3664     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3665         // We use COPY_TO_REGCLASS for these bitconvert operations.
3666         // copyPhysReg() expands the resultant COPY instructions after
3667         // regalloc is done. This gives greater freedom for the allocator
3668         // and related passes (coalescing, copy propagation, et. al.) to
3669         // be more effective.
3670         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3671       Sched<[WriteFCopy]> {
3672   bits<5> Rd;
3673   bits<5> Rn;
3674   let Inst{30-23} = 0b00111100;
3675   let Inst{21}    = 1;
3676   let Inst{20-19} = rmode;
3677   let Inst{18-16} = opcode;
3678   let Inst{15-10} = 0b000000;
3679   let Inst{9-5}   = Rn;
3680   let Inst{4-0}   = Rd;
3681 }
3682
3683 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3684 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3685                      RegisterClass srcType, RegisterOperand dstType, string asm,
3686                      string kind>
3687     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3688         "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3689       Sched<[WriteFCopy]> {
3690   bits<5> Rd;
3691   bits<5> Rn;
3692   let Inst{30-23} = 0b00111101;
3693   let Inst{21}    = 1;
3694   let Inst{20-19} = rmode;
3695   let Inst{18-16} = opcode;
3696   let Inst{15-10} = 0b000000;
3697   let Inst{9-5}   = Rn;
3698   let Inst{4-0}   = Rd;
3699
3700   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3701 }
3702
3703 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3704 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3705                      RegisterOperand srcType, RegisterClass dstType, string asm,
3706                      string kind>
3707     : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3708         "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3709       Sched<[WriteFCopy]> {
3710   bits<5> Rd;
3711   bits<5> Rn;
3712   let Inst{30-23} = 0b00111101;
3713   let Inst{21}    = 1;
3714   let Inst{20-19} = rmode;
3715   let Inst{18-16} = opcode;
3716   let Inst{15-10} = 0b000000;
3717   let Inst{9-5}   = Rn;
3718   let Inst{4-0}   = Rd;
3719
3720   let DecoderMethod =  "DecodeFMOVLaneInstruction";
3721 }
3722
3723
3724
3725 multiclass UnscaledConversion<string asm> {
3726   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3727     let Inst{31} = 0; // 32-bit GPR flag
3728     let Inst{22} = 0; // 32-bit FPR flag
3729   }
3730
3731   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3732     let Inst{31} = 1; // 64-bit GPR flag
3733     let Inst{22} = 1; // 64-bit FPR flag
3734   }
3735
3736   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3737     let Inst{31} = 0; // 32-bit GPR flag
3738     let Inst{22} = 0; // 32-bit FPR flag
3739   }
3740
3741   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3742     let Inst{31} = 1; // 64-bit GPR flag
3743     let Inst{22} = 1; // 64-bit FPR flag
3744   }
3745
3746   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3747                                              asm, ".d"> {
3748     let Inst{31} = 1;
3749     let Inst{22} = 0;
3750   }
3751
3752   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3753                                                asm, ".d"> {
3754     let Inst{31} = 1;
3755     let Inst{22} = 0;
3756   }
3757 }
3758
3759 //---
3760 // Floating point conversion
3761 //---
3762
3763 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3764                        RegisterClass srcType, string asm, list<dag> pattern>
3765     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3766       Sched<[WriteFCvt]> {
3767   bits<5> Rd;
3768   bits<5> Rn;
3769   let Inst{31-24} = 0b00011110;
3770   let Inst{23-22} = type;
3771   let Inst{21-17} = 0b10001;
3772   let Inst{16-15} = opcode;
3773   let Inst{14-10} = 0b10000;
3774   let Inst{9-5}   = Rn;
3775   let Inst{4-0}   = Rd;
3776 }
3777
3778 multiclass FPConversion<string asm> {
3779   // Double-precision to Half-precision
3780   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3781                              [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3782
3783   // Double-precision to Single-precision
3784   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3785                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3786
3787   // Half-precision to Double-precision
3788   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3789                              [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3790
3791   // Half-precision to Single-precision
3792   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3793                              [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3794
3795   // Single-precision to Double-precision
3796   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3797                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3798
3799   // Single-precision to Half-precision
3800   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3801                              [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3802 }
3803
3804 //---
3805 // Single operand floating point data processing
3806 //---
3807
3808 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3809 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3810                               ValueType vt, string asm, SDPatternOperator node>
3811     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3812          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3813       Sched<[WriteF]> {
3814   bits<5> Rd;
3815   bits<5> Rn;
3816   let Inst{31-23} = 0b000111100;
3817   let Inst{21-19} = 0b100;
3818   let Inst{18-15} = opcode;
3819   let Inst{14-10} = 0b10000;
3820   let Inst{9-5}   = Rn;
3821   let Inst{4-0}   = Rd;
3822 }
3823
3824 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3825                                SDPatternOperator node = null_frag> {
3826   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3827     let Inst{22} = 0; // 32-bit size flag
3828   }
3829
3830   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3831     let Inst{22} = 1; // 64-bit size flag
3832   }
3833 }
3834
3835 //---
3836 // Two operand floating point data processing
3837 //---
3838
3839 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3840 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3841                            string asm, list<dag> pat>
3842     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3843          asm, "\t$Rd, $Rn, $Rm", "", pat>,
3844       Sched<[WriteF]> {
3845   bits<5> Rd;
3846   bits<5> Rn;
3847   bits<5> Rm;
3848   let Inst{31-23} = 0b000111100;
3849   let Inst{21}    = 1;
3850   let Inst{20-16} = Rm;
3851   let Inst{15-12} = opcode;
3852   let Inst{11-10} = 0b10;
3853   let Inst{9-5}   = Rn;
3854   let Inst{4-0}   = Rd;
3855 }
3856
3857 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3858                             SDPatternOperator node = null_frag> {
3859   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3860                          [(set (f32 FPR32:$Rd),
3861                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3862     let Inst{22} = 0; // 32-bit size flag
3863   }
3864
3865   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3866                          [(set (f64 FPR64:$Rd),
3867                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3868     let Inst{22} = 1; // 64-bit size flag
3869   }
3870 }
3871
3872 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3873   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3874                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3875     let Inst{22} = 0; // 32-bit size flag
3876   }
3877
3878   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3879                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3880     let Inst{22} = 1; // 64-bit size flag
3881   }
3882 }
3883
3884
3885 //---
3886 // Three operand floating point data processing
3887 //---
3888
3889 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3890                              RegisterClass regtype, string asm, list<dag> pat>
3891     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3892          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3893       Sched<[WriteFMul]> {
3894   bits<5> Rd;
3895   bits<5> Rn;
3896   bits<5> Rm;
3897   bits<5> Ra;
3898   let Inst{31-23} = 0b000111110;
3899   let Inst{21}    = isNegated;
3900   let Inst{20-16} = Rm;
3901   let Inst{15}    = isSub;
3902   let Inst{14-10} = Ra;
3903   let Inst{9-5}   = Rn;
3904   let Inst{4-0}   = Rd;
3905 }
3906
3907 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3908                               SDPatternOperator node> {
3909   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3910             [(set FPR32:$Rd,
3911                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3912     let Inst{22} = 0; // 32-bit size flag
3913   }
3914
3915   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3916             [(set FPR64:$Rd,
3917                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3918     let Inst{22} = 1; // 64-bit size flag
3919   }
3920 }
3921
3922 //---
3923 // Floating point data comparisons
3924 //---
3925
3926 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3927 class BaseOneOperandFPComparison<bit signalAllNans,
3928                                  RegisterClass regtype, string asm,
3929                                  list<dag> pat>
3930     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3931       Sched<[WriteFCmp]> {
3932   bits<5> Rn;
3933   let Inst{31-23} = 0b000111100;
3934   let Inst{21}    = 1;
3935
3936   let Inst{15-10} = 0b001000;
3937   let Inst{9-5}   = Rn;
3938   let Inst{4}     = signalAllNans;
3939   let Inst{3-0}   = 0b1000;
3940
3941   // Rm should be 0b00000 canonically, but we need to accept any value.
3942   let PostEncoderMethod = "fixOneOperandFPComparison";
3943 }
3944
3945 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3946 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3947                                 string asm, list<dag> pat>
3948     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3949       Sched<[WriteFCmp]> {
3950   bits<5> Rm;
3951   bits<5> Rn;
3952   let Inst{31-23} = 0b000111100;
3953   let Inst{21}    = 1;
3954   let Inst{20-16} = Rm;
3955   let Inst{15-10} = 0b001000;
3956   let Inst{9-5}   = Rn;
3957   let Inst{4}     = signalAllNans;
3958   let Inst{3-0}   = 0b0000;
3959 }
3960
3961 multiclass FPComparison<bit signalAllNans, string asm,
3962                         SDPatternOperator OpNode = null_frag> {
3963   let Defs = [NZCV] in {
3964   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3965       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
3966     let Inst{22} = 0;
3967   }
3968
3969   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3970       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
3971     let Inst{22} = 0;
3972   }
3973
3974   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3975       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
3976     let Inst{22} = 1;
3977   }
3978
3979   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3980       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
3981     let Inst{22} = 1;
3982   }
3983   } // Defs = [NZCV]
3984 }
3985
3986 //---
3987 // Floating point conditional comparisons
3988 //---
3989
3990 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3991 class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
3992                            string mnemonic, list<dag> pat>
3993     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3994          mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
3995       Sched<[WriteFCmp]> {
3996   let Uses = [NZCV];
3997   let Defs = [NZCV];
3998
3999   bits<5> Rn;
4000   bits<5> Rm;
4001   bits<4> nzcv;
4002   bits<4> cond;
4003
4004   let Inst{31-23} = 0b000111100;
4005   let Inst{21}    = 1;
4006   let Inst{20-16} = Rm;
4007   let Inst{15-12} = cond;
4008   let Inst{11-10} = 0b01;
4009   let Inst{9-5}   = Rn;
4010   let Inst{4}     = signalAllNans;
4011   let Inst{3-0}   = nzcv;
4012 }
4013
4014 multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4015                             SDPatternOperator OpNode = null_frag> {
4016   def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4017       [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4018                           (i32 imm:$cond), NZCV))]> {
4019     let Inst{22} = 0;
4020   }
4021   def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4022       [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4023                           (i32 imm:$cond), NZCV))]> {
4024     let Inst{22} = 1;
4025   }
4026 }
4027
4028 //---
4029 // Floating point conditional select
4030 //---
4031
4032 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4033     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4034          asm, "\t$Rd, $Rn, $Rm, $cond", "",
4035          [(set regtype:$Rd,
4036                (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4037                           (i32 imm:$cond), NZCV))]>,
4038       Sched<[WriteF]> {
4039   bits<5> Rd;
4040   bits<5> Rn;
4041   bits<5> Rm;
4042   bits<4> cond;
4043
4044   let Inst{31-23} = 0b000111100;
4045   let Inst{21}    = 1;
4046   let Inst{20-16} = Rm;
4047   let Inst{15-12} = cond;
4048   let Inst{11-10} = 0b11;
4049   let Inst{9-5}   = Rn;
4050   let Inst{4-0}   = Rd;
4051 }
4052
4053 multiclass FPCondSelect<string asm> {
4054   let Uses = [NZCV] in {
4055   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4056     let Inst{22} = 0;
4057   }
4058
4059   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4060     let Inst{22} = 1;
4061   }
4062   } // Uses = [NZCV]
4063 }
4064
4065 //---
4066 // Floating move immediate
4067 //---
4068
4069 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4070   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4071       [(set regtype:$Rd, fpimmtype:$imm)]>,
4072     Sched<[WriteFImm]> {
4073   bits<5> Rd;
4074   bits<8> imm;
4075   let Inst{31-23} = 0b000111100;
4076   let Inst{21}    = 1;
4077   let Inst{20-13} = imm;
4078   let Inst{12-5}  = 0b10000000;
4079   let Inst{4-0}   = Rd;
4080 }
4081
4082 multiclass FPMoveImmediate<string asm> {
4083   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4084     let Inst{22} = 0;
4085   }
4086
4087   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4088     let Inst{22} = 1;
4089   }
4090 }
4091 } // end of 'let Predicates = [HasFPARMv8]'
4092
4093 //----------------------------------------------------------------------------
4094 // AdvSIMD
4095 //----------------------------------------------------------------------------
4096
4097 let Predicates = [HasNEON] in {
4098
4099 //----------------------------------------------------------------------------
4100 // AdvSIMD three register vector instructions
4101 //----------------------------------------------------------------------------
4102
4103 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4104 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4105                         RegisterOperand regtype, string asm, string kind,
4106                         list<dag> pattern>
4107   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4108       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4109       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4110     Sched<[WriteV]> {
4111   bits<5> Rd;
4112   bits<5> Rn;
4113   bits<5> Rm;
4114   let Inst{31}    = 0;
4115   let Inst{30}    = Q;
4116   let Inst{29}    = U;
4117   let Inst{28-24} = 0b01110;
4118   let Inst{23-22} = size;
4119   let Inst{21}    = 1;
4120   let Inst{20-16} = Rm;
4121   let Inst{15-11} = opcode;
4122   let Inst{10}    = 1;
4123   let Inst{9-5}   = Rn;
4124   let Inst{4-0}   = Rd;
4125 }
4126
4127 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4128 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4129                         RegisterOperand regtype, string asm, string kind,
4130                         list<dag> pattern>
4131   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4132       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4133       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4134     Sched<[WriteV]> {
4135   bits<5> Rd;
4136   bits<5> Rn;
4137   bits<5> Rm;
4138   let Inst{31}    = 0;
4139   let Inst{30}    = Q;
4140   let Inst{29}    = U;
4141   let Inst{28-24} = 0b01110;
4142   let Inst{23-22} = size;
4143   let Inst{21}    = 1;
4144   let Inst{20-16} = Rm;
4145   let Inst{15-11} = opcode;
4146   let Inst{10}    = 1;
4147   let Inst{9-5}   = Rn;
4148   let Inst{4-0}   = Rd;
4149 }
4150
4151 // All operand sizes distinguished in the encoding.
4152 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4153                                SDPatternOperator OpNode> {
4154   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4155                                       asm, ".8b",
4156          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4157   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4158                                       asm, ".16b",
4159          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4160   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4161                                       asm, ".4h",
4162          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4163   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4164                                       asm, ".8h",
4165          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4166   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4167                                       asm, ".2s",
4168          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4169   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4170                                       asm, ".4s",
4171          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4172   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
4173                                       asm, ".2d",
4174          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4175 }
4176
4177 // As above, but D sized elements unsupported.
4178 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4179                                   SDPatternOperator OpNode> {
4180   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4181                                       asm, ".8b",
4182         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4183   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4184                                       asm, ".16b",
4185         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4186   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4187                                       asm, ".4h",
4188         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4189   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4190                                       asm, ".8h",
4191         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4192   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4193                                       asm, ".2s",
4194         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4195   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4196                                       asm, ".4s",
4197         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4198 }
4199
4200 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4201                                   SDPatternOperator OpNode> {
4202   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
4203                                       asm, ".8b",
4204       [(set (v8i8 V64:$dst),
4205             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4206   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
4207                                       asm, ".16b",
4208       [(set (v16i8 V128:$dst),
4209             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4210   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
4211                                       asm, ".4h",
4212       [(set (v4i16 V64:$dst),
4213             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4214   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
4215                                       asm, ".8h",
4216       [(set (v8i16 V128:$dst),
4217             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4218   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
4219                                       asm, ".2s",
4220       [(set (v2i32 V64:$dst),
4221             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4222   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
4223                                       asm, ".4s",
4224       [(set (v4i32 V128:$dst),
4225             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4226 }
4227
4228 // As above, but only B sized elements supported.
4229 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4230                                 SDPatternOperator OpNode> {
4231   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
4232                                       asm, ".8b",
4233     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4234   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
4235                                       asm, ".16b",
4236     [(set (v16i8 V128:$Rd),
4237           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4238 }
4239
4240 // As above, but only S and D sized floating point elements supported.
4241 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
4242                                  string asm, SDPatternOperator OpNode> {
4243   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4244                                       asm, ".2s",
4245         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4246   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4247                                       asm, ".4s",
4248         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4249   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4250                                       asm, ".2d",
4251         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4252 }
4253
4254 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
4255                                     string asm,
4256                                     SDPatternOperator OpNode> {
4257   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
4258                                       asm, ".2s",
4259         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4260   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
4261                                       asm, ".4s",
4262         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4263   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
4264                                       asm, ".2d",
4265         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4266 }
4267
4268 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
4269                                  string asm, SDPatternOperator OpNode> {
4270   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
4271                                       asm, ".2s",
4272      [(set (v2f32 V64:$dst),
4273            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4274   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
4275                                       asm, ".4s",
4276      [(set (v4f32 V128:$dst),
4277            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4278   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
4279                                       asm, ".2d",
4280      [(set (v2f64 V128:$dst),
4281            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4282 }
4283
4284 // As above, but D and B sized elements unsupported.
4285 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4286                                 SDPatternOperator OpNode> {
4287   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
4288                                       asm, ".4h",
4289         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4290   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
4291                                       asm, ".8h",
4292         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4293   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
4294                                       asm, ".2s",
4295         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4296   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
4297                                       asm, ".4s",
4298         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4299 }
4300
4301 // Logical three vector ops share opcode bits, and only use B sized elements.
4302 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4303                                   SDPatternOperator OpNode = null_frag> {
4304   def v8i8  : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
4305                                      asm, ".8b",
4306                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4307   def v16i8  : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
4308                                      asm, ".16b",
4309                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4310
4311   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4312           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4313   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4314           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4315   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4316           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4317
4318   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4319       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4320   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4321       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4322   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4323       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4324 }
4325
4326 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4327                                   string asm, SDPatternOperator OpNode> {
4328   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
4329                                      asm, ".8b",
4330              [(set (v8i8 V64:$dst),
4331                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4332   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
4333                                      asm, ".16b",
4334              [(set (v16i8 V128:$dst),
4335                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4336                            (v16i8 V128:$Rm)))]>;
4337
4338   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4339                            (v4i16 V64:$RHS))),
4340           (!cast<Instruction>(NAME#"v8i8")
4341             V64:$LHS, V64:$MHS, V64:$RHS)>;
4342   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4343                            (v2i32 V64:$RHS))),
4344           (!cast<Instruction>(NAME#"v8i8")
4345             V64:$LHS, V64:$MHS, V64:$RHS)>;
4346   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4347                            (v1i64 V64:$RHS))),
4348           (!cast<Instruction>(NAME#"v8i8")
4349             V64:$LHS, V64:$MHS, V64:$RHS)>;
4350
4351   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4352                            (v8i16 V128:$RHS))),
4353       (!cast<Instruction>(NAME#"v16i8")
4354         V128:$LHS, V128:$MHS, V128:$RHS)>;
4355   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4356                            (v4i32 V128:$RHS))),
4357       (!cast<Instruction>(NAME#"v16i8")
4358         V128:$LHS, V128:$MHS, V128:$RHS)>;
4359   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4360                            (v2i64 V128:$RHS))),
4361       (!cast<Instruction>(NAME#"v16i8")
4362         V128:$LHS, V128:$MHS, V128:$RHS)>;
4363 }
4364
4365
4366 //----------------------------------------------------------------------------
4367 // AdvSIMD two register vector instructions.
4368 //----------------------------------------------------------------------------
4369
4370 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4371 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4372                         RegisterOperand regtype, string asm, string dstkind,
4373                         string srckind, list<dag> pattern>
4374   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4375       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4376       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4377     Sched<[WriteV]> {
4378   bits<5> Rd;
4379   bits<5> Rn;
4380   let Inst{31}    = 0;
4381   let Inst{30}    = Q;
4382   let Inst{29}    = U;
4383   let Inst{28-24} = 0b01110;
4384   let Inst{23-22} = size;
4385   let Inst{21-17} = 0b10000;
4386   let Inst{16-12} = opcode;
4387   let Inst{11-10} = 0b10;
4388   let Inst{9-5}   = Rn;
4389   let Inst{4-0}   = Rd;
4390 }
4391
4392 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4393 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4394                             RegisterOperand regtype, string asm, string dstkind,
4395                             string srckind, list<dag> pattern>
4396   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4397       "{\t$Rd" # dstkind # ", $Rn" # srckind #
4398       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4399     Sched<[WriteV]> {
4400   bits<5> Rd;
4401   bits<5> Rn;
4402   let Inst{31}    = 0;
4403   let Inst{30}    = Q;
4404   let Inst{29}    = U;
4405   let Inst{28-24} = 0b01110;
4406   let Inst{23-22} = size;
4407   let Inst{21-17} = 0b10000;
4408   let Inst{16-12} = opcode;
4409   let Inst{11-10} = 0b10;
4410   let Inst{9-5}   = Rn;
4411   let Inst{4-0}   = Rd;
4412 }
4413
4414 // Supports B, H, and S element sizes.
4415 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4416                             SDPatternOperator OpNode> {
4417   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4418                                       asm, ".8b", ".8b",
4419                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4420   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4421                                       asm, ".16b", ".16b",
4422                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4423   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4424                                       asm, ".4h", ".4h",
4425                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4426   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4427                                       asm, ".8h", ".8h",
4428                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4429   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4430                                       asm, ".2s", ".2s",
4431                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4432   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4433                                       asm, ".4s", ".4s",
4434                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4435 }
4436
4437 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4438                             RegisterOperand regtype, string asm, string dstkind,
4439                             string srckind, string amount>
4440   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4441       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4442       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4443     Sched<[WriteV]> {
4444   bits<5> Rd;
4445   bits<5> Rn;
4446   let Inst{31}    = 0;
4447   let Inst{30}    = Q;
4448   let Inst{29-24} = 0b101110;
4449   let Inst{23-22} = size;
4450   let Inst{21-10} = 0b100001001110;
4451   let Inst{9-5}   = Rn;
4452   let Inst{4-0}   = Rd;
4453 }
4454
4455 multiclass SIMDVectorLShiftLongBySizeBHS {
4456   let hasSideEffects = 0 in {
4457   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4458                                              "shll", ".8h",  ".8b", "8">;
4459   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4460                                              "shll2", ".8h", ".16b", "8">;
4461   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4462                                              "shll", ".4s",  ".4h", "16">;
4463   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4464                                              "shll2", ".4s", ".8h", "16">;
4465   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4466                                              "shll", ".2d",  ".2s", "32">;
4467   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4468                                              "shll2", ".2d", ".4s", "32">;
4469   }
4470 }
4471
4472 // Supports all element sizes.
4473 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4474                              SDPatternOperator OpNode> {
4475   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4476                                       asm, ".4h", ".8b",
4477                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4478   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4479                                       asm, ".8h", ".16b",
4480                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4481   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4482                                       asm, ".2s", ".4h",
4483                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4484   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4485                                       asm, ".4s", ".8h",
4486                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4487   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4488                                       asm, ".1d", ".2s",
4489                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4490   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4491                                       asm, ".2d", ".4s",
4492                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4493 }
4494
4495 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4496                                  SDPatternOperator OpNode> {
4497   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4498                                           asm, ".4h", ".8b",
4499       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4500                                       (v8i8 V64:$Rn)))]>;
4501   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4502                                           asm, ".8h", ".16b",
4503       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4504                                       (v16i8 V128:$Rn)))]>;
4505   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4506                                           asm, ".2s", ".4h",
4507       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4508                                       (v4i16 V64:$Rn)))]>;
4509   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4510                                           asm, ".4s", ".8h",
4511       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4512                                       (v8i16 V128:$Rn)))]>;
4513   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4514                                           asm, ".1d", ".2s",
4515       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4516                                       (v2i32 V64:$Rn)))]>;
4517   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4518                                           asm, ".2d", ".4s",
4519       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4520                                       (v4i32 V128:$Rn)))]>;
4521 }
4522
4523 // Supports all element sizes, except 1xD.
4524 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4525                                   SDPatternOperator OpNode> {
4526   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4527                                     asm, ".8b", ".8b",
4528     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4529   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4530                                     asm, ".16b", ".16b",
4531     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4532   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4533                                     asm, ".4h", ".4h",
4534     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4535   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4536                                     asm, ".8h", ".8h",
4537     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4538   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4539                                     asm, ".2s", ".2s",
4540     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4541   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4542                                     asm, ".4s", ".4s",
4543     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4544   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4545                                     asm, ".2d", ".2d",
4546     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4547 }
4548
4549 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4550                              SDPatternOperator OpNode = null_frag> {
4551   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4552                                 asm, ".8b", ".8b",
4553     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4554   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4555                                 asm, ".16b", ".16b",
4556     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4557   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4558                                 asm, ".4h", ".4h",
4559     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4560   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4561                                 asm, ".8h", ".8h",
4562     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4563   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4564                                 asm, ".2s", ".2s",
4565     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4566   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4567                                 asm, ".4s", ".4s",
4568     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4569   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4570                                 asm, ".2d", ".2d",
4571     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4572 }
4573
4574
4575 // Supports only B element sizes.
4576 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4577                           SDPatternOperator OpNode> {
4578   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4579                                 asm, ".8b", ".8b",
4580                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4581   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4582                                 asm, ".16b", ".16b",
4583                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4584
4585 }
4586
4587 // Supports only B and H element sizes.
4588 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4589                                 SDPatternOperator OpNode> {
4590   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4591                                 asm, ".8b", ".8b",
4592                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4593   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4594                                 asm, ".16b", ".16b",
4595                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4596   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4597                                 asm, ".4h", ".4h",
4598                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4599   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4600                                 asm, ".8h", ".8h",
4601                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4602 }
4603
4604 // Supports only S and D element sizes, uses high bit of the size field
4605 // as an extra opcode bit.
4606 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4607                            SDPatternOperator OpNode> {
4608   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4609                                 asm, ".2s", ".2s",
4610                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4611   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4612                                 asm, ".4s", ".4s",
4613                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4614   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4615                                 asm, ".2d", ".2d",
4616                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4617 }
4618
4619 // Supports only S element size.
4620 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4621                            SDPatternOperator OpNode> {
4622   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4623                                 asm, ".2s", ".2s",
4624                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4625   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4626                                 asm, ".4s", ".4s",
4627                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4628 }
4629
4630
4631 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4632                            SDPatternOperator OpNode> {
4633   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4634                                 asm, ".2s", ".2s",
4635                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4636   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4637                                 asm, ".4s", ".4s",
4638                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4639   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4640                                 asm, ".2d", ".2d",
4641                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4642 }
4643
4644 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4645                            SDPatternOperator OpNode> {
4646   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4647                                 asm, ".2s", ".2s",
4648                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4649   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4650                                 asm, ".4s", ".4s",
4651                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4652   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4653                                 asm, ".2d", ".2d",
4654                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4655 }
4656
4657
4658 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4659                            RegisterOperand inreg, RegisterOperand outreg,
4660                            string asm, string outkind, string inkind,
4661                            list<dag> pattern>
4662   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4663       "{\t$Rd" # outkind # ", $Rn" # inkind #
4664       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4665     Sched<[WriteV]> {
4666   bits<5> Rd;
4667   bits<5> Rn;
4668   let Inst{31}    = 0;
4669   let Inst{30}    = Q;
4670   let Inst{29}    = U;
4671   let Inst{28-24} = 0b01110;
4672   let Inst{23-22} = size;
4673   let Inst{21-17} = 0b10000;
4674   let Inst{16-12} = opcode;
4675   let Inst{11-10} = 0b10;
4676   let Inst{9-5}   = Rn;
4677   let Inst{4-0}   = Rd;
4678 }
4679
4680 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4681                            RegisterOperand inreg, RegisterOperand outreg,
4682                            string asm, string outkind, string inkind,
4683                            list<dag> pattern>
4684   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4685       "{\t$Rd" # outkind # ", $Rn" # inkind #
4686       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4687     Sched<[WriteV]> {
4688   bits<5> Rd;
4689   bits<5> Rn;
4690   let Inst{31}    = 0;
4691   let Inst{30}    = Q;
4692   let Inst{29}    = U;
4693   let Inst{28-24} = 0b01110;
4694   let Inst{23-22} = size;
4695   let Inst{21-17} = 0b10000;
4696   let Inst{16-12} = opcode;
4697   let Inst{11-10} = 0b10;
4698   let Inst{9-5}   = Rn;
4699   let Inst{4-0}   = Rd;
4700 }
4701
4702 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4703                               SDPatternOperator OpNode> {
4704   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4705                                       asm, ".8b", ".8h",
4706         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4707   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4708                                       asm#"2", ".16b", ".8h", []>;
4709   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4710                                       asm, ".4h", ".4s",
4711         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4712   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4713                                       asm#"2", ".8h", ".4s", []>;
4714   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4715                                       asm, ".2s", ".2d",
4716         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4717   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4718                                       asm#"2", ".4s", ".2d", []>;
4719
4720   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4721             (!cast<Instruction>(NAME # "v16i8")
4722                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4723   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4724             (!cast<Instruction>(NAME # "v8i16")
4725                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4726   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4727             (!cast<Instruction>(NAME # "v4i32")
4728                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4729 }
4730
4731 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4732                            RegisterOperand regtype,
4733                            string asm, string kind, string zero,
4734                            ValueType dty, ValueType sty, SDNode OpNode>
4735   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4736       "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
4737       "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
4738       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4739     Sched<[WriteV]> {
4740   bits<5> Rd;
4741   bits<5> Rn;
4742   let Inst{31}    = 0;
4743   let Inst{30}    = Q;
4744   let Inst{29}    = U;
4745   let Inst{28-24} = 0b01110;
4746   let Inst{23-22} = size;
4747   let Inst{21-17} = 0b10000;
4748   let Inst{16-12} = opcode;
4749   let Inst{11-10} = 0b10;
4750   let Inst{9-5}   = Rn;
4751   let Inst{4-0}   = Rd;
4752 }
4753
4754 // Comparisons support all element sizes, except 1xD.
4755 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4756                             SDNode OpNode> {
4757   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4758                                      asm, ".8b", "0",
4759                                      v8i8, v8i8, OpNode>;
4760   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4761                                      asm, ".16b", "0",
4762                                      v16i8, v16i8, OpNode>;
4763   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4764                                      asm, ".4h", "0",
4765                                      v4i16, v4i16, OpNode>;
4766   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4767                                      asm, ".8h", "0",
4768                                      v8i16, v8i16, OpNode>;
4769   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4770                                      asm, ".2s", "0",
4771                                      v2i32, v2i32, OpNode>;
4772   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4773                                      asm, ".4s", "0",
4774                                      v4i32, v4i32, OpNode>;
4775   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4776                                      asm, ".2d", "0",
4777                                      v2i64, v2i64, OpNode>;
4778 }
4779
4780 // FP Comparisons support only S and D element sizes.
4781 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4782                               string asm, SDNode OpNode> {
4783
4784   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4785                                      asm, ".2s", "0.0",
4786                                      v2i32, v2f32, OpNode>;
4787   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4788                                      asm, ".4s", "0.0",
4789                                      v4i32, v4f32, OpNode>;
4790   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4791                                      asm, ".2d", "0.0",
4792                                      v2i64, v2f64, OpNode>;
4793
4794   def : InstAlias<asm # " $Vd.2s, $Vn.2s, #0",
4795                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4796   def : InstAlias<asm # " $Vd.4s, $Vn.4s, #0",
4797                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4798   def : InstAlias<asm # " $Vd.2d, $Vn.2d, #0",
4799                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4800   def : InstAlias<asm # ".2s $Vd, $Vn, #0",
4801                   (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
4802   def : InstAlias<asm # ".4s $Vd, $Vn, #0",
4803                   (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
4804   def : InstAlias<asm # ".2d $Vd, $Vn, #0",
4805                   (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
4806 }
4807
4808 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4809 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4810                              RegisterOperand outtype, RegisterOperand intype,
4811                              string asm, string VdTy, string VnTy,
4812                              list<dag> pattern>
4813   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4814       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4815     Sched<[WriteV]> {
4816   bits<5> Rd;
4817   bits<5> Rn;
4818   let Inst{31}    = 0;
4819   let Inst{30}    = Q;
4820   let Inst{29}    = U;
4821   let Inst{28-24} = 0b01110;
4822   let Inst{23-22} = size;
4823   let Inst{21-17} = 0b10000;
4824   let Inst{16-12} = opcode;
4825   let Inst{11-10} = 0b10;
4826   let Inst{9-5}   = Rn;
4827   let Inst{4-0}   = Rd;
4828 }
4829
4830 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4831                              RegisterOperand outtype, RegisterOperand intype,
4832                              string asm, string VdTy, string VnTy,
4833                              list<dag> pattern>
4834   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4835       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4836     Sched<[WriteV]> {
4837   bits<5> Rd;
4838   bits<5> Rn;
4839   let Inst{31}    = 0;
4840   let Inst{30}    = Q;
4841   let Inst{29}    = U;
4842   let Inst{28-24} = 0b01110;
4843   let Inst{23-22} = size;
4844   let Inst{21-17} = 0b10000;
4845   let Inst{16-12} = opcode;
4846   let Inst{11-10} = 0b10;
4847   let Inst{9-5}   = Rn;
4848   let Inst{4-0}   = Rd;
4849 }
4850
4851 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4852   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4853                                     asm, ".4s", ".4h", []>;
4854   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4855                                     asm#"2", ".4s", ".8h", []>;
4856   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4857                                     asm, ".2d", ".2s", []>;
4858   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4859                                     asm#"2", ".2d", ".4s", []>;
4860 }
4861
4862 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4863   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4864                                     asm, ".4h", ".4s", []>;
4865   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4866                                     asm#"2", ".8h", ".4s", []>;
4867   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4868                                     asm, ".2s", ".2d", []>;
4869   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4870                                     asm#"2", ".4s", ".2d", []>;
4871 }
4872
4873 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4874                                      Intrinsic OpNode> {
4875   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4876                                      asm, ".2s", ".2d",
4877                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4878   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4879                                     asm#"2", ".4s", ".2d", []>;
4880
4881   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4882             (!cast<Instruction>(NAME # "v4f32")
4883                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4884 }
4885
4886 //----------------------------------------------------------------------------
4887 // AdvSIMD three register different-size vector instructions.
4888 //----------------------------------------------------------------------------
4889
4890 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4891 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4892                       RegisterOperand outtype, RegisterOperand intype1,
4893                       RegisterOperand intype2, string asm,
4894                       string outkind, string inkind1, string inkind2,
4895                       list<dag> pattern>
4896   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4897       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4898       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4899     Sched<[WriteV]> {
4900   bits<5> Rd;
4901   bits<5> Rn;
4902   bits<5> Rm;
4903   let Inst{31}    = 0;
4904   let Inst{30}    = size{0};
4905   let Inst{29}    = U;
4906   let Inst{28-24} = 0b01110;
4907   let Inst{23-22} = size{2-1};
4908   let Inst{21}    = 1;
4909   let Inst{20-16} = Rm;
4910   let Inst{15-12} = opcode;
4911   let Inst{11-10} = 0b00;
4912   let Inst{9-5}   = Rn;
4913   let Inst{4-0}   = Rd;
4914 }
4915
4916 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4917 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4918                       RegisterOperand outtype, RegisterOperand intype1,
4919                       RegisterOperand intype2, string asm,
4920                       string outkind, string inkind1, string inkind2,
4921                       list<dag> pattern>
4922   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4923       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4924       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4925     Sched<[WriteV]> {
4926   bits<5> Rd;
4927   bits<5> Rn;
4928   bits<5> Rm;
4929   let Inst{31}    = 0;
4930   let Inst{30}    = size{0};
4931   let Inst{29}    = U;
4932   let Inst{28-24} = 0b01110;
4933   let Inst{23-22} = size{2-1};
4934   let Inst{21}    = 1;
4935   let Inst{20-16} = Rm;
4936   let Inst{15-12} = opcode;
4937   let Inst{11-10} = 0b00;
4938   let Inst{9-5}   = Rn;
4939   let Inst{4-0}   = Rd;
4940 }
4941
4942 // FIXME: TableGen doesn't know how to deal with expanded types that also
4943 //        change the element count (in this case, placing the results in
4944 //        the high elements of the result register rather than the low
4945 //        elements). Until that's fixed, we can't code-gen those.
4946 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4947                                     Intrinsic IntOp> {
4948   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4949                                                   V64, V128, V128,
4950                                                   asm, ".8b", ".8h", ".8h",
4951      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4952   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4953                                                   V128, V128, V128,
4954                                                   asm#"2", ".16b", ".8h", ".8h",
4955      []>;
4956   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4957                                                   V64, V128, V128,
4958                                                   asm, ".4h", ".4s", ".4s",
4959      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4960   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4961                                                   V128, V128, V128,
4962                                                   asm#"2", ".8h", ".4s", ".4s",
4963      []>;
4964   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4965                                                   V64, V128, V128,
4966                                                   asm, ".2s", ".2d", ".2d",
4967      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4968   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4969                                                   V128, V128, V128,
4970                                                   asm#"2", ".4s", ".2d", ".2d",
4971      []>;
4972
4973
4974   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4975   // a version attached to an instruction.
4976   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4977                                                    (v8i16 V128:$Rm))),
4978             (!cast<Instruction>(NAME # "v8i16_v16i8")
4979                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4980                 V128:$Rn, V128:$Rm)>;
4981   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4982                                                     (v4i32 V128:$Rm))),
4983             (!cast<Instruction>(NAME # "v4i32_v8i16")
4984                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4985                 V128:$Rn, V128:$Rm)>;
4986   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4987                                                     (v2i64 V128:$Rm))),
4988             (!cast<Instruction>(NAME # "v2i64_v4i32")
4989                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4990                 V128:$Rn, V128:$Rm)>;
4991 }
4992
4993 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4994                                       Intrinsic IntOp> {
4995   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4996                                             V128, V64, V64,
4997                                             asm, ".8h", ".8b", ".8b",
4998       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4999   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5000                                             V128, V128, V128,
5001                                             asm#"2", ".8h", ".16b", ".16b", []>;
5002   let Predicates = [HasCrypto] in {
5003     def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5004                                               V128, V64, V64,
5005                                               asm, ".1q", ".1d", ".1d", []>;
5006     def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5007                                               V128, V128, V128,
5008                                               asm#"2", ".1q", ".2d", ".2d", []>;
5009   }
5010
5011   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5012                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
5013       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5014 }
5015
5016 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5017                                  SDPatternOperator OpNode> {
5018   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5019                                                   V128, V64, V64,
5020                                                   asm, ".4s", ".4h", ".4h",
5021       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5022   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5023                                                   V128, V128, V128,
5024                                                   asm#"2", ".4s", ".8h", ".8h",
5025       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5026                                       (extract_high_v8i16 V128:$Rm)))]>;
5027   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5028                                                   V128, V64, V64,
5029                                                   asm, ".2d", ".2s", ".2s",
5030       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5031   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5032                                                   V128, V128, V128,
5033                                                   asm#"2", ".2d", ".4s", ".4s",
5034       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5035                                       (extract_high_v4i32 V128:$Rm)))]>;
5036 }
5037
5038 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5039                                   SDPatternOperator OpNode = null_frag> {
5040   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5041                                                   V128, V64, V64,
5042                                                   asm, ".8h", ".8b", ".8b",
5043       [(set (v8i16 V128:$Rd),
5044             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5045   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5046                                                  V128, V128, V128,
5047                                                  asm#"2", ".8h", ".16b", ".16b",
5048       [(set (v8i16 V128:$Rd),
5049             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5050                                 (extract_high_v16i8 V128:$Rm)))))]>;
5051   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5052                                                   V128, V64, V64,
5053                                                   asm, ".4s", ".4h", ".4h",
5054       [(set (v4i32 V128:$Rd),
5055             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5056   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5057                                                   V128, V128, V128,
5058                                                   asm#"2", ".4s", ".8h", ".8h",
5059       [(set (v4i32 V128:$Rd),
5060             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5061                                   (extract_high_v8i16 V128:$Rm)))))]>;
5062   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5063                                                   V128, V64, V64,
5064                                                   asm, ".2d", ".2s", ".2s",
5065       [(set (v2i64 V128:$Rd),
5066             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5067   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5068                                                   V128, V128, V128,
5069                                                   asm#"2", ".2d", ".4s", ".4s",
5070       [(set (v2i64 V128:$Rd),
5071             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5072                                  (extract_high_v4i32 V128:$Rm)))))]>;
5073 }
5074
5075 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5076                                           string asm,
5077                                           SDPatternOperator OpNode> {
5078   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5079                                                   V128, V64, V64,
5080                                                   asm, ".8h", ".8b", ".8b",
5081     [(set (v8i16 V128:$dst),
5082           (add (v8i16 V128:$Rd),
5083                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5084   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5085                                                  V128, V128, V128,
5086                                                  asm#"2", ".8h", ".16b", ".16b",
5087     [(set (v8i16 V128:$dst),
5088           (add (v8i16 V128:$Rd),
5089                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5090                                    (extract_high_v16i8 V128:$Rm))))))]>;
5091   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5092                                                   V128, V64, V64,
5093                                                   asm, ".4s", ".4h", ".4h",
5094     [(set (v4i32 V128:$dst),
5095           (add (v4i32 V128:$Rd),
5096                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5097   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5098                                                   V128, V128, V128,
5099                                                   asm#"2", ".4s", ".8h", ".8h",
5100     [(set (v4i32 V128:$dst),
5101           (add (v4i32 V128:$Rd),
5102                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5103                                     (extract_high_v8i16 V128:$Rm))))))]>;
5104   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5105                                                   V128, V64, V64,
5106                                                   asm, ".2d", ".2s", ".2s",
5107     [(set (v2i64 V128:$dst),
5108           (add (v2i64 V128:$Rd),
5109                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5110   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5111                                                   V128, V128, V128,
5112                                                   asm#"2", ".2d", ".4s", ".4s",
5113     [(set (v2i64 V128:$dst),
5114           (add (v2i64 V128:$Rd),
5115                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5116                                     (extract_high_v4i32 V128:$Rm))))))]>;
5117 }
5118
5119 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5120                                   SDPatternOperator OpNode = null_frag> {
5121   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5122                                                   V128, V64, V64,
5123                                                   asm, ".8h", ".8b", ".8b",
5124       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5125   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5126                                                  V128, V128, V128,
5127                                                  asm#"2", ".8h", ".16b", ".16b",
5128       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5129                                       (extract_high_v16i8 V128:$Rm)))]>;
5130   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5131                                                   V128, V64, V64,
5132                                                   asm, ".4s", ".4h", ".4h",
5133       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5134   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5135                                                   V128, V128, V128,
5136                                                   asm#"2", ".4s", ".8h", ".8h",
5137       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5138                                       (extract_high_v8i16 V128:$Rm)))]>;
5139   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5140                                                   V128, V64, V64,
5141                                                   asm, ".2d", ".2s", ".2s",
5142       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5143   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5144                                                   V128, V128, V128,
5145                                                   asm#"2", ".2d", ".4s", ".4s",
5146       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5147                                       (extract_high_v4i32 V128:$Rm)))]>;
5148 }
5149
5150 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5151                                       string asm,
5152                                       SDPatternOperator OpNode> {
5153   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5154                                                   V128, V64, V64,
5155                                                   asm, ".8h", ".8b", ".8b",
5156     [(set (v8i16 V128:$dst),
5157           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5158   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5159                                                  V128, V128, V128,
5160                                                  asm#"2", ".8h", ".16b", ".16b",
5161     [(set (v8i16 V128:$dst),
5162           (OpNode (v8i16 V128:$Rd),
5163                   (extract_high_v16i8 V128:$Rn),
5164                   (extract_high_v16i8 V128:$Rm)))]>;
5165   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5166                                                   V128, V64, V64,
5167                                                   asm, ".4s", ".4h", ".4h",
5168     [(set (v4i32 V128:$dst),
5169           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5170   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5171                                                   V128, V128, V128,
5172                                                   asm#"2", ".4s", ".8h", ".8h",
5173     [(set (v4i32 V128:$dst),
5174           (OpNode (v4i32 V128:$Rd),
5175                   (extract_high_v8i16 V128:$Rn),
5176                   (extract_high_v8i16 V128:$Rm)))]>;
5177   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5178                                                   V128, V64, V64,
5179                                                   asm, ".2d", ".2s", ".2s",
5180     [(set (v2i64 V128:$dst),
5181           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5182   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5183                                                   V128, V128, V128,
5184                                                   asm#"2", ".2d", ".4s", ".4s",
5185     [(set (v2i64 V128:$dst),
5186           (OpNode (v2i64 V128:$Rd),
5187                   (extract_high_v4i32 V128:$Rn),
5188                   (extract_high_v4i32 V128:$Rm)))]>;
5189 }
5190
5191 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5192                                            SDPatternOperator Accum> {
5193   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5194                                                   V128, V64, V64,
5195                                                   asm, ".4s", ".4h", ".4h",
5196     [(set (v4i32 V128:$dst),
5197           (Accum (v4i32 V128:$Rd),
5198                  (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5199                                                 (v4i16 V64:$Rm)))))]>;
5200   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5201                                                   V128, V128, V128,
5202                                                   asm#"2", ".4s", ".8h", ".8h",
5203     [(set (v4i32 V128:$dst),
5204           (Accum (v4i32 V128:$Rd),
5205                  (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5206                                             (extract_high_v8i16 V128:$Rm)))))]>;
5207   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5208                                                   V128, V64, V64,
5209                                                   asm, ".2d", ".2s", ".2s",
5210     [(set (v2i64 V128:$dst),
5211           (Accum (v2i64 V128:$Rd),
5212                  (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5213                                                 (v2i32 V64:$Rm)))))]>;
5214   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5215                                                   V128, V128, V128,
5216                                                   asm#"2", ".2d", ".4s", ".4s",
5217     [(set (v2i64 V128:$dst),
5218           (Accum (v2i64 V128:$Rd),
5219                  (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5220                                             (extract_high_v4i32 V128:$Rm)))))]>;
5221 }
5222
5223 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5224                                   SDPatternOperator OpNode> {
5225   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5226                                                   V128, V128, V64,
5227                                                   asm, ".8h", ".8h", ".8b",
5228        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5229   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5230                                                   V128, V128, V128,
5231                                                   asm#"2", ".8h", ".8h", ".16b",
5232        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5233                                        (extract_high_v16i8 V128:$Rm)))]>;
5234   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5235                                                   V128, V128, V64,
5236                                                   asm, ".4s", ".4s", ".4h",
5237        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5238   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5239                                                   V128, V128, V128,
5240                                                   asm#"2", ".4s", ".4s", ".8h",
5241        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5242                                        (extract_high_v8i16 V128:$Rm)))]>;
5243   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5244                                                   V128, V128, V64,
5245                                                   asm, ".2d", ".2d", ".2s",
5246        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5247   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5248                                                   V128, V128, V128,
5249                                                   asm#"2", ".2d", ".2d", ".4s",
5250        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5251                                        (extract_high_v4i32 V128:$Rm)))]>;
5252 }
5253
5254 //----------------------------------------------------------------------------
5255 // AdvSIMD bitwise extract from vector
5256 //----------------------------------------------------------------------------
5257
5258 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5259                              string asm, string kind>
5260   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5261       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5262       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5263       [(set (vty regtype:$Rd),
5264             (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5265     Sched<[WriteV]> {
5266   bits<5> Rd;
5267   bits<5> Rn;
5268   bits<5> Rm;
5269   bits<4> imm;
5270   let Inst{31}    = 0;
5271   let Inst{30}    = size;
5272   let Inst{29-21} = 0b101110000;
5273   let Inst{20-16} = Rm;
5274   let Inst{15}    = 0;
5275   let Inst{14-11} = imm;
5276   let Inst{10}    = 0;
5277   let Inst{9-5}   = Rn;
5278   let Inst{4-0}   = Rd;
5279 }
5280
5281
5282 multiclass SIMDBitwiseExtract<string asm> {
5283   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5284     let imm{3} = 0;
5285   }
5286   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5287 }
5288
5289 //----------------------------------------------------------------------------
5290 // AdvSIMD zip vector
5291 //----------------------------------------------------------------------------
5292
5293 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5294                         string asm, string kind, SDNode OpNode, ValueType valty>
5295   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5296       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5297       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5298       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5299     Sched<[WriteV]> {
5300   bits<5> Rd;
5301   bits<5> Rn;
5302   bits<5> Rm;
5303   let Inst{31}    = 0;
5304   let Inst{30}    = size{0};
5305   let Inst{29-24} = 0b001110;
5306   let Inst{23-22} = size{2-1};
5307   let Inst{21}    = 0;
5308   let Inst{20-16} = Rm;
5309   let Inst{15}    = 0;
5310   let Inst{14-12} = opc;
5311   let Inst{11-10} = 0b10;
5312   let Inst{9-5}   = Rn;
5313   let Inst{4-0}   = Rd;
5314 }
5315
5316 multiclass SIMDZipVector<bits<3>opc, string asm,
5317                          SDNode OpNode> {
5318   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5319       asm, ".8b", OpNode, v8i8>;
5320   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5321       asm, ".16b", OpNode, v16i8>;
5322   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5323       asm, ".4h", OpNode, v4i16>;
5324   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5325       asm, ".8h", OpNode, v8i16>;
5326   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5327       asm, ".2s", OpNode, v2i32>;
5328   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5329       asm, ".4s", OpNode, v4i32>;
5330   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5331       asm, ".2d", OpNode, v2i64>;
5332
5333   def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5334         (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5335   def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5336         (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5337   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5338         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5339   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5340         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5341   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5342         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5343 }
5344
5345 //----------------------------------------------------------------------------
5346 // AdvSIMD three register scalar instructions
5347 //----------------------------------------------------------------------------
5348
5349 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5350 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
5351                         RegisterClass regtype, string asm,
5352                         list<dag> pattern>
5353   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5354       "\t$Rd, $Rn, $Rm", "", pattern>,
5355     Sched<[WriteV]> {
5356   bits<5> Rd;
5357   bits<5> Rn;
5358   bits<5> Rm;
5359   let Inst{31-30} = 0b01;
5360   let Inst{29}    = U;
5361   let Inst{28-24} = 0b11110;
5362   let Inst{23-22} = size;
5363   let Inst{21}    = 1;
5364   let Inst{20-16} = Rm;
5365   let Inst{15-11} = opcode;
5366   let Inst{10}    = 1;
5367   let Inst{9-5}   = Rn;
5368   let Inst{4-0}   = Rd;
5369 }
5370
5371 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5372 class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5373                         dag oops, dag iops, string asm,
5374             list<dag> pattern>
5375   : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5376     Sched<[WriteV]> {
5377   bits<5> Rd;
5378   bits<5> Rn;
5379   bits<5> Rm;
5380   let Inst{31-30} = 0b01;
5381   let Inst{29}    = U;
5382   let Inst{28-24} = 0b11110;
5383   let Inst{23-22} = size;
5384   let Inst{21}    = R;
5385   let Inst{20-16} = Rm;
5386   let Inst{15-11} = opcode;
5387   let Inst{10}    = 1;
5388   let Inst{9-5}   = Rn;
5389   let Inst{4-0}   = Rd;
5390 }
5391
5392 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5393                             SDPatternOperator OpNode> {
5394   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5395     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5396 }
5397
5398 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5399                                SDPatternOperator OpNode> {
5400   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
5401     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5402   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
5403   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5404   def v1i8   : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
5405
5406   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5407             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5408   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5409             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5410 }
5411
5412 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5413                              SDPatternOperator OpNode> {
5414   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
5415                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5416   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
5417 }
5418
5419 multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5420                                  SDPatternOperator OpNode = null_frag> {
5421   def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5422                                      (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm), 
5423                                      asm, []>;
5424   def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5425                                      (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm), 
5426                                      asm, []>;
5427 }
5428
5429 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
5430                              SDPatternOperator OpNode = null_frag> {
5431   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5432     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5433       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5434     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5435       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5436   }
5437
5438   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5439             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5440 }
5441
5442 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
5443                                 SDPatternOperator OpNode = null_frag> {
5444   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5445     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
5446       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5447     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
5448       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5449   }
5450
5451   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5452             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5453 }
5454
5455 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5456               dag oops, dag iops, string asm, string cstr, list<dag> pat>
5457   : I<oops, iops, asm,
5458       "\t$Rd, $Rn, $Rm", cstr, pat>,
5459     Sched<[WriteV]> {
5460   bits<5> Rd;
5461   bits<5> Rn;
5462   bits<5> Rm;
5463   let Inst{31-30} = 0b01;
5464   let Inst{29}    = U;
5465   let Inst{28-24} = 0b11110;
5466   let Inst{23-22} = size;
5467   let Inst{21}    = 1;
5468   let Inst{20-16} = Rm;
5469   let Inst{15-11} = opcode;
5470   let Inst{10}    = 0;
5471   let Inst{9-5}   = Rn;
5472   let Inst{4-0}   = Rd;
5473 }
5474
5475 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5476 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5477                                   SDPatternOperator OpNode = null_frag> {
5478   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5479                                       (outs FPR32:$Rd),
5480                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5481   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5482                                       (outs FPR64:$Rd),
5483                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5484             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5485 }
5486
5487 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5488 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5489                                   SDPatternOperator OpNode = null_frag> {
5490   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5491                                       (outs FPR32:$dst),
5492                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5493                                       asm, "$Rd = $dst", []>;
5494   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5495                                       (outs FPR64:$dst),
5496                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5497                                       asm, "$Rd = $dst",
5498             [(set (i64 FPR64:$dst),
5499                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5500 }
5501
5502 //----------------------------------------------------------------------------
5503 // AdvSIMD two register scalar instructions
5504 //----------------------------------------------------------------------------
5505
5506 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5507 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5508                         RegisterClass regtype, RegisterClass regtype2,
5509                         string asm, list<dag> pat>
5510   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5511       "\t$Rd, $Rn", "", pat>,
5512     Sched<[WriteV]> {
5513   bits<5> Rd;
5514   bits<5> Rn;
5515   let Inst{31-30} = 0b01;
5516   let Inst{29}    = U;
5517   let Inst{28-24} = 0b11110;
5518   let Inst{23-22} = size;
5519   let Inst{21-17} = 0b10000;
5520   let Inst{16-12} = opcode;
5521   let Inst{11-10} = 0b10;
5522   let Inst{9-5}   = Rn;
5523   let Inst{4-0}   = Rd;
5524 }
5525
5526 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5527 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5528                         RegisterClass regtype, RegisterClass regtype2,
5529                         string asm, list<dag> pat>
5530   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5531       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5532     Sched<[WriteV]> {
5533   bits<5> Rd;
5534   bits<5> Rn;
5535   let Inst{31-30} = 0b01;
5536   let Inst{29}    = U;
5537   let Inst{28-24} = 0b11110;
5538   let Inst{23-22} = size;
5539   let Inst{21-17} = 0b10000;
5540   let Inst{16-12} = opcode;
5541   let Inst{11-10} = 0b10;
5542   let Inst{9-5}   = Rn;
5543   let Inst{4-0}   = Rd;
5544 }
5545
5546
5547 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5548 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5549                         RegisterClass regtype, string asm, string zero>
5550   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5551       "\t$Rd, $Rn, #" # zero, "", []>,
5552     Sched<[WriteV]> {
5553   bits<5> Rd;
5554   bits<5> Rn;
5555   let Inst{31-30} = 0b01;
5556   let Inst{29}    = U;
5557   let Inst{28-24} = 0b11110;
5558   let Inst{23-22} = size;
5559   let Inst{21-17} = 0b10000;
5560   let Inst{16-12} = opcode;
5561   let Inst{11-10} = 0b10;
5562   let Inst{9-5}   = Rn;
5563   let Inst{4-0}   = Rd;
5564 }
5565
5566 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5567   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5568      [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5569     Sched<[WriteV]> {
5570   bits<5> Rd;
5571   bits<5> Rn;
5572   let Inst{31-17} = 0b011111100110000;
5573   let Inst{16-12} = opcode;
5574   let Inst{11-10} = 0b10;
5575   let Inst{9-5}   = Rn;
5576   let Inst{4-0}   = Rd;
5577 }
5578
5579 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5580                              SDPatternOperator OpNode> {
5581   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm, "0">;
5582
5583   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5584             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5585 }
5586
5587 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5588                               SDPatternOperator OpNode> {
5589   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm, "0.0">;
5590   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm, "0.0">;
5591
5592   def : InstAlias<asm # " $Rd, $Rn, #0",
5593                   (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5594   def : InstAlias<asm # " $Rd, $Rn, #0",
5595                   (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5596
5597   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5598             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5599 }
5600
5601 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5602                           SDPatternOperator OpNode = null_frag> {
5603   def v1i64       : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5604     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5605
5606   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5607             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5608 }
5609
5610 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5611   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5612   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5613 }
5614
5615 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5616                               SDPatternOperator OpNode> {
5617   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5618                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5619   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5620                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5621 }
5622
5623 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5624                              SDPatternOperator OpNode = null_frag> {
5625   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5626     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5627            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5628     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5629            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5630     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5631     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5632   }
5633
5634   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5635             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5636 }
5637
5638 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5639                                  Intrinsic OpNode> {
5640   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5641     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5642         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5643     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5644         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5645     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5646     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5647   }
5648
5649   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5650             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5651 }
5652
5653
5654
5655 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5656 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5657                                  SDPatternOperator OpNode = null_frag> {
5658   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5659         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5660   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5661   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5662 }
5663
5664 //----------------------------------------------------------------------------
5665 // AdvSIMD scalar pairwise instructions
5666 //----------------------------------------------------------------------------
5667
5668 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5669 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5670                         RegisterOperand regtype, RegisterOperand vectype,
5671                         string asm, string kind>
5672   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5673       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5674     Sched<[WriteV]> {
5675   bits<5> Rd;
5676   bits<5> Rn;
5677   let Inst{31-30} = 0b01;
5678   let Inst{29}    = U;
5679   let Inst{28-24} = 0b11110;
5680   let Inst{23-22} = size;
5681   let Inst{21-17} = 0b11000;
5682   let Inst{16-12} = opcode;
5683   let Inst{11-10} = 0b10;
5684   let Inst{9-5}   = Rn;
5685   let Inst{4-0}   = Rd;
5686 }
5687
5688 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5689   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5690                                       asm, ".2d">;
5691 }
5692
5693 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5694   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5695                                       asm, ".2s">;
5696   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5697                                       asm, ".2d">;
5698 }
5699
5700 //----------------------------------------------------------------------------
5701 // AdvSIMD across lanes instructions
5702 //----------------------------------------------------------------------------
5703
5704 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5705 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5706                           RegisterClass regtype, RegisterOperand vectype,
5707                           string asm, string kind, list<dag> pattern>
5708   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5709       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5710     Sched<[WriteV]> {
5711   bits<5> Rd;
5712   bits<5> Rn;
5713   let Inst{31}    = 0;
5714   let Inst{30}    = Q;
5715   let Inst{29}    = U;
5716   let Inst{28-24} = 0b01110;
5717   let Inst{23-22} = size;
5718   let Inst{21-17} = 0b11000;
5719   let Inst{16-12} = opcode;
5720   let Inst{11-10} = 0b10;
5721   let Inst{9-5}   = Rn;
5722   let Inst{4-0}   = Rd;
5723 }
5724
5725 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5726                               string asm> {
5727   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5728                                    asm, ".8b", []>;
5729   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5730                                    asm, ".16b", []>;
5731   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5732                                    asm, ".4h", []>;
5733   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5734                                    asm, ".8h", []>;
5735   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5736                                    asm, ".4s", []>;
5737 }
5738
5739 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5740   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5741                                    asm, ".8b", []>;
5742   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5743                                    asm, ".16b", []>;
5744   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5745                                    asm, ".4h", []>;
5746   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5747                                    asm, ".8h", []>;
5748   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5749                                    asm, ".4s", []>;
5750 }
5751
5752 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5753                             Intrinsic intOp> {
5754   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5755                                    asm, ".4s",
5756         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5757 }
5758
5759 //----------------------------------------------------------------------------
5760 // AdvSIMD INS/DUP instructions
5761 //----------------------------------------------------------------------------
5762
5763 // FIXME: There has got to be a better way to factor these. ugh.
5764
5765 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5766                      string operands, string constraints, list<dag> pattern>
5767   : I<outs, ins, asm, operands, constraints, pattern>,
5768     Sched<[WriteV]> {
5769   bits<5> Rd;
5770   bits<5> Rn;
5771   let Inst{31} = 0;
5772   let Inst{30} = Q;
5773   let Inst{29} = op;
5774   let Inst{28-21} = 0b01110000;
5775   let Inst{15} = 0;
5776   let Inst{10} = 1;
5777   let Inst{9-5} = Rn;
5778   let Inst{4-0} = Rd;
5779 }
5780
5781 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5782                       RegisterOperand vecreg, RegisterClass regtype>
5783   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5784                    "{\t$Rd" # size # ", $Rn" #
5785                    "|" # size # "\t$Rd, $Rn}", "",
5786                    [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
5787   let Inst{20-16} = imm5;
5788   let Inst{14-11} = 0b0001;
5789 }
5790
5791 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5792                          ValueType vectype, ValueType insreg,
5793                          RegisterOperand vecreg, Operand idxtype,
5794                          ValueType elttype, SDNode OpNode>
5795   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5796                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5797                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5798                  [(set (vectype vecreg:$Rd),
5799                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5800   let Inst{14-11} = 0b0000;
5801 }
5802
5803 class SIMDDup64FromElement
5804   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5805                        VectorIndexD, i64, AArch64duplane64> {
5806   bits<1> idx;
5807   let Inst{20} = idx;
5808   let Inst{19-16} = 0b1000;
5809 }
5810
5811 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5812                            RegisterOperand vecreg>
5813   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5814                        VectorIndexS, i64, AArch64duplane32> {
5815   bits<2> idx;
5816   let Inst{20-19} = idx;
5817   let Inst{18-16} = 0b100;
5818 }
5819
5820 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5821                            RegisterOperand vecreg>
5822   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5823                        VectorIndexH, i64, AArch64duplane16> {
5824   bits<3> idx;
5825   let Inst{20-18} = idx;
5826   let Inst{17-16} = 0b10;
5827 }
5828
5829 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5830                           RegisterOperand vecreg>
5831   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5832                        VectorIndexB, i64, AArch64duplane8> {
5833   bits<4> idx;
5834   let Inst{20-17} = idx;
5835   let Inst{16} = 1;
5836 }
5837
5838 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5839                   Operand idxtype, string asm, list<dag> pattern>
5840   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5841                    "{\t$Rd, $Rn" # size # "$idx" #
5842                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5843   let Inst{14-11} = imm4;
5844 }
5845
5846 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5847                Operand idxtype>
5848   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5849 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5850                Operand idxtype>
5851   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5852       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5853
5854 class SIMDMovAlias<string asm, string size, Instruction inst,
5855                    RegisterClass regtype, Operand idxtype>
5856     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5857                     "|" # size # "\t$dst, $src$idx}",
5858                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5859
5860 multiclass SMov {
5861   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5862     bits<4> idx;
5863     let Inst{20-17} = idx;
5864     let Inst{16} = 1;
5865   }
5866   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5867     bits<4> idx;
5868     let Inst{20-17} = idx;
5869     let Inst{16} = 1;
5870   }
5871   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5872     bits<3> idx;
5873     let Inst{20-18} = idx;
5874     let Inst{17-16} = 0b10;
5875   }
5876   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5877     bits<3> idx;
5878     let Inst{20-18} = idx;
5879     let Inst{17-16} = 0b10;
5880   }
5881   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5882     bits<2> idx;
5883     let Inst{20-19} = idx;
5884     let Inst{18-16} = 0b100;
5885   }
5886 }
5887
5888 multiclass UMov {
5889   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5890     bits<4> idx;
5891     let Inst{20-17} = idx;
5892     let Inst{16} = 1;
5893   }
5894   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5895     bits<3> idx;
5896     let Inst{20-18} = idx;
5897     let Inst{17-16} = 0b10;
5898   }
5899   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5900     bits<2> idx;
5901     let Inst{20-19} = idx;
5902     let Inst{18-16} = 0b100;
5903   }
5904   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5905     bits<1> idx;
5906     let Inst{20} = idx;
5907     let Inst{19-16} = 0b1000;
5908   }
5909   def : SIMDMovAlias<"mov", ".s",
5910                      !cast<Instruction>(NAME#"vi32"),
5911                      GPR32, VectorIndexS>;
5912   def : SIMDMovAlias<"mov", ".d",
5913                      !cast<Instruction>(NAME#"vi64"),
5914                      GPR64, VectorIndexD>;
5915 }
5916
5917 class SIMDInsFromMain<string size, ValueType vectype,
5918                       RegisterClass regtype, Operand idxtype>
5919   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5920                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5921                    "{\t$Rd" # size # "$idx, $Rn" #
5922                    "|" # size # "\t$Rd$idx, $Rn}",
5923                    "$Rd = $dst",
5924             [(set V128:$dst,
5925               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5926   let Inst{14-11} = 0b0011;
5927 }
5928
5929 class SIMDInsFromElement<string size, ValueType vectype,
5930                          ValueType elttype, Operand idxtype>
5931   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5932                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5933                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5934                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
5935                    "$Rd = $dst",
5936          [(set V128:$dst,
5937                (vector_insert
5938                  (vectype V128:$Rd),
5939                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5940                  idxtype:$idx))]>;
5941
5942 class SIMDInsMainMovAlias<string size, Instruction inst,
5943                           RegisterClass regtype, Operand idxtype>
5944     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5945                         "|" # size #"\t$dst$idx, $src}",
5946                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5947 class SIMDInsElementMovAlias<string size, Instruction inst,
5948                              Operand idxtype>
5949     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5950                       # "|" # size #" $dst$idx, $src$idx2}",
5951                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5952
5953
5954 multiclass SIMDIns {
5955   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5956     bits<4> idx;
5957     let Inst{20-17} = idx;
5958     let Inst{16} = 1;
5959   }
5960   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5961     bits<3> idx;
5962     let Inst{20-18} = idx;
5963     let Inst{17-16} = 0b10;
5964   }
5965   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5966     bits<2> idx;
5967     let Inst{20-19} = idx;
5968     let Inst{18-16} = 0b100;
5969   }
5970   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5971     bits<1> idx;
5972     let Inst{20} = idx;
5973     let Inst{19-16} = 0b1000;
5974   }
5975
5976   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5977     bits<4> idx;
5978     bits<4> idx2;
5979     let Inst{20-17} = idx;
5980     let Inst{16} = 1;
5981     let Inst{14-11} = idx2;
5982   }
5983   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5984     bits<3> idx;
5985     bits<3> idx2;
5986     let Inst{20-18} = idx;
5987     let Inst{17-16} = 0b10;
5988     let Inst{14-12} = idx2;
5989     let Inst{11} = {?};
5990   }
5991   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5992     bits<2> idx;
5993     bits<2> idx2;
5994     let Inst{20-19} = idx;
5995     let Inst{18-16} = 0b100;
5996     let Inst{14-13} = idx2;
5997     let Inst{12-11} = {?,?};
5998   }
5999   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6000     bits<1> idx;
6001     bits<1> idx2;
6002     let Inst{20} = idx;
6003     let Inst{19-16} = 0b1000;
6004     let Inst{14} = idx2;
6005     let Inst{13-11} = {?,?,?};
6006   }
6007
6008   // For all forms of the INS instruction, the "mov" mnemonic is the
6009   // preferred alias. Why they didn't just call the instruction "mov" in
6010   // the first place is a very good question indeed...
6011   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6012                          GPR32, VectorIndexB>;
6013   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6014                          GPR32, VectorIndexH>;
6015   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6016                          GPR32, VectorIndexS>;
6017   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6018                          GPR64, VectorIndexD>;
6019
6020   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6021                          VectorIndexB>;
6022   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6023                          VectorIndexH>;
6024   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6025                          VectorIndexS>;
6026   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6027                          VectorIndexD>;
6028 }
6029
6030 //----------------------------------------------------------------------------
6031 // AdvSIMD TBL/TBX
6032 //----------------------------------------------------------------------------
6033
6034 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6035 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6036                           RegisterOperand listtype, string asm, string kind>
6037   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6038        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6039     Sched<[WriteV]> {
6040   bits<5> Vd;
6041   bits<5> Vn;
6042   bits<5> Vm;
6043   let Inst{31}    = 0;
6044   let Inst{30}    = Q;
6045   let Inst{29-21} = 0b001110000;
6046   let Inst{20-16} = Vm;
6047   let Inst{15}    = 0;
6048   let Inst{14-13} = len;
6049   let Inst{12}    = op;
6050   let Inst{11-10} = 0b00;
6051   let Inst{9-5}   = Vn;
6052   let Inst{4-0}   = Vd;
6053 }
6054
6055 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6056 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6057                           RegisterOperand listtype, string asm, string kind>
6058   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6059        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6060     Sched<[WriteV]> {
6061   bits<5> Vd;
6062   bits<5> Vn;
6063   bits<5> Vm;
6064   let Inst{31}    = 0;
6065   let Inst{30}    = Q;
6066   let Inst{29-21} = 0b001110000;
6067   let Inst{20-16} = Vm;
6068   let Inst{15}    = 0;
6069   let Inst{14-13} = len;
6070   let Inst{12}    = op;
6071   let Inst{11-10} = 0b00;
6072   let Inst{9-5}   = Vn;
6073   let Inst{4-0}   = Vd;
6074 }
6075
6076 class SIMDTableLookupAlias<string asm, Instruction inst,
6077                           RegisterOperand vectype, RegisterOperand listtype>
6078     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6079                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6080
6081 multiclass SIMDTableLookup<bit op, string asm> {
6082   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6083                                       asm, ".8b">;
6084   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6085                                       asm, ".8b">;
6086   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6087                                       asm, ".8b">;
6088   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6089                                       asm, ".8b">;
6090   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6091                                       asm, ".16b">;
6092   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6093                                       asm, ".16b">;
6094   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6095                                       asm, ".16b">;
6096   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6097                                       asm, ".16b">;
6098
6099   def : SIMDTableLookupAlias<asm # ".8b",
6100                          !cast<Instruction>(NAME#"v8i8One"),
6101                          V64, VecListOne128>;
6102   def : SIMDTableLookupAlias<asm # ".8b",
6103                          !cast<Instruction>(NAME#"v8i8Two"),
6104                          V64, VecListTwo128>;
6105   def : SIMDTableLookupAlias<asm # ".8b",
6106                          !cast<Instruction>(NAME#"v8i8Three"),
6107                          V64, VecListThree128>;
6108   def : SIMDTableLookupAlias<asm # ".8b",
6109                          !cast<Instruction>(NAME#"v8i8Four"),
6110                          V64, VecListFour128>;
6111   def : SIMDTableLookupAlias<asm # ".16b",
6112                          !cast<Instruction>(NAME#"v16i8One"),
6113                          V128, VecListOne128>;
6114   def : SIMDTableLookupAlias<asm # ".16b",
6115                          !cast<Instruction>(NAME#"v16i8Two"),
6116                          V128, VecListTwo128>;
6117   def : SIMDTableLookupAlias<asm # ".16b",
6118                          !cast<Instruction>(NAME#"v16i8Three"),
6119                          V128, VecListThree128>;
6120   def : SIMDTableLookupAlias<asm # ".16b",
6121                          !cast<Instruction>(NAME#"v16i8Four"),
6122                          V128, VecListFour128>;
6123 }
6124
6125 multiclass SIMDTableLookupTied<bit op, string asm> {
6126   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6127                                       asm, ".8b">;
6128   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6129                                       asm, ".8b">;
6130   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6131                                       asm, ".8b">;
6132   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6133                                       asm, ".8b">;
6134   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6135                                       asm, ".16b">;
6136   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6137                                       asm, ".16b">;
6138   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6139                                       asm, ".16b">;
6140   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6141                                       asm, ".16b">;
6142
6143   def : SIMDTableLookupAlias<asm # ".8b",
6144                          !cast<Instruction>(NAME#"v8i8One"),
6145                          V64, VecListOne128>;
6146   def : SIMDTableLookupAlias<asm # ".8b",
6147                          !cast<Instruction>(NAME#"v8i8Two"),
6148                          V64, VecListTwo128>;
6149   def : SIMDTableLookupAlias<asm # ".8b",
6150                          !cast<Instruction>(NAME#"v8i8Three"),
6151                          V64, VecListThree128>;
6152   def : SIMDTableLookupAlias<asm # ".8b",
6153                          !cast<Instruction>(NAME#"v8i8Four"),
6154                          V64, VecListFour128>;
6155   def : SIMDTableLookupAlias<asm # ".16b",
6156                          !cast<Instruction>(NAME#"v16i8One"),
6157                          V128, VecListOne128>;
6158   def : SIMDTableLookupAlias<asm # ".16b",
6159                          !cast<Instruction>(NAME#"v16i8Two"),
6160                          V128, VecListTwo128>;
6161   def : SIMDTableLookupAlias<asm # ".16b",
6162                          !cast<Instruction>(NAME#"v16i8Three"),
6163                          V128, VecListThree128>;
6164   def : SIMDTableLookupAlias<asm # ".16b",
6165                          !cast<Instruction>(NAME#"v16i8Four"),
6166                          V128, VecListFour128>;
6167 }
6168
6169
6170 //----------------------------------------------------------------------------
6171 // AdvSIMD scalar CPY
6172 //----------------------------------------------------------------------------
6173 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6174 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6175                         string kind, Operand idxtype>
6176   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6177        "{\t$dst, $src" # kind # "$idx" #
6178        "|\t$dst, $src$idx}", "", []>,
6179     Sched<[WriteV]> {
6180   bits<5> dst;
6181   bits<5> src;
6182   let Inst{31-21} = 0b01011110000;
6183   let Inst{15-10} = 0b000001;
6184   let Inst{9-5}   = src;
6185   let Inst{4-0}   = dst;
6186 }
6187
6188 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6189       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6190     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6191                     # "|\t$dst, $src$index}",
6192                 (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6193
6194
6195 multiclass SIMDScalarCPY<string asm> {
6196   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6197     bits<4> idx;
6198     let Inst{20-17} = idx;
6199     let Inst{16} = 1;
6200   }
6201   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6202     bits<3> idx;
6203     let Inst{20-18} = idx;
6204     let Inst{17-16} = 0b10;
6205   }
6206   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6207     bits<2> idx;
6208     let Inst{20-19} = idx;
6209     let Inst{18-16} = 0b100;
6210   }
6211   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6212     bits<1> idx;
6213     let Inst{20} = idx;
6214     let Inst{19-16} = 0b1000;
6215   }
6216
6217   def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6218                                                           VectorIndexD:$idx)))),
6219             (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6220
6221   // 'DUP' mnemonic aliases.
6222   def : SIMDScalarCPYAlias<"dup", ".b",
6223                            !cast<Instruction>(NAME#"i8"),
6224                            FPR8, V128, VectorIndexB>;
6225   def : SIMDScalarCPYAlias<"dup", ".h",
6226                            !cast<Instruction>(NAME#"i16"),
6227                            FPR16, V128, VectorIndexH>;
6228   def : SIMDScalarCPYAlias<"dup", ".s",
6229                            !cast<Instruction>(NAME#"i32"),
6230                            FPR32, V128, VectorIndexS>;
6231   def : SIMDScalarCPYAlias<"dup", ".d",
6232                            !cast<Instruction>(NAME#"i64"),
6233                            FPR64, V128, VectorIndexD>;
6234 }
6235
6236 //----------------------------------------------------------------------------
6237 // AdvSIMD modified immediate instructions
6238 //----------------------------------------------------------------------------
6239
6240 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
6241                           string asm, string op_string,
6242                           string cstr, list<dag> pattern>
6243   : I<oops, iops, asm, op_string, cstr, pattern>,
6244     Sched<[WriteV]> {
6245   bits<5> Rd;
6246   bits<8> imm8;
6247   let Inst{31}    = 0;
6248   let Inst{30}    = Q;
6249   let Inst{29}    = op;
6250   let Inst{28-19} = 0b0111100000;
6251   let Inst{18-16} = imm8{7-5};
6252   let Inst{11-10} = 0b01;
6253   let Inst{9-5}   = imm8{4-0};
6254   let Inst{4-0}   = Rd;
6255 }
6256
6257 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
6258                                 Operand immtype, dag opt_shift_iop,
6259                                 string opt_shift, string asm, string kind,
6260                                 list<dag> pattern>
6261   : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
6262                         !con((ins immtype:$imm8), opt_shift_iop), asm,
6263                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
6264                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6265                         "", pattern> {
6266   let DecoderMethod = "DecodeModImmInstruction";
6267 }
6268
6269 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6270                                 Operand immtype, dag opt_shift_iop,
6271                                 string opt_shift, string asm, string kind,
6272                                 list<dag> pattern>
6273   : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
6274                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6275                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6276                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6277                         "$Rd = $dst", pattern> {
6278   let DecoderMethod = "DecodeModImmTiedInstruction";
6279 }
6280
6281 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6282                                      RegisterOperand vectype, string asm,
6283                                      string kind, list<dag> pattern>
6284   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6285                               (ins logical_vec_shift:$shift),
6286                               "$shift", asm, kind, pattern> {
6287   bits<2> shift;
6288   let Inst{15}    = b15_b12{1};
6289   let Inst{14-13} = shift;
6290   let Inst{12}    = b15_b12{0};
6291 }
6292
6293 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6294                                      RegisterOperand vectype, string asm,
6295                                      string kind, list<dag> pattern>
6296   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6297                               (ins logical_vec_shift:$shift),
6298                               "$shift", asm, kind, pattern> {
6299   bits<2> shift;
6300   let Inst{15}    = b15_b12{1};
6301   let Inst{14-13} = shift;
6302   let Inst{12}    = b15_b12{0};
6303 }
6304
6305
6306 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6307                                          RegisterOperand vectype, string asm,
6308                                          string kind, list<dag> pattern>
6309   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6310                               (ins logical_vec_hw_shift:$shift),
6311                               "$shift", asm, kind, pattern> {
6312   bits<2> shift;
6313   let Inst{15} = b15_b12{1};
6314   let Inst{14} = 0;
6315   let Inst{13} = shift{0};
6316   let Inst{12} = b15_b12{0};
6317 }
6318
6319 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6320                                          RegisterOperand vectype, string asm,
6321                                          string kind, list<dag> pattern>
6322   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6323                               (ins logical_vec_hw_shift:$shift),
6324                               "$shift", asm, kind, pattern> {
6325   bits<2> shift;
6326   let Inst{15} = b15_b12{1};
6327   let Inst{14} = 0;
6328   let Inst{13} = shift{0};
6329   let Inst{12} = b15_b12{0};
6330 }
6331
6332 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6333                                       string asm> {
6334   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6335                                                  asm, ".4h", []>;
6336   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6337                                                  asm, ".8h", []>;
6338
6339   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6340                                              asm, ".2s", []>;
6341   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6342                                              asm, ".4s", []>;
6343 }
6344
6345 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6346                                       bits<2> w_cmode, string asm,
6347                                       SDNode OpNode> {
6348   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6349                                                  asm, ".4h",
6350              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6351                                              imm0_255:$imm8,
6352                                              (i32 imm:$shift)))]>;
6353   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6354                                                  asm, ".8h",
6355              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6356                                               imm0_255:$imm8,
6357                                               (i32 imm:$shift)))]>;
6358
6359   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6360                                              asm, ".2s",
6361              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6362                                              imm0_255:$imm8,
6363                                              (i32 imm:$shift)))]>;
6364   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6365                                              asm, ".4s",
6366              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6367                                               imm0_255:$imm8,
6368                                               (i32 imm:$shift)))]>;
6369 }
6370
6371 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6372                              RegisterOperand vectype, string asm,
6373                              string kind, list<dag> pattern>
6374   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
6375                               (ins move_vec_shift:$shift),
6376                               "$shift", asm, kind, pattern> {
6377   bits<1> shift;
6378   let Inst{15-13} = cmode{3-1};
6379   let Inst{12}    = shift;
6380 }
6381
6382 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
6383                                    RegisterOperand vectype,
6384                                    Operand imm_type, string asm,
6385                                    string kind, list<dag> pattern>
6386   : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
6387                               asm, kind, pattern> {
6388   let Inst{15-12} = cmode;
6389 }
6390
6391 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6392                                    list<dag> pattern>
6393   : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6394                         "\t$Rd, $imm8", "", pattern> {
6395   let Inst{15-12} = cmode;
6396   let DecoderMethod = "DecodeModImmInstruction";
6397 }
6398
6399 //----------------------------------------------------------------------------
6400 // AdvSIMD indexed element
6401 //----------------------------------------------------------------------------
6402
6403 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6404 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6405                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6406                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6407                       string apple_kind, string dst_kind, string lhs_kind,
6408                       string rhs_kind, list<dag> pattern>
6409   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6410       asm,
6411       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6412       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6413     Sched<[WriteV]> {
6414   bits<5> Rd;
6415   bits<5> Rn;
6416   bits<5> Rm;
6417
6418   let Inst{31}    = 0;
6419   let Inst{30}    = Q;
6420   let Inst{29}    = U;
6421   let Inst{28}    = Scalar;
6422   let Inst{27-24} = 0b1111;
6423   let Inst{23-22} = size;
6424   // Bit 21 must be set by the derived class.
6425   let Inst{20-16} = Rm;
6426   let Inst{15-12} = opc;
6427   // Bit 11 must be set by the derived class.
6428   let Inst{10}    = 0;
6429   let Inst{9-5}   = Rn;
6430   let Inst{4-0}   = Rd;
6431 }
6432
6433 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6434 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6435                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
6436                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
6437                       string apple_kind, string dst_kind, string lhs_kind,
6438                       string rhs_kind, list<dag> pattern>
6439   : I<(outs dst_reg:$dst),
6440       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6441       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6442       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6443     Sched<[WriteV]> {
6444   bits<5> Rd;
6445   bits<5> Rn;
6446   bits<5> Rm;
6447
6448   let Inst{31}    = 0;
6449   let Inst{30}    = Q;
6450   let Inst{29}    = U;
6451   let Inst{28}    = Scalar;
6452   let Inst{27-24} = 0b1111;
6453   let Inst{23-22} = size;
6454   // Bit 21 must be set by the derived class.
6455   let Inst{20-16} = Rm;
6456   let Inst{15-12} = opc;
6457   // Bit 11 must be set by the derived class.
6458   let Inst{10}    = 0;
6459   let Inst{9-5}   = Rn;
6460   let Inst{4-0}   = Rd;
6461 }
6462
6463 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
6464                            SDPatternOperator OpNode> {
6465   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6466                                       V64, V64,
6467                                       V128, VectorIndexS,
6468                                       asm, ".2s", ".2s", ".2s", ".s",
6469     [(set (v2f32 V64:$Rd),
6470         (OpNode (v2f32 V64:$Rn),
6471          (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6472     bits<2> idx;
6473     let Inst{11} = idx{1};
6474     let Inst{21} = idx{0};
6475   }
6476
6477   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6478                                       V128, V128,
6479                                       V128, VectorIndexS,
6480                                       asm, ".4s", ".4s", ".4s", ".s",
6481     [(set (v4f32 V128:$Rd),
6482         (OpNode (v4f32 V128:$Rn),
6483          (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6484     bits<2> idx;
6485     let Inst{11} = idx{1};
6486     let Inst{21} = idx{0};
6487   }
6488
6489   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6490                                       V128, V128,
6491                                       V128, VectorIndexD,
6492                                       asm, ".2d", ".2d", ".2d", ".d",
6493     [(set (v2f64 V128:$Rd),
6494         (OpNode (v2f64 V128:$Rn),
6495          (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6496     bits<1> idx;
6497     let Inst{11} = idx{0};
6498     let Inst{21} = 0;
6499   }
6500
6501   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6502                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6503                                       asm, ".s", "", "", ".s",
6504     [(set (f32 FPR32Op:$Rd),
6505           (OpNode (f32 FPR32Op:$Rn),
6506                   (f32 (vector_extract (v4f32 V128:$Rm),
6507                                        VectorIndexS:$idx))))]> {
6508     bits<2> idx;
6509     let Inst{11} = idx{1};
6510     let Inst{21} = idx{0};
6511   }
6512
6513   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6514                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6515                                       asm, ".d", "", "", ".d",
6516     [(set (f64 FPR64Op:$Rd),
6517           (OpNode (f64 FPR64Op:$Rn),
6518                   (f64 (vector_extract (v2f64 V128:$Rm),
6519                                        VectorIndexD:$idx))))]> {
6520     bits<1> idx;
6521     let Inst{11} = idx{0};
6522     let Inst{21} = 0;
6523   }
6524 }
6525
6526 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6527   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6528   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6529                            (AArch64duplane32 (v4f32 V128:$Rm),
6530                                            VectorIndexS:$idx))),
6531             (!cast<Instruction>(INST # v2i32_indexed)
6532                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6533   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6534                            (AArch64dup (f32 FPR32Op:$Rm)))),
6535             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6536                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6537
6538
6539   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6540   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6541                            (AArch64duplane32 (v4f32 V128:$Rm),
6542                                            VectorIndexS:$idx))),
6543             (!cast<Instruction>(INST # "v4i32_indexed")
6544                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6545   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6546                            (AArch64dup (f32 FPR32Op:$Rm)))),
6547             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6548                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6549
6550   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6551   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6552                            (AArch64duplane64 (v2f64 V128:$Rm),
6553                                            VectorIndexD:$idx))),
6554             (!cast<Instruction>(INST # "v2i64_indexed")
6555                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6556   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6557                            (AArch64dup (f64 FPR64Op:$Rm)))),
6558             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6559                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6560
6561   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6562   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6563                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6564             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6565                 V128:$Rm, VectorIndexS:$idx)>;
6566   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6567                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6568             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6569                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6570
6571   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6572   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6573                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6574             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6575                 V128:$Rm, VectorIndexD:$idx)>;
6576 }
6577
6578 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6579   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6580                                           V128, VectorIndexS,
6581                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6582     bits<2> idx;
6583     let Inst{11} = idx{1};
6584     let Inst{21} = idx{0};
6585   }
6586
6587   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6588                                       V128, V128,
6589                                       V128, VectorIndexS,
6590                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6591     bits<2> idx;
6592     let Inst{11} = idx{1};
6593     let Inst{21} = idx{0};
6594   }
6595
6596   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6597                                       V128, V128,
6598                                       V128, VectorIndexD,
6599                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6600     bits<1> idx;
6601     let Inst{11} = idx{0};
6602     let Inst{21} = 0;
6603   }
6604
6605
6606   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6607                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6608                                       asm, ".s", "", "", ".s", []> {
6609     bits<2> idx;
6610     let Inst{11} = idx{1};
6611     let Inst{21} = idx{0};
6612   }
6613
6614   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6615                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6616                                       asm, ".d", "", "", ".d", []> {
6617     bits<1> idx;
6618     let Inst{11} = idx{0};
6619     let Inst{21} = 0;
6620   }
6621 }
6622
6623 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6624                          SDPatternOperator OpNode> {
6625   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6626                                       V128_lo, VectorIndexH,
6627                                       asm, ".4h", ".4h", ".4h", ".h",
6628     [(set (v4i16 V64:$Rd),
6629         (OpNode (v4i16 V64:$Rn),
6630          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6631     bits<3> idx;
6632     let Inst{11} = idx{2};
6633     let Inst{21} = idx{1};
6634     let Inst{20} = idx{0};
6635   }
6636
6637   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6638                                       V128, V128,
6639                                       V128_lo, VectorIndexH,
6640                                       asm, ".8h", ".8h", ".8h", ".h",
6641     [(set (v8i16 V128:$Rd),
6642        (OpNode (v8i16 V128:$Rn),
6643          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6644     bits<3> idx;
6645     let Inst{11} = idx{2};
6646     let Inst{21} = idx{1};
6647     let Inst{20} = idx{0};
6648   }
6649
6650   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6651                                       V64, V64,
6652                                       V128, VectorIndexS,
6653                                       asm, ".2s", ".2s", ".2s",  ".s",
6654     [(set (v2i32 V64:$Rd),
6655        (OpNode (v2i32 V64:$Rn),
6656           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6657     bits<2> idx;
6658     let Inst{11} = idx{1};
6659     let Inst{21} = idx{0};
6660   }
6661
6662   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6663                                       V128, V128,
6664                                       V128, VectorIndexS,
6665                                       asm, ".4s", ".4s", ".4s", ".s",
6666     [(set (v4i32 V128:$Rd),
6667        (OpNode (v4i32 V128:$Rn),
6668           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6669     bits<2> idx;
6670     let Inst{11} = idx{1};
6671     let Inst{21} = idx{0};
6672   }
6673
6674   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6675                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6676                                       asm, ".h", "", "", ".h", []> {
6677     bits<3> idx;
6678     let Inst{11} = idx{2};
6679     let Inst{21} = idx{1};
6680     let Inst{20} = idx{0};
6681   }
6682
6683   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6684                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6685                                       asm, ".s", "", "", ".s",
6686       [(set (i32 FPR32Op:$Rd),
6687             (OpNode FPR32Op:$Rn,
6688                     (i32 (vector_extract (v4i32 V128:$Rm),
6689                                          VectorIndexS:$idx))))]> {
6690     bits<2> idx;
6691     let Inst{11} = idx{1};
6692     let Inst{21} = idx{0};
6693   }
6694 }
6695
6696 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6697                                SDPatternOperator OpNode> {
6698   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6699                                       V64, V64,
6700                                       V128_lo, VectorIndexH,
6701                                       asm, ".4h", ".4h", ".4h", ".h",
6702     [(set (v4i16 V64:$Rd),
6703         (OpNode (v4i16 V64:$Rn),
6704          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6705     bits<3> idx;
6706     let Inst{11} = idx{2};
6707     let Inst{21} = idx{1};
6708     let Inst{20} = idx{0};
6709   }
6710
6711   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6712                                       V128, V128,
6713                                       V128_lo, VectorIndexH,
6714                                       asm, ".8h", ".8h", ".8h", ".h",
6715     [(set (v8i16 V128:$Rd),
6716        (OpNode (v8i16 V128:$Rn),
6717          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6718     bits<3> idx;
6719     let Inst{11} = idx{2};
6720     let Inst{21} = idx{1};
6721     let Inst{20} = idx{0};
6722   }
6723
6724   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6725                                       V64, V64,
6726                                       V128, VectorIndexS,
6727                                       asm, ".2s", ".2s", ".2s", ".s",
6728     [(set (v2i32 V64:$Rd),
6729        (OpNode (v2i32 V64:$Rn),
6730           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6731     bits<2> idx;
6732     let Inst{11} = idx{1};
6733     let Inst{21} = idx{0};
6734   }
6735
6736   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6737                                       V128, V128,
6738                                       V128, VectorIndexS,
6739                                       asm, ".4s", ".4s", ".4s", ".s",
6740     [(set (v4i32 V128:$Rd),
6741        (OpNode (v4i32 V128:$Rn),
6742           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6743     bits<2> idx;
6744     let Inst{11} = idx{1};
6745     let Inst{21} = idx{0};
6746   }
6747 }
6748
6749 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6750                                    SDPatternOperator OpNode> {
6751   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6752                                           V128_lo, VectorIndexH,
6753                                           asm, ".4h", ".4h", ".4h", ".h",
6754     [(set (v4i16 V64:$dst),
6755         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6756          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6757     bits<3> idx;
6758     let Inst{11} = idx{2};
6759     let Inst{21} = idx{1};
6760     let Inst{20} = idx{0};
6761   }
6762
6763   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6764                                       V128, V128,
6765                                       V128_lo, VectorIndexH,
6766                                       asm, ".8h", ".8h", ".8h", ".h",
6767     [(set (v8i16 V128:$dst),
6768        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6769          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6770     bits<3> idx;
6771     let Inst{11} = idx{2};
6772     let Inst{21} = idx{1};
6773     let Inst{20} = idx{0};
6774   }
6775
6776   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6777                                       V64, V64,
6778                                       V128, VectorIndexS,
6779                                       asm, ".2s", ".2s", ".2s", ".s",
6780     [(set (v2i32 V64:$dst),
6781        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6782           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6783     bits<2> idx;
6784     let Inst{11} = idx{1};
6785     let Inst{21} = idx{0};
6786   }
6787
6788   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6789                                       V128, V128,
6790                                       V128, VectorIndexS,
6791                                       asm, ".4s", ".4s", ".4s", ".s",
6792     [(set (v4i32 V128:$dst),
6793        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6794           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6795     bits<2> idx;
6796     let Inst{11} = idx{1};
6797     let Inst{21} = idx{0};
6798   }
6799 }
6800
6801 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6802                              SDPatternOperator OpNode> {
6803   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6804                                       V128, V64,
6805                                       V128_lo, VectorIndexH,
6806                                       asm, ".4s", ".4s", ".4h", ".h",
6807     [(set (v4i32 V128:$Rd),
6808         (OpNode (v4i16 V64:$Rn),
6809          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6810     bits<3> idx;
6811     let Inst{11} = idx{2};
6812     let Inst{21} = idx{1};
6813     let Inst{20} = idx{0};
6814   }
6815
6816   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6817                                       V128, V128,
6818                                       V128_lo, VectorIndexH,
6819                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6820     [(set (v4i32 V128:$Rd),
6821           (OpNode (extract_high_v8i16 V128:$Rn),
6822                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6823                                                       VectorIndexH:$idx))))]> {
6824
6825     bits<3> idx;
6826     let Inst{11} = idx{2};
6827     let Inst{21} = idx{1};
6828     let Inst{20} = idx{0};
6829   }
6830
6831   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6832                                       V128, V64,
6833                                       V128, VectorIndexS,
6834                                       asm, ".2d", ".2d", ".2s", ".s",
6835     [(set (v2i64 V128:$Rd),
6836         (OpNode (v2i32 V64:$Rn),
6837          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6838     bits<2> idx;
6839     let Inst{11} = idx{1};
6840     let Inst{21} = idx{0};
6841   }
6842
6843   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6844                                       V128, V128,
6845                                       V128, VectorIndexS,
6846                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6847     [(set (v2i64 V128:$Rd),
6848           (OpNode (extract_high_v4i32 V128:$Rn),
6849                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
6850                                                       VectorIndexS:$idx))))]> {
6851     bits<2> idx;
6852     let Inst{11} = idx{1};
6853     let Inst{21} = idx{0};
6854   }
6855
6856   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6857                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6858                                       asm, ".h", "", "", ".h", []> {
6859     bits<3> idx;
6860     let Inst{11} = idx{2};
6861     let Inst{21} = idx{1};
6862     let Inst{20} = idx{0};
6863   }
6864
6865   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6866                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6867                                       asm, ".s", "", "", ".s", []> {
6868     bits<2> idx;
6869     let Inst{11} = idx{1};
6870     let Inst{21} = idx{0};
6871   }
6872 }
6873
6874 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6875                                        SDPatternOperator Accum> {
6876   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6877                                       V128, V64,
6878                                       V128_lo, VectorIndexH,
6879                                       asm, ".4s", ".4s", ".4h", ".h",
6880     [(set (v4i32 V128:$dst),
6881           (Accum (v4i32 V128:$Rd),
6882                  (v4i32 (int_aarch64_neon_sqdmull
6883                              (v4i16 V64:$Rn),
6884                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6885                                                     VectorIndexH:$idx))))))]> {
6886     bits<3> idx;
6887     let Inst{11} = idx{2};
6888     let Inst{21} = idx{1};
6889     let Inst{20} = idx{0};
6890   }
6891
6892   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6893   // intermediate EXTRACT_SUBREG would be untyped.
6894   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6895                 (i32 (vector_extract (v4i32
6896                          (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6897                              (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6898                                                     VectorIndexH:$idx)))),
6899                          (i64 0))))),
6900             (EXTRACT_SUBREG
6901                 (!cast<Instruction>(NAME # v4i16_indexed)
6902                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6903                     V128_lo:$Rm, VectorIndexH:$idx),
6904                 ssub)>;
6905
6906   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6907                                       V128, V128,
6908                                       V128_lo, VectorIndexH,
6909                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6910     [(set (v4i32 V128:$dst),
6911           (Accum (v4i32 V128:$Rd),
6912                  (v4i32 (int_aarch64_neon_sqdmull
6913                             (extract_high_v8i16 V128:$Rn),
6914                             (extract_high_v8i16
6915                                 (AArch64duplane16 (v8i16 V128_lo:$Rm),
6916                                                 VectorIndexH:$idx))))))]> {
6917     bits<3> idx;
6918     let Inst{11} = idx{2};
6919     let Inst{21} = idx{1};
6920     let Inst{20} = idx{0};
6921   }
6922
6923   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6924                                       V128, V64,
6925                                       V128, VectorIndexS,
6926                                       asm, ".2d", ".2d", ".2s", ".s",
6927     [(set (v2i64 V128:$dst),
6928         (Accum (v2i64 V128:$Rd),
6929                (v2i64 (int_aarch64_neon_sqdmull
6930                           (v2i32 V64:$Rn),
6931                           (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
6932                                                  VectorIndexS:$idx))))))]> {
6933     bits<2> idx;
6934     let Inst{11} = idx{1};
6935     let Inst{21} = idx{0};
6936   }
6937
6938   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6939                                       V128, V128,
6940                                       V128, VectorIndexS,
6941                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6942     [(set (v2i64 V128:$dst),
6943           (Accum (v2i64 V128:$Rd),
6944                  (v2i64 (int_aarch64_neon_sqdmull
6945                             (extract_high_v4i32 V128:$Rn),
6946                             (extract_high_v4i32
6947                                 (AArch64duplane32 (v4i32 V128:$Rm),
6948                                                 VectorIndexS:$idx))))))]> {
6949     bits<2> idx;
6950     let Inst{11} = idx{1};
6951     let Inst{21} = idx{0};
6952   }
6953
6954   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6955                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6956                                       asm, ".h", "", "", ".h", []> {
6957     bits<3> idx;
6958     let Inst{11} = idx{2};
6959     let Inst{21} = idx{1};
6960     let Inst{20} = idx{0};
6961   }
6962
6963
6964   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6965                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6966                                       asm, ".s", "", "", ".s",
6967     [(set (i64 FPR64Op:$dst),
6968           (Accum (i64 FPR64Op:$Rd),
6969                  (i64 (int_aarch64_neon_sqdmulls_scalar
6970                             (i32 FPR32Op:$Rn),
6971                             (i32 (vector_extract (v4i32 V128:$Rm),
6972                                                  VectorIndexS:$idx))))))]> {
6973
6974     bits<2> idx;
6975     let Inst{11} = idx{1};
6976     let Inst{21} = idx{0};
6977   }
6978 }
6979
6980 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6981                                    SDPatternOperator OpNode> {
6982   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6983   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6984                                       V128, V64,
6985                                       V128_lo, VectorIndexH,
6986                                       asm, ".4s", ".4s", ".4h", ".h",
6987     [(set (v4i32 V128:$Rd),
6988         (OpNode (v4i16 V64:$Rn),
6989          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6990     bits<3> idx;
6991     let Inst{11} = idx{2};
6992     let Inst{21} = idx{1};
6993     let Inst{20} = idx{0};
6994   }
6995
6996   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6997                                       V128, V128,
6998                                       V128_lo, VectorIndexH,
6999                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7000     [(set (v4i32 V128:$Rd),
7001           (OpNode (extract_high_v8i16 V128:$Rn),
7002                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7003                                                       VectorIndexH:$idx))))]> {
7004
7005     bits<3> idx;
7006     let Inst{11} = idx{2};
7007     let Inst{21} = idx{1};
7008     let Inst{20} = idx{0};
7009   }
7010
7011   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7012                                       V128, V64,
7013                                       V128, VectorIndexS,
7014                                       asm, ".2d", ".2d", ".2s", ".s",
7015     [(set (v2i64 V128:$Rd),
7016         (OpNode (v2i32 V64:$Rn),
7017          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7018     bits<2> idx;
7019     let Inst{11} = idx{1};
7020     let Inst{21} = idx{0};
7021   }
7022
7023   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7024                                       V128, V128,
7025                                       V128, VectorIndexS,
7026                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7027     [(set (v2i64 V128:$Rd),
7028           (OpNode (extract_high_v4i32 V128:$Rn),
7029                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7030                                                       VectorIndexS:$idx))))]> {
7031     bits<2> idx;
7032     let Inst{11} = idx{1};
7033     let Inst{21} = idx{0};
7034   }
7035   }
7036 }
7037
7038 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7039                                        SDPatternOperator OpNode> {
7040   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7041   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7042                                       V128, V64,
7043                                       V128_lo, VectorIndexH,
7044                                       asm, ".4s", ".4s", ".4h", ".h",
7045     [(set (v4i32 V128:$dst),
7046         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7047          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7048     bits<3> idx;
7049     let Inst{11} = idx{2};
7050     let Inst{21} = idx{1};
7051     let Inst{20} = idx{0};
7052   }
7053
7054   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7055                                       V128, V128,
7056                                       V128_lo, VectorIndexH,
7057                                       asm#"2", ".4s", ".4s", ".8h", ".h",
7058     [(set (v4i32 V128:$dst),
7059           (OpNode (v4i32 V128:$Rd),
7060                   (extract_high_v8i16 V128:$Rn),
7061                   (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7062                                                       VectorIndexH:$idx))))]> {
7063     bits<3> idx;
7064     let Inst{11} = idx{2};
7065     let Inst{21} = idx{1};
7066     let Inst{20} = idx{0};
7067   }
7068
7069   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7070                                       V128, V64,
7071                                       V128, VectorIndexS,
7072                                       asm, ".2d", ".2d", ".2s", ".s",
7073     [(set (v2i64 V128:$dst),
7074         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7075          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7076     bits<2> idx;
7077     let Inst{11} = idx{1};
7078     let Inst{21} = idx{0};
7079   }
7080
7081   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7082                                       V128, V128,
7083                                       V128, VectorIndexS,
7084                                       asm#"2", ".2d", ".2d", ".4s", ".s",
7085     [(set (v2i64 V128:$dst),
7086           (OpNode (v2i64 V128:$Rd),
7087                   (extract_high_v4i32 V128:$Rn),
7088                   (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7089                                                       VectorIndexS:$idx))))]> {
7090     bits<2> idx;
7091     let Inst{11} = idx{1};
7092     let Inst{21} = idx{0};
7093   }
7094   }
7095 }
7096
7097 //----------------------------------------------------------------------------
7098 // AdvSIMD scalar shift by immediate
7099 //----------------------------------------------------------------------------
7100
7101 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7102 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7103                      RegisterClass regtype1, RegisterClass regtype2,
7104                      Operand immtype, string asm, list<dag> pattern>
7105   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7106       asm, "\t$Rd, $Rn, $imm", "", pattern>,
7107     Sched<[WriteV]> {
7108   bits<5> Rd;
7109   bits<5> Rn;
7110   bits<7> imm;
7111   let Inst{31-30} = 0b01;
7112   let Inst{29}    = U;
7113   let Inst{28-23} = 0b111110;
7114   let Inst{22-16} = fixed_imm;
7115   let Inst{15-11} = opc;
7116   let Inst{10}    = 1;
7117   let Inst{9-5} = Rn;
7118   let Inst{4-0} = Rd;
7119 }
7120
7121 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7122 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7123                      RegisterClass regtype1, RegisterClass regtype2,
7124                      Operand immtype, string asm, list<dag> pattern>
7125   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7126       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7127     Sched<[WriteV]> {
7128   bits<5> Rd;
7129   bits<5> Rn;
7130   bits<7> imm;
7131   let Inst{31-30} = 0b01;
7132   let Inst{29}    = U;
7133   let Inst{28-23} = 0b111110;
7134   let Inst{22-16} = fixed_imm;
7135   let Inst{15-11} = opc;
7136   let Inst{10}    = 1;
7137   let Inst{9-5} = Rn;
7138   let Inst{4-0} = Rd;
7139 }
7140
7141
7142 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
7143   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7144                               FPR32, FPR32, vecshiftR32, asm, []> {
7145     let Inst{20-16} = imm{4-0};
7146   }
7147
7148   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7149                               FPR64, FPR64, vecshiftR64, asm, []> {
7150     let Inst{21-16} = imm{5-0};
7151   }
7152 }
7153
7154 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7155                              SDPatternOperator OpNode> {
7156   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7157                               FPR64, FPR64, vecshiftR64, asm,
7158   [(set (i64 FPR64:$Rd),
7159      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7160     let Inst{21-16} = imm{5-0};
7161   }
7162
7163   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7164             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7165 }
7166
7167 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7168                                  SDPatternOperator OpNode = null_frag> {
7169   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7170                               FPR64, FPR64, vecshiftR64, asm,
7171   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7172                                                    (i32 vecshiftR64:$imm)))]> {
7173     let Inst{21-16} = imm{5-0};
7174   }
7175
7176   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7177                            (i32 vecshiftR64:$imm))),
7178             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7179                                             vecshiftR64:$imm)>;
7180 }
7181
7182 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7183                              SDPatternOperator OpNode> {
7184   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7185                               FPR64, FPR64, vecshiftL64, asm,
7186     [(set (v1i64 FPR64:$Rd),
7187        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7188     let Inst{21-16} = imm{5-0};
7189   }
7190 }
7191
7192 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7193 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7194   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7195                               FPR64, FPR64, vecshiftL64, asm, []> {
7196     let Inst{21-16} = imm{5-0};
7197   }
7198 }
7199
7200 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7201 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7202                                SDPatternOperator OpNode = null_frag> {
7203   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7204                               FPR8, FPR16, vecshiftR8, asm, []> {
7205     let Inst{18-16} = imm{2-0};
7206   }
7207
7208   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7209                               FPR16, FPR32, vecshiftR16, asm, []> {
7210     let Inst{19-16} = imm{3-0};
7211   }
7212
7213   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7214                               FPR32, FPR64, vecshiftR32, asm,
7215     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7216     let Inst{20-16} = imm{4-0};
7217   }
7218 }
7219
7220 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7221                                 SDPatternOperator OpNode> {
7222   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7223                               FPR8, FPR8, vecshiftL8, asm, []> {
7224     let Inst{18-16} = imm{2-0};
7225   }
7226
7227   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7228                               FPR16, FPR16, vecshiftL16, asm, []> {
7229     let Inst{19-16} = imm{3-0};
7230   }
7231
7232   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7233                               FPR32, FPR32, vecshiftL32, asm,
7234     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7235     let Inst{20-16} = imm{4-0};
7236   }
7237
7238   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7239                               FPR64, FPR64, vecshiftL64, asm,
7240     [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7241     let Inst{21-16} = imm{5-0};
7242   }
7243
7244   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7245             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7246 }
7247
7248 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7249   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7250                               FPR8, FPR8, vecshiftR8, asm, []> {
7251     let Inst{18-16} = imm{2-0};
7252   }
7253
7254   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7255                               FPR16, FPR16, vecshiftR16, asm, []> {
7256     let Inst{19-16} = imm{3-0};
7257   }
7258
7259   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7260                               FPR32, FPR32, vecshiftR32, asm, []> {
7261     let Inst{20-16} = imm{4-0};
7262   }
7263
7264   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7265                               FPR64, FPR64, vecshiftR64, asm, []> {
7266     let Inst{21-16} = imm{5-0};
7267   }
7268 }
7269
7270 //----------------------------------------------------------------------------
7271 // AdvSIMD vector x indexed element
7272 //----------------------------------------------------------------------------
7273
7274 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7275 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7276                      RegisterOperand dst_reg, RegisterOperand src_reg,
7277                      Operand immtype,
7278                      string asm, string dst_kind, string src_kind,
7279                      list<dag> pattern>
7280   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7281       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7282            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7283     Sched<[WriteV]> {
7284   bits<5> Rd;
7285   bits<5> Rn;
7286   let Inst{31}    = 0;
7287   let Inst{30}    = Q;
7288   let Inst{29}    = U;
7289   let Inst{28-23} = 0b011110;
7290   let Inst{22-16} = fixed_imm;
7291   let Inst{15-11} = opc;
7292   let Inst{10}    = 1;
7293   let Inst{9-5}   = Rn;
7294   let Inst{4-0}   = Rd;
7295 }
7296
7297 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7298 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7299                      RegisterOperand vectype1, RegisterOperand vectype2,
7300                      Operand immtype,
7301                      string asm, string dst_kind, string src_kind,
7302                      list<dag> pattern>
7303   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7304       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7305            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7306     Sched<[WriteV]> {
7307   bits<5> Rd;
7308   bits<5> Rn;
7309   let Inst{31}    = 0;
7310   let Inst{30}    = Q;
7311   let Inst{29}    = U;
7312   let Inst{28-23} = 0b011110;
7313   let Inst{22-16} = fixed_imm;
7314   let Inst{15-11} = opc;
7315   let Inst{10}    = 1;
7316   let Inst{9-5}   = Rn;
7317   let Inst{4-0}   = Rd;
7318 }
7319
7320 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7321                               Intrinsic OpNode> {
7322   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7323                                   V64, V64, vecshiftR32,
7324                                   asm, ".2s", ".2s",
7325       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
7326     bits<5> imm;
7327     let Inst{20-16} = imm;
7328   }
7329
7330   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7331                                   V128, V128, vecshiftR32,
7332                                   asm, ".4s", ".4s",
7333       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7334     bits<5> imm;
7335     let Inst{20-16} = imm;
7336   }
7337
7338   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7339                                   V128, V128, vecshiftR64,
7340                                   asm, ".2d", ".2d",
7341       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7342     bits<6> imm;
7343     let Inst{21-16} = imm;
7344   }
7345 }
7346
7347 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
7348                                   Intrinsic OpNode> {
7349   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7350                                   V64, V64, vecshiftR32,
7351                                   asm, ".2s", ".2s",
7352       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7353     bits<5> imm;
7354     let Inst{20-16} = imm;
7355   }
7356
7357   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7358                                   V128, V128, vecshiftR32,
7359                                   asm, ".4s", ".4s",
7360       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7361     bits<5> imm;
7362     let Inst{20-16} = imm;
7363   }
7364
7365   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7366                                   V128, V128, vecshiftR64,
7367                                   asm, ".2d", ".2d",
7368       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7369     bits<6> imm;
7370     let Inst{21-16} = imm;
7371   }
7372 }
7373
7374 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7375                                      SDPatternOperator OpNode> {
7376   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7377                                   V64, V128, vecshiftR16Narrow,
7378                                   asm, ".8b", ".8h",
7379       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7380     bits<3> imm;
7381     let Inst{18-16} = imm;
7382   }
7383
7384   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7385                                   V128, V128, vecshiftR16Narrow,
7386                                   asm#"2", ".16b", ".8h", []> {
7387     bits<3> imm;
7388     let Inst{18-16} = imm;
7389     let hasSideEffects = 0;
7390   }
7391
7392   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7393                                   V64, V128, vecshiftR32Narrow,
7394                                   asm, ".4h", ".4s",
7395       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7396     bits<4> imm;
7397     let Inst{19-16} = imm;
7398   }
7399
7400   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7401                                   V128, V128, vecshiftR32Narrow,
7402                                   asm#"2", ".8h", ".4s", []> {
7403     bits<4> imm;
7404     let Inst{19-16} = imm;
7405     let hasSideEffects = 0;
7406   }
7407
7408   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7409                                   V64, V128, vecshiftR64Narrow,
7410                                   asm, ".2s", ".2d",
7411       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7412     bits<5> imm;
7413     let Inst{20-16} = imm;
7414   }
7415
7416   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7417                                   V128, V128, vecshiftR64Narrow,
7418                                   asm#"2", ".4s", ".2d", []> {
7419     bits<5> imm;
7420     let Inst{20-16} = imm;
7421     let hasSideEffects = 0;
7422   }
7423
7424   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7425   // themselves, so put them here instead.
7426
7427   // Patterns involving what's effectively an insert high and a normal
7428   // intrinsic, represented by CONCAT_VECTORS.
7429   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7430                                                    vecshiftR16Narrow:$imm)),
7431             (!cast<Instruction>(NAME # "v16i8_shift")
7432                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7433                 V128:$Rn, vecshiftR16Narrow:$imm)>;
7434   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7435                                                      vecshiftR32Narrow:$imm)),
7436             (!cast<Instruction>(NAME # "v8i16_shift")
7437                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7438                 V128:$Rn, vecshiftR32Narrow:$imm)>;
7439   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7440                                                      vecshiftR64Narrow:$imm)),
7441             (!cast<Instruction>(NAME # "v4i32_shift")
7442                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7443                 V128:$Rn, vecshiftR64Narrow:$imm)>;
7444 }
7445
7446 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7447                                 SDPatternOperator OpNode> {
7448   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7449                                   V64, V64, vecshiftL8,
7450                                   asm, ".8b", ".8b",
7451                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7452                        (i32 vecshiftL8:$imm)))]> {
7453     bits<3> imm;
7454     let Inst{18-16} = imm;
7455   }
7456
7457   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7458                                   V128, V128, vecshiftL8,
7459                                   asm, ".16b", ".16b",
7460              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7461                    (i32 vecshiftL8:$imm)))]> {
7462     bits<3> imm;
7463     let Inst{18-16} = imm;
7464   }
7465
7466   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7467                                   V64, V64, vecshiftL16,
7468                                   asm, ".4h", ".4h",
7469               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7470                     (i32 vecshiftL16:$imm)))]> {
7471     bits<4> imm;
7472     let Inst{19-16} = imm;
7473   }
7474
7475   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7476                                   V128, V128, vecshiftL16,
7477                                   asm, ".8h", ".8h",
7478             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7479                   (i32 vecshiftL16:$imm)))]> {
7480     bits<4> imm;
7481     let Inst{19-16} = imm;
7482   }
7483
7484   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7485                                   V64, V64, vecshiftL32,
7486                                   asm, ".2s", ".2s",
7487               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7488                     (i32 vecshiftL32:$imm)))]> {
7489     bits<5> imm;
7490     let Inst{20-16} = imm;
7491   }
7492
7493   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7494                                   V128, V128, vecshiftL32,
7495                                   asm, ".4s", ".4s",
7496             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7497                   (i32 vecshiftL32:$imm)))]> {
7498     bits<5> imm;
7499     let Inst{20-16} = imm;
7500   }
7501
7502   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7503                                   V128, V128, vecshiftL64,
7504                                   asm, ".2d", ".2d",
7505             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7506                   (i32 vecshiftL64:$imm)))]> {
7507     bits<6> imm;
7508     let Inst{21-16} = imm;
7509   }
7510 }
7511
7512 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7513                                 SDPatternOperator OpNode> {
7514   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7515                                   V64, V64, vecshiftR8,
7516                                   asm, ".8b", ".8b",
7517                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7518                        (i32 vecshiftR8:$imm)))]> {
7519     bits<3> imm;
7520     let Inst{18-16} = imm;
7521   }
7522
7523   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7524                                   V128, V128, vecshiftR8,
7525                                   asm, ".16b", ".16b",
7526              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7527                    (i32 vecshiftR8:$imm)))]> {
7528     bits<3> imm;
7529     let Inst{18-16} = imm;
7530   }
7531
7532   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7533                                   V64, V64, vecshiftR16,
7534                                   asm, ".4h", ".4h",
7535               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7536                     (i32 vecshiftR16:$imm)))]> {
7537     bits<4> imm;
7538     let Inst{19-16} = imm;
7539   }
7540
7541   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7542                                   V128, V128, vecshiftR16,
7543                                   asm, ".8h", ".8h",
7544             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7545                   (i32 vecshiftR16:$imm)))]> {
7546     bits<4> imm;
7547     let Inst{19-16} = imm;
7548   }
7549
7550   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7551                                   V64, V64, vecshiftR32,
7552                                   asm, ".2s", ".2s",
7553               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7554                     (i32 vecshiftR32:$imm)))]> {
7555     bits<5> imm;
7556     let Inst{20-16} = imm;
7557   }
7558
7559   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7560                                   V128, V128, vecshiftR32,
7561                                   asm, ".4s", ".4s",
7562             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7563                   (i32 vecshiftR32:$imm)))]> {
7564     bits<5> imm;
7565     let Inst{20-16} = imm;
7566   }
7567
7568   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7569                                   V128, V128, vecshiftR64,
7570                                   asm, ".2d", ".2d",
7571             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7572                   (i32 vecshiftR64:$imm)))]> {
7573     bits<6> imm;
7574     let Inst{21-16} = imm;
7575   }
7576 }
7577
7578 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7579 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7580                                     SDPatternOperator OpNode = null_frag> {
7581   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7582                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
7583                  [(set (v8i8 V64:$dst),
7584                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7585                            (i32 vecshiftR8:$imm)))]> {
7586     bits<3> imm;
7587     let Inst{18-16} = imm;
7588   }
7589
7590   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7591                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
7592              [(set (v16i8 V128:$dst),
7593                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7594                        (i32 vecshiftR8:$imm)))]> {
7595     bits<3> imm;
7596     let Inst{18-16} = imm;
7597   }
7598
7599   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7600                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
7601               [(set (v4i16 V64:$dst),
7602                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7603                         (i32 vecshiftR16:$imm)))]> {
7604     bits<4> imm;
7605     let Inst{19-16} = imm;
7606   }
7607
7608   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7609                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
7610             [(set (v8i16 V128:$dst),
7611               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7612                       (i32 vecshiftR16:$imm)))]> {
7613     bits<4> imm;
7614     let Inst{19-16} = imm;
7615   }
7616
7617   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7618                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
7619               [(set (v2i32 V64:$dst),
7620                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7621                         (i32 vecshiftR32:$imm)))]> {
7622     bits<5> imm;
7623     let Inst{20-16} = imm;
7624   }
7625
7626   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7627                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
7628             [(set (v4i32 V128:$dst),
7629               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7630                       (i32 vecshiftR32:$imm)))]> {
7631     bits<5> imm;
7632     let Inst{20-16} = imm;
7633   }
7634
7635   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7636                                   V128, V128, vecshiftR64,
7637                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7638               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7639                       (i32 vecshiftR64:$imm)))]> {
7640     bits<6> imm;
7641     let Inst{21-16} = imm;
7642   }
7643 }
7644
7645 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7646                                     SDPatternOperator OpNode = null_frag> {
7647   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7648                                   V64, V64, vecshiftL8,
7649                                   asm, ".8b", ".8b",
7650                     [(set (v8i8 V64:$dst),
7651                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7652                                   (i32 vecshiftL8:$imm)))]> {
7653     bits<3> imm;
7654     let Inst{18-16} = imm;
7655   }
7656
7657   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7658                                   V128, V128, vecshiftL8,
7659                                   asm, ".16b", ".16b",
7660                     [(set (v16i8 V128:$dst),
7661                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7662                                   (i32 vecshiftL8:$imm)))]> {
7663     bits<3> imm;
7664     let Inst{18-16} = imm;
7665   }
7666
7667   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7668                                   V64, V64, vecshiftL16,
7669                                   asm, ".4h", ".4h",
7670                     [(set (v4i16 V64:$dst),
7671                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7672                                    (i32 vecshiftL16:$imm)))]> {
7673     bits<4> imm;
7674     let Inst{19-16} = imm;
7675   }
7676
7677   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7678                                   V128, V128, vecshiftL16,
7679                                   asm, ".8h", ".8h",
7680                     [(set (v8i16 V128:$dst),
7681                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7682                                   (i32 vecshiftL16:$imm)))]> {
7683     bits<4> imm;
7684     let Inst{19-16} = imm;
7685   }
7686
7687   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7688                                   V64, V64, vecshiftL32,
7689                                   asm, ".2s", ".2s",
7690                     [(set (v2i32 V64:$dst),
7691                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7692                                   (i32 vecshiftL32:$imm)))]> {
7693     bits<5> imm;
7694     let Inst{20-16} = imm;
7695   }
7696
7697   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7698                                   V128, V128, vecshiftL32,
7699                                   asm, ".4s", ".4s",
7700                     [(set (v4i32 V128:$dst),
7701                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7702                                   (i32 vecshiftL32:$imm)))]> {
7703     bits<5> imm;
7704     let Inst{20-16} = imm;
7705   }
7706
7707   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7708                                   V128, V128, vecshiftL64,
7709                                   asm, ".2d", ".2d",
7710                     [(set (v2i64 V128:$dst),
7711                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7712                                   (i32 vecshiftL64:$imm)))]> {
7713     bits<6> imm;
7714     let Inst{21-16} = imm;
7715   }
7716 }
7717
7718 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7719                                    SDPatternOperator OpNode> {
7720   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7721                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
7722       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7723     bits<3> imm;
7724     let Inst{18-16} = imm;
7725   }
7726
7727   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7728                                   V128, V128, vecshiftL8,
7729                                   asm#"2", ".8h", ".16b",
7730       [(set (v8i16 V128:$Rd),
7731             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7732     bits<3> imm;
7733     let Inst{18-16} = imm;
7734   }
7735
7736   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7737                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
7738       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7739     bits<4> imm;
7740     let Inst{19-16} = imm;
7741   }
7742
7743   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7744                                   V128, V128, vecshiftL16,
7745                                   asm#"2", ".4s", ".8h",
7746       [(set (v4i32 V128:$Rd),
7747             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7748
7749     bits<4> imm;
7750     let Inst{19-16} = imm;
7751   }
7752
7753   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7754                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
7755       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7756     bits<5> imm;
7757     let Inst{20-16} = imm;
7758   }
7759
7760   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7761                                   V128, V128, vecshiftL32,
7762                                   asm#"2", ".2d", ".4s",
7763       [(set (v2i64 V128:$Rd),
7764             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7765     bits<5> imm;
7766     let Inst{20-16} = imm;
7767   }
7768 }
7769
7770
7771 //---
7772 // Vector load/store
7773 //---
7774 // SIMD ldX/stX no-index memory references don't allow the optional
7775 // ", #0" constant and handle post-indexing explicitly, so we use
7776 // a more specialized parse method for them. Otherwise, it's the same as
7777 // the general GPR64sp handling.
7778
7779 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7780                    string asm, dag oops, dag iops, list<dag> pattern>
7781   : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
7782   bits<5> Vt;
7783   bits<5> Rn;
7784   let Inst{31} = 0;
7785   let Inst{30} = Q;
7786   let Inst{29-23} = 0b0011000;
7787   let Inst{22} = L;
7788   let Inst{21-16} = 0b000000;
7789   let Inst{15-12} = opcode;
7790   let Inst{11-10} = size;
7791   let Inst{9-5} = Rn;
7792   let Inst{4-0} = Vt;
7793 }
7794
7795 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7796                        string asm, dag oops, dag iops>
7797   : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
7798   bits<5> Vt;
7799   bits<5> Rn;
7800   bits<5> Xm;
7801   let Inst{31} = 0;
7802   let Inst{30} = Q;
7803   let Inst{29-23} = 0b0011001;
7804   let Inst{22} = L;
7805   let Inst{21} = 0;
7806   let Inst{20-16} = Xm;
7807   let Inst{15-12} = opcode;
7808   let Inst{11-10} = size;
7809   let Inst{9-5} = Rn;
7810   let Inst{4-0} = Vt;
7811 }
7812
7813 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7814 // register post-index addressing from the zero register.
7815 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7816                            int Offset, int Size> {
7817   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7818   //      "ld1\t$Vt, [$Rn], #16"
7819   // may get mapped to
7820   //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
7821   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
7822                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7823                       GPR64sp:$Rn,
7824                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7825                       XZR), 1>;
7826
7827   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7828   //      "ld1.8b\t$Vt, [$Rn], #16"
7829   // may get mapped to
7830   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
7831   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
7832                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7833                       GPR64sp:$Rn,
7834                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7835                       XZR), 0>;
7836
7837   // E.g. "ld1.8b { v0, v1 }, [x1]"
7838   //      "ld1\t$Vt, [$Rn]"
7839   // may get mapped to
7840   //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
7841   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
7842                   (!cast<Instruction>(NAME # Count # "v" # layout)
7843                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7844                       GPR64sp:$Rn), 0>;
7845
7846   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7847   //      "ld1\t$Vt, [$Rn], $Xm"
7848   // may get mapped to
7849   //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
7850   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
7851                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7852                       GPR64sp:$Rn,
7853                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7854                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7855 }
7856
7857 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7858                        int Offset64, bits<4> opcode> {
7859   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7860     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7861                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7862                            (ins GPR64sp:$Rn), []>;
7863     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7864                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7865                            (ins GPR64sp:$Rn), []>;
7866     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7867                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7868                            (ins GPR64sp:$Rn), []>;
7869     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7870                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7871                            (ins GPR64sp:$Rn), []>;
7872     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7873                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7874                            (ins GPR64sp:$Rn), []>;
7875     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7876                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7877                            (ins GPR64sp:$Rn), []>;
7878     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7879                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7880                            (ins GPR64sp:$Rn), []>;
7881
7882
7883     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7884                        (outs GPR64sp:$wback,
7885                              !cast<RegisterOperand>(veclist # "16b"):$Vt),
7886                        (ins GPR64sp:$Rn,
7887                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7888     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7889                        (outs GPR64sp:$wback,
7890                              !cast<RegisterOperand>(veclist # "8h"):$Vt),
7891                        (ins GPR64sp:$Rn,
7892                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7893     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7894                        (outs GPR64sp:$wback,
7895                              !cast<RegisterOperand>(veclist # "4s"):$Vt),
7896                        (ins GPR64sp:$Rn,
7897                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7898     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7899                        (outs GPR64sp:$wback,
7900                              !cast<RegisterOperand>(veclist # "2d"):$Vt),
7901                        (ins GPR64sp:$Rn,
7902                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7903     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7904                        (outs GPR64sp:$wback,
7905                              !cast<RegisterOperand>(veclist # "8b"):$Vt),
7906                        (ins GPR64sp:$Rn,
7907                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7908     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7909                        (outs GPR64sp:$wback,
7910                              !cast<RegisterOperand>(veclist # "4h"):$Vt),
7911                        (ins GPR64sp:$Rn,
7912                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7913     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7914                        (outs GPR64sp:$wback,
7915                              !cast<RegisterOperand>(veclist # "2s"):$Vt),
7916                        (ins GPR64sp:$Rn,
7917                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7918   }
7919
7920   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7921   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7922   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7923   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7924   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7925   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7926   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7927 }
7928
7929 // Only ld1/st1 has a v1d version.
7930 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7931                        int Offset64, bits<4> opcode> {
7932   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7933     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7934                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7935                                  GPR64sp:$Rn), []>;
7936     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7937                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7938                                 GPR64sp:$Rn), []>;
7939     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7940                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7941                                 GPR64sp:$Rn), []>;
7942     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7943                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7944                                 GPR64sp:$Rn), []>;
7945     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7946                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7947                                 GPR64sp:$Rn), []>;
7948     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7949                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7950                                 GPR64sp:$Rn), []>;
7951     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7952                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7953                                 GPR64sp:$Rn), []>;
7954
7955     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
7956                        (outs GPR64sp:$wback),
7957                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7958                             GPR64sp:$Rn,
7959                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7960     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
7961                        (outs GPR64sp:$wback),
7962                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7963                             GPR64sp:$Rn,
7964                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7965     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
7966                        (outs GPR64sp:$wback),
7967                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7968                             GPR64sp:$Rn,
7969                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7970     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
7971                        (outs GPR64sp:$wback),
7972                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7973                             GPR64sp:$Rn,
7974                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7975     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
7976                        (outs GPR64sp:$wback),
7977                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7978                             GPR64sp:$Rn,
7979                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7980     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
7981                        (outs GPR64sp:$wback),
7982                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7983                             GPR64sp:$Rn,
7984                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7985     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
7986                        (outs GPR64sp:$wback),
7987                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7988                             GPR64sp:$Rn,
7989                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7990   }
7991
7992   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7993   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7994   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7995   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7996   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7997   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7998   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7999 }
8000
8001 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
8002                        int Offset128, int Offset64, bits<4> opcode>
8003   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
8004
8005   // LD1 instructions have extra "1d" variants.
8006   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8007     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8008                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8009                            (ins GPR64sp:$Rn), []>;
8010
8011     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8012                        (outs GPR64sp:$wback,
8013                              !cast<RegisterOperand>(veclist # "1d"):$Vt),
8014                        (ins GPR64sp:$Rn,
8015                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8016   }
8017
8018   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8019 }
8020
8021 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
8022                        int Offset128, int Offset64, bits<4> opcode>
8023   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
8024
8025   // ST1 instructions have extra "1d" variants.
8026   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8027     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8028                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8029                                 GPR64sp:$Rn), []>;
8030
8031     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8032                        (outs GPR64sp:$wback),
8033                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8034                             GPR64sp:$Rn,
8035                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8036   }
8037
8038   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8039 }
8040
8041 multiclass SIMDLd1Multiple<string asm> {
8042   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8043   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8044   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8045   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8046 }
8047
8048 multiclass SIMDSt1Multiple<string asm> {
8049   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8050   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8051   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8052   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8053 }
8054
8055 multiclass SIMDLd2Multiple<string asm> {
8056   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8057 }
8058
8059 multiclass SIMDSt2Multiple<string asm> {
8060   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8061 }
8062
8063 multiclass SIMDLd3Multiple<string asm> {
8064   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8065 }
8066
8067 multiclass SIMDSt3Multiple<string asm> {
8068   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8069 }
8070
8071 multiclass SIMDLd4Multiple<string asm> {
8072   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8073 }
8074
8075 multiclass SIMDSt4Multiple<string asm> {
8076   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8077 }
8078
8079 //---
8080 // AdvSIMD Load/store single-element
8081 //---
8082
8083 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8084                          string asm, string operands, string cst,
8085                          dag oops, dag iops, list<dag> pattern>
8086   : I<oops, iops, asm, operands, cst, pattern> {
8087   bits<5> Vt;
8088   bits<5> Rn;
8089   let Inst{31} = 0;
8090   let Inst{29-24} = 0b001101;
8091   let Inst{22} = L;
8092   let Inst{21} = R;
8093   let Inst{15-13} = opcode;
8094   let Inst{9-5} = Rn;
8095   let Inst{4-0} = Vt;
8096 }
8097
8098 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8099                          string asm, string operands, string cst,
8100                          dag oops, dag iops, list<dag> pattern>
8101   : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8102   bits<5> Vt;
8103   bits<5> Rn;
8104   let Inst{31} = 0;
8105   let Inst{29-24} = 0b001101;
8106   let Inst{22} = L;
8107   let Inst{21} = R;
8108   let Inst{15-13} = opcode;
8109   let Inst{9-5} = Rn;
8110   let Inst{4-0} = Vt;
8111 }
8112
8113
8114 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8115 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8116                   Operand listtype>
8117   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8118                        (outs listtype:$Vt), (ins GPR64sp:$Rn),
8119                        []> {
8120   let Inst{30} = Q;
8121   let Inst{23} = 0;
8122   let Inst{20-16} = 0b00000;
8123   let Inst{12} = S;
8124   let Inst{11-10} = size;
8125 }
8126 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8127 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8128                       string asm, Operand listtype, Operand GPR64pi>
8129   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8130                        "$Rn = $wback",
8131                        (outs GPR64sp:$wback, listtype:$Vt),
8132                        (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8133   bits<5> Xm;
8134   let Inst{30} = Q;
8135   let Inst{23} = 1;
8136   let Inst{20-16} = Xm;
8137   let Inst{12} = S;
8138   let Inst{11-10} = size;
8139 }
8140
8141 multiclass SIMDLdrAliases<string asm, string layout, string Count,
8142                           int Offset, int Size> {
8143   // E.g. "ld1r { v0.8b }, [x1], #1"
8144   //      "ld1r.8b\t$Vt, [$Rn], #1"
8145   // may get mapped to
8146   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8147   def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8148                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8149                       GPR64sp:$Rn,
8150                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8151                       XZR), 1>;
8152
8153   // E.g. "ld1r.8b { v0 }, [x1], #1"
8154   //      "ld1r.8b\t$Vt, [$Rn], #1"
8155   // may get mapped to
8156   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8157   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8158                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8159                       GPR64sp:$Rn,
8160                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8161                       XZR), 0>;
8162
8163   // E.g. "ld1r.8b { v0 }, [x1]"
8164   //      "ld1r.8b\t$Vt, [$Rn]"
8165   // may get mapped to
8166   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8167   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8168                   (!cast<Instruction>(NAME # "v" # layout)
8169                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8170                       GPR64sp:$Rn), 0>;
8171
8172   // E.g. "ld1r.8b { v0 }, [x1], x2"
8173   //      "ld1r.8b\t$Vt, [$Rn], $Xm"
8174   // may get mapped to
8175   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8176   def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8177                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
8178                       GPR64sp:$Rn,
8179                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8180                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8181 }
8182
8183 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8184   int Offset1, int Offset2, int Offset4, int Offset8> {
8185   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8186                         !cast<Operand>("VecList" # Count # "8b")>;
8187   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8188                         !cast<Operand>("VecList" # Count #"16b")>;
8189   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8190                         !cast<Operand>("VecList" # Count #"4h")>;
8191   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8192                         !cast<Operand>("VecList" # Count #"8h")>;
8193   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8194                         !cast<Operand>("VecList" # Count #"2s")>;
8195   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8196                         !cast<Operand>("VecList" # Count #"4s")>;
8197   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8198                         !cast<Operand>("VecList" # Count #"1d")>;
8199   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8200                         !cast<Operand>("VecList" # Count #"2d")>;
8201
8202   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8203                                  !cast<Operand>("VecList" # Count # "8b"),
8204                                  !cast<Operand>("GPR64pi" # Offset1)>;
8205   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8206                                  !cast<Operand>("VecList" # Count # "16b"),
8207                                  !cast<Operand>("GPR64pi" # Offset1)>;
8208   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8209                                  !cast<Operand>("VecList" # Count # "4h"),
8210                                  !cast<Operand>("GPR64pi" # Offset2)>;
8211   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8212                                  !cast<Operand>("VecList" # Count # "8h"),
8213                                  !cast<Operand>("GPR64pi" # Offset2)>;
8214   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8215                                  !cast<Operand>("VecList" # Count # "2s"),
8216                                  !cast<Operand>("GPR64pi" # Offset4)>;
8217   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8218                                  !cast<Operand>("VecList" # Count # "4s"),
8219                                  !cast<Operand>("GPR64pi" # Offset4)>;
8220   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8221                                  !cast<Operand>("VecList" # Count # "1d"),
8222                                  !cast<Operand>("GPR64pi" # Offset8)>;
8223   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8224                                  !cast<Operand>("VecList" # Count # "2d"),
8225                                  !cast<Operand>("GPR64pi" # Offset8)>;
8226
8227   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
8228   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8229   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
8230   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
8231   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
8232   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
8233   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
8234   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
8235 }
8236
8237 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8238                       dag oops, dag iops, list<dag> pattern>
8239   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8240                        pattern> {
8241   // idx encoded in Q:S:size fields.
8242   bits<4> idx;
8243   let Inst{30} = idx{3};
8244   let Inst{23} = 0;
8245   let Inst{20-16} = 0b00000;
8246   let Inst{12} = idx{2};
8247   let Inst{11-10} = idx{1-0};
8248 }
8249 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8250                       dag oops, dag iops, list<dag> pattern>
8251   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8252                            oops, iops, pattern> {
8253   // idx encoded in Q:S:size fields.
8254   bits<4> idx;
8255   let Inst{30} = idx{3};
8256   let Inst{23} = 0;
8257   let Inst{20-16} = 0b00000;
8258   let Inst{12} = idx{2};
8259   let Inst{11-10} = idx{1-0};
8260 }
8261 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8262                           dag oops, dag iops>
8263   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8264                        "$Rn = $wback", oops, iops, []> {
8265   // idx encoded in Q:S:size fields.
8266   bits<4> idx;
8267   bits<5> Xm;
8268   let Inst{30} = idx{3};
8269   let Inst{23} = 1;
8270   let Inst{20-16} = Xm;
8271   let Inst{12} = idx{2};
8272   let Inst{11-10} = idx{1-0};
8273 }
8274 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8275                           dag oops, dag iops>
8276   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8277                            "$Rn = $wback", oops, iops, []> {
8278   // idx encoded in Q:S:size fields.
8279   bits<4> idx;
8280   bits<5> Xm;
8281   let Inst{30} = idx{3};
8282   let Inst{23} = 1;
8283   let Inst{20-16} = Xm;
8284   let Inst{12} = idx{2};
8285   let Inst{11-10} = idx{1-0};
8286 }
8287
8288 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8289                       dag oops, dag iops, list<dag> pattern>
8290   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8291                        pattern> {
8292   // idx encoded in Q:S:size<1> fields.
8293   bits<3> idx;
8294   let Inst{30} = idx{2};
8295   let Inst{23} = 0;
8296   let Inst{20-16} = 0b00000;
8297   let Inst{12} = idx{1};
8298   let Inst{11} = idx{0};
8299   let Inst{10} = size;
8300 }
8301 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8302                       dag oops, dag iops, list<dag> pattern>
8303   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8304                            oops, iops, pattern> {
8305   // idx encoded in Q:S:size<1> fields.
8306   bits<3> idx;
8307   let Inst{30} = idx{2};
8308   let Inst{23} = 0;
8309   let Inst{20-16} = 0b00000;
8310   let Inst{12} = idx{1};
8311   let Inst{11} = idx{0};
8312   let Inst{10} = size;
8313 }
8314
8315 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8316                           dag oops, dag iops>
8317   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8318                        "$Rn = $wback", oops, iops, []> {
8319   // idx encoded in Q:S:size<1> fields.
8320   bits<3> idx;
8321   bits<5> Xm;
8322   let Inst{30} = idx{2};
8323   let Inst{23} = 1;
8324   let Inst{20-16} = Xm;
8325   let Inst{12} = idx{1};
8326   let Inst{11} = idx{0};
8327   let Inst{10} = size;
8328 }
8329 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8330                           dag oops, dag iops>
8331   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8332                            "$Rn = $wback", oops, iops, []> {
8333   // idx encoded in Q:S:size<1> fields.
8334   bits<3> idx;
8335   bits<5> Xm;
8336   let Inst{30} = idx{2};
8337   let Inst{23} = 1;
8338   let Inst{20-16} = Xm;
8339   let Inst{12} = idx{1};
8340   let Inst{11} = idx{0};
8341   let Inst{10} = size;
8342 }
8343 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8344                       dag oops, dag iops, list<dag> pattern>
8345   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8346                        pattern> {
8347   // idx encoded in Q:S fields.
8348   bits<2> idx;
8349   let Inst{30} = idx{1};
8350   let Inst{23} = 0;
8351   let Inst{20-16} = 0b00000;
8352   let Inst{12} = idx{0};
8353   let Inst{11-10} = size;
8354 }
8355 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8356                       dag oops, dag iops, list<dag> pattern>
8357   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8358                            oops, iops, pattern> {
8359   // idx encoded in Q:S fields.
8360   bits<2> idx;
8361   let Inst{30} = idx{1};
8362   let Inst{23} = 0;
8363   let Inst{20-16} = 0b00000;
8364   let Inst{12} = idx{0};
8365   let Inst{11-10} = size;
8366 }
8367 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8368                           string asm, dag oops, dag iops>
8369   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8370                        "$Rn = $wback", oops, iops, []> {
8371   // idx encoded in Q:S fields.
8372   bits<2> idx;
8373   bits<5> Xm;
8374   let Inst{30} = idx{1};
8375   let Inst{23} = 1;
8376   let Inst{20-16} = Xm;
8377   let Inst{12} = idx{0};
8378   let Inst{11-10} = size;
8379 }
8380 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8381                           string asm, dag oops, dag iops>
8382   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8383                            "$Rn = $wback", oops, iops, []> {
8384   // idx encoded in Q:S fields.
8385   bits<2> idx;
8386   bits<5> Xm;
8387   let Inst{30} = idx{1};
8388   let Inst{23} = 1;
8389   let Inst{20-16} = Xm;
8390   let Inst{12} = idx{0};
8391   let Inst{11-10} = size;
8392 }
8393 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8394                       dag oops, dag iops, list<dag> pattern>
8395   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8396                        pattern> {
8397   // idx encoded in Q field.
8398   bits<1> idx;
8399   let Inst{30} = idx;
8400   let Inst{23} = 0;
8401   let Inst{20-16} = 0b00000;
8402   let Inst{12} = 0;
8403   let Inst{11-10} = size;
8404 }
8405 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8406                       dag oops, dag iops, list<dag> pattern>
8407   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8408                            oops, iops, pattern> {
8409   // idx encoded in Q field.
8410   bits<1> idx;
8411   let Inst{30} = idx;
8412   let Inst{23} = 0;
8413   let Inst{20-16} = 0b00000;
8414   let Inst{12} = 0;
8415   let Inst{11-10} = size;
8416 }
8417 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8418                           string asm, dag oops, dag iops>
8419   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8420                        "$Rn = $wback", oops, iops, []> {
8421   // idx encoded in Q field.
8422   bits<1> idx;
8423   bits<5> Xm;
8424   let Inst{30} = idx;
8425   let Inst{23} = 1;
8426   let Inst{20-16} = Xm;
8427   let Inst{12} = 0;
8428   let Inst{11-10} = size;
8429 }
8430 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8431                           string asm, dag oops, dag iops>
8432   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8433                            "$Rn = $wback", oops, iops, []> {
8434   // idx encoded in Q field.
8435   bits<1> idx;
8436   bits<5> Xm;
8437   let Inst{30} = idx;
8438   let Inst{23} = 1;
8439   let Inst{20-16} = Xm;
8440   let Inst{12} = 0;
8441   let Inst{11-10} = size;
8442 }
8443
8444 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8445 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8446                          RegisterOperand listtype,
8447                          RegisterOperand GPR64pi> {
8448   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8449                            (outs listtype:$dst),
8450                            (ins listtype:$Vt, VectorIndexB:$idx,
8451                                 GPR64sp:$Rn), []>;
8452
8453   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8454                             (outs GPR64sp:$wback, listtype:$dst),
8455                             (ins listtype:$Vt, VectorIndexB:$idx,
8456                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8457 }
8458 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8459 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8460                          RegisterOperand listtype,
8461                          RegisterOperand GPR64pi> {
8462   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8463                             (outs listtype:$dst),
8464                             (ins listtype:$Vt, VectorIndexH:$idx,
8465                                  GPR64sp:$Rn), []>;
8466
8467   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8468                             (outs GPR64sp:$wback, listtype:$dst),
8469                             (ins listtype:$Vt, VectorIndexH:$idx,
8470                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8471 }
8472 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8473 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8474                          RegisterOperand listtype,
8475                          RegisterOperand GPR64pi> {
8476   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8477                             (outs listtype:$dst),
8478                             (ins listtype:$Vt, VectorIndexS:$idx,
8479                                  GPR64sp:$Rn), []>;
8480
8481   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8482                             (outs GPR64sp:$wback, listtype:$dst),
8483                             (ins listtype:$Vt, VectorIndexS:$idx,
8484                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8485 }
8486 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8487 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8488                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8489   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8490                             (outs listtype:$dst),
8491                             (ins listtype:$Vt, VectorIndexD:$idx,
8492                                  GPR64sp:$Rn), []>;
8493
8494   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8495                             (outs GPR64sp:$wback, listtype:$dst),
8496                             (ins listtype:$Vt, VectorIndexD:$idx,
8497                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8498 }
8499 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8500 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8501                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8502   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8503                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8504                                         GPR64sp:$Rn), []>;
8505
8506   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8507                                     (outs GPR64sp:$wback),
8508                                     (ins listtype:$Vt, VectorIndexB:$idx,
8509                                          GPR64sp:$Rn, GPR64pi:$Xm)>;
8510 }
8511 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8512 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8513                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8514   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8515                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8516                                          GPR64sp:$Rn), []>;
8517
8518   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8519                             (outs GPR64sp:$wback),
8520                             (ins listtype:$Vt, VectorIndexH:$idx,
8521                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8522 }
8523 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8524 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8525                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8526   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8527                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8528                                          GPR64sp:$Rn), []>;
8529
8530   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8531                             (outs GPR64sp:$wback),
8532                             (ins listtype:$Vt, VectorIndexS:$idx,
8533                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8534 }
8535 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8536 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8537                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8538   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8539                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8540                                          GPR64sp:$Rn), []>;
8541
8542   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8543                             (outs GPR64sp:$wback),
8544                             (ins listtype:$Vt, VectorIndexD:$idx,
8545                                  GPR64sp:$Rn, GPR64pi:$Xm)>;
8546 }
8547
8548 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8549                                  string Count, int Offset, Operand idxtype> {
8550   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8551   //      "ld1\t$Vt, [$Rn], #1"
8552   // may get mapped to
8553   //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8554   def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8555                   (!cast<Instruction>(NAME # Type  # "_POST")
8556                       GPR64sp:$Rn,
8557                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8558                       idxtype:$idx, XZR), 1>;
8559
8560   // E.g. "ld1.8b { v0 }[0], [x1], #1"
8561   //      "ld1.8b\t$Vt, [$Rn], #1"
8562   // may get mapped to
8563   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8564   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
8565                   (!cast<Instruction>(NAME # Type # "_POST")
8566                       GPR64sp:$Rn,
8567                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8568                       idxtype:$idx, XZR), 0>;
8569
8570   // E.g. "ld1.8b { v0 }[0], [x1]"
8571   //      "ld1.8b\t$Vt, [$Rn]"
8572   // may get mapped to
8573   //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8574   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
8575                       (!cast<Instruction>(NAME # Type)
8576                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8577                          idxtype:$idx, GPR64sp:$Rn), 0>;
8578
8579   // E.g. "ld1.8b { v0 }[0], [x1], x2"
8580   //      "ld1.8b\t$Vt, [$Rn], $Xm"
8581   // may get mapped to
8582   //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8583   def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
8584                       (!cast<Instruction>(NAME # Type # "_POST")
8585                          GPR64sp:$Rn,
8586                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8587                          idxtype:$idx,
8588                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8589 }
8590
8591 multiclass SIMDLdSt1SingleAliases<string asm> {
8592   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
8593   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8594   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8595   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8596 }
8597
8598 multiclass SIMDLdSt2SingleAliases<string asm> {
8599   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
8600   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
8601   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
8602   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8603 }
8604
8605 multiclass SIMDLdSt3SingleAliases<string asm> {
8606   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
8607   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
8608   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8609   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8610 }
8611
8612 multiclass SIMDLdSt4SingleAliases<string asm> {
8613   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
8614   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
8615   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8616   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8617 }
8618 } // end of 'let Predicates = [HasNEON]'
8619
8620 //----------------------------------------------------------------------------
8621 // AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
8622 //----------------------------------------------------------------------------
8623
8624 let Predicates = [HasNEON, HasV8_1a] in {
8625
8626 class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
8627                                     RegisterOperand regtype, string asm, 
8628                                     string kind, list<dag> pattern>
8629   : BaseSIMDThreeSameVectorTied<Q, U, size, opcode, regtype, asm, kind, 
8630                                 pattern> {
8631   let Inst{21}=0;
8632 }
8633 multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
8634                                              SDPatternOperator Accum> {
8635   def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
8636     [(set (v4i16 V64:$dst),
8637           (Accum (v4i16 V64:$Rd),
8638                  (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
8639                                                    (v4i16 V64:$Rm)))))]>;         
8640   def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
8641     [(set (v8i16 V128:$dst),
8642           (Accum (v8i16 V128:$Rd),
8643                  (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
8644                                                    (v8i16 V128:$Rm)))))]>;
8645   def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
8646     [(set (v2i32 V64:$dst),
8647           (Accum (v2i32 V64:$Rd),
8648                  (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
8649                                                    (v2i32 V64:$Rm)))))]>;
8650   def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
8651     [(set (v4i32 V128:$dst),
8652           (Accum (v4i32 V128:$Rd),
8653                  (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
8654                                                    (v4i32 V128:$Rm)))))]>;
8655 }
8656
8657 multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
8658                                      SDPatternOperator Accum> {
8659   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8660                                           V64, V64, V128_lo, VectorIndexH,
8661                                           asm, ".4h", ".4h", ".4h", ".h",
8662     [(set (v4i16 V64:$dst),
8663           (Accum (v4i16 V64:$Rd),
8664                  (v4i16 (int_aarch64_neon_sqrdmulh
8665                           (v4i16 V64:$Rn),
8666                           (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8667                                                     VectorIndexH:$idx))))))]> {
8668     bits<3> idx;
8669     let Inst{11} = idx{2};
8670     let Inst{21} = idx{1};
8671     let Inst{20} = idx{0};
8672   }
8673
8674   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8675                                           V128, V128, V128_lo, VectorIndexH,
8676                                           asm, ".8h", ".8h", ".8h", ".h",
8677     [(set (v8i16 V128:$dst),
8678           (Accum (v8i16 V128:$Rd),
8679                  (v8i16 (int_aarch64_neon_sqrdmulh
8680                           (v8i16 V128:$Rn),
8681                           (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8682                                                    VectorIndexH:$idx))))))]> {
8683     bits<3> idx;
8684     let Inst{11} = idx{2};
8685     let Inst{21} = idx{1};
8686     let Inst{20} = idx{0};
8687   }
8688
8689   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8690                                           V64, V64, V128, VectorIndexS,
8691                                           asm, ".2s", ".2s", ".2s", ".s",
8692     [(set (v2i32 V64:$dst),
8693         (Accum (v2i32 V64:$Rd),
8694                (v2i32 (int_aarch64_neon_sqrdmulh
8695                         (v2i32 V64:$Rn),
8696                         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8697                                                  VectorIndexS:$idx))))))]> {
8698     bits<2> idx;
8699     let Inst{11} = idx{1};
8700     let Inst{21} = idx{0};
8701   }
8702
8703   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but 
8704   // an intermediate EXTRACT_SUBREG would be untyped.
8705   // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we 
8706   // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
8707   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8708                        (i32 (vector_extract 
8709                                (v4i32 (insert_subvector
8710                                        (undef), 
8711                                         (v2i32 (int_aarch64_neon_sqrdmulh 
8712                                                  (v2i32 V64:$Rn),
8713                                                  (v2i32 (AArch64duplane32 
8714                                                           (v4i32 V128:$Rm),
8715                                                           VectorIndexS:$idx)))),
8716                                       (i32 0))),
8717                                (i64 0))))),
8718             (EXTRACT_SUBREG
8719                 (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
8720                           (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)), 
8721                                                 FPR32Op:$Rd, 
8722                                                 ssub)), 
8723                           V64:$Rn,
8724                           V128:$Rm, 
8725                           VectorIndexS:$idx)),
8726                 ssub)>;
8727
8728   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8729                                           V128, V128, V128, VectorIndexS,
8730                                           asm, ".4s", ".4s", ".4s", ".s",
8731     [(set (v4i32 V128:$dst),
8732           (Accum (v4i32 V128:$Rd),
8733                  (v4i32 (int_aarch64_neon_sqrdmulh
8734                           (v4i32 V128:$Rn),
8735                           (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8736                                                    VectorIndexS:$idx))))))]> {
8737     bits<2> idx;
8738     let Inst{11} = idx{1};
8739     let Inst{21} = idx{0};
8740   }
8741
8742   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
8743   // an intermediate EXTRACT_SUBREG would be untyped.
8744   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8745                         (i32 (vector_extract 
8746                                (v4i32 (int_aarch64_neon_sqrdmulh 
8747                                         (v4i32 V128:$Rn),
8748                                         (v4i32 (AArch64duplane32 
8749                                                  (v4i32 V128:$Rm),
8750                                                  VectorIndexS:$idx)))),
8751                                (i64 0))))),
8752             (EXTRACT_SUBREG
8753                 (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
8754                          (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)), 
8755                                                FPR32Op:$Rd, 
8756                                                ssub)), 
8757                          V128:$Rn,
8758                          V128:$Rm, 
8759                          VectorIndexS:$idx)),
8760                 ssub)>;
8761
8762   def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8763                                         FPR16Op, FPR16Op, V128_lo,
8764                                         VectorIndexH, asm, ".h", "", "", ".h", 
8765                                         []> {
8766     bits<3> idx;
8767     let Inst{11} = idx{2};
8768     let Inst{21} = idx{1};
8769     let Inst{20} = idx{0};
8770   }
8771
8772   def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8773                                         FPR32Op, FPR32Op, V128, VectorIndexS,
8774                                         asm, ".s", "", "", ".s",
8775     [(set (i32 FPR32Op:$dst),
8776           (Accum (i32 FPR32Op:$Rd),
8777                  (i32 (int_aarch64_neon_sqrdmulh
8778                         (i32 FPR32Op:$Rn),
8779                         (i32 (vector_extract (v4i32 V128:$Rm),
8780                                              VectorIndexS:$idx))))))]> {
8781     bits<2> idx;
8782     let Inst{11} = idx{1};
8783     let Inst{21} = idx{0};
8784   }
8785 }
8786 } // let Predicates = [HasNeon, HasV8_1a]
8787
8788 //----------------------------------------------------------------------------
8789 // Crypto extensions
8790 //----------------------------------------------------------------------------
8791
8792 let Predicates = [HasCrypto] in {
8793 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8794 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8795               list<dag> pat>
8796   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8797     Sched<[WriteV]>{
8798   bits<5> Rd;
8799   bits<5> Rn;
8800   let Inst{31-16} = 0b0100111000101000;
8801   let Inst{15-12} = opc;
8802   let Inst{11-10} = 0b10;
8803   let Inst{9-5}   = Rn;
8804   let Inst{4-0}   = Rd;
8805 }
8806
8807 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8808   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8809             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8810
8811 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8812   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8813             "$Rd = $dst",
8814             [(set (v16i8 V128:$dst),
8815                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8816
8817 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8818 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8819                      dag oops, dag iops, list<dag> pat>
8820   : I<oops, iops, asm,
8821       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8822       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8823     Sched<[WriteV]>{
8824   bits<5> Rd;
8825   bits<5> Rn;
8826   bits<5> Rm;
8827   let Inst{31-21} = 0b01011110000;
8828   let Inst{20-16} = Rm;
8829   let Inst{15}    = 0;
8830   let Inst{14-12} = opc;
8831   let Inst{11-10} = 0b00;
8832   let Inst{9-5}   = Rn;
8833   let Inst{4-0}   = Rd;
8834 }
8835
8836 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8837   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8838                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8839                    [(set (v4i32 FPR128:$dst),
8840                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8841                                  (v4i32 V128:$Rm)))]>;
8842
8843 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8844   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8845                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
8846                    [(set (v4i32 V128:$dst),
8847                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8848                                  (v4i32 V128:$Rm)))]>;
8849
8850 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8851   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8852                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8853                    [(set (v4i32 FPR128:$dst),
8854                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8855                                  (v4i32 V128:$Rm)))]>;
8856
8857 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8858 class SHA2OpInst<bits<4> opc, string asm, string kind,
8859                  string cstr, dag oops, dag iops,
8860                  list<dag> pat>
8861   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8862                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8863     Sched<[WriteV]>{
8864   bits<5> Rd;
8865   bits<5> Rn;
8866   let Inst{31-16} = 0b0101111000101000;
8867   let Inst{15-12} = opc;
8868   let Inst{11-10} = 0b10;
8869   let Inst{9-5}   = Rn;
8870   let Inst{4-0}   = Rd;
8871 }
8872
8873 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8874   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8875                (ins V128:$Rd, V128:$Rn),
8876                [(set (v4i32 V128:$dst),
8877                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8878
8879 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8880   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8881                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8882 } // end of 'let Predicates = [HasCrypto]'
8883
8884 //----------------------------------------------------------------------------
8885 // v8.1 atomic instructions extension:
8886 // * CAS
8887 // * CASP
8888 // * SWP
8889 // * LDOPregister<OP>, and aliases STOPregister<OP>
8890
8891 // Instruction encodings:
8892 //
8893 //      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
8894 // CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
8895 // CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
8896 // SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
8897 // LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
8898 // ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
8899
8900 // Instruction syntax:
8901 //
8902 // CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8903 // CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
8904 // CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
8905 // CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
8906 // SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8907 // SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
8908 // LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
8909 // LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
8910 // ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
8911 // ST<OP>{<order>} <Xs>, [<Xn|SP>]
8912
8913 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
8914 class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
8915                       string cstr, list<dag> pattern>
8916       : I<oops, iops, asm, operands, cstr, pattern> {
8917   bits<2> Sz;
8918   bit NP;
8919   bit Acq;
8920   bit Rel;
8921   bits<5> Rs;
8922   bits<5> Rn;
8923   bits<5> Rt;
8924   let Inst{31-30} = Sz;
8925   let Inst{29-24} = 0b001000;
8926   let Inst{23} = NP;
8927   let Inst{22} = Acq;
8928   let Inst{21} = 0b1;
8929   let Inst{20-16} = Rs;
8930   let Inst{15} = Rel;
8931   let Inst{14-10} = 0b11111;
8932   let Inst{9-5} = Rn;
8933   let Inst{4-0} = Rt;
8934 }
8935
8936 class BaseCAS<string order, string size, RegisterClass RC>
8937       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8938                         "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
8939                         "$out = $Rs",[]> {
8940   let NP = 1;
8941 }
8942
8943 multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
8944   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
8945   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
8946   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
8947   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
8948 }
8949
8950 class BaseCASP<string order, string size, RegisterOperand RC>
8951       : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
8952                         "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
8953                         "$out = $Rs",[]> {
8954   let NP = 0;
8955 }
8956
8957 multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
8958   let Sz = 0b00, Acq = Acq, Rel = Rel in 
8959     def s : BaseCASP<order, "", WSeqPairClassOperand>;
8960   let Sz = 0b01, Acq = Acq, Rel = Rel in 
8961     def d : BaseCASP<order, "", XSeqPairClassOperand>;
8962 }
8963
8964 let Predicates = [HasV8_1a] in
8965 class BaseSWP<string order, string size, RegisterClass RC>
8966       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
8967           "\t$Rs, $Rt, [$Rn]","",[]> {
8968   bits<2> Sz;
8969   bit Acq;
8970   bit Rel;
8971   bits<5> Rs;
8972   bits<3> opc = 0b000;
8973   bits<5> Rn;
8974   bits<5> Rt;
8975   let Inst{31-30} = Sz;
8976   let Inst{29-24} = 0b111000;
8977   let Inst{23} = Acq;
8978   let Inst{22} = Rel;
8979   let Inst{21} = 0b1;
8980   let Inst{20-16} = Rs;
8981   let Inst{15} = 0b1;
8982   let Inst{14-12} = opc;
8983   let Inst{11-10} = 0b00;
8984   let Inst{9-5} = Rn;
8985   let Inst{4-0} = Rt;
8986 }
8987
8988 multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
8989   let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
8990   let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
8991   let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
8992   let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
8993 }
8994
8995 let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
8996 class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
8997       : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
8998           "\t$Rs, $Rt, [$Rn]","",[]> {
8999   bits<2> Sz;
9000   bit Acq;
9001   bit Rel;
9002   bits<5> Rs;
9003   bits<3> opc;
9004   bits<5> Rn;
9005   bits<5> Rt;
9006   let Inst{31-30} = Sz;
9007   let Inst{29-24} = 0b111000;
9008   let Inst{23} = Acq;
9009   let Inst{22} = Rel;
9010   let Inst{21} = 0b1;
9011   let Inst{20-16} = Rs;
9012   let Inst{15} = 0b0;
9013   let Inst{14-12} = opc;
9014   let Inst{11-10} = 0b00;
9015   let Inst{9-5} = Rn;
9016   let Inst{4-0} = Rt;
9017 }
9018
9019 multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel, 
9020                         string order> {
9021   let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in 
9022     def b : BaseLDOPregister<op, order, "b", GPR32>;
9023   let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in 
9024     def h : BaseLDOPregister<op, order, "h", GPR32>;
9025   let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in 
9026     def s : BaseLDOPregister<op, order, "", GPR32>;
9027   let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in 
9028     def d : BaseLDOPregister<op, order, "", GPR64>;
9029 }
9030
9031 let Predicates = [HasV8_1a] in
9032 class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
9033                         Instruction inst> :
9034       InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
9035
9036 multiclass STOPregister<string asm, string instr> {
9037   def : BaseSTOPregister<asm # "lb", GPR32, WZR, 
9038                     !cast<Instruction>(instr # "Lb")>;
9039   def : BaseSTOPregister<asm # "lh", GPR32, WZR, 
9040                     !cast<Instruction>(instr # "Lh")>;
9041   def : BaseSTOPregister<asm # "l",  GPR32, WZR, 
9042                     !cast<Instruction>(instr # "Ls")>;
9043   def : BaseSTOPregister<asm # "l",  GPR64, XZR, 
9044                     !cast<Instruction>(instr # "Ld")>;
9045   def : BaseSTOPregister<asm # "b",  GPR32, WZR, 
9046                     !cast<Instruction>(instr # "b")>;
9047   def : BaseSTOPregister<asm # "h",  GPR32, WZR, 
9048                     !cast<Instruction>(instr # "h")>;
9049   def : BaseSTOPregister<asm,        GPR32, WZR, 
9050                     !cast<Instruction>(instr # "s")>;
9051   def : BaseSTOPregister<asm,        GPR64, XZR, 
9052                     !cast<Instruction>(instr # "d")>;
9053 }
9054
9055 //----------------------------------------------------------------------------
9056 // Allow the size specifier tokens to be upper case, not just lower.
9057 def : TokenAlias<".8B", ".8b">;
9058 def : TokenAlias<".4H", ".4h">;
9059 def : TokenAlias<".2S", ".2s">;
9060 def : TokenAlias<".1D", ".1d">;
9061 def : TokenAlias<".16B", ".16b">;
9062 def : TokenAlias<".8H", ".8h">;
9063 def : TokenAlias<".4S", ".4s">;
9064 def : TokenAlias<".2D", ".2d">;
9065 def : TokenAlias<".1Q", ".1q">;
9066 def : TokenAlias<".B", ".b">;
9067 def : TokenAlias<".H", ".h">;
9068 def : TokenAlias<".S", ".s">;
9069 def : TokenAlias<".D", ".d">;
9070 def : TokenAlias<".Q", ".q">;