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