[ARM64] Add a PostEncoderMethod to FCMP - the Rm field should canonically be 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 = "DecodeFixedPointScaleImm32";
308   let ParserMatchClass = Imm1_32Operand;
309 }
310 def fixedpoint64 : Operand<i64> {
311   let EncoderMethod = "getFixedPointScaleOpValue";
312   let DecoderMethod = "DecodeFixedPointScaleImm64";
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     // imm<5> must be zero.
1607     let imm{5}   = 0;
1608   }
1609   def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1610                       [(set GPR64:$Rd,
1611                         (ARM64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1612
1613     let Inst{31} = 1;
1614     let Inst{22} = 1;
1615   }
1616 }
1617
1618 //---
1619 // Bitfield
1620 //---
1621
1622 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1623 class BaseBitfieldImm<bits<2> opc,
1624                       RegisterClass regtype, Operand imm_type, string asm>
1625     : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1626          asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1627       Sched<[WriteIS]> {
1628   bits<5> Rd;
1629   bits<5> Rn;
1630   bits<6> immr;
1631   bits<6> imms;
1632
1633   let Inst{30-29} = opc;
1634   let Inst{28-23} = 0b100110;
1635   let Inst{21-16} = immr;
1636   let Inst{15-10} = imms;
1637   let Inst{9-5}   = Rn;
1638   let Inst{4-0}   = Rd;
1639 }
1640
1641 multiclass BitfieldImm<bits<2> opc, string asm> {
1642   def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1643     let Inst{31} = 0;
1644     let Inst{22} = 0;
1645     // imms<5> and immr<5> must be zero, else ReservedValue().
1646     let Inst{21} = 0;
1647     let Inst{15} = 0;
1648   }
1649   def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1650     let Inst{31} = 1;
1651     let Inst{22} = 1;
1652   }
1653 }
1654
1655 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1656 class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1657                       RegisterClass regtype, Operand imm_type, string asm>
1658     : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
1659                              imm_type:$imms),
1660          asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
1661       Sched<[WriteIS]> {
1662   bits<5> Rd;
1663   bits<5> Rn;
1664   bits<6> immr;
1665   bits<6> imms;
1666
1667   let Inst{30-29} = opc;
1668   let Inst{28-23} = 0b100110;
1669   let Inst{21-16} = immr;
1670   let Inst{15-10} = imms;
1671   let Inst{9-5}   = Rn;
1672   let Inst{4-0}   = Rd;
1673 }
1674
1675 multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
1676   def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
1677     let Inst{31} = 0;
1678     let Inst{22} = 0;
1679     // imms<5> and immr<5> must be zero, else ReservedValue().
1680     let Inst{21} = 0;
1681     let Inst{15} = 0;
1682   }
1683   def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
1684     let Inst{31} = 1;
1685     let Inst{22} = 1;
1686   }
1687 }
1688
1689 //---
1690 // Logical
1691 //---
1692
1693 // Logical (immediate)
1694 class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
1695                      RegisterClass sregtype, Operand imm_type, string asm,
1696                      list<dag> pattern>
1697     : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
1698          asm, "\t$Rd, $Rn, $imm", "", pattern>,
1699       Sched<[WriteI]> {
1700   bits<5>  Rd;
1701   bits<5>  Rn;
1702   bits<13> imm;
1703   let Inst{30-29} = opc;
1704   let Inst{28-23} = 0b100100;
1705   let Inst{22}    = imm{12};
1706   let Inst{21-16} = imm{11-6};
1707   let Inst{15-10} = imm{5-0};
1708   let Inst{9-5}   = Rn;
1709   let Inst{4-0}   = Rd;
1710
1711   let DecoderMethod = "DecodeLogicalImmInstruction";
1712 }
1713
1714 // Logical (shifted register)
1715 class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
1716                       logical_shifted_reg shifted_regtype, string asm,
1717                       list<dag> pattern>
1718     : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1719         asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1720       Sched<[WriteISReg]> {
1721   // The operands are in order to match the 'addr' MI operands, so we
1722   // don't need an encoder method and by-name matching. Just use the default
1723   // in-order handling. Since we're using by-order, make sure the names
1724   // do not match.
1725   bits<5> dst;
1726   bits<5> src1;
1727   bits<5> src2;
1728   bits<8> shift;
1729   let Inst{30-29} = opc;
1730   let Inst{28-24} = 0b01010;
1731   let Inst{23-22} = shift{7-6};
1732   let Inst{21}    = N;
1733   let Inst{20-16} = src2;
1734   let Inst{15-10} = shift{5-0};
1735   let Inst{9-5}   = src1;
1736   let Inst{4-0}   = dst;
1737
1738   let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1739 }
1740
1741 // Aliases for register+register logical instructions.
1742 class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
1743     : InstAlias<asm#" $dst, $src1, $src2",
1744                 (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
1745
1746 let AddedComplexity = 6 in
1747 multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode> {
1748   def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
1749                            [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
1750                                                logical_imm32:$imm))]> {
1751     let Inst{31} = 0;
1752     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1753   }
1754   def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
1755                            [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
1756                                                logical_imm64:$imm))]> {
1757     let Inst{31} = 1;
1758   }
1759 }
1760
1761 multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode> {
1762   let isCompare = 1, Defs = [CPSR] in {
1763   def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
1764       [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
1765     let Inst{31} = 0;
1766     let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
1767   }
1768   def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
1769       [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
1770     let Inst{31} = 1;
1771   }
1772   } // end Defs = [CPSR]
1773 }
1774
1775 class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
1776     : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1777              [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1778       Sched<[WriteI]>;
1779
1780 // Split from LogicalImm as not all instructions have both.
1781 multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
1782                       SDPatternOperator OpNode> {
1783   def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
1784   def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
1785
1786   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
1787                             [(set GPR32:$Rd, (OpNode GPR32:$Rn,
1788                                                  logical_shifted_reg32:$Rm))]> {
1789     let Inst{31} = 0;
1790   }
1791   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
1792                             [(set GPR64:$Rd, (OpNode GPR64:$Rn,
1793                                                  logical_shifted_reg64:$Rm))]> {
1794     let Inst{31} = 1;
1795   }
1796
1797   def : LogicalRegAlias<mnemonic,
1798                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
1799   def : LogicalRegAlias<mnemonic,
1800                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
1801 }
1802
1803 // Split from LogicalReg to allow setting CPSR Defs
1804 multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic> {
1805   let Defs = [CPSR], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
1806   def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic, []>{
1807     let Inst{31} = 0;
1808   }
1809   def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic, []>{
1810     let Inst{31} = 1;
1811   }
1812   } // Defs = [CPSR]
1813
1814   def : LogicalRegAlias<mnemonic,
1815                         !cast<Instruction>(NAME#"Wrs"), GPR32>;
1816   def : LogicalRegAlias<mnemonic,
1817                         !cast<Instruction>(NAME#"Xrs"), GPR64>;
1818 }
1819
1820 //---
1821 // Conditionally set flags
1822 //---
1823
1824 // Condition code.
1825 // 4-bit immediate. Pretty-printed as <cc>
1826 def ccode : Operand<i32> {
1827   let PrintMethod = "printCondCode";
1828 }
1829
1830 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1831 class BaseCondSetFlagsImm<bit op, RegisterClass regtype, string asm>
1832     : I<(outs), (ins regtype:$Rn, imm0_31:$imm, imm0_15:$nzcv, ccode:$cond),
1833          asm, "\t$Rn, $imm, $nzcv, $cond", "", []>,
1834       Sched<[WriteI]> {
1835   let Uses = [CPSR];
1836   let Defs = [CPSR];
1837
1838   bits<5> Rn;
1839   bits<5> imm;
1840   bits<4> nzcv;
1841   bits<4> cond;
1842
1843   let Inst{30}    = op;
1844   let Inst{29-21} = 0b111010010;
1845   let Inst{20-16} = imm;
1846   let Inst{15-12} = cond;
1847   let Inst{11-10} = 0b10;
1848   let Inst{9-5}   = Rn;
1849   let Inst{4}     = 0b0;
1850   let Inst{3-0}   = nzcv;
1851 }
1852
1853 multiclass CondSetFlagsImm<bit op, string asm> {
1854   def Wi : BaseCondSetFlagsImm<op, GPR32, asm> {
1855     let Inst{31} = 0;
1856   }
1857   def Xi : BaseCondSetFlagsImm<op, GPR64, asm> {
1858     let Inst{31} = 1;
1859   }
1860 }
1861
1862 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1863 class BaseCondSetFlagsReg<bit op, RegisterClass regtype, string asm>
1864     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
1865          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
1866       Sched<[WriteI]> {
1867   let Uses = [CPSR];
1868   let Defs = [CPSR];
1869
1870   bits<5> Rn;
1871   bits<5> Rm;
1872   bits<4> nzcv;
1873   bits<4> cond;
1874
1875   let Inst{30}    = op;
1876   let Inst{29-21} = 0b111010010;
1877   let Inst{20-16} = Rm;
1878   let Inst{15-12} = cond;
1879   let Inst{11-10} = 0b00;
1880   let Inst{9-5}   = Rn;
1881   let Inst{4}     = 0b0;
1882   let Inst{3-0}   = nzcv;
1883 }
1884
1885 multiclass CondSetFlagsReg<bit op, string asm> {
1886   def Wr : BaseCondSetFlagsReg<op, GPR32, asm> {
1887     let Inst{31} = 0;
1888   }
1889   def Xr : BaseCondSetFlagsReg<op, GPR64, asm> {
1890     let Inst{31} = 1;
1891   }
1892 }
1893
1894 //---
1895 // Conditional select
1896 //---
1897
1898 class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
1899     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1900          asm, "\t$Rd, $Rn, $Rm, $cond", "",
1901          [(set regtype:$Rd,
1902                (ARM64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), CPSR))]>,
1903       Sched<[WriteI]> {
1904   let Uses = [CPSR];
1905
1906   bits<5> Rd;
1907   bits<5> Rn;
1908   bits<5> Rm;
1909   bits<4> cond;
1910
1911   let Inst{30}    = op;
1912   let Inst{29-21} = 0b011010100;
1913   let Inst{20-16} = Rm;
1914   let Inst{15-12} = cond;
1915   let Inst{11-10} = op2;
1916   let Inst{9-5}   = Rn;
1917   let Inst{4-0}   = Rd;
1918 }
1919
1920 multiclass CondSelect<bit op, bits<2> op2, string asm> {
1921   def Wr : BaseCondSelect<op, op2, GPR32, asm> {
1922     let Inst{31} = 0;
1923   }
1924   def Xr : BaseCondSelect<op, op2, GPR64, asm> {
1925     let Inst{31} = 1;
1926   }
1927 }
1928
1929 class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
1930                        PatFrag frag>
1931     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
1932          asm, "\t$Rd, $Rn, $Rm, $cond", "",
1933          [(set regtype:$Rd,
1934                (ARM64csel regtype:$Rn, (frag regtype:$Rm),
1935                (i32 imm:$cond), CPSR))]>,
1936       Sched<[WriteI]> {
1937   let Uses = [CPSR];
1938
1939   bits<5> Rd;
1940   bits<5> Rn;
1941   bits<5> Rm;
1942   bits<4> cond;
1943
1944   let Inst{30}    = op;
1945   let Inst{29-21} = 0b011010100;
1946   let Inst{20-16} = Rm;
1947   let Inst{15-12} = cond;
1948   let Inst{11-10} = op2;
1949   let Inst{9-5}   = Rn;
1950   let Inst{4-0}   = Rd;
1951 }
1952
1953 multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
1954   def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
1955     let Inst{31} = 0;
1956   }
1957   def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
1958     let Inst{31} = 1;
1959   }
1960 }
1961
1962 //---
1963 // Special Mask Value
1964 //---
1965 def maski8_or_more : Operand<i32>,
1966   ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
1967 }
1968 def maski16_or_more : Operand<i32>,
1969   ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
1970 }
1971
1972
1973 //---
1974 // Load/store
1975 //---
1976
1977 // (unsigned immediate)
1978 // Indexed for 8-bit registers. offset is in range [0,4095].
1979 def MemoryIndexed8Operand : AsmOperandClass {
1980   let Name = "MemoryIndexed8";
1981   let DiagnosticType = "InvalidMemoryIndexed8";
1982 }
1983 def am_indexed8 : Operand<i64>,
1984                   ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []> {
1985   let PrintMethod = "printAMIndexed8";
1986   let EncoderMethod
1987       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale1>";
1988   let ParserMatchClass = MemoryIndexed8Operand;
1989   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
1990 }
1991
1992 // Indexed for 16-bit registers. offset is multiple of 2 in range [0,8190],
1993 // stored as immval/2 (the 12-bit literal that encodes directly into the insn).
1994 def MemoryIndexed16Operand : AsmOperandClass {
1995   let Name = "MemoryIndexed16";
1996   let DiagnosticType = "InvalidMemoryIndexed16";
1997 }
1998 def am_indexed16 : Operand<i64>,
1999                    ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []> {
2000   let PrintMethod = "printAMIndexed16";
2001   let EncoderMethod
2002       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale2>";
2003   let ParserMatchClass = MemoryIndexed16Operand;
2004   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2005 }
2006
2007 // Indexed for 32-bit registers. offset is multiple of 4 in range [0,16380],
2008 // stored as immval/4 (the 12-bit literal that encodes directly into the insn).
2009 def MemoryIndexed32Operand : AsmOperandClass {
2010   let Name = "MemoryIndexed32";
2011   let DiagnosticType = "InvalidMemoryIndexed32";
2012 }
2013 def am_indexed32 : Operand<i64>,
2014                    ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []> {
2015   let PrintMethod = "printAMIndexed32";
2016   let EncoderMethod
2017       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale4>";
2018   let ParserMatchClass = MemoryIndexed32Operand;
2019   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2020 }
2021
2022 // Indexed for 64-bit registers. offset is multiple of 8 in range [0,32760],
2023 // stored as immval/8 (the 12-bit literal that encodes directly into the insn).
2024 def MemoryIndexed64Operand : AsmOperandClass {
2025   let Name = "MemoryIndexed64";
2026   let DiagnosticType = "InvalidMemoryIndexed64";
2027 }
2028 def am_indexed64 : Operand<i64>,
2029                    ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []> {
2030   let PrintMethod = "printAMIndexed64";
2031   let EncoderMethod
2032       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale8>";
2033   let ParserMatchClass = MemoryIndexed64Operand;
2034   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2035 }
2036
2037 // Indexed for 128-bit registers. offset is multiple of 16 in range [0,65520],
2038 // stored as immval/16 (the 12-bit literal that encodes directly into the insn).
2039 def MemoryIndexed128Operand : AsmOperandClass {
2040   let Name = "MemoryIndexed128";
2041   let DiagnosticType = "InvalidMemoryIndexed128";
2042 }
2043 def am_indexed128 : Operand<i64>,
2044                    ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []> {
2045   let PrintMethod = "printAMIndexed128";
2046   let EncoderMethod
2047       = "getAMIndexed8OpValue<ARM64::fixup_arm64_ldst_imm12_scale16>";
2048   let ParserMatchClass = MemoryIndexed128Operand;
2049   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2050 }
2051
2052 // No offset.
2053 def MemoryNoIndexOperand : AsmOperandClass { let Name = "MemoryNoIndex"; }
2054 def am_noindex : Operand<i64>,
2055                  ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
2056   let PrintMethod = "printAMNoIndex";
2057   let ParserMatchClass = MemoryNoIndexOperand;
2058   let MIOperandInfo = (ops GPR64sp:$base);
2059 }
2060
2061 class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2062                       string asm, list<dag> pattern>
2063     : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2064   bits<5> dst;
2065
2066   bits<17> addr;
2067   bits<5> base = addr{4-0};
2068   bits<12> offset = addr{16-5};
2069
2070   let Inst{31-30} = sz;
2071   let Inst{29-27} = 0b111;
2072   let Inst{26}    = V;
2073   let Inst{25-24} = 0b01;
2074   let Inst{23-22} = opc;
2075   let Inst{21-10} = offset;
2076   let Inst{9-5}   = base;
2077   let Inst{4-0}   = dst;
2078
2079   let DecoderMethod = "DecodeUnsignedLdStInstruction";
2080 }
2081
2082 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2083 class LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2084              Operand indextype, string asm, list<dag> pattern>
2085     : BaseLoadStoreUI<sz, V, opc,
2086                       (outs regtype:$Rt), (ins indextype:$addr), asm, pattern>,
2087       Sched<[WriteLD]>;
2088
2089 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2090 class StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2091              Operand indextype, string asm, list<dag> pattern>
2092     : BaseLoadStoreUI<sz, V, opc,
2093                       (outs), (ins regtype:$Rt, indextype:$addr), asm, pattern>,
2094       Sched<[WriteST]>;
2095
2096 def PrefetchOperand : AsmOperandClass {
2097   let Name = "Prefetch";
2098   let ParserMethod = "tryParsePrefetch";
2099 }
2100 def prfop : Operand<i32> {
2101   let PrintMethod = "printPrefetchOp";
2102   let ParserMatchClass = PrefetchOperand;
2103 }
2104
2105 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2106 class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2107     : BaseLoadStoreUI<sz, V, opc,
2108                       (outs), (ins prfop:$Rt, am_indexed64:$addr), asm, pat>,
2109       Sched<[WriteLD]>;
2110
2111 //---
2112 // Load literal
2113 //---
2114
2115 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2116 class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2117     : I<(outs regtype:$Rt), (ins am_brcond:$label),
2118         asm, "\t$Rt, $label", "", []>,
2119       Sched<[WriteLD]> {
2120   bits<5> Rt;
2121   bits<19> label;
2122   let Inst{31-30} = opc;
2123   let Inst{29-27} = 0b011;
2124   let Inst{26}    = V;
2125   let Inst{25-24} = 0b00;
2126   let Inst{23-5}  = label;
2127   let Inst{4-0}   = Rt;
2128 }
2129
2130 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2131 class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2132     : I<(outs), (ins prfop:$Rt, am_brcond:$label),
2133         asm, "\t$Rt, $label", "", pat>,
2134       Sched<[WriteLD]> {
2135   bits<5> Rt;
2136   bits<19> label;
2137   let Inst{31-30} = opc;
2138   let Inst{29-27} = 0b011;
2139   let Inst{26}    = V;
2140   let Inst{25-24} = 0b00;
2141   let Inst{23-5}  = label;
2142   let Inst{4-0}   = Rt;
2143 }
2144
2145 //---
2146 // Load/store register offset
2147 //---
2148
2149 class MemROAsmOperand<int sz> : AsmOperandClass {
2150   let Name = "MemoryRegisterOffset"#sz;
2151 }
2152
2153 def MemROAsmOperand8 : MemROAsmOperand<8>;
2154 def MemROAsmOperand16 : MemROAsmOperand<16>;
2155 def MemROAsmOperand32 : MemROAsmOperand<32>;
2156 def MemROAsmOperand64 : MemROAsmOperand<64>;
2157 def MemROAsmOperand128 : MemROAsmOperand<128>;
2158
2159 class ro_indexed<int sz> : Operand<i64> { // ComplexPattern<...>
2160   let PrintMethod = "printMemoryRegOffset"#sz;
2161   let MIOperandInfo = (ops GPR64sp:$base, GPR64:$offset, i32imm:$extend);
2162 }
2163
2164 def ro_indexed8 : ro_indexed<8>, ComplexPattern<i64, 3, "SelectAddrModeRO8", []> {
2165   let ParserMatchClass = MemROAsmOperand8;
2166 }
2167
2168 def ro_indexed16 : ro_indexed<16>, ComplexPattern<i64, 3, "SelectAddrModeRO16", []> {
2169   let ParserMatchClass = MemROAsmOperand16;
2170 }
2171
2172 def ro_indexed32 : ro_indexed<32>, ComplexPattern<i64, 3, "SelectAddrModeRO32", []> {
2173   let ParserMatchClass = MemROAsmOperand32;
2174 }
2175
2176 def ro_indexed64 : ro_indexed<64>, ComplexPattern<i64, 3, "SelectAddrModeRO64", []> {
2177   let ParserMatchClass = MemROAsmOperand64;
2178 }
2179
2180 def ro_indexed128 : ro_indexed<128>, ComplexPattern<i64, 3, "SelectAddrModeRO128", []> {
2181   let ParserMatchClass = MemROAsmOperand128;
2182 }
2183
2184 class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2185                       string asm, dag ins, dag outs, list<dag> pat>
2186     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2187   // The operands are in order to match the 'addr' MI operands, so we
2188   // don't need an encoder method and by-name matching. Just use the default
2189   // in-order handling. Since we're using by-order, make sure the names
2190   // do not match.
2191   bits<5> dst;
2192   bits<5> base;
2193   bits<5> offset;
2194   bits<4> extend;
2195   let Inst{31-30} = sz;
2196   let Inst{29-27} = 0b111;
2197   let Inst{26}    = V;
2198   let Inst{25-24} = 0b00;
2199   let Inst{23-22} = opc;
2200   let Inst{21}    = 1;
2201   let Inst{20-16} = offset;
2202   let Inst{15-13} = extend{3-1};
2203
2204   let Inst{12}    = extend{0};
2205   let Inst{11-10} = 0b10;
2206   let Inst{9-5}   = base;
2207   let Inst{4-0}   = dst;
2208
2209   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2210 }
2211
2212 class Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2213              string asm, list<dag> pat>
2214   : LoadStore8RO<sz, V, opc, regtype, asm,
2215                  (outs regtype:$Rt), (ins ro_indexed8:$addr), pat>,
2216     Sched<[WriteLDIdx, ReadAdrBase]>;
2217
2218 class Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2219              string asm, list<dag> pat>
2220   : LoadStore8RO<sz, V, opc, regtype, asm,
2221                  (outs), (ins regtype:$Rt, ro_indexed8:$addr), pat>,
2222     Sched<[WriteSTIdx, ReadAdrBase]>;
2223
2224 class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2225                       string asm, dag ins, dag outs, list<dag> pat>
2226     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2227   // The operands are in order to match the 'addr' MI operands, so we
2228   // don't need an encoder method and by-name matching. Just use the default
2229   // in-order handling. Since we're using by-order, make sure the names
2230   // do not match.
2231   bits<5> dst;
2232   bits<5> base;
2233   bits<5> offset;
2234   bits<4> extend;
2235   let Inst{31-30} = sz;
2236   let Inst{29-27} = 0b111;
2237   let Inst{26}    = V;
2238   let Inst{25-24} = 0b00;
2239   let Inst{23-22} = opc;
2240   let Inst{21}    = 1;
2241   let Inst{20-16} = offset;
2242   let Inst{15-13} = extend{3-1};
2243
2244   let Inst{12}    = extend{0};
2245   let Inst{11-10} = 0b10;
2246   let Inst{9-5}   = base;
2247   let Inst{4-0}   = dst;
2248
2249   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2250 }
2251
2252 class Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2253              string asm, list<dag> pat>
2254   : LoadStore16RO<sz, V, opc, regtype, asm,
2255                  (outs regtype:$Rt), (ins ro_indexed16:$addr), pat>,
2256     Sched<[WriteLDIdx, ReadAdrBase]>;
2257
2258 class Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2259              string asm, list<dag> pat>
2260   : LoadStore16RO<sz, V, opc, regtype, asm,
2261                  (outs), (ins regtype:$Rt, ro_indexed16:$addr), pat>,
2262     Sched<[WriteSTIdx, ReadAdrBase]>;
2263
2264 class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2265                       string asm, dag ins, dag outs, list<dag> pat>
2266     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2267   // The operands are in order to match the 'addr' MI operands, so we
2268   // don't need an encoder method and by-name matching. Just use the default
2269   // in-order handling. Since we're using by-order, make sure the names
2270   // do not match.
2271   bits<5> dst;
2272   bits<5> base;
2273   bits<5> offset;
2274   bits<4> extend;
2275   let Inst{31-30} = sz;
2276   let Inst{29-27} = 0b111;
2277   let Inst{26}    = V;
2278   let Inst{25-24} = 0b00;
2279   let Inst{23-22} = opc;
2280   let Inst{21}    = 1;
2281   let Inst{20-16} = offset;
2282   let Inst{15-13} = extend{3-1};
2283
2284   let Inst{12}    = extend{0};
2285   let Inst{11-10} = 0b10;
2286   let Inst{9-5}   = base;
2287   let Inst{4-0}   = dst;
2288
2289   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2290 }
2291
2292 class Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2293              string asm, list<dag> pat>
2294   : LoadStore32RO<sz, V, opc, regtype, asm,
2295                  (outs regtype:$Rt), (ins ro_indexed32:$addr), pat>,
2296     Sched<[WriteLDIdx, ReadAdrBase]>;
2297
2298 class Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2299              string asm, list<dag> pat>
2300   : LoadStore32RO<sz, V, opc, regtype, asm,
2301                  (outs), (ins regtype:$Rt, ro_indexed32:$addr), pat>,
2302     Sched<[WriteSTIdx, ReadAdrBase]>;
2303
2304 class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2305                       string asm, dag ins, dag outs, list<dag> pat>
2306     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2307   // The operands are in order to match the 'addr' MI operands, so we
2308   // don't need an encoder method and by-name matching. Just use the default
2309   // in-order handling. Since we're using by-order, make sure the names
2310   // do not match.
2311   bits<5> dst;
2312   bits<5> base;
2313   bits<5> offset;
2314   bits<4> extend;
2315   let Inst{31-30} = sz;
2316   let Inst{29-27} = 0b111;
2317   let Inst{26}    = V;
2318   let Inst{25-24} = 0b00;
2319   let Inst{23-22} = opc;
2320   let Inst{21}    = 1;
2321   let Inst{20-16} = offset;
2322   let Inst{15-13} = extend{3-1};
2323
2324   let Inst{12}    = extend{0};
2325   let Inst{11-10} = 0b10;
2326   let Inst{9-5}   = base;
2327   let Inst{4-0}   = dst;
2328
2329   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2330 }
2331
2332 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2333 class Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2334              string asm, list<dag> pat>
2335   : LoadStore64RO<sz, V, opc, regtype, asm,
2336                  (outs regtype:$Rt), (ins ro_indexed64:$addr), pat>,
2337     Sched<[WriteLDIdx, ReadAdrBase]>;
2338
2339 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2340 class Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2341              string asm, list<dag> pat>
2342   : LoadStore64RO<sz, V, opc, regtype, asm,
2343                  (outs), (ins regtype:$Rt, ro_indexed64:$addr), pat>,
2344     Sched<[WriteSTIdx, ReadAdrBase]>;
2345
2346
2347 class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2348                       string asm, dag ins, dag outs, list<dag> pat>
2349     : I<ins, outs, asm, "\t$Rt, $addr", "", pat> {
2350   // The operands are in order to match the 'addr' MI operands, so we
2351   // don't need an encoder method and by-name matching. Just use the default
2352   // in-order handling. Since we're using by-order, make sure the names
2353   // do not match.
2354   bits<5> dst;
2355   bits<5> base;
2356   bits<5> offset;
2357   bits<4> extend;
2358   let Inst{31-30} = sz;
2359   let Inst{29-27} = 0b111;
2360   let Inst{26}    = V;
2361   let Inst{25-24} = 0b00;
2362   let Inst{23-22} = opc;
2363   let Inst{21}    = 1;
2364   let Inst{20-16} = offset;
2365   let Inst{15-13} = extend{3-1};
2366
2367   let Inst{12}    = extend{0};
2368   let Inst{11-10} = 0b10;
2369   let Inst{9-5}   = base;
2370   let Inst{4-0}   = dst;
2371
2372   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2373 }
2374
2375 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2376 class Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2377              string asm, list<dag> pat>
2378   : LoadStore128RO<sz, V, opc, regtype, asm,
2379                  (outs regtype:$Rt), (ins ro_indexed128:$addr), pat>,
2380     Sched<[WriteLDIdx, ReadAdrBase]>;
2381
2382 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2383 class Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2384              string asm, list<dag> pat>
2385   : LoadStore128RO<sz, V, opc, regtype, asm,
2386                  (outs), (ins regtype:$Rt, ro_indexed128:$addr), pat>,
2387     Sched<[WriteSTIdx, ReadAdrBase]>;
2388
2389 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2390 class PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2391     : I<(outs), (ins prfop:$Rt, ro_indexed64:$addr), asm,
2392          "\t$Rt, $addr", "", pat>,
2393       Sched<[WriteLD]> {
2394   // The operands are in order to match the 'addr' MI operands, so we
2395   // don't need an encoder method and by-name matching. Just use the default
2396   // in-order handling. Since we're using by-order, make sure the names
2397   // do not match.
2398   bits<5> dst;
2399   bits<5> base;
2400   bits<5> offset;
2401   bits<4> extend;
2402   let Inst{31-30} = sz;
2403   let Inst{29-27} = 0b111;
2404   let Inst{26}    = V;
2405   let Inst{25-24} = 0b00;
2406   let Inst{23-22} = opc;
2407   let Inst{21}    = 1;
2408   let Inst{20-16} = offset;
2409   let Inst{15-13} = extend{3-1};
2410
2411   let Inst{12}    = extend{0};
2412   let Inst{11-10} = 0b10;
2413   let Inst{9-5}   = base;
2414   let Inst{4-0}   = dst;
2415
2416   let DecoderMethod = "DecodeRegOffsetLdStInstruction";
2417 }
2418
2419 //---
2420 // Load/store unscaled immediate
2421 //---
2422
2423 def MemoryUnscaledOperand : AsmOperandClass {
2424   let Name = "MemoryUnscaled";
2425   let DiagnosticType = "InvalidMemoryIndexedSImm9";
2426 }
2427 class am_unscaled_operand : Operand<i64> {
2428   let PrintMethod = "printAMUnscaled";
2429   let ParserMatchClass = MemoryUnscaledOperand;
2430   let MIOperandInfo = (ops GPR64sp:$base, i64imm:$offset);
2431 }
2432 def am_unscaled   : am_unscaled_operand;
2433 def am_unscaled8  : am_unscaled_operand,
2434                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2435 def am_unscaled16 : am_unscaled_operand,
2436                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2437 def am_unscaled32 : am_unscaled_operand,
2438                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2439 def am_unscaled64 : am_unscaled_operand,
2440                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2441 def am_unscaled128 : am_unscaled_operand,
2442                     ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2443
2444 class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2445                            string asm, list<dag> pattern>
2446     : I<oops, iops, asm, "\t$Rt, $addr", "", pattern> {
2447   // The operands are in order to match the 'addr' MI operands, so we
2448   // don't need an encoder method and by-name matching. Just use the default
2449   // in-order handling. Since we're using by-order, make sure the names
2450   // do not match.
2451   bits<5> dst;
2452   bits<5> base;
2453   bits<9> offset;
2454   let Inst{31-30} = sz;
2455   let Inst{29-27} = 0b111;
2456   let Inst{26}    = V;
2457   let Inst{25-24} = 0b00;
2458   let Inst{23-22} = opc;
2459   let Inst{21}    = 0;
2460   let Inst{20-12} = offset;
2461   let Inst{11-10} = 0b00;
2462   let Inst{9-5}   = base;
2463   let Inst{4-0}   = dst;
2464
2465   let DecoderMethod = "DecodeSignedLdStInstruction";
2466 }
2467
2468 let AddedComplexity = 1 in // try this before LoadUI
2469 class LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2470                    Operand amtype, string asm, list<dag> pattern>
2471     : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
2472                            (ins amtype:$addr), asm, pattern>,
2473       Sched<[WriteLD]>;
2474
2475 let AddedComplexity = 1 in // try this before StoreUI
2476 class StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2477                     Operand amtype, string asm, list<dag> pattern>
2478     : BaseLoadStoreUnscale<sz, V, opc, (outs),
2479                            (ins regtype:$Rt, amtype:$addr), asm, pattern>,
2480       Sched<[WriteST]>;
2481
2482 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2483 class PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2484     : BaseLoadStoreUnscale<sz, V, opc, (outs),
2485                            (ins prfop:$Rt, am_unscaled:$addr), asm, pat>,
2486       Sched<[WriteLD]>;
2487
2488 //---
2489 // Load/store unscaled immediate, unprivileged
2490 //---
2491
2492 class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
2493                                 dag oops, dag iops, string asm>
2494     : I<oops, iops, asm, "\t$Rt, $addr", "", []> {
2495   // The operands are in order to match the 'addr' MI operands, so we
2496   // don't need an encoder method and by-name matching. Just use the default
2497   // in-order handling. Since we're using by-order, make sure the names
2498   // do not match.
2499   bits<5> dst;
2500   bits<5> base;
2501   bits<9> offset;
2502   let Inst{31-30} = sz;
2503   let Inst{29-27} = 0b111;
2504   let Inst{26}    = V;
2505   let Inst{25-24} = 0b00;
2506   let Inst{23-22} = opc;
2507   let Inst{21}    = 0;
2508   let Inst{20-12} = offset;
2509   let Inst{11-10} = 0b10;
2510   let Inst{9-5}   = base;
2511   let Inst{4-0}   = dst;
2512
2513   let DecoderMethod = "DecodeSignedLdStInstruction";
2514 }
2515
2516 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2517 class LoadUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2518                    string asm>
2519     : BaseLoadStoreUnprivileged<sz, V, opc,
2520                       (outs regtype:$Rt), (ins am_unscaled:$addr), asm>,
2521       Sched<[WriteLD]>;
2522 }
2523
2524 let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in {
2525 class StoreUnprivileged<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2526                     string asm>
2527     : BaseLoadStoreUnprivileged<sz, V, opc,
2528                       (outs), (ins regtype:$Rt, am_unscaled:$addr), asm>,
2529       Sched<[WriteST]>;
2530 }
2531
2532 //---
2533 // Load/store pre-indexed
2534 //---
2535
2536 class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2537                           string asm, string cstr>
2538     : I<oops, iops, asm, "\t$Rt, $addr!", cstr, []> {
2539   // The operands are in order to match the 'addr' MI operands, so we
2540   // don't need an encoder method and by-name matching. Just use the default
2541   // in-order handling.
2542   bits<5> dst;
2543   bits<5> base;
2544   bits<9> offset;
2545   let Inst{31-30} = sz;
2546   let Inst{29-27} = 0b111;
2547   let Inst{26}    = V;
2548   let Inst{25-24} = 0;
2549   let Inst{23-22} = opc;
2550   let Inst{21}    = 0;
2551   let Inst{20-12} = offset;
2552   let Inst{11-10} = 0b11;
2553   let Inst{9-5}   = base;
2554   let Inst{4-0}   = dst;
2555
2556   let DecoderMethod = "DecodeSignedLdStInstruction";
2557 }
2558
2559 let hasSideEffects = 0 in {
2560 let mayStore = 0, mayLoad = 1 in
2561 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2562 //        we need the complex addressing mode for the memory reference, but
2563 //        we also need the write-back specified as a tied operand to the
2564 //        base register. That combination does not play nicely with
2565 //        the asm matcher and friends.
2566 class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2567              string asm>
2568     : BaseLoadStorePreIdx<sz, V, opc,
2569                      (outs regtype:$Rt/*, GPR64sp:$wback*/),
2570                      (ins am_unscaled:$addr), asm, ""/*"$addr.base = $wback"*/>,
2571       Sched<[WriteLD, WriteAdr]>;
2572
2573 let mayStore = 1, mayLoad = 0 in
2574 class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2575              string asm>
2576     : BaseLoadStorePreIdx<sz, V, opc,
2577                       (outs/* GPR64sp:$wback*/),
2578                       (ins regtype:$Rt, am_unscaled:$addr),
2579                        asm, ""/*"$addr.base = $wback"*/>,
2580       Sched<[WriteAdr, WriteST]>;
2581 } // hasSideEffects = 0
2582
2583 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2584 // logic finally gets smart enough to strip off tied operands that are just
2585 // for isel convenience, we can get rid of these pseudos and just reference
2586 // the real instructions directly.
2587 //
2588 // Ironically, also because of the writeback operands, we can't put the
2589 // matcher pattern directly on the instruction, but need to define it
2590 // separately.
2591 //
2592 // Loads aren't matched with patterns here at all, but rather in C++
2593 // custom lowering.
2594 let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in {
2595 class LoadPreIdxPseudo<RegisterClass regtype>
2596     : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2597              (ins am_noindex:$addr, simm9:$offset), [],
2598               "$addr.base = $wback,@earlyclobber $wback">,
2599       Sched<[WriteLD, WriteAdr]>;
2600 class LoadPostIdxPseudo<RegisterClass regtype>
2601     : Pseudo<(outs regtype:$Rt, GPR64sp:$wback),
2602              (ins am_noindex:$addr, simm9:$offset), [],
2603               "$addr.base = $wback,@earlyclobber $wback">,
2604       Sched<[WriteLD, WriteI]>;
2605 }
2606 multiclass StorePreIdxPseudo<RegisterClass regtype, ValueType Ty,
2607                              SDPatternOperator OpNode> {
2608   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2609   def _isel: Pseudo<(outs GPR64sp:$wback),
2610                     (ins regtype:$Rt, am_noindex:$addr, simm9:$offset), [],
2611                     "$addr.base = $wback,@earlyclobber $wback">,
2612       Sched<[WriteAdr, WriteST]>;
2613
2614   def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$offset),
2615             (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2616                                             simm9:$offset)>;
2617 }
2618
2619 //---
2620 // Load/store post-indexed
2621 //---
2622
2623 // (pre-index) load/stores.
2624 class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2625                           string asm, string cstr>
2626     : I<oops, iops, asm, "\t$Rt, $addr, $idx", cstr, []> {
2627   // The operands are in order to match the 'addr' MI operands, so we
2628   // don't need an encoder method and by-name matching. Just use the default
2629   // in-order handling.
2630   bits<5> dst;
2631   bits<5> base;
2632   bits<9> offset;
2633   let Inst{31-30} = sz;
2634   let Inst{29-27} = 0b111;
2635   let Inst{26}    = V;
2636   let Inst{25-24} = 0b00;
2637   let Inst{23-22} = opc;
2638   let Inst{21}    = 0b0;
2639   let Inst{20-12} = offset;
2640   let Inst{11-10} = 0b01;
2641   let Inst{9-5}   = base;
2642   let Inst{4-0}   = dst;
2643
2644   let DecoderMethod = "DecodeSignedLdStInstruction";
2645 }
2646
2647 let hasSideEffects = 0 in {
2648 let mayStore = 0, mayLoad = 1 in
2649 // FIXME: Modeling the write-back of these instructions for isel is tricky.
2650 //        we need the complex addressing mode for the memory reference, but
2651 //        we also need the write-back specified as a tied operand to the
2652 //        base register. That combination does not play nicely with
2653 //        the asm matcher and friends.
2654 class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2655              string asm>
2656     : BaseLoadStorePostIdx<sz, V, opc,
2657                       (outs regtype:$Rt/*, GPR64sp:$wback*/),
2658                       (ins am_noindex:$addr, simm9:$idx),
2659                       asm, ""/*"$addr.base = $wback"*/>,
2660       Sched<[WriteLD, WriteI]>;
2661
2662 let mayStore = 1, mayLoad = 0 in
2663 class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2664              string asm>
2665     : BaseLoadStorePostIdx<sz, V, opc,
2666                       (outs/* GPR64sp:$wback*/),
2667                       (ins regtype:$Rt, am_noindex:$addr, simm9:$idx),
2668                        asm, ""/*"$addr.base = $wback"*/>,
2669     Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2670 } // hasSideEffects = 0
2671
2672 // ISel pseudo-instructions which have the tied operands. When the MC lowering
2673 // logic finally gets smart enough to strip off tied operands that are just
2674 // for isel convenience, we can get rid of these pseudos and just reference
2675 // the real instructions directly.
2676 //
2677 // Ironically, also because of the writeback operands, we can't put the
2678 // matcher pattern directly on the instruction, but need to define it
2679 // separately.
2680 multiclass StorePostIdxPseudo<RegisterClass regtype, ValueType Ty,
2681                               SDPatternOperator OpNode, Instruction Insn> {
2682   let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
2683   def _isel: Pseudo<(outs GPR64sp:$wback),
2684                     (ins regtype:$Rt, am_noindex:$addr, simm9:$idx), [],
2685                     "$addr.base = $wback,@earlyclobber $wback">,
2686       PseudoInstExpansion<(Insn regtype:$Rt, am_noindex:$addr, simm9:$idx)>,
2687       Sched<[WriteAdr, WriteST, ReadAdrBase]>;
2688
2689   def : Pat<(OpNode (Ty regtype:$Rt), am_noindex:$addr, simm9:$idx),
2690             (!cast<Instruction>(NAME#_isel) regtype:$Rt, am_noindex:$addr,
2691                                             simm9:$idx)>;
2692 }
2693
2694 //---
2695 // Load/store pair
2696 //---
2697
2698 // (indexed, offset)
2699
2700 class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
2701                               string asm>
2702     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2703   // The operands are in order to match the 'addr' MI operands, so we
2704   // don't need an encoder method and by-name matching. Just use the default
2705   // in-order handling. Since we're using by-order, make sure the names
2706   // do not match.
2707   bits<5> dst;
2708   bits<5> dst2;
2709   bits<5> base;
2710   bits<7> offset;
2711   let Inst{31-30} = opc;
2712   let Inst{29-27} = 0b101;
2713   let Inst{26}    = V;
2714   let Inst{25-23} = 0b010;
2715   let Inst{22}    = L;
2716   let Inst{21-15} = offset;
2717   let Inst{14-10} = dst2;
2718   let Inst{9-5}   = base;
2719   let Inst{4-0}   = dst;
2720
2721   let DecoderMethod = "DecodePairLdStInstruction";
2722 }
2723
2724 let hasSideEffects = 0 in {
2725 let mayStore = 0, mayLoad = 1 in
2726 class LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
2727                      Operand indextype, string asm>
2728     : BaseLoadStorePairOffset<opc, V, 1,
2729                               (outs regtype:$Rt, regtype:$Rt2),
2730                               (ins indextype:$addr), asm>,
2731       Sched<[WriteLD, WriteLDHi]>;
2732
2733 let mayLoad = 0, mayStore = 1 in
2734 class StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
2735                       Operand indextype, string asm>
2736     : BaseLoadStorePairOffset<opc, V, 0, (outs),
2737                              (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2738                              asm>,
2739       Sched<[WriteSTP]>;
2740 } // hasSideEffects = 0
2741
2742 // (pre-indexed)
2743
2744 def MemoryIndexed32SImm7 : AsmOperandClass {
2745   let Name = "MemoryIndexed32SImm7";
2746   let DiagnosticType = "InvalidMemoryIndexed32SImm7";
2747 }
2748 def am_indexed32simm7 : Operand<i32> { // ComplexPattern<...>
2749   let PrintMethod = "printAMIndexed32";
2750   let ParserMatchClass = MemoryIndexed32SImm7;
2751   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2752 }
2753
2754 def MemoryIndexed64SImm7 : AsmOperandClass {
2755   let Name = "MemoryIndexed64SImm7";
2756   let DiagnosticType = "InvalidMemoryIndexed64SImm7";
2757 }
2758 def am_indexed64simm7 : Operand<i32> { // ComplexPattern<...>
2759   let PrintMethod = "printAMIndexed64";
2760   let ParserMatchClass = MemoryIndexed64SImm7;
2761   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2762 }
2763
2764 def MemoryIndexed128SImm7 : AsmOperandClass {
2765   let Name = "MemoryIndexed128SImm7";
2766   let DiagnosticType = "InvalidMemoryIndexed128SImm7";
2767 }
2768 def am_indexed128simm7 : Operand<i32> { // ComplexPattern<...>
2769   let PrintMethod = "printAMIndexed128";
2770   let ParserMatchClass = MemoryIndexed128SImm7;
2771   let MIOperandInfo = (ops GPR64sp:$base, i32imm:$offset);
2772 }
2773
2774 class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2775                               string asm>
2776     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr!", "", []> {
2777   // The operands are in order to match the 'addr' MI operands, so we
2778   // don't need an encoder method and by-name matching. Just use the default
2779   // in-order handling. Since we're using by-order, make sure the names
2780   // do not match.
2781   bits<5> dst;
2782   bits<5> dst2;
2783   bits<5> base;
2784   bits<7> offset;
2785   let Inst{31-30} = opc;
2786   let Inst{29-27} = 0b101;
2787   let Inst{26}    = V;
2788   let Inst{25-23} = 0b011;
2789   let Inst{22}    = L;
2790   let Inst{21-15} = offset;
2791   let Inst{14-10} = dst2;
2792   let Inst{9-5}   = base;
2793   let Inst{4-0}   = dst;
2794
2795   let DecoderMethod = "DecodePairLdStInstruction";
2796 }
2797
2798 let hasSideEffects = 0 in {
2799 let mayStore = 0, mayLoad = 1 in
2800 class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2801                      Operand addrmode, string asm>
2802     : BaseLoadStorePairPreIdx<opc, V, 1,
2803                               (outs regtype:$Rt, regtype:$Rt2),
2804                               (ins addrmode:$addr), asm>,
2805       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2806
2807 let mayStore = 1, mayLoad = 0 in
2808 class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
2809                       Operand addrmode, string asm>
2810     : BaseLoadStorePairPreIdx<opc, V, 0, (outs),
2811                              (ins regtype:$Rt, regtype:$Rt2, addrmode:$addr),
2812                              asm>,
2813       Sched<[WriteAdr, WriteSTP]>;
2814 } // hasSideEffects = 0
2815
2816 // (post-indexed)
2817
2818 class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
2819                               string asm>
2820     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr, $idx", "", []> {
2821   // The operands are in order to match the 'addr' MI operands, so we
2822   // don't need an encoder method and by-name matching. Just use the default
2823   // in-order handling. Since we're using by-order, make sure the names
2824   // do not match.
2825   bits<5> dst;
2826   bits<5> dst2;
2827   bits<5> base;
2828   bits<7> offset;
2829   let Inst{31-30} = opc;
2830   let Inst{29-27} = 0b101;
2831   let Inst{26}    = V;
2832   let Inst{25-23} = 0b001;
2833   let Inst{22}    = L;
2834   let Inst{21-15} = offset;
2835   let Inst{14-10} = dst2;
2836   let Inst{9-5}   = base;
2837   let Inst{4-0}   = dst;
2838
2839   let DecoderMethod = "DecodePairLdStInstruction";
2840 }
2841
2842 let hasSideEffects = 0 in {
2843 let mayStore = 0, mayLoad = 1 in
2844 class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2845                       Operand idxtype, string asm>
2846     : BaseLoadStorePairPostIdx<opc, V, 1,
2847                               (outs regtype:$Rt, regtype:$Rt2),
2848                               (ins am_noindex:$addr, idxtype:$idx), asm>,
2849       Sched<[WriteLD, WriteLDHi, WriteAdr]>;
2850
2851 let mayStore = 1, mayLoad = 0 in
2852 class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
2853                        Operand idxtype, string asm>
2854     : BaseLoadStorePairPostIdx<opc, V, 0, (outs),
2855                              (ins regtype:$Rt, regtype:$Rt2,
2856                                   am_noindex:$addr, idxtype:$idx),
2857                              asm>,
2858       Sched<[WriteAdr, WriteSTP]>;
2859 } // hasSideEffects = 0
2860
2861 //  (no-allocate)
2862
2863 class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
2864                               string asm>
2865     : I<oops, iops, asm, "\t$Rt, $Rt2, $addr", "", []> {
2866   // The operands are in order to match the 'addr' MI operands, so we
2867   // don't need an encoder method and by-name matching. Just use the default
2868   // in-order handling. Since we're using by-order, make sure the names
2869   // do not match.
2870   bits<5> dst;
2871   bits<5> dst2;
2872   bits<5> base;
2873   bits<7> offset;
2874   let Inst{31-30} = opc;
2875   let Inst{29-27} = 0b101;
2876   let Inst{26}    = V;
2877   let Inst{25-23} = 0b000;
2878   let Inst{22}    = L;
2879   let Inst{21-15} = offset;
2880   let Inst{14-10} = dst2;
2881   let Inst{9-5}   = base;
2882   let Inst{4-0}   = dst;
2883
2884   let DecoderMethod = "DecodePairLdStInstruction";
2885 }
2886
2887 let hasSideEffects = 0 in {
2888 let mayStore = 0, mayLoad = 1 in
2889 class LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2890                      Operand indextype, string asm>
2891     : BaseLoadStorePairNoAlloc<opc, V, 1,
2892                               (outs regtype:$Rt, regtype:$Rt2),
2893                               (ins indextype:$addr), asm>,
2894       Sched<[WriteLD, WriteLDHi]>;
2895
2896 let mayStore = 1, mayLoad = 0 in
2897 class StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
2898                       Operand indextype, string asm>
2899     : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
2900                              (ins regtype:$Rt, regtype:$Rt2, indextype:$addr),
2901                              asm>,
2902       Sched<[WriteSTP]>;
2903 } // hasSideEffects = 0
2904
2905 //---
2906 // Load/store exclusive
2907 //---
2908
2909 // True exclusive operations write to and/or read from the system's exclusive
2910 // monitors, which as far as a compiler is concerned can be modelled as a
2911 // random shared memory address. Hence LoadExclusive mayStore.
2912 //
2913 // Since these instructions have the undefined register bits set to 1 in
2914 // their canonical form, we need a post encoder method to set those bits
2915 // to 1 when encoding these instructions. We do this using the
2916 // fixLoadStoreExclusive function. This function has template parameters:
2917 //
2918 // fixLoadStoreExclusive<int hasRs, int hasRt2>
2919 //
2920 // hasRs indicates that the instruction uses the Rs field, so we won't set
2921 // it to 1 (and the same for Rt2). We don't need template parameters for
2922 // the other register fields since Rt and Rn are always used.
2923 //
2924 let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
2925 class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2926                              dag oops, dag iops, string asm, string operands>
2927     : I<oops, iops, asm, operands, "", []> {
2928   let Inst{31-30} = sz;
2929   let Inst{29-24} = 0b001000;
2930   let Inst{23}    = o2;
2931   let Inst{22}    = L;
2932   let Inst{21}    = o1;
2933   let Inst{15}    = o0;
2934
2935   let DecoderMethod = "DecodeExclusiveLdStInstruction";
2936 }
2937
2938 // Neither Rs nor Rt2 operands.
2939 class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2940                                dag oops, dag iops, string asm, string operands>
2941     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
2942   bits<5> reg;
2943   bits<5> base;
2944   let Inst{9-5} = base;
2945   let Inst{4-0} = reg;
2946
2947   let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
2948 }
2949
2950 // Simple load acquires don't set the exclusive monitor
2951 let mayLoad = 1, mayStore = 0 in
2952 class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2953                   RegisterClass regtype, string asm>
2954     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2955                                (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2956       Sched<[WriteLD]>;
2957
2958 class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2959                     RegisterClass regtype, string asm>
2960     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
2961                                (ins am_noindex:$addr), asm, "\t$Rt, $addr">,
2962       Sched<[WriteLD]>;
2963
2964 class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2965                        RegisterClass regtype, string asm>
2966     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
2967                              (outs regtype:$Rt, regtype:$Rt2),
2968                              (ins am_noindex:$addr), asm,
2969                              "\t$Rt, $Rt2, $addr">,
2970       Sched<[WriteLD, WriteLDHi]> {
2971   bits<5> dst1;
2972   bits<5> dst2;
2973   bits<5> base;
2974   let Inst{14-10} = dst2;
2975   let Inst{9-5} = base;
2976   let Inst{4-0} = dst1;
2977
2978   let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
2979 }
2980
2981 // Simple store release operations do not check the exclusive monitor.
2982 let mayLoad = 0, mayStore = 1 in
2983 class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2984                    RegisterClass regtype, string asm>
2985     : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
2986                                (ins regtype:$Rt, am_noindex:$addr),
2987                                asm, "\t$Rt, $addr">,
2988       Sched<[WriteST]>;
2989
2990 let mayLoad = 1, mayStore = 1 in
2991 class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
2992                      RegisterClass regtype, string asm>
2993     : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
2994                              (ins regtype:$Rt, am_noindex:$addr),
2995                              asm, "\t$Ws, $Rt, $addr">,
2996       Sched<[WriteSTX]> {
2997   bits<5> status;
2998   bits<5> reg;
2999   bits<5> base;
3000   let Inst{20-16} = status;
3001   let Inst{9-5} = base;
3002   let Inst{4-0} = reg;
3003
3004   let Constraints = "@earlyclobber $Ws";
3005   let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3006 }
3007
3008 class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3009                          RegisterClass regtype, string asm>
3010     : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3011                              (outs GPR32:$Ws),
3012                              (ins regtype:$Rt, regtype:$Rt2, am_noindex:$addr),
3013                               asm, "\t$Ws, $Rt, $Rt2, $addr">,
3014       Sched<[WriteSTX]> {
3015   bits<5> status;
3016   bits<5> dst1;
3017   bits<5> dst2;
3018   bits<5> base;
3019   let Inst{20-16} = status;
3020   let Inst{14-10} = dst2;
3021   let Inst{9-5} = base;
3022   let Inst{4-0} = dst1;
3023
3024   let Constraints = "@earlyclobber $Ws";
3025 }
3026
3027 //---
3028 // Exception generation
3029 //---
3030
3031 let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3032 class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3033     : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3034       Sched<[WriteSys]> {
3035   bits<16> imm;
3036   let Inst{31-24} = 0b11010100;
3037   let Inst{23-21} = op1;
3038   let Inst{20-5}  = imm;
3039   let Inst{4-2}   = 0b000;
3040   let Inst{1-0}   = ll;
3041 }
3042
3043 //---
3044 // Floating point to integer conversion
3045 //---
3046
3047 class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3048                       RegisterClass srcType, RegisterClass dstType,
3049                       string asm, list<dag> pattern>
3050     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3051          asm, "\t$Rd, $Rn", "", pattern>,
3052       Sched<[WriteFCvt]> {
3053   bits<5> Rd;
3054   bits<5> Rn;
3055   let Inst{30-29} = 0b00;
3056   let Inst{28-24} = 0b11110;
3057   let Inst{23-22} = type;
3058   let Inst{21}    = 1;
3059   let Inst{20-19} = rmode;
3060   let Inst{18-16} = opcode;
3061   let Inst{15-10} = 0;
3062   let Inst{9-5}   = Rn;
3063   let Inst{4-0}   = Rd;
3064 }
3065
3066 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3067 class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3068                       RegisterClass srcType, RegisterClass dstType,
3069                       Operand immType, string asm>
3070     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3071          asm, "\t$Rd, $Rn, $scale", "", []>,
3072       Sched<[WriteFCvt]> {
3073   bits<5> Rd;
3074   bits<5> Rn;
3075   bits<6> scale;
3076   let Inst{30-29} = 0b00;
3077   let Inst{28-24} = 0b11110;
3078   let Inst{23-22} = type;
3079   let Inst{21}    = 0;
3080   let Inst{20-19} = rmode;
3081   let Inst{18-16} = opcode;
3082   let Inst{15-10} = scale;
3083   let Inst{9-5}   = Rn;
3084   let Inst{4-0}   = Rd;
3085 }
3086
3087 multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3088            SDPatternOperator OpN> {
3089   // Unscaled single-precision to 32-bit
3090   def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3091                                      [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3092     let Inst{31} = 0; // 32-bit GPR flag
3093   }
3094
3095   // Unscaled single-precision to 64-bit
3096   def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3097                                      [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3098     let Inst{31} = 1; // 64-bit GPR flag
3099   }
3100
3101   // Unscaled double-precision to 32-bit
3102   def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3103                                      [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3104     let Inst{31} = 0; // 32-bit GPR flag
3105   }
3106
3107   // Unscaled double-precision to 64-bit
3108   def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3109                                      [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3110     let Inst{31} = 1; // 64-bit GPR flag
3111   }
3112 }
3113
3114 multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3115            SDPatternOperator OpN> {
3116   // Scaled single-precision to 32-bit
3117   def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3118                               fixedpoint32, asm> {
3119     let Inst{31} = 0; // 32-bit GPR flag
3120     let scale{5} = 1;
3121   }
3122
3123   // Scaled single-precision to 64-bit
3124   def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3125                               fixedpoint64, asm> {
3126     let Inst{31} = 1; // 64-bit GPR flag
3127   }
3128
3129   // Scaled double-precision to 32-bit
3130   def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3131                               fixedpoint32, asm> {
3132     let Inst{31} = 0; // 32-bit GPR flag
3133     let scale{5} = 1;
3134   }
3135
3136   // Scaled double-precision to 64-bit
3137   def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3138                               fixedpoint64, asm> {
3139     let Inst{31} = 1; // 64-bit GPR flag
3140   }
3141 }
3142
3143 //---
3144 // Integer to floating point conversion
3145 //---
3146
3147 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3148 class BaseIntegerToFP<bit isUnsigned,
3149                       RegisterClass srcType, RegisterClass dstType,
3150                       Operand immType, string asm>
3151     : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3152          asm, "\t$Rd, $Rn, $scale", "", []>,
3153       Sched<[WriteFCvt]> {
3154   bits<5> Rd;
3155   bits<5> Rn;
3156   bits<6> scale;
3157   let Inst{30-23} = 0b00111100;
3158   let Inst{21-17} = 0b00001;
3159   let Inst{16}    = isUnsigned;
3160   let Inst{15-10} = scale;
3161   let Inst{9-5}   = Rn;
3162   let Inst{4-0}   = Rd;
3163 }
3164
3165 class BaseIntegerToFPUnscaled<bit isUnsigned,
3166                       RegisterClass srcType, RegisterClass dstType,
3167                       ValueType dvt, string asm, SDNode node>
3168     : I<(outs dstType:$Rd), (ins srcType:$Rn),
3169          asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3170       Sched<[WriteFCvt]> {
3171   bits<5> Rd;
3172   bits<5> Rn;
3173   bits<6> scale;
3174   let Inst{30-23} = 0b00111100;
3175   let Inst{21-17} = 0b10001;
3176   let Inst{16}    = isUnsigned;
3177   let Inst{15-10} = 0b000000;
3178   let Inst{9-5}   = Rn;
3179   let Inst{4-0}   = Rd;
3180 }
3181
3182 multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3183   // Unscaled
3184   def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3185     let Inst{31} = 0; // 32-bit GPR flag
3186     let Inst{22} = 0; // 32-bit FPR flag
3187   }
3188
3189   def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3190     let Inst{31} = 0; // 32-bit GPR flag
3191     let Inst{22} = 1; // 64-bit FPR flag
3192   }
3193
3194   def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3195     let Inst{31} = 1; // 64-bit GPR flag
3196     let Inst{22} = 0; // 32-bit FPR flag
3197   }
3198
3199   def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3200     let Inst{31} = 1; // 64-bit GPR flag
3201     let Inst{22} = 1; // 64-bit FPR flag
3202   }
3203
3204   // Scaled
3205   def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint32, asm> {
3206     let Inst{31} = 0; // 32-bit GPR flag
3207     let Inst{22} = 0; // 32-bit FPR flag
3208     let scale{5} = 1;
3209   }
3210
3211   def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint32, asm> {
3212     let Inst{31} = 0; // 32-bit GPR flag
3213     let Inst{22} = 1; // 64-bit FPR flag
3214     let scale{5} = 1;
3215   }
3216
3217   def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint64, asm> {
3218     let Inst{31} = 1; // 64-bit GPR flag
3219     let Inst{22} = 0; // 32-bit FPR flag
3220   }
3221
3222   def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint64, asm> {
3223     let Inst{31} = 1; // 64-bit GPR flag
3224     let Inst{22} = 1; // 64-bit FPR flag
3225   }
3226 }
3227
3228 //---
3229 // Unscaled integer <-> floating point conversion (i.e. FMOV)
3230 //---
3231
3232 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3233 class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3234                       RegisterClass srcType, RegisterClass dstType,
3235                       string asm>
3236     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3237         // We use COPY_TO_REGCLASS for these bitconvert operations.
3238         // copyPhysReg() expands the resultant COPY instructions after
3239         // regalloc is done. This gives greater freedom for the allocator
3240         // and related passes (coalescing, copy propagation, et. al.) to
3241         // be more effective.
3242         [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3243       Sched<[WriteFCopy]> {
3244   bits<5> Rd;
3245   bits<5> Rn;
3246   let Inst{30-23} = 0b00111100;
3247   let Inst{21}    = 1;
3248   let Inst{20-19} = rmode;
3249   let Inst{18-16} = opcode;
3250   let Inst{15-10} = 0b000000;
3251   let Inst{9-5}   = Rn;
3252   let Inst{4-0}   = Rd;
3253 }
3254
3255 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3256 class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3257                      RegisterClass srcType, RegisterOperand dstType, string asm>
3258     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd[1], $Rn", "", []>,
3259       Sched<[WriteFCopy]> {
3260   bits<5> Rd;
3261   bits<5> Rn;
3262   let Inst{30-23} = 0b00111101;
3263   let Inst{21}    = 1;
3264   let Inst{20-19} = rmode;
3265   let Inst{18-16} = opcode;
3266   let Inst{15-10} = 0b000000;
3267   let Inst{9-5}   = Rn;
3268   let Inst{4-0}   = Rd;
3269 }
3270
3271 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3272 class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3273                      RegisterOperand srcType, RegisterClass dstType, string asm>
3274     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn[1]", "", []>,
3275       Sched<[WriteFCopy]> {
3276   bits<5> Rd;
3277   bits<5> Rn;
3278   let Inst{30-23} = 0b00111101;
3279   let Inst{21}    = 1;
3280   let Inst{20-19} = rmode;
3281   let Inst{18-16} = opcode;
3282   let Inst{15-10} = 0b000000;
3283   let Inst{9-5}   = Rn;
3284   let Inst{4-0}   = Rd;
3285 }
3286
3287
3288
3289 multiclass UnscaledConversion<string asm> {
3290   def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3291     let Inst{31} = 0; // 32-bit GPR flag
3292     let Inst{22} = 0; // 32-bit FPR flag
3293   }
3294
3295   def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3296     let Inst{31} = 1; // 64-bit GPR flag
3297     let Inst{22} = 1; // 64-bit FPR flag
3298   }
3299
3300   def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3301     let Inst{31} = 0; // 32-bit GPR flag
3302     let Inst{22} = 0; // 32-bit FPR flag
3303   }
3304
3305   def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3306     let Inst{31} = 1; // 64-bit GPR flag
3307     let Inst{22} = 1; // 64-bit FPR flag
3308   }
3309
3310   def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3311                                              asm#".d"> {
3312     let Inst{31} = 1;
3313     let Inst{22} = 0;
3314   }
3315
3316   def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3317                                                asm#".d"> {
3318     let Inst{31} = 1;
3319     let Inst{22} = 0;
3320   }
3321
3322   def : InstAlias<asm#"$Vd.d[1], $Rn",
3323                   (!cast<Instruction>(NAME#XDHighr) V128:$Vd, GPR64:$Rn), 0>;
3324   def : InstAlias<asm#"$Rd, $Vn.d[1]",
3325                   (!cast<Instruction>(NAME#DXHighr) GPR64:$Rd, V128:$Vn), 0>;
3326 }
3327
3328 //---
3329 // Floating point conversion
3330 //---
3331
3332 class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3333                        RegisterClass srcType, string asm, list<dag> pattern>
3334     : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3335       Sched<[WriteFCvt]> {
3336   bits<5> Rd;
3337   bits<5> Rn;
3338   let Inst{31-24} = 0b00011110;
3339   let Inst{23-22} = type;
3340   let Inst{21-17} = 0b10001;
3341   let Inst{16-15} = opcode;
3342   let Inst{14-10} = 0b10000;
3343   let Inst{9-5}   = Rn;
3344   let Inst{4-0}   = Rd;
3345 }
3346
3347 multiclass FPConversion<string asm> {
3348   // Double-precision to Half-precision
3349   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3350   def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm, []>;
3351
3352   // Double-precision to Single-precision
3353   def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3354                              [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3355
3356   // Half-precision to Double-precision
3357   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3358   def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm, []>;
3359
3360   // Half-precision to Single-precision
3361   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3362   def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm, []>;
3363
3364   // Single-precision to Double-precision
3365   def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3366                              [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3367
3368   // Single-precision to Half-precision
3369   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3370   def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm, []>;
3371 }
3372
3373 //---
3374 // Single operand floating point data processing
3375 //---
3376
3377 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3378 class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3379                               ValueType vt, string asm, SDPatternOperator node>
3380     : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3381          [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3382       Sched<[WriteF]> {
3383   bits<5> Rd;
3384   bits<5> Rn;
3385   let Inst{31-23} = 0b000111100;
3386   let Inst{21-19} = 0b100;
3387   let Inst{18-15} = opcode;
3388   let Inst{14-10} = 0b10000;
3389   let Inst{9-5}   = Rn;
3390   let Inst{4-0}   = Rd;
3391 }
3392
3393 multiclass SingleOperandFPData<bits<4> opcode, string asm,
3394                                SDPatternOperator node = null_frag> {
3395   def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3396     let Inst{22} = 0; // 32-bit size flag
3397   }
3398
3399   def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3400     let Inst{22} = 1; // 64-bit size flag
3401   }
3402 }
3403
3404 //---
3405 // Two operand floating point data processing
3406 //---
3407
3408 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3409 class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
3410                            string asm, list<dag> pat>
3411     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3412          asm, "\t$Rd, $Rn, $Rm", "", pat>,
3413       Sched<[WriteF]> {
3414   bits<5> Rd;
3415   bits<5> Rn;
3416   bits<5> Rm;
3417   let Inst{31-23} = 0b000111100;
3418   let Inst{21}    = 1;
3419   let Inst{20-16} = Rm;
3420   let Inst{15-12} = opcode;
3421   let Inst{11-10} = 0b10;
3422   let Inst{9-5}   = Rn;
3423   let Inst{4-0}   = Rd;
3424 }
3425
3426 multiclass TwoOperandFPData<bits<4> opcode, string asm,
3427                             SDPatternOperator node = null_frag> {
3428   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3429                          [(set (f32 FPR32:$Rd),
3430                                (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
3431     let Inst{22} = 0; // 32-bit size flag
3432   }
3433
3434   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3435                          [(set (f64 FPR64:$Rd),
3436                                (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
3437     let Inst{22} = 1; // 64-bit size flag
3438   }
3439 }
3440
3441 multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
3442   def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
3443                   [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
3444     let Inst{22} = 0; // 32-bit size flag
3445   }
3446
3447   def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
3448                   [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
3449     let Inst{22} = 1; // 64-bit size flag
3450   }
3451 }
3452
3453
3454 //---
3455 // Three operand floating point data processing
3456 //---
3457
3458 class BaseThreeOperandFPData<bit isNegated, bit isSub,
3459                              RegisterClass regtype, string asm, list<dag> pat>
3460     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
3461          asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
3462       Sched<[WriteFMul]> {
3463   bits<5> Rd;
3464   bits<5> Rn;
3465   bits<5> Rm;
3466   bits<5> Ra;
3467   let Inst{31-23} = 0b000111110;
3468   let Inst{21}    = isNegated;
3469   let Inst{20-16} = Rm;
3470   let Inst{15}    = isSub;
3471   let Inst{14-10} = Ra;
3472   let Inst{9-5}   = Rn;
3473   let Inst{4-0}   = Rd;
3474 }
3475
3476 multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
3477                               SDPatternOperator node> {
3478   def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
3479             [(set FPR32:$Rd,
3480                   (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
3481     let Inst{22} = 0; // 32-bit size flag
3482   }
3483
3484   def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
3485             [(set FPR64:$Rd,
3486                   (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
3487     let Inst{22} = 1; // 64-bit size flag
3488   }
3489 }
3490
3491 //---
3492 // Floating point data comparisons
3493 //---
3494
3495 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3496 class BaseOneOperandFPComparison<bit signalAllNans,
3497                                  RegisterClass regtype, string asm,
3498                                  list<dag> pat>
3499     : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
3500       Sched<[WriteFCmp]> {
3501   bits<5> Rn;
3502   let Inst{31-23} = 0b000111100;
3503   let Inst{21}    = 1;
3504
3505   let Inst{15-10} = 0b001000;
3506   let Inst{9-5}   = Rn;
3507   let Inst{4}     = signalAllNans;
3508   let Inst{3-0}   = 0b1000;
3509
3510   // Rm should be 0b00000 canonically, but we need to accept any value.
3511   let PostEncoderMethod = "fixOneOperandFPComparison";
3512 }
3513
3514 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3515 class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
3516                                 string asm, list<dag> pat>
3517     : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
3518       Sched<[WriteFCmp]> {
3519   bits<5> Rm;
3520   bits<5> Rn;
3521   let Inst{31-23} = 0b000111100;
3522   let Inst{21}    = 1;
3523   let Inst{20-16} = Rm;
3524   let Inst{15-10} = 0b001000;
3525   let Inst{9-5}   = Rn;
3526   let Inst{4}     = signalAllNans;
3527   let Inst{3-0}   = 0b0000;
3528 }
3529
3530 multiclass FPComparison<bit signalAllNans, string asm,
3531                         SDPatternOperator OpNode = null_frag> {
3532   let Defs = [CPSR] in {
3533   def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
3534       [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit CPSR)]> {
3535     let Inst{22} = 0;
3536   }
3537
3538   def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
3539       [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit CPSR)]> {
3540     let Inst{22} = 0;
3541   }
3542
3543   def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
3544       [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit CPSR)]> {
3545     let Inst{22} = 1;
3546   }
3547
3548   def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
3549       [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit CPSR)]> {
3550     let Inst{22} = 1;
3551   }
3552   } // Defs = [CPSR]
3553 }
3554
3555 //---
3556 // Floating point conditional comparisons
3557 //---
3558
3559 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3560 class BaseFPCondComparison<bit signalAllNans,
3561                               RegisterClass regtype, string asm>
3562     : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm0_15:$nzcv, ccode:$cond),
3563          asm, "\t$Rn, $Rm, $nzcv, $cond", "", []>,
3564       Sched<[WriteFCmp]> {
3565   bits<5> Rn;
3566   bits<5> Rm;
3567   bits<4> nzcv;
3568   bits<4> cond;
3569
3570   let Inst{31-23} = 0b000111100;
3571   let Inst{21}    = 1;
3572   let Inst{20-16} = Rm;
3573   let Inst{15-12} = cond;
3574   let Inst{11-10} = 0b01;
3575   let Inst{9-5}   = Rn;
3576   let Inst{4}     = signalAllNans;
3577   let Inst{3-0}   = nzcv;
3578 }
3579
3580 multiclass FPCondComparison<bit signalAllNans, string asm> {
3581   let Defs = [CPSR], Uses = [CPSR] in {
3582   def Srr : BaseFPCondComparison<signalAllNans, FPR32, asm> {
3583     let Inst{22} = 0;
3584   }
3585
3586   def Drr : BaseFPCondComparison<signalAllNans, FPR64, asm> {
3587     let Inst{22} = 1;
3588   }
3589   } // Defs = [CPSR], Uses = [CPSR]
3590 }
3591
3592 //---
3593 // Floating point conditional select
3594 //---
3595
3596 class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
3597     : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3598          asm, "\t$Rd, $Rn, $Rm, $cond", "",
3599          [(set regtype:$Rd,
3600                (ARM64csel (vt regtype:$Rn), regtype:$Rm,
3601                           (i32 imm:$cond), CPSR))]>,
3602       Sched<[WriteF]> {
3603   bits<5> Rd;
3604   bits<5> Rn;
3605   bits<5> Rm;
3606   bits<4> cond;
3607
3608   let Inst{31-23} = 0b000111100;
3609   let Inst{21}    = 1;
3610   let Inst{20-16} = Rm;
3611   let Inst{15-12} = cond;
3612   let Inst{11-10} = 0b11;
3613   let Inst{9-5}   = Rn;
3614   let Inst{4-0}   = Rd;
3615 }
3616
3617 multiclass FPCondSelect<string asm> {
3618   let Uses = [CPSR] in {
3619   def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
3620     let Inst{22} = 0;
3621   }
3622
3623   def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
3624     let Inst{22} = 1;
3625   }
3626   } // Uses = [CPSR]
3627 }
3628
3629 //---
3630 // Floating move immediate
3631 //---
3632
3633 class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
3634   : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
3635       [(set regtype:$Rd, fpimmtype:$imm)]>,
3636     Sched<[WriteFImm]> {
3637   bits<5> Rd;
3638   bits<8> imm;
3639   let Inst{31-23} = 0b000111100;
3640   let Inst{21}    = 1;
3641   let Inst{20-13} = imm;
3642   let Inst{12-5}  = 0b10000000;
3643   let Inst{4-0}   = Rd;
3644 }
3645
3646 multiclass FPMoveImmediate<string asm> {
3647   def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
3648     let Inst{22} = 0;
3649   }
3650
3651   def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
3652     let Inst{22} = 1;
3653   }
3654 }
3655
3656 //----------------------------------------------------------------------------
3657 // AdvSIMD
3658 //----------------------------------------------------------------------------
3659
3660 def VectorIndexBOperand : AsmOperandClass { let Name = "VectorIndexB"; }
3661 def VectorIndexHOperand : AsmOperandClass { let Name = "VectorIndexH"; }
3662 def VectorIndexSOperand : AsmOperandClass { let Name = "VectorIndexS"; }
3663 def VectorIndexDOperand : AsmOperandClass { let Name = "VectorIndexD"; }
3664 def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
3665   return ((uint64_t)Imm) < 16;
3666 }]> {
3667   let ParserMatchClass = VectorIndexBOperand;
3668   let PrintMethod = "printVectorIndex";
3669   let MIOperandInfo = (ops i64imm);
3670 }
3671 def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
3672   return ((uint64_t)Imm) < 8;
3673 }]> {
3674   let ParserMatchClass = VectorIndexHOperand;
3675   let PrintMethod = "printVectorIndex";
3676   let MIOperandInfo = (ops i64imm);
3677 }
3678 def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
3679   return ((uint64_t)Imm) < 4;
3680 }]> {
3681   let ParserMatchClass = VectorIndexSOperand;
3682   let PrintMethod = "printVectorIndex";
3683   let MIOperandInfo = (ops i64imm);
3684 }
3685 def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
3686   return ((uint64_t)Imm) < 2;
3687 }]> {
3688   let ParserMatchClass = VectorIndexDOperand;
3689   let PrintMethod = "printVectorIndex";
3690   let MIOperandInfo = (ops i64imm);
3691 }
3692
3693 //----------------------------------------------------------------------------
3694 // AdvSIMD three register vector instructions
3695 //----------------------------------------------------------------------------
3696
3697 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3698 class BaseSIMDThreeSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3699                         RegisterOperand regtype, string asm, string kind,
3700                         list<dag> pattern>
3701   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
3702       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3703       "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
3704     Sched<[WriteV]> {
3705   bits<5> Rd;
3706   bits<5> Rn;
3707   bits<5> Rm;
3708   let Inst{31}    = 0;
3709   let Inst{30}    = Q;
3710   let Inst{29}    = U;
3711   let Inst{28-24} = 0b01110;
3712   let Inst{23-22} = size;
3713   let Inst{21}    = 1;
3714   let Inst{20-16} = Rm;
3715   let Inst{15-11} = opcode;
3716   let Inst{10}    = 1;
3717   let Inst{9-5}   = Rn;
3718   let Inst{4-0}   = Rd;
3719 }
3720
3721 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3722 class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3723                         RegisterOperand regtype, string asm, string kind,
3724                         list<dag> pattern>
3725   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
3726       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
3727       "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
3728     Sched<[WriteV]> {
3729   bits<5> Rd;
3730   bits<5> Rn;
3731   bits<5> Rm;
3732   let Inst{31}    = 0;
3733   let Inst{30}    = Q;
3734   let Inst{29}    = U;
3735   let Inst{28-24} = 0b01110;
3736   let Inst{23-22} = size;
3737   let Inst{21}    = 1;
3738   let Inst{20-16} = Rm;
3739   let Inst{15-11} = opcode;
3740   let Inst{10}    = 1;
3741   let Inst{9-5}   = Rn;
3742   let Inst{4-0}   = Rd;
3743 }
3744
3745 // All operand sizes distinguished in the encoding.
3746 multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
3747                                SDPatternOperator OpNode> {
3748   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3749                                       asm, ".8b",
3750          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3751   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3752                                       asm, ".16b",
3753          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3754   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3755                                       asm, ".4h",
3756          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3757   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3758                                       asm, ".8h",
3759          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3760   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3761                                       asm, ".2s",
3762          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3763   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3764                                       asm, ".4s",
3765          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3766   def v2i64 : BaseSIMDThreeSameVector<1, U, 0b11, opc, V128,
3767                                       asm, ".2d",
3768          [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
3769 }
3770
3771 // As above, but D sized elements unsupported.
3772 multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
3773                                   SDPatternOperator OpNode> {
3774   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3775                                       asm, ".8b",
3776         [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
3777   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3778                                       asm, ".16b",
3779         [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
3780   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3781                                       asm, ".4h",
3782         [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
3783   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3784                                       asm, ".8h",
3785         [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
3786   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3787                                       asm, ".2s",
3788         [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
3789   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3790                                       asm, ".4s",
3791         [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
3792 }
3793
3794 multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
3795                                   SDPatternOperator OpNode> {
3796   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b00, opc, V64,
3797                                       asm, ".8b",
3798       [(set (v8i8 V64:$dst),
3799             (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3800   def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b00, opc, V128,
3801                                       asm, ".16b",
3802       [(set (v16i8 V128:$dst),
3803             (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3804   def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b01, opc, V64,
3805                                       asm, ".4h",
3806       [(set (v4i16 V64:$dst),
3807             (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3808   def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b01, opc, V128,
3809                                       asm, ".8h",
3810       [(set (v8i16 V128:$dst),
3811             (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3812   def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b10, opc, V64,
3813                                       asm, ".2s",
3814       [(set (v2i32 V64:$dst),
3815             (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3816   def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b10, opc, V128,
3817                                       asm, ".4s",
3818       [(set (v4i32 V128:$dst),
3819             (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3820 }
3821
3822 // As above, but only B sized elements supported.
3823 multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
3824                                 SDPatternOperator OpNode> {
3825   def v8i8  : BaseSIMDThreeSameVector<0, U, 0b00, opc, V64,
3826                                       asm, ".8b",
3827     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3828   def v16i8 : BaseSIMDThreeSameVector<1, U, 0b00, opc, V128,
3829                                       asm, ".16b",
3830     [(set (v16i8 V128:$Rd),
3831           (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
3832 }
3833
3834 // As above, but only S and D sized floating point elements supported.
3835 multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<5> opc,
3836                                  string asm, SDPatternOperator OpNode> {
3837   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3838                                       asm, ".2s",
3839         [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3840   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3841                                       asm, ".4s",
3842         [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3843   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3844                                       asm, ".2d",
3845         [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3846 }
3847
3848 multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<5> opc,
3849                                     string asm,
3850                                     SDPatternOperator OpNode> {
3851   def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0}, opc, V64,
3852                                       asm, ".2s",
3853         [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3854   def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0}, opc, V128,
3855                                       asm, ".4s",
3856         [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3857   def v2f64 : BaseSIMDThreeSameVector<1, U, {S,1}, opc, V128,
3858                                       asm, ".2d",
3859         [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3860 }
3861
3862 multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<5> opc,
3863                                  string asm, SDPatternOperator OpNode> {
3864   def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0}, opc, V64,
3865                                       asm, ".2s",
3866      [(set (v2f32 V64:$dst),
3867            (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
3868   def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0}, opc, V128,
3869                                       asm, ".4s",
3870      [(set (v4f32 V128:$dst),
3871            (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
3872   def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,1}, opc, V128,
3873                                       asm, ".2d",
3874      [(set (v2f64 V128:$dst),
3875            (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
3876 }
3877
3878 // As above, but D and B sized elements unsupported.
3879 multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
3880                                 SDPatternOperator OpNode> {
3881   def v4i16 : BaseSIMDThreeSameVector<0, U, 0b01, opc, V64,
3882                                       asm, ".4h",
3883         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
3884   def v8i16 : BaseSIMDThreeSameVector<1, U, 0b01, opc, V128,
3885                                       asm, ".8h",
3886         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
3887   def v2i32 : BaseSIMDThreeSameVector<0, U, 0b10, opc, V64,
3888                                       asm, ".2s",
3889         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
3890   def v4i32 : BaseSIMDThreeSameVector<1, U, 0b10, opc, V128,
3891                                       asm, ".4s",
3892         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
3893 }
3894
3895 // Logical three vector ops share opcode bits, and only use B sized elements.
3896 multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
3897                                   SDPatternOperator OpNode = null_frag> {
3898   def v8i8  : BaseSIMDThreeSameVector<0, U, size, 0b00011, V64,
3899                                      asm, ".8b",
3900                          [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
3901   def v16i8  : BaseSIMDThreeSameVector<1, U, size, 0b00011, V128,
3902                                      asm, ".16b",
3903                          [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
3904
3905   def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
3906           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3907   def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
3908           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3909   def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
3910           (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
3911
3912   def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
3913       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3914   def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
3915       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3916   def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
3917       (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
3918 }
3919
3920 multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
3921                                   string asm, SDPatternOperator OpNode> {
3922   def v8i8  : BaseSIMDThreeSameVectorTied<0, U, size, 0b00011, V64,
3923                                      asm, ".8b",
3924              [(set (v8i8 V64:$dst),
3925                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
3926   def v16i8  : BaseSIMDThreeSameVectorTied<1, U, size, 0b00011, V128,
3927                                      asm, ".16b",
3928              [(set (v16i8 V128:$dst),
3929                    (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
3930                            (v16i8 V128:$Rm)))]>;
3931
3932   def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
3933                            (v4i16 V64:$RHS))),
3934           (!cast<Instruction>(NAME#"v8i8")
3935             V64:$LHS, V64:$MHS, V64:$RHS)>;
3936   def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
3937                            (v2i32 V64:$RHS))),
3938           (!cast<Instruction>(NAME#"v8i8")
3939             V64:$LHS, V64:$MHS, V64:$RHS)>;
3940   def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
3941                            (v1i64 V64:$RHS))),
3942           (!cast<Instruction>(NAME#"v8i8")
3943             V64:$LHS, V64:$MHS, V64:$RHS)>;
3944
3945   def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
3946                            (v8i16 V128:$RHS))),
3947       (!cast<Instruction>(NAME#"v16i8")
3948         V128:$LHS, V128:$MHS, V128:$RHS)>;
3949   def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
3950                            (v4i32 V128:$RHS))),
3951       (!cast<Instruction>(NAME#"v16i8")
3952         V128:$LHS, V128:$MHS, V128:$RHS)>;
3953   def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
3954                            (v2i64 V128:$RHS))),
3955       (!cast<Instruction>(NAME#"v16i8")
3956         V128:$LHS, V128:$MHS, V128:$RHS)>;
3957 }
3958
3959
3960 //----------------------------------------------------------------------------
3961 // AdvSIMD two register vector instructions.
3962 //----------------------------------------------------------------------------
3963
3964 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3965 class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
3966                         RegisterOperand regtype, string asm, string dstkind,
3967                         string srckind, list<dag> pattern>
3968   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
3969       "{\t$Rd" # dstkind # ", $Rn" # srckind #
3970       "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
3971     Sched<[WriteV]> {
3972   bits<5> Rd;
3973   bits<5> Rn;
3974   let Inst{31}    = 0;
3975   let Inst{30}    = Q;
3976   let Inst{29}    = U;
3977   let Inst{28-24} = 0b01110;
3978   let Inst{23-22} = size;
3979   let Inst{21-17} = 0b10000;
3980   let Inst{16-12} = opcode;
3981   let Inst{11-10} = 0b10;
3982   let Inst{9-5}   = Rn;
3983   let Inst{4-0}   = Rd;
3984 }
3985
3986 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3987 class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
3988                             RegisterOperand regtype, string asm, string dstkind,
3989                             string srckind, list<dag> pattern>
3990   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
3991       "{\t$Rd" # dstkind # ", $Rn" # srckind #
3992       "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
3993     Sched<[WriteV]> {
3994   bits<5> Rd;
3995   bits<5> Rn;
3996   let Inst{31}    = 0;
3997   let Inst{30}    = Q;
3998   let Inst{29}    = U;
3999   let Inst{28-24} = 0b01110;
4000   let Inst{23-22} = size;
4001   let Inst{21-17} = 0b10000;
4002   let Inst{16-12} = opcode;
4003   let Inst{11-10} = 0b10;
4004   let Inst{9-5}   = Rn;
4005   let Inst{4-0}   = Rd;
4006 }
4007
4008 // Supports B, H, and S element sizes.
4009 multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4010                             SDPatternOperator OpNode> {
4011   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4012                                       asm, ".8b", ".8b",
4013                           [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4014   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4015                                       asm, ".16b", ".16b",
4016                           [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4017   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4018                                       asm, ".4h", ".4h",
4019                           [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4020   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4021                                       asm, ".8h", ".8h",
4022                           [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4023   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4024                                       asm, ".2s", ".2s",
4025                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4026   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4027                                       asm, ".4s", ".4s",
4028                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4029 }
4030
4031 class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4032                             RegisterOperand regtype, string asm, string dstkind,
4033                             string srckind, string amount>
4034   : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4035       "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4036       "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4037     Sched<[WriteV]> {
4038   bits<5> Rd;
4039   bits<5> Rn;
4040   let Inst{31}    = 0;
4041   let Inst{30}    = Q;
4042   let Inst{29-24} = 0b101110;
4043   let Inst{23-22} = size;
4044   let Inst{21-10} = 0b100001001110;
4045   let Inst{9-5}   = Rn;
4046   let Inst{4-0}   = Rd;
4047 }
4048
4049 multiclass SIMDVectorLShiftLongBySizeBHS {
4050   let neverHasSideEffects = 1 in {
4051   def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4052                                              "shll", ".8h",  ".8b", "8">;
4053   def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4054                                              "shll2", ".8h", ".16b", "8">;
4055   def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4056                                              "shll", ".4s",  ".4h", "16">;
4057   def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4058                                              "shll2", ".4s", ".8h", "16">;
4059   def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4060                                              "shll", ".2d",  ".2s", "32">;
4061   def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4062                                              "shll2", ".2d", ".4s", "32">;
4063   }
4064 }
4065
4066 // Supports all element sizes.
4067 multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4068                              SDPatternOperator OpNode> {
4069   def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4070                                       asm, ".4h", ".8b",
4071                [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4072   def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4073                                       asm, ".8h", ".16b",
4074                [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4075   def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4076                                       asm, ".2s", ".4h",
4077                [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4078   def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4079                                       asm, ".4s", ".8h",
4080                [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4081   def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4082                                       asm, ".1d", ".2s",
4083                [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4084   def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4085                                       asm, ".2d", ".4s",
4086                [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4087 }
4088
4089 multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4090                                  SDPatternOperator OpNode> {
4091   def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4092                                           asm, ".4h", ".8b",
4093       [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4094                                       (v8i8 V64:$Rn)))]>;
4095   def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4096                                           asm, ".8h", ".16b",
4097       [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4098                                       (v16i8 V128:$Rn)))]>;
4099   def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4100                                           asm, ".2s", ".4h",
4101       [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4102                                       (v4i16 V64:$Rn)))]>;
4103   def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4104                                           asm, ".4s", ".8h",
4105       [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4106                                       (v8i16 V128:$Rn)))]>;
4107   def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4108                                           asm, ".1d", ".2s",
4109       [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4110                                       (v2i32 V64:$Rn)))]>;
4111   def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4112                                           asm, ".2d", ".4s",
4113       [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4114                                       (v4i32 V128:$Rn)))]>;
4115 }
4116
4117 // Supports all element sizes, except 1xD.
4118 multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4119                                   SDPatternOperator OpNode> {
4120   def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, V64,
4121                                     asm, ".8b", ".8b",
4122     [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4123   def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, V128,
4124                                     asm, ".16b", ".16b",
4125     [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4126   def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, V64,
4127                                     asm, ".4h", ".4h",
4128     [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4129   def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, V128,
4130                                     asm, ".8h", ".8h",
4131     [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4132   def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, V64,
4133                                     asm, ".2s", ".2s",
4134     [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4135   def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, V128,
4136                                     asm, ".4s", ".4s",
4137     [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4138   def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, V128,
4139                                     asm, ".2d", ".2d",
4140     [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4141 }
4142
4143 multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4144                              SDPatternOperator OpNode = null_frag> {
4145   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4146                                 asm, ".8b", ".8b",
4147     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4148   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4149                                 asm, ".16b", ".16b",
4150     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4151   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4152                                 asm, ".4h", ".4h",
4153     [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4154   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4155                                 asm, ".8h", ".8h",
4156     [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4157   def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, V64,
4158                                 asm, ".2s", ".2s",
4159     [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4160   def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, V128,
4161                                 asm, ".4s", ".4s",
4162     [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4163   def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, V128,
4164                                 asm, ".2d", ".2d",
4165     [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4166 }
4167
4168
4169 // Supports only B element sizes.
4170 multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4171                           SDPatternOperator OpNode> {
4172   def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, V64,
4173                                 asm, ".8b", ".8b",
4174                     [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4175   def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, V128,
4176                                 asm, ".16b", ".16b",
4177                     [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4178
4179 }
4180
4181 // Supports only B and H element sizes.
4182 multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4183                                 SDPatternOperator OpNode> {
4184   def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, V64,
4185                                 asm, ".8b", ".8b",
4186                     [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4187   def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, V128,
4188                                 asm, ".16b", ".16b",
4189                     [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4190   def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, V64,
4191                                 asm, ".4h", ".4h",
4192                     [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4193   def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, V128,
4194                                 asm, ".8h", ".8h",
4195                     [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4196 }
4197
4198 // Supports only S and D element sizes, uses high bit of the size field
4199 // as an extra opcode bit.
4200 multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4201                            SDPatternOperator OpNode> {
4202   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4203                                 asm, ".2s", ".2s",
4204                           [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4205   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4206                                 asm, ".4s", ".4s",
4207                           [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4208   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4209                                 asm, ".2d", ".2d",
4210                           [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4211 }
4212
4213 // Supports only S element size.
4214 multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4215                            SDPatternOperator OpNode> {
4216   def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4217                                 asm, ".2s", ".2s",
4218                           [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4219   def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4220                                 asm, ".4s", ".4s",
4221                           [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4222 }
4223
4224
4225 multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4226                            SDPatternOperator OpNode> {
4227   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4228                                 asm, ".2s", ".2s",
4229                           [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4230   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4231                                 asm, ".4s", ".4s",
4232                           [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4233   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4234                                 asm, ".2d", ".2d",
4235                           [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4236 }
4237
4238 multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4239                            SDPatternOperator OpNode> {
4240   def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, V64,
4241                                 asm, ".2s", ".2s",
4242                           [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4243   def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, V128,
4244                                 asm, ".4s", ".4s",
4245                           [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4246   def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, V128,
4247                                 asm, ".2d", ".2d",
4248                           [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4249 }
4250
4251
4252 class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4253                            RegisterOperand inreg, RegisterOperand outreg,
4254                            string asm, string outkind, string inkind,
4255                            list<dag> pattern>
4256   : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4257       "{\t$Rd" # outkind # ", $Rn" # inkind #
4258       "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4259     Sched<[WriteV]> {
4260   bits<5> Rd;
4261   bits<5> Rn;
4262   let Inst{31}    = 0;
4263   let Inst{30}    = Q;
4264   let Inst{29}    = U;
4265   let Inst{28-24} = 0b01110;
4266   let Inst{23-22} = size;
4267   let Inst{21-17} = 0b10000;
4268   let Inst{16-12} = opcode;
4269   let Inst{11-10} = 0b10;
4270   let Inst{9-5}   = Rn;
4271   let Inst{4-0}   = Rd;
4272 }
4273
4274 class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4275                            RegisterOperand inreg, RegisterOperand outreg,
4276                            string asm, string outkind, string inkind,
4277                            list<dag> pattern>
4278   : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4279       "{\t$Rd" # outkind # ", $Rn" # inkind #
4280       "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4281     Sched<[WriteV]> {
4282   bits<5> Rd;
4283   bits<5> Rn;
4284   let Inst{31}    = 0;
4285   let Inst{30}    = Q;
4286   let Inst{29}    = U;
4287   let Inst{28-24} = 0b01110;
4288   let Inst{23-22} = size;
4289   let Inst{21-17} = 0b10000;
4290   let Inst{16-12} = opcode;
4291   let Inst{11-10} = 0b10;
4292   let Inst{9-5}   = Rn;
4293   let Inst{4-0}   = Rd;
4294 }
4295
4296 multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4297                               SDPatternOperator OpNode> {
4298   def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4299                                       asm, ".8b", ".8h",
4300         [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4301   def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4302                                       asm#"2", ".16b", ".8h", []>;
4303   def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4304                                       asm, ".4h", ".4s",
4305         [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4306   def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4307                                       asm#"2", ".8h", ".4s", []>;
4308   def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4309                                       asm, ".2s", ".2d",
4310         [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4311   def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4312                                       asm#"2", ".4s", ".2d", []>;
4313
4314   def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4315             (!cast<Instruction>(NAME # "v16i8")
4316                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4317   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4318             (!cast<Instruction>(NAME # "v8i16")
4319                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4320   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4321             (!cast<Instruction>(NAME # "v4i32")
4322                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4323 }
4324
4325 class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4326                            RegisterOperand regtype, string asm, string kind,
4327                            ValueType dty, ValueType sty, SDNode OpNode>
4328   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4329       "{\t$Rd" # kind # ", $Rn" # kind # ", #0" #
4330       "|" # kind # "\t$Rd, $Rn, #0}", "",
4331       [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
4332     Sched<[WriteV]> {
4333   bits<5> Rd;
4334   bits<5> Rn;
4335   let Inst{31}    = 0;
4336   let Inst{30}    = Q;
4337   let Inst{29}    = U;
4338   let Inst{28-24} = 0b01110;
4339   let Inst{23-22} = size;
4340   let Inst{21-17} = 0b10000;
4341   let Inst{16-12} = opcode;
4342   let Inst{11-10} = 0b10;
4343   let Inst{9-5}   = Rn;
4344   let Inst{4-0}   = Rd;
4345 }
4346
4347 // Comparisons support all element sizes, except 1xD.
4348 multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
4349                             SDNode OpNode> {
4350   def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, opc, V64,
4351                                      asm, ".8b",
4352                                      v8i8, v8i8, OpNode>;
4353   def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, opc, V128,
4354                                      asm, ".16b",
4355                                      v16i8, v16i8, OpNode>;
4356   def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, opc, V64,
4357                                      asm, ".4h",
4358                                      v4i16, v4i16, OpNode>;
4359   def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, opc, V128,
4360                                      asm, ".8h",
4361                                      v8i16, v8i16, OpNode>;
4362   def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, opc, V64,
4363                                      asm, ".2s",
4364                                      v2i32, v2i32, OpNode>;
4365   def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, opc, V128,
4366                                      asm, ".4s",
4367                                      v4i32, v4i32, OpNode>;
4368   def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, opc, V128,
4369                                      asm, ".2d",
4370                                      v2i64, v2i64, OpNode>;
4371 }
4372
4373 // FP Comparisons support only S and D element sizes.
4374 multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
4375                               string asm, SDNode OpNode> {
4376   def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, opc, V64,
4377                                      asm, ".2s",
4378                                      v2i32, v2f32, OpNode>;
4379   def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, opc, V128,
4380                                      asm, ".4s",
4381                                      v4i32, v4f32, OpNode>;
4382   def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, opc, V128,
4383                                      asm, ".2d",
4384                                      v2i64, v2f64, OpNode>;
4385 }
4386
4387 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4388 class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4389                              RegisterOperand outtype, RegisterOperand intype,
4390                              string asm, string VdTy, string VnTy,
4391                              list<dag> pattern>
4392   : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
4393       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
4394     Sched<[WriteV]> {
4395   bits<5> Rd;
4396   bits<5> Rn;
4397   let Inst{31}    = 0;
4398   let Inst{30}    = Q;
4399   let Inst{29}    = U;
4400   let Inst{28-24} = 0b01110;
4401   let Inst{23-22} = size;
4402   let Inst{21-17} = 0b10000;
4403   let Inst{16-12} = opcode;
4404   let Inst{11-10} = 0b10;
4405   let Inst{9-5}   = Rn;
4406   let Inst{4-0}   = Rd;
4407 }
4408
4409 class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4410                              RegisterOperand outtype, RegisterOperand intype,
4411                              string asm, string VdTy, string VnTy,
4412                              list<dag> pattern>
4413   : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
4414       !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
4415     Sched<[WriteV]> {
4416   bits<5> Rd;
4417   bits<5> Rn;
4418   let Inst{31}    = 0;
4419   let Inst{30}    = Q;
4420   let Inst{29}    = U;
4421   let Inst{28-24} = 0b01110;
4422   let Inst{23-22} = size;
4423   let Inst{21-17} = 0b10000;
4424   let Inst{16-12} = opcode;
4425   let Inst{11-10} = 0b10;
4426   let Inst{9-5}   = Rn;
4427   let Inst{4-0}   = Rd;
4428 }
4429
4430 multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
4431   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
4432                                     asm, ".4s", ".4h", []>;
4433   def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
4434                                     asm#"2", ".4s", ".8h", []>;
4435   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
4436                                     asm, ".2d", ".2s", []>;
4437   def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
4438                                     asm#"2", ".2d", ".4s", []>;
4439 }
4440
4441 multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
4442   def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
4443                                     asm, ".4h", ".4s", []>;
4444   def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
4445                                     asm#"2", ".8h", ".4s", []>;
4446   def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4447                                     asm, ".2s", ".2d", []>;
4448   def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4449                                     asm#"2", ".4s", ".2d", []>;
4450 }
4451
4452 multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
4453                                      Intrinsic OpNode> {
4454   def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
4455                                      asm, ".2s", ".2d",
4456                           [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4457   def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
4458                                     asm#"2", ".4s", ".2d", []>;
4459
4460   def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
4461             (!cast<Instruction>(NAME # "v4f32")
4462                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4463 }
4464
4465 //----------------------------------------------------------------------------
4466 // AdvSIMD three register different-size vector instructions.
4467 //----------------------------------------------------------------------------
4468
4469 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4470 class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
4471                       RegisterOperand outtype, RegisterOperand intype1,
4472                       RegisterOperand intype2, string asm,
4473                       string outkind, string inkind1, string inkind2,
4474                       list<dag> pattern>
4475   : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
4476       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4477       "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
4478     Sched<[WriteV]> {
4479   bits<5> Rd;
4480   bits<5> Rn;
4481   bits<5> Rm;
4482   let Inst{31}    = 0;
4483   let Inst{30}    = size{0};
4484   let Inst{29}    = U;
4485   let Inst{28-24} = 0b01110;
4486   let Inst{23-22} = size{2-1};
4487   let Inst{21}    = 1;
4488   let Inst{20-16} = Rm;
4489   let Inst{15-12} = opcode;
4490   let Inst{11-10} = 0b00;
4491   let Inst{9-5}   = Rn;
4492   let Inst{4-0}   = Rd;
4493 }
4494
4495 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4496 class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
4497                       RegisterOperand outtype, RegisterOperand intype1,
4498                       RegisterOperand intype2, string asm,
4499                       string outkind, string inkind1, string inkind2,
4500                       list<dag> pattern>
4501   : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
4502       "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
4503       "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4504     Sched<[WriteV]> {
4505   bits<5> Rd;
4506   bits<5> Rn;
4507   bits<5> Rm;
4508   let Inst{31}    = 0;
4509   let Inst{30}    = size{0};
4510   let Inst{29}    = U;
4511   let Inst{28-24} = 0b01110;
4512   let Inst{23-22} = size{2-1};
4513   let Inst{21}    = 1;
4514   let Inst{20-16} = Rm;
4515   let Inst{15-12} = opcode;
4516   let Inst{11-10} = 0b00;
4517   let Inst{9-5}   = Rn;
4518   let Inst{4-0}   = Rd;
4519 }
4520
4521 // FIXME: TableGen doesn't know how to deal with expanded types that also
4522 //        change the element count (in this case, placing the results in
4523 //        the high elements of the result register rather than the low
4524 //        elements). Until that's fixed, we can't code-gen those.
4525 multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
4526                                     Intrinsic IntOp> {
4527   def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4528                                                   V64, V128, V128,
4529                                                   asm, ".8b", ".8h", ".8h",
4530      [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4531   def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4532                                                   V128, V128, V128,
4533                                                   asm#"2", ".16b", ".8h", ".8h",
4534      []>;
4535   def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4536                                                   V64, V128, V128,
4537                                                   asm, ".4h", ".4s", ".4s",
4538      [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4539   def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4540                                                   V128, V128, V128,
4541                                                   asm#"2", ".8h", ".4s", ".4s",
4542      []>;
4543   def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4544                                                   V64, V128, V128,
4545                                                   asm, ".2s", ".2d", ".2d",
4546      [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4547   def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4548                                                   V128, V128, V128,
4549                                                   asm#"2", ".4s", ".2d", ".2d",
4550      []>;
4551
4552
4553   // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
4554   // a version attached to an instruction.
4555   def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
4556                                                    (v8i16 V128:$Rm))),
4557             (!cast<Instruction>(NAME # "v8i16_v16i8")
4558                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4559                 V128:$Rn, V128:$Rm)>;
4560   def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
4561                                                     (v4i32 V128:$Rm))),
4562             (!cast<Instruction>(NAME # "v4i32_v8i16")
4563                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4564                 V128:$Rn, V128:$Rm)>;
4565   def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
4566                                                     (v2i64 V128:$Rm))),
4567             (!cast<Instruction>(NAME # "v2i64_v4i32")
4568                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
4569                 V128:$Rn, V128:$Rm)>;
4570 }
4571
4572 multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
4573                                       Intrinsic IntOp> {
4574   def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4575                                             V128, V64, V64,
4576                                             asm, ".8h", ".8b", ".8b",
4577       [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4578   def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4579                                             V128, V128, V128,
4580                                             asm#"2", ".8h", ".16b", ".16b", []>;
4581   def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
4582                                             V128, V64, V64,
4583                                             asm, ".1q", ".1d", ".1d", []>;
4584   def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
4585                                             V128, V128, V128,
4586                                             asm#"2", ".1q", ".2d", ".2d", []>;
4587
4588   def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
4589                           (v8i8 (extract_high_v16i8 V128:$Rm)))),
4590       (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
4591 }
4592
4593 multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
4594                                  SDPatternOperator OpNode> {
4595   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4596                                                   V128, V64, V64,
4597                                                   asm, ".4s", ".4h", ".4h",
4598       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4599   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4600                                                   V128, V128, V128,
4601                                                   asm#"2", ".4s", ".8h", ".8h",
4602       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4603                                       (extract_high_v8i16 V128:$Rm)))]>;
4604   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4605                                                   V128, V64, V64,
4606                                                   asm, ".2d", ".2s", ".2s",
4607       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4608   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4609                                                   V128, V128, V128,
4610                                                   asm#"2", ".2d", ".4s", ".4s",
4611       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4612                                       (extract_high_v4i32 V128:$Rm)))]>;
4613 }
4614
4615 multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
4616                                   SDPatternOperator OpNode = null_frag> {
4617   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4618                                                   V128, V64, V64,
4619                                                   asm, ".8h", ".8b", ".8b",
4620       [(set (v8i16 V128:$Rd),
4621             (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
4622   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4623                                                  V128, V128, V128,
4624                                                  asm#"2", ".8h", ".16b", ".16b",
4625       [(set (v8i16 V128:$Rd),
4626             (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4627                                 (extract_high_v16i8 V128:$Rm)))))]>;
4628   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4629                                                   V128, V64, V64,
4630                                                   asm, ".4s", ".4h", ".4h",
4631       [(set (v4i32 V128:$Rd),
4632             (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
4633   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4634                                                   V128, V128, V128,
4635                                                   asm#"2", ".4s", ".8h", ".8h",
4636       [(set (v4i32 V128:$Rd),
4637             (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4638                                   (extract_high_v8i16 V128:$Rm)))))]>;
4639   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4640                                                   V128, V64, V64,
4641                                                   asm, ".2d", ".2s", ".2s",
4642       [(set (v2i64 V128:$Rd),
4643             (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
4644   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4645                                                   V128, V128, V128,
4646                                                   asm#"2", ".2d", ".4s", ".4s",
4647       [(set (v2i64 V128:$Rd),
4648             (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4649                                  (extract_high_v4i32 V128:$Rm)))))]>;
4650 }
4651
4652 multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
4653                                           string asm,
4654                                           SDPatternOperator OpNode> {
4655   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4656                                                   V128, V64, V64,
4657                                                   asm, ".8h", ".8b", ".8b",
4658     [(set (v8i16 V128:$dst),
4659           (add (v8i16 V128:$Rd),
4660                (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
4661   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4662                                                  V128, V128, V128,
4663                                                  asm#"2", ".8h", ".16b", ".16b",
4664     [(set (v8i16 V128:$dst),
4665           (add (v8i16 V128:$Rd),
4666                (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
4667                                    (extract_high_v16i8 V128:$Rm))))))]>;
4668   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4669                                                   V128, V64, V64,
4670                                                   asm, ".4s", ".4h", ".4h",
4671     [(set (v4i32 V128:$dst),
4672           (add (v4i32 V128:$Rd),
4673                (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
4674   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4675                                                   V128, V128, V128,
4676                                                   asm#"2", ".4s", ".8h", ".8h",
4677     [(set (v4i32 V128:$dst),
4678           (add (v4i32 V128:$Rd),
4679                (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
4680                                     (extract_high_v8i16 V128:$Rm))))))]>;
4681   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4682                                                   V128, V64, V64,
4683                                                   asm, ".2d", ".2s", ".2s",
4684     [(set (v2i64 V128:$dst),
4685           (add (v2i64 V128:$Rd),
4686                (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
4687   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4688                                                   V128, V128, V128,
4689                                                   asm#"2", ".2d", ".4s", ".4s",
4690     [(set (v2i64 V128:$dst),
4691           (add (v2i64 V128:$Rd),
4692                (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
4693                                     (extract_high_v4i32 V128:$Rm))))))]>;
4694 }
4695
4696 multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
4697                                   SDPatternOperator OpNode = null_frag> {
4698   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4699                                                   V128, V64, V64,
4700                                                   asm, ".8h", ".8b", ".8b",
4701       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4702   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4703                                                  V128, V128, V128,
4704                                                  asm#"2", ".8h", ".16b", ".16b",
4705       [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
4706                                       (extract_high_v16i8 V128:$Rm)))]>;
4707   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4708                                                   V128, V64, V64,
4709                                                   asm, ".4s", ".4h", ".4h",
4710       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4711   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4712                                                   V128, V128, V128,
4713                                                   asm#"2", ".4s", ".8h", ".8h",
4714       [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
4715                                       (extract_high_v8i16 V128:$Rm)))]>;
4716   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4717                                                   V128, V64, V64,
4718                                                   asm, ".2d", ".2s", ".2s",
4719       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4720   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4721                                                   V128, V128, V128,
4722                                                   asm#"2", ".2d", ".4s", ".4s",
4723       [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
4724                                       (extract_high_v4i32 V128:$Rm)))]>;
4725 }
4726
4727 multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
4728                                       string asm,
4729                                       SDPatternOperator OpNode> {
4730   def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
4731                                                   V128, V64, V64,
4732                                                   asm, ".8h", ".8b", ".8b",
4733     [(set (v8i16 V128:$dst),
4734           (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4735   def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
4736                                                  V128, V128, V128,
4737                                                  asm#"2", ".8h", ".16b", ".16b",
4738     [(set (v8i16 V128:$dst),
4739           (OpNode (v8i16 V128:$Rd),
4740                   (extract_high_v16i8 V128:$Rn),
4741                   (extract_high_v16i8 V128:$Rm)))]>;
4742   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4743                                                   V128, V64, V64,
4744                                                   asm, ".4s", ".4h", ".4h",
4745     [(set (v4i32 V128:$dst),
4746           (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4747   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4748                                                   V128, V128, V128,
4749                                                   asm#"2", ".4s", ".8h", ".8h",
4750     [(set (v4i32 V128:$dst),
4751           (OpNode (v4i32 V128:$Rd),
4752                   (extract_high_v8i16 V128:$Rn),
4753                   (extract_high_v8i16 V128:$Rm)))]>;
4754   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4755                                                   V128, V64, V64,
4756                                                   asm, ".2d", ".2s", ".2s",
4757     [(set (v2i64 V128:$dst),
4758           (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4759   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4760                                                   V128, V128, V128,
4761                                                   asm#"2", ".2d", ".4s", ".4s",
4762     [(set (v2i64 V128:$dst),
4763           (OpNode (v2i64 V128:$Rd),
4764                   (extract_high_v4i32 V128:$Rn),
4765                   (extract_high_v4i32 V128:$Rm)))]>;
4766 }
4767
4768 multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
4769                                            SDPatternOperator Accum> {
4770   def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
4771                                                   V128, V64, V64,
4772                                                   asm, ".4s", ".4h", ".4h",
4773     [(set (v4i32 V128:$dst),
4774           (Accum (v4i32 V128:$Rd),
4775                  (v4i32 (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
4776                                                 (v4i16 V64:$Rm)))))]>;
4777   def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
4778                                                   V128, V128, V128,
4779                                                   asm#"2", ".4s", ".8h", ".8h",
4780     [(set (v4i32 V128:$dst),
4781           (Accum (v4i32 V128:$Rd),
4782                  (v4i32 (int_arm64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
4783                                             (extract_high_v8i16 V128:$Rm)))))]>;
4784   def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
4785                                                   V128, V64, V64,
4786                                                   asm, ".2d", ".2s", ".2s",
4787     [(set (v2i64 V128:$dst),
4788           (Accum (v2i64 V128:$Rd),
4789                  (v2i64 (int_arm64_neon_sqdmull (v2i32 V64:$Rn),
4790                                                 (v2i32 V64:$Rm)))))]>;
4791   def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
4792                                                   V128, V128, V128,
4793                                                   asm#"2", ".2d", ".4s", ".4s",
4794     [(set (v2i64 V128:$dst),
4795           (Accum (v2i64 V128:$Rd),
4796                  (v2i64 (int_arm64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
4797                                             (extract_high_v4i32 V128:$Rm)))))]>;
4798 }
4799
4800 multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
4801                                   SDPatternOperator OpNode> {
4802   def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
4803                                                   V128, V128, V64,
4804                                                   asm, ".8h", ".8h", ".8b",
4805        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
4806   def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
4807                                                   V128, V128, V128,
4808                                                   asm#"2", ".8h", ".8h", ".16b",
4809        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
4810                                        (extract_high_v16i8 V128:$Rm)))]>;
4811   def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
4812                                                   V128, V128, V64,
4813                                                   asm, ".4s", ".4s", ".4h",
4814        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
4815   def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
4816                                                   V128, V128, V128,
4817                                                   asm#"2", ".4s", ".4s", ".8h",
4818        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
4819                                        (extract_high_v8i16 V128:$Rm)))]>;
4820   def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
4821                                                   V128, V128, V64,
4822                                                   asm, ".2d", ".2d", ".2s",
4823        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
4824   def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
4825                                                   V128, V128, V128,
4826                                                   asm#"2", ".2d", ".2d", ".4s",
4827        [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
4828                                        (extract_high_v4i32 V128:$Rm)))]>;
4829 }
4830
4831 //----------------------------------------------------------------------------
4832 // AdvSIMD bitwise extract from vector
4833 //----------------------------------------------------------------------------
4834
4835 class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
4836                              string asm, string kind>
4837   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
4838       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
4839       "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
4840       [(set (vty regtype:$Rd),
4841             (ARM64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
4842     Sched<[WriteV]> {
4843   bits<5> Rd;
4844   bits<5> Rn;
4845   bits<5> Rm;
4846   bits<4> imm;
4847   let Inst{31}    = 0;
4848   let Inst{30}    = size;
4849   let Inst{29-21} = 0b101110000;
4850   let Inst{20-16} = Rm;
4851   let Inst{15}    = 0;
4852   let Inst{14-11} = imm;
4853   let Inst{10}    = 0;
4854   let Inst{9-5}   = Rn;
4855   let Inst{4-0}   = Rd;
4856 }
4857
4858
4859 multiclass SIMDBitwiseExtract<string asm> {
4860   def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
4861     let imm{3} = 0;
4862   }
4863   def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
4864 }
4865
4866 //----------------------------------------------------------------------------
4867 // AdvSIMD zip vector
4868 //----------------------------------------------------------------------------
4869
4870 class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
4871                         string asm, string kind, SDNode OpNode, ValueType valty>
4872   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4873       "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4874       "|" # kind # "\t$Rd, $Rn, $Rm}", "",
4875       [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
4876     Sched<[WriteV]> {
4877   bits<5> Rd;
4878   bits<5> Rn;
4879   bits<5> Rm;
4880   let Inst{31}    = 0;
4881   let Inst{30}    = size{0};
4882   let Inst{29-24} = 0b001110;
4883   let Inst{23-22} = size{2-1};
4884   let Inst{21}    = 0;
4885   let Inst{20-16} = Rm;
4886   let Inst{15}    = 0;
4887   let Inst{14-12} = opc;
4888   let Inst{11-10} = 0b10;
4889   let Inst{9-5}   = Rn;
4890   let Inst{4-0}   = Rd;
4891 }
4892
4893 multiclass SIMDZipVector<bits<3>opc, string asm,
4894                          SDNode OpNode> {
4895   def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
4896       asm, ".8b", OpNode, v8i8>;
4897   def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
4898       asm, ".16b", OpNode, v16i8>;
4899   def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
4900       asm, ".4h", OpNode, v4i16>;
4901   def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
4902       asm, ".8h", OpNode, v8i16>;
4903   def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
4904       asm, ".2s", OpNode, v2i32>;
4905   def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
4906       asm, ".4s", OpNode, v4i32>;
4907   def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
4908       asm, ".2d", OpNode, v2i64>;
4909
4910   def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
4911         (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
4912   def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
4913         (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
4914   def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
4915         (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
4916 }
4917
4918 //----------------------------------------------------------------------------
4919 // AdvSIMD three register scalar instructions
4920 //----------------------------------------------------------------------------
4921
4922 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4923 class BaseSIMDThreeScalar<bit U, bits<2> size, bits<5> opcode,
4924                         RegisterClass regtype, string asm,
4925                         list<dag> pattern>
4926   : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4927       "\t$Rd, $Rn, $Rm", "", pattern>,
4928     Sched<[WriteV]> {
4929   bits<5> Rd;
4930   bits<5> Rn;
4931   bits<5> Rm;
4932   let Inst{31-30} = 0b01;
4933   let Inst{29}    = U;
4934   let Inst{28-24} = 0b11110;
4935   let Inst{23-22} = size;
4936   let Inst{21}    = 1;
4937   let Inst{20-16} = Rm;
4938   let Inst{15-11} = opcode;
4939   let Inst{10}    = 1;
4940   let Inst{9-5}   = Rn;
4941   let Inst{4-0}   = Rd;
4942 }
4943
4944 multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
4945                             SDPatternOperator OpNode> {
4946   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4947     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4948 }
4949
4950 multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
4951                                SDPatternOperator OpNode> {
4952   def v1i64  : BaseSIMDThreeScalar<U, 0b11, opc, FPR64, asm,
4953     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
4954   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm, []>;
4955   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4956   def v1i8   : BaseSIMDThreeScalar<U, 0b00, opc, FPR8 , asm, []>;
4957
4958   def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
4959             (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
4960   def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
4961             (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
4962 }
4963
4964 multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
4965                              SDPatternOperator OpNode> {
4966   def v1i32  : BaseSIMDThreeScalar<U, 0b10, opc, FPR32, asm,
4967                              [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
4968   def v1i16  : BaseSIMDThreeScalar<U, 0b01, opc, FPR16, asm, []>;
4969 }
4970
4971 multiclass SIMDThreeScalarSD<bit U, bit S, bits<5> opc, string asm,
4972                              SDPatternOperator OpNode = null_frag> {
4973   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
4974     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
4975       [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
4976     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
4977       [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
4978   }
4979
4980   def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4981             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
4982 }
4983
4984 multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<5> opc, string asm,
4985                                 SDPatternOperator OpNode = null_frag> {
4986   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
4987     def #NAME#64 : BaseSIMDThreeScalar<U, {S,1}, opc, FPR64, asm,
4988       [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
4989     def #NAME#32 : BaseSIMDThreeScalar<U, {S,0}, opc, FPR32, asm,
4990       [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
4991   }
4992
4993   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
4994             (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
4995 }
4996
4997 class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
4998               dag oops, dag iops, string asm, string cstr, list<dag> pat>
4999   : I<oops, iops, asm,
5000       "\t$Rd, $Rn, $Rm", cstr, pat>,
5001     Sched<[WriteV]> {
5002   bits<5> Rd;
5003   bits<5> Rn;
5004   bits<5> Rm;
5005   let Inst{31-30} = 0b01;
5006   let Inst{29}    = U;
5007   let Inst{28-24} = 0b11110;
5008   let Inst{23-22} = size;
5009   let Inst{21}    = 1;
5010   let Inst{20-16} = Rm;
5011   let Inst{15-11} = opcode;
5012   let Inst{10}    = 0;
5013   let Inst{9-5}   = Rn;
5014   let Inst{4-0}   = Rd;
5015 }
5016
5017 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5018 multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5019                                   SDPatternOperator OpNode = null_frag> {
5020   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5021                                       (outs FPR32:$Rd),
5022                                       (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5023   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5024                                       (outs FPR64:$Rd),
5025                                       (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5026             [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5027 }
5028
5029 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5030 multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5031                                   SDPatternOperator OpNode = null_frag> {
5032   def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5033                                       (outs FPR32:$dst),
5034                                       (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5035                                       asm, "$Rd = $dst", []>;
5036   def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5037                                       (outs FPR64:$dst),
5038                                       (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5039                                       asm, "$Rd = $dst",
5040             [(set (i64 FPR64:$dst),
5041                   (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5042 }
5043
5044 //----------------------------------------------------------------------------
5045 // AdvSIMD two register scalar instructions
5046 //----------------------------------------------------------------------------
5047
5048 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5049 class BaseSIMDTwoScalar<bit U, bits<2> size, bits<5> opcode,
5050                         RegisterClass regtype, RegisterClass regtype2,
5051                         string asm, list<dag> pat>
5052   : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5053       "\t$Rd, $Rn", "", pat>,
5054     Sched<[WriteV]> {
5055   bits<5> Rd;
5056   bits<5> Rn;
5057   let Inst{31-30} = 0b01;
5058   let Inst{29}    = U;
5059   let Inst{28-24} = 0b11110;
5060   let Inst{23-22} = size;
5061   let Inst{21-17} = 0b10000;
5062   let Inst{16-12} = opcode;
5063   let Inst{11-10} = 0b10;
5064   let Inst{9-5}   = Rn;
5065   let Inst{4-0}   = Rd;
5066 }
5067
5068 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5069 class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5070                         RegisterClass regtype, RegisterClass regtype2,
5071                         string asm, list<dag> pat>
5072   : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5073       "\t$Rd, $Rn", "$Rd = $dst", pat>,
5074     Sched<[WriteV]> {
5075   bits<5> Rd;
5076   bits<5> Rn;
5077   let Inst{31-30} = 0b01;
5078   let Inst{29}    = U;
5079   let Inst{28-24} = 0b11110;
5080   let Inst{23-22} = size;
5081   let Inst{21-17} = 0b10000;
5082   let Inst{16-12} = opcode;
5083   let Inst{11-10} = 0b10;
5084   let Inst{9-5}   = Rn;
5085   let Inst{4-0}   = Rd;
5086 }
5087
5088
5089 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5090 class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<5> opcode,
5091                         RegisterClass regtype, string asm>
5092   : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5093       "\t$Rd, $Rn, #0", "", []>,
5094     Sched<[WriteV]> {
5095   bits<5> Rd;
5096   bits<5> Rn;
5097   let Inst{31-30} = 0b01;
5098   let Inst{29}    = U;
5099   let Inst{28-24} = 0b11110;
5100   let Inst{23-22} = size;
5101   let Inst{21-17} = 0b10000;
5102   let Inst{16-12} = opcode;
5103   let Inst{11-10} = 0b10;
5104   let Inst{9-5}   = Rn;
5105   let Inst{4-0}   = Rd;
5106 }
5107
5108 class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5109   : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5110      [(set (f32 FPR32:$Rd), (int_arm64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5111     Sched<[WriteV]> {
5112   bits<5> Rd;
5113   bits<5> Rn;
5114   let Inst{31-17} = 0b011111100110000;
5115   let Inst{16-12} = opcode;
5116   let Inst{11-10} = 0b10;
5117   let Inst{9-5}   = Rn;
5118   let Inst{4-0}   = Rd;
5119 }
5120
5121 multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5122                              SDPatternOperator OpNode> {
5123   def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, opc, FPR64, asm>;
5124
5125   def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5126             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5127 }
5128
5129 multiclass SIMDCmpTwoScalarSD<bit U, bit S, bits<5> opc, string asm,
5130                               SDPatternOperator OpNode> {
5131   def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, opc, FPR64, asm>;
5132   def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, opc, FPR32, asm>;
5133
5134   def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5135             (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5136 }
5137
5138 multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5139                           SDPatternOperator OpNode = null_frag> {
5140   def v1i64       : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5141     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5142
5143   def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5144             (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5145 }
5146
5147 multiclass SIMDTwoScalarSD<bit U, bit S, bits<5> opc, string asm> {
5148   def v1i64       : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,[]>;
5149   def v1i32       : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,[]>;
5150 }
5151
5152 multiclass SIMDTwoScalarCVTSD<bit U, bit S, bits<5> opc, string asm,
5153                               SDPatternOperator OpNode> {
5154   def v1i64 : BaseSIMDTwoScalar<U, {S,1}, opc, FPR64, FPR64, asm,
5155                                 [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5156   def v1i32 : BaseSIMDTwoScalar<U, {S,0}, opc, FPR32, FPR32, asm,
5157                                 [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5158 }
5159
5160 multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5161                              SDPatternOperator OpNode = null_frag> {
5162   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5163     def v1i64  : BaseSIMDTwoScalar<U, 0b11, opc, FPR64, FPR64, asm,
5164            [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5165     def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR32, asm,
5166            [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5167     def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR16, asm, []>;
5168     def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5169   }
5170
5171   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5172             (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5173 }
5174
5175 multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5176                                  Intrinsic OpNode> {
5177   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5178     def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5179         [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5180     def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5181         [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5182     def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5183     def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5184   }
5185
5186   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5187             (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5188 }
5189
5190
5191
5192 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5193 multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5194                                  SDPatternOperator OpNode = null_frag> {
5195   def v1i32  : BaseSIMDTwoScalar<U, 0b10, opc, FPR32, FPR64, asm,
5196         [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5197   def v1i16  : BaseSIMDTwoScalar<U, 0b01, opc, FPR16, FPR32, asm, []>;
5198   def v1i8   : BaseSIMDTwoScalar<U, 0b00, opc, FPR8 , FPR16, asm, []>;
5199 }
5200
5201 //----------------------------------------------------------------------------
5202 // AdvSIMD scalar pairwise instructions
5203 //----------------------------------------------------------------------------
5204
5205 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5206 class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5207                         RegisterOperand regtype, RegisterOperand vectype,
5208                         string asm, string kind>
5209   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5210       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5211     Sched<[WriteV]> {
5212   bits<5> Rd;
5213   bits<5> Rn;
5214   let Inst{31-30} = 0b01;
5215   let Inst{29}    = U;
5216   let Inst{28-24} = 0b11110;
5217   let Inst{23-22} = size;
5218   let Inst{21-17} = 0b11000;
5219   let Inst{16-12} = opcode;
5220   let Inst{11-10} = 0b10;
5221   let Inst{9-5}   = Rn;
5222   let Inst{4-0}   = Rd;
5223 }
5224
5225 multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
5226   def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
5227                                       asm, ".2d">;
5228 }
5229
5230 multiclass SIMDPairwiseScalarSD<bit U, bit S, bits<5> opc, string asm> {
5231   def v2i32p : BaseSIMDPairwiseScalar<U, {S,0}, opc, FPR32Op, V64,
5232                                       asm, ".2s">;
5233   def v2i64p : BaseSIMDPairwiseScalar<U, {S,1}, opc, FPR64Op, V128,
5234                                       asm, ".2d">;
5235 }
5236
5237 //----------------------------------------------------------------------------
5238 // AdvSIMD across lanes instructions
5239 //----------------------------------------------------------------------------
5240
5241 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5242 class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
5243                           RegisterClass regtype, RegisterOperand vectype,
5244                           string asm, string kind, list<dag> pattern>
5245   : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5246       "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
5247     Sched<[WriteV]> {
5248   bits<5> Rd;
5249   bits<5> Rn;
5250   let Inst{31}    = 0;
5251   let Inst{30}    = Q;
5252   let Inst{29}    = U;
5253   let Inst{28-24} = 0b01110;
5254   let Inst{23-22} = size;
5255   let Inst{21-17} = 0b11000;
5256   let Inst{16-12} = opcode;
5257   let Inst{11-10} = 0b10;
5258   let Inst{9-5}   = Rn;
5259   let Inst{4-0}   = Rd;
5260 }
5261
5262 multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
5263                               string asm> {
5264   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
5265                                    asm, ".8b", []>;
5266   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
5267                                    asm, ".16b", []>;
5268   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
5269                                    asm, ".4h", []>;
5270   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
5271                                    asm, ".8h", []>;
5272   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
5273                                    asm, ".4s", []>;
5274 }
5275
5276 multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
5277   def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
5278                                    asm, ".8b", []>;
5279   def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
5280                                    asm, ".16b", []>;
5281   def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
5282                                    asm, ".4h", []>;
5283   def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
5284                                    asm, ".8h", []>;
5285   def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
5286                                    asm, ".4s", []>;
5287 }
5288
5289 multiclass SIMDAcrossLanesS<bits<5> opcode, bit sz1, string asm,
5290                             Intrinsic intOp> {
5291   def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
5292                                    asm, ".4s",
5293         [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
5294 }
5295
5296 //----------------------------------------------------------------------------
5297 // AdvSIMD INS/DUP instructions
5298 //----------------------------------------------------------------------------
5299
5300 // FIXME: There has got to be a better way to factor these. ugh.
5301
5302 class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
5303                      string operands, string constraints, list<dag> pattern>
5304   : I<outs, ins, asm, operands, constraints, pattern>,
5305     Sched<[WriteV]> {
5306   bits<5> Rd;
5307   bits<5> Rn;
5308   let Inst{31} = 0;
5309   let Inst{30} = Q;
5310   let Inst{29} = op;
5311   let Inst{28-21} = 0b01110000;
5312   let Inst{15} = 0;
5313   let Inst{10} = 1;
5314   let Inst{9-5} = Rn;
5315   let Inst{4-0} = Rd;
5316 }
5317
5318 class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
5319                       RegisterOperand vecreg, RegisterClass regtype>
5320   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
5321                    "{\t$Rd" # size # ", $Rn" #
5322                    "|" # size # "\t$Rd, $Rn}", "",
5323                    [(set (vectype vecreg:$Rd), (ARM64dup regtype:$Rn))]> {
5324   let Inst{20-16} = imm5;
5325   let Inst{14-11} = 0b0001;
5326 }
5327
5328 class SIMDDupFromElement<bit Q, string dstkind, string srckind,
5329                          ValueType vectype, ValueType insreg,
5330                          RegisterOperand vecreg, Operand idxtype,
5331                          ValueType elttype, SDNode OpNode>
5332   : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
5333                    "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
5334                    "|" # dstkind # "\t$Rd, $Rn$idx}", "",
5335                  [(set (vectype vecreg:$Rd),
5336                        (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
5337   let Inst{14-11} = 0b0000;
5338 }
5339
5340 class SIMDDup64FromElement
5341   : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
5342                        VectorIndexD, i64, ARM64duplane64> {
5343   bits<1> idx;
5344   let Inst{20} = idx;
5345   let Inst{19-16} = 0b1000;
5346 }
5347
5348 class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
5349                            RegisterOperand vecreg>
5350   : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
5351                        VectorIndexS, i64, ARM64duplane32> {
5352   bits<2> idx;
5353   let Inst{20-19} = idx;
5354   let Inst{18-16} = 0b100;
5355 }
5356
5357 class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
5358                            RegisterOperand vecreg>
5359   : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
5360                        VectorIndexH, i64, ARM64duplane16> {
5361   bits<3> idx;
5362   let Inst{20-18} = idx;
5363   let Inst{17-16} = 0b10;
5364 }
5365
5366 class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
5367                           RegisterOperand vecreg>
5368   : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
5369                        VectorIndexB, i64, ARM64duplane8> {
5370   bits<4> idx;
5371   let Inst{20-17} = idx;
5372   let Inst{16} = 1;
5373 }
5374
5375 class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
5376                   Operand idxtype, string asm, list<dag> pattern>
5377   : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
5378                    "{\t$Rd, $Rn" # size # "$idx" #
5379                    "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
5380   let Inst{14-11} = imm4;
5381 }
5382
5383 class SIMDSMov<bit Q, string size, RegisterClass regtype,
5384                Operand idxtype>
5385   : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
5386 class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
5387                Operand idxtype>
5388   : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
5389       [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
5390
5391 class SIMDMovAlias<string asm, string size, Instruction inst,
5392                    RegisterClass regtype, Operand idxtype>
5393     : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
5394                     "|" # size # "\t$dst, $src$idx}",
5395                 (inst regtype:$dst, V128:$src, idxtype:$idx)>;
5396
5397 multiclass SMov {
5398   def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
5399     bits<4> idx;
5400     let Inst{20-17} = idx;
5401     let Inst{16} = 1;
5402   }
5403   def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
5404     bits<4> idx;
5405     let Inst{20-17} = idx;
5406     let Inst{16} = 1;
5407   }
5408   def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
5409     bits<3> idx;
5410     let Inst{20-18} = idx;
5411     let Inst{17-16} = 0b10;
5412   }
5413   def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
5414     bits<3> idx;
5415     let Inst{20-18} = idx;
5416     let Inst{17-16} = 0b10;
5417   }
5418   def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
5419     bits<2> idx;
5420     let Inst{20-19} = idx;
5421     let Inst{18-16} = 0b100;
5422   }
5423 }
5424
5425 multiclass UMov {
5426   def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
5427     bits<4> idx;
5428     let Inst{20-17} = idx;
5429     let Inst{16} = 1;
5430   }
5431   def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
5432     bits<3> idx;
5433     let Inst{20-18} = idx;
5434     let Inst{17-16} = 0b10;
5435   }
5436   def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
5437     bits<2> idx;
5438     let Inst{20-19} = idx;
5439     let Inst{18-16} = 0b100;
5440   }
5441   def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
5442     bits<1> idx;
5443     let Inst{20} = idx;
5444     let Inst{19-16} = 0b1000;
5445   }
5446   def : SIMDMovAlias<"mov", ".s",
5447                      !cast<Instruction>(NAME#"vi32"),
5448                      GPR32, VectorIndexS>;
5449   def : SIMDMovAlias<"mov", ".d",
5450                      !cast<Instruction>(NAME#"vi64"),
5451                      GPR64, VectorIndexD>;
5452 }
5453
5454 class SIMDInsFromMain<string size, ValueType vectype,
5455                       RegisterClass regtype, Operand idxtype>
5456   : BaseSIMDInsDup<1, 0, (outs V128:$dst),
5457                    (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
5458                    "{\t$Rd" # size # "$idx, $Rn" #
5459                    "|" # size # "\t$Rd$idx, $Rn}",
5460                    "$Rd = $dst",
5461             [(set V128:$dst,
5462               (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
5463   let Inst{14-11} = 0b0011;
5464 }
5465
5466 class SIMDInsFromElement<string size, ValueType vectype,
5467                          ValueType elttype, Operand idxtype>
5468   : BaseSIMDInsDup<1, 1, (outs V128:$dst),
5469                    (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
5470                    "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
5471                    "|" # size # "\t$Rd$idx, $Rn$idx2}",
5472                    "$Rd = $dst",
5473          [(set V128:$dst,
5474                (vector_insert
5475                  (vectype V128:$Rd),
5476                  (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
5477                  idxtype:$idx))]>;
5478
5479 class SIMDInsMainMovAlias<string size, Instruction inst,
5480                           RegisterClass regtype, Operand idxtype>
5481     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
5482                         "|" # size #"\t$dst$idx, $src}",
5483                 (inst V128:$dst, idxtype:$idx, regtype:$src)>;
5484 class SIMDInsElementMovAlias<string size, Instruction inst,
5485                              Operand idxtype>
5486     : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
5487                       # "|" # size #" $dst$idx, $src$idx2}",
5488                 (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
5489
5490
5491 multiclass SIMDIns {
5492   def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
5493     bits<4> idx;
5494     let Inst{20-17} = idx;
5495     let Inst{16} = 1;
5496   }
5497   def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
5498     bits<3> idx;
5499     let Inst{20-18} = idx;
5500     let Inst{17-16} = 0b10;
5501   }
5502   def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
5503     bits<2> idx;
5504     let Inst{20-19} = idx;
5505     let Inst{18-16} = 0b100;
5506   }
5507   def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
5508     bits<1> idx;
5509     let Inst{20} = idx;
5510     let Inst{19-16} = 0b1000;
5511   }
5512
5513   def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
5514     bits<4> idx;
5515     bits<4> idx2;
5516     let Inst{20-17} = idx;
5517     let Inst{16} = 1;
5518     let Inst{14-11} = idx2;
5519   }
5520   def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
5521     bits<3> idx;
5522     bits<3> idx2;
5523     let Inst{20-18} = idx;
5524     let Inst{17-16} = 0b10;
5525     let Inst{14-12} = idx2;
5526     let Inst{11} = 0;
5527   }
5528   def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
5529     bits<2> idx;
5530     bits<2> idx2;
5531     let Inst{20-19} = idx;
5532     let Inst{18-16} = 0b100;
5533     let Inst{14-13} = idx2;
5534     let Inst{12-11} = 0;
5535   }
5536   def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
5537     bits<1> idx;
5538     bits<1> idx2;
5539     let Inst{20} = idx;
5540     let Inst{19-16} = 0b1000;
5541     let Inst{14} = idx2;
5542     let Inst{13-11} = 0;
5543   }
5544
5545   // For all forms of the INS instruction, the "mov" mnemonic is the
5546   // preferred alias. Why they didn't just call the instruction "mov" in
5547   // the first place is a very good question indeed...
5548   def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
5549                          GPR32, VectorIndexB>;
5550   def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
5551                          GPR32, VectorIndexH>;
5552   def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
5553                          GPR32, VectorIndexS>;
5554   def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
5555                          GPR64, VectorIndexD>;
5556
5557   def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
5558                          VectorIndexB>;
5559   def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
5560                          VectorIndexH>;
5561   def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
5562                          VectorIndexS>;
5563   def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
5564                          VectorIndexD>;
5565 }
5566
5567 //----------------------------------------------------------------------------
5568 // AdvSIMD TBL/TBX
5569 //----------------------------------------------------------------------------
5570
5571 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5572 class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5573                           RegisterOperand listtype, string asm, string kind>
5574   : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
5575        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
5576     Sched<[WriteV]> {
5577   bits<5> Vd;
5578   bits<5> Vn;
5579   bits<5> Vm;
5580   let Inst{31}    = 0;
5581   let Inst{30}    = Q;
5582   let Inst{29-21} = 0b001110000;
5583   let Inst{20-16} = Vm;
5584   let Inst{15}    = 0;
5585   let Inst{14-13} = len;
5586   let Inst{12}    = op;
5587   let Inst{11-10} = 0b00;
5588   let Inst{9-5}   = Vn;
5589   let Inst{4-0}   = Vd;
5590 }
5591
5592 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5593 class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
5594                           RegisterOperand listtype, string asm, string kind>
5595   : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
5596        "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
5597     Sched<[WriteV]> {
5598   bits<5> Vd;
5599   bits<5> Vn;
5600   bits<5> Vm;
5601   let Inst{31}    = 0;
5602   let Inst{30}    = Q;
5603   let Inst{29-21} = 0b001110000;
5604   let Inst{20-16} = Vm;
5605   let Inst{15}    = 0;
5606   let Inst{14-13} = len;
5607   let Inst{12}    = op;
5608   let Inst{11-10} = 0b00;
5609   let Inst{9-5}   = Vn;
5610   let Inst{4-0}   = Vd;
5611 }
5612
5613 class SIMDTableLookupAlias<string asm, Instruction inst,
5614                           RegisterOperand vectype, RegisterOperand listtype>
5615     : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
5616                 (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
5617
5618 multiclass SIMDTableLookup<bit op, string asm> {
5619   def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
5620                                       asm, ".8b">;
5621   def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
5622                                       asm, ".8b">;
5623   def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
5624                                       asm, ".8b">;
5625   def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
5626                                       asm, ".8b">;
5627   def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
5628                                       asm, ".16b">;
5629   def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
5630                                       asm, ".16b">;
5631   def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
5632                                       asm, ".16b">;
5633   def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
5634                                       asm, ".16b">;
5635
5636   def : SIMDTableLookupAlias<asm # ".8b",
5637                          !cast<Instruction>(NAME#"v8i8One"),
5638                          V64, VecListOne128>;
5639   def : SIMDTableLookupAlias<asm # ".8b",
5640                          !cast<Instruction>(NAME#"v8i8Two"),
5641                          V64, VecListTwo128>;
5642   def : SIMDTableLookupAlias<asm # ".8b",
5643                          !cast<Instruction>(NAME#"v8i8Three"),
5644                          V64, VecListThree128>;
5645   def : SIMDTableLookupAlias<asm # ".8b",
5646                          !cast<Instruction>(NAME#"v8i8Four"),
5647                          V64, VecListFour128>;
5648   def : SIMDTableLookupAlias<asm # ".16b",
5649                          !cast<Instruction>(NAME#"v16i8One"),
5650                          V128, VecListOne128>;
5651   def : SIMDTableLookupAlias<asm # ".16b",
5652                          !cast<Instruction>(NAME#"v16i8Two"),
5653                          V128, VecListTwo128>;
5654   def : SIMDTableLookupAlias<asm # ".16b",
5655                          !cast<Instruction>(NAME#"v16i8Three"),
5656                          V128, VecListThree128>;
5657   def : SIMDTableLookupAlias<asm # ".16b",
5658                          !cast<Instruction>(NAME#"v16i8Four"),
5659                          V128, VecListFour128>;
5660 }
5661
5662 multiclass SIMDTableLookupTied<bit op, string asm> {
5663   def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
5664                                       asm, ".8b">;
5665   def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
5666                                       asm, ".8b">;
5667   def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
5668                                       asm, ".8b">;
5669   def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
5670                                       asm, ".8b">;
5671   def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
5672                                       asm, ".16b">;
5673   def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
5674                                       asm, ".16b">;
5675   def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
5676                                       asm, ".16b">;
5677   def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
5678                                       asm, ".16b">;
5679
5680   def : SIMDTableLookupAlias<asm # ".8b",
5681                          !cast<Instruction>(NAME#"v8i8One"),
5682                          V64, VecListOne128>;
5683   def : SIMDTableLookupAlias<asm # ".8b",
5684                          !cast<Instruction>(NAME#"v8i8Two"),
5685                          V64, VecListTwo128>;
5686   def : SIMDTableLookupAlias<asm # ".8b",
5687                          !cast<Instruction>(NAME#"v8i8Three"),
5688                          V64, VecListThree128>;
5689   def : SIMDTableLookupAlias<asm # ".8b",
5690                          !cast<Instruction>(NAME#"v8i8Four"),
5691                          V64, VecListFour128>;
5692   def : SIMDTableLookupAlias<asm # ".16b",
5693                          !cast<Instruction>(NAME#"v16i8One"),
5694                          V128, VecListOne128>;
5695   def : SIMDTableLookupAlias<asm # ".16b",
5696                          !cast<Instruction>(NAME#"v16i8Two"),
5697                          V128, VecListTwo128>;
5698   def : SIMDTableLookupAlias<asm # ".16b",
5699                          !cast<Instruction>(NAME#"v16i8Three"),
5700                          V128, VecListThree128>;
5701   def : SIMDTableLookupAlias<asm # ".16b",
5702                          !cast<Instruction>(NAME#"v16i8Four"),
5703                          V128, VecListFour128>;
5704 }
5705
5706
5707 //----------------------------------------------------------------------------
5708 // AdvSIMD scalar CPY
5709 //----------------------------------------------------------------------------
5710 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5711 class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
5712                         string kind, Operand idxtype>
5713   : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
5714        "{\t$dst, $src" # kind # "$idx" #
5715        "|\t$dst, $src$idx}", "", []>,
5716     Sched<[WriteV]> {
5717   bits<5> dst;
5718   bits<5> src;
5719   let Inst{31-21} = 0b01011110000;
5720   let Inst{15-10} = 0b000001;
5721   let Inst{9-5}   = src;
5722   let Inst{4-0}   = dst;
5723 }
5724
5725 class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
5726       RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
5727     : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
5728                     # "|\t$dst, $src$index}",
5729                 (inst regtype:$dst, vectype:$src, idxtype:$index)>;
5730
5731
5732 multiclass SIMDScalarCPY<string asm> {
5733   def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
5734     bits<4> idx;
5735     let Inst{20-17} = idx;
5736     let Inst{16} = 1;
5737   }
5738   def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
5739     bits<3> idx;
5740     let Inst{20-18} = idx;
5741     let Inst{17-16} = 0b10;
5742   }
5743   def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
5744     bits<2> idx;
5745     let Inst{20-19} = idx;
5746     let Inst{18-16} = 0b100;
5747   }
5748   def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
5749     bits<1> idx;
5750     let Inst{20} = idx;
5751     let Inst{19-16} = 0b1000;
5752   }
5753
5754   // 'DUP' mnemonic aliases.
5755   def : SIMDScalarCPYAlias<"dup", ".b",
5756                            !cast<Instruction>(NAME#"i8"),
5757                            FPR8, V128, VectorIndexB>;
5758   def : SIMDScalarCPYAlias<"dup", ".h",
5759                            !cast<Instruction>(NAME#"i16"),
5760                            FPR16, V128, VectorIndexH>;
5761   def : SIMDScalarCPYAlias<"dup", ".s",
5762                            !cast<Instruction>(NAME#"i32"),
5763                            FPR32, V128, VectorIndexS>;
5764   def : SIMDScalarCPYAlias<"dup", ".d",
5765                            !cast<Instruction>(NAME#"i64"),
5766                            FPR64, V128, VectorIndexD>;
5767 }
5768
5769 //----------------------------------------------------------------------------
5770 // AdvSIMD modified immediate instructions
5771 //----------------------------------------------------------------------------
5772
5773 class BaseSIMDModifiedImm<bit Q, bit op, dag oops, dag iops,
5774                           string asm, string op_string,
5775                           string cstr, list<dag> pattern>
5776   : I<oops, iops, asm, op_string, cstr, pattern>,
5777     Sched<[WriteV]> {
5778   bits<5> Rd;
5779   bits<8> imm8;
5780   let Inst{31}    = 0;
5781   let Inst{30}    = Q;
5782   let Inst{29}    = op;
5783   let Inst{28-19} = 0b0111100000;
5784   let Inst{18-16} = imm8{7-5};
5785   let Inst{11-10} = 0b01;
5786   let Inst{9-5}   = imm8{4-0};
5787   let Inst{4-0}   = Rd;
5788 }
5789
5790 class BaseSIMDModifiedImmVector<bit Q, bit op, RegisterOperand vectype,
5791                                 Operand immtype, dag opt_shift_iop,
5792                                 string opt_shift, string asm, string kind,
5793                                 list<dag> pattern>
5794   : BaseSIMDModifiedImm<Q, op, (outs vectype:$Rd),
5795                         !con((ins immtype:$imm8), opt_shift_iop), asm,
5796                         "{\t$Rd" # kind # ", $imm8" # opt_shift #
5797                         "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5798                         "", pattern> {
5799   let DecoderMethod = "DecodeModImmInstruction";
5800 }
5801
5802 class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
5803                                 Operand immtype, dag opt_shift_iop,
5804                                 string opt_shift, string asm, string kind,
5805                                 list<dag> pattern>
5806   : BaseSIMDModifiedImm<Q, op, (outs vectype:$dst),
5807                         !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
5808                         asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
5809                              "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
5810                         "$Rd = $dst", pattern> {
5811   let DecoderMethod = "DecodeModImmTiedInstruction";
5812 }
5813
5814 class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
5815                                      RegisterOperand vectype, string asm,
5816                                      string kind, list<dag> pattern>
5817   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5818                               (ins logical_vec_shift:$shift),
5819                               "$shift", asm, kind, pattern> {
5820   bits<2> shift;
5821   let Inst{15}    = b15_b12{1};
5822   let Inst{14-13} = shift;
5823   let Inst{12}    = b15_b12{0};
5824 }
5825
5826 class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
5827                                      RegisterOperand vectype, string asm,
5828                                      string kind, list<dag> pattern>
5829   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5830                               (ins logical_vec_shift:$shift),
5831                               "$shift", asm, kind, pattern> {
5832   bits<2> shift;
5833   let Inst{15}    = b15_b12{1};
5834   let Inst{14-13} = shift;
5835   let Inst{12}    = b15_b12{0};
5836 }
5837
5838
5839 class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
5840                                          RegisterOperand vectype, string asm,
5841                                          string kind, list<dag> pattern>
5842   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5843                               (ins logical_vec_hw_shift:$shift),
5844                               "$shift", asm, kind, pattern> {
5845   bits<2> shift;
5846   let Inst{15} = b15_b12{1};
5847   let Inst{14} = 0;
5848   let Inst{13} = shift{0};
5849   let Inst{12} = b15_b12{0};
5850 }
5851
5852 class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
5853                                          RegisterOperand vectype, string asm,
5854                                          string kind, list<dag> pattern>
5855   : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
5856                               (ins logical_vec_hw_shift:$shift),
5857                               "$shift", asm, kind, pattern> {
5858   bits<2> shift;
5859   let Inst{15} = b15_b12{1};
5860   let Inst{14} = 0;
5861   let Inst{13} = shift{0};
5862   let Inst{12} = b15_b12{0};
5863 }
5864
5865 multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
5866                                       string asm> {
5867   def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
5868                                                  asm, ".4h", []>;
5869   def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
5870                                                  asm, ".8h", []>;
5871
5872   def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
5873                                              asm, ".2s", []>;
5874   def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
5875                                              asm, ".4s", []>;
5876 }
5877
5878 multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
5879                                       bits<2> w_cmode, string asm,
5880                                       SDNode OpNode> {
5881   def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
5882                                                  asm, ".4h",
5883              [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
5884                                              imm0_255:$imm8,
5885                                              (i32 imm:$shift)))]>;
5886   def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
5887                                                  asm, ".8h",
5888              [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
5889                                               imm0_255:$imm8,
5890                                               (i32 imm:$shift)))]>;
5891
5892   def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
5893                                              asm, ".2s",
5894              [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
5895                                              imm0_255:$imm8,
5896                                              (i32 imm:$shift)))]>;
5897   def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
5898                                              asm, ".4s",
5899              [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
5900                                               imm0_255:$imm8,
5901                                               (i32 imm:$shift)))]>;
5902 }
5903
5904 class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
5905                              RegisterOperand vectype, string asm,
5906                              string kind, list<dag> pattern>
5907   : BaseSIMDModifiedImmVector<Q, op, vectype, imm0_255,
5908                               (ins move_vec_shift:$shift),
5909                               "$shift", asm, kind, pattern> {
5910   bits<1> shift;
5911   let Inst{15-13} = cmode{3-1};
5912   let Inst{12}    = shift;
5913 }
5914
5915 class SIMDModifiedImmVectorNoShift<bit Q, bit op, bits<4> cmode,
5916                                    RegisterOperand vectype,
5917                                    Operand imm_type, string asm,
5918                                    string kind, list<dag> pattern>
5919   : BaseSIMDModifiedImmVector<Q, op, vectype, imm_type, (ins), "",
5920                               asm, kind, pattern> {
5921   let Inst{15-12} = cmode;
5922 }
5923
5924 class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
5925                                    list<dag> pattern>
5926   : BaseSIMDModifiedImm<Q, op, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
5927                         "\t$Rd, $imm8", "", pattern> {
5928   let Inst{15-12} = cmode;
5929   let DecoderMethod = "DecodeModImmInstruction";
5930 }
5931
5932 //----------------------------------------------------------------------------
5933 // AdvSIMD indexed element
5934 //----------------------------------------------------------------------------
5935
5936 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5937 class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5938                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
5939                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
5940                       string apple_kind, string dst_kind, string lhs_kind,
5941                       string rhs_kind, list<dag> pattern>
5942   : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
5943       asm,
5944       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5945       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
5946     Sched<[WriteV]> {
5947   bits<5> Rd;
5948   bits<5> Rn;
5949   bits<5> Rm;
5950
5951   let Inst{31}    = 0;
5952   let Inst{30}    = Q;
5953   let Inst{29}    = U;
5954   let Inst{28}    = Scalar;
5955   let Inst{27-24} = 0b1111;
5956   let Inst{23-22} = size;
5957   // Bit 21 must be set by the derived class.
5958   let Inst{20-16} = Rm;
5959   let Inst{15-12} = opc;
5960   // Bit 11 must be set by the derived class.
5961   let Inst{10}    = 0;
5962   let Inst{9-5}   = Rn;
5963   let Inst{4-0}   = Rd;
5964 }
5965
5966 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5967 class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
5968                       RegisterOperand dst_reg, RegisterOperand lhs_reg,
5969                       RegisterOperand rhs_reg, Operand vec_idx, string asm,
5970                       string apple_kind, string dst_kind, string lhs_kind,
5971                       string rhs_kind, list<dag> pattern>
5972   : I<(outs dst_reg:$dst),
5973       (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
5974       "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
5975       "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
5976     Sched<[WriteV]> {
5977   bits<5> Rd;
5978   bits<5> Rn;
5979   bits<5> Rm;
5980
5981   let Inst{31}    = 0;
5982   let Inst{30}    = Q;
5983   let Inst{29}    = U;
5984   let Inst{28}    = Scalar;
5985   let Inst{27-24} = 0b1111;
5986   let Inst{23-22} = size;
5987   // Bit 21 must be set by the derived class.
5988   let Inst{20-16} = Rm;
5989   let Inst{15-12} = opc;
5990   // Bit 11 must be set by the derived class.
5991   let Inst{10}    = 0;
5992   let Inst{9-5}   = Rn;
5993   let Inst{4-0}   = Rd;
5994 }
5995
5996 multiclass SIMDFPIndexedSD<bit U, bits<4> opc, string asm,
5997                            SDPatternOperator OpNode> {
5998   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
5999                                       V64, V64,
6000                                       V128, VectorIndexS,
6001                                       asm, ".2s", ".2s", ".2s", ".s",
6002     [(set (v2f32 V64:$Rd),
6003         (OpNode (v2f32 V64:$Rn),
6004          (v2f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6005     bits<2> idx;
6006     let Inst{11} = idx{1};
6007     let Inst{21} = idx{0};
6008   }
6009
6010   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6011                                       V128, V128,
6012                                       V128, VectorIndexS,
6013                                       asm, ".4s", ".4s", ".4s", ".s",
6014     [(set (v4f32 V128:$Rd),
6015         (OpNode (v4f32 V128:$Rn),
6016          (v4f32 (ARM64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6017     bits<2> idx;
6018     let Inst{11} = idx{1};
6019     let Inst{21} = idx{0};
6020   }
6021
6022   def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6023                                       V128, V128,
6024                                       V128, VectorIndexD,
6025                                       asm, ".2d", ".2d", ".2d", ".d",
6026     [(set (v2f64 V128:$Rd),
6027         (OpNode (v2f64 V128:$Rn),
6028          (v2f64 (ARM64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6029     bits<1> idx;
6030     let Inst{11} = idx{0};
6031     let Inst{21} = 0;
6032   }
6033
6034   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6035                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6036                                       asm, ".s", "", "", ".s",
6037     [(set (f32 FPR32Op:$Rd),
6038           (OpNode (f32 FPR32Op:$Rn),
6039                   (f32 (vector_extract (v4f32 V128:$Rm),
6040                                        VectorIndexS:$idx))))]> {
6041     bits<2> idx;
6042     let Inst{11} = idx{1};
6043     let Inst{21} = idx{0};
6044   }
6045
6046   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6047                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6048                                       asm, ".d", "", "", ".d",
6049     [(set (f64 FPR64Op:$Rd),
6050           (OpNode (f64 FPR64Op:$Rn),
6051                   (f64 (vector_extract (v2f64 V128:$Rm),
6052                                        VectorIndexD:$idx))))]> {
6053     bits<1> idx;
6054     let Inst{11} = idx{0};
6055     let Inst{21} = 0;
6056   }
6057 }
6058
6059 multiclass SIMDFPIndexedSDTiedPatterns<string INST, SDPatternOperator OpNode> {
6060   // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6061   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6062                            (ARM64duplane32 (v4f32 V128:$Rm),
6063                                            VectorIndexS:$idx))),
6064             (!cast<Instruction>(INST # v2i32_indexed)
6065                 V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6066   def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6067                            (ARM64dup (f32 FPR32Op:$Rm)))),
6068             (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6069                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6070
6071
6072   // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6073   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6074                            (ARM64duplane32 (v4f32 V128:$Rm),
6075                                            VectorIndexS:$idx))),
6076             (!cast<Instruction>(INST # "v4i32_indexed")
6077                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6078   def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6079                            (ARM64dup (f32 FPR32Op:$Rm)))),
6080             (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6081                 (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6082
6083   // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6084   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6085                            (ARM64duplane64 (v2f64 V128:$Rm),
6086                                            VectorIndexD:$idx))),
6087             (!cast<Instruction>(INST # "v2i64_indexed")
6088                 V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6089   def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6090                            (ARM64dup (f64 FPR64Op:$Rm)))),
6091             (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6092                 (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6093
6094   // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6095   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6096                          (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6097             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6098                 V128:$Rm, VectorIndexS:$idx)>;
6099   def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6100                          (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6101             (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6102                 (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6103
6104   // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6105   def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6106                          (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6107             (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6108                 V128:$Rm, VectorIndexD:$idx)>;
6109 }
6110
6111 multiclass SIMDFPIndexedSDTied<bit U, bits<4> opc, string asm> {
6112   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6113                                           V128, VectorIndexS,
6114                                           asm, ".2s", ".2s", ".2s", ".s", []> {
6115     bits<2> idx;
6116     let Inst{11} = idx{1};
6117     let Inst{21} = idx{0};
6118   }
6119
6120   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6121                                       V128, V128,
6122                                       V128, VectorIndexS,
6123                                       asm, ".4s", ".4s", ".4s", ".s", []> {
6124     bits<2> idx;
6125     let Inst{11} = idx{1};
6126     let Inst{21} = idx{0};
6127   }
6128
6129   def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6130                                       V128, V128,
6131                                       V128, VectorIndexD,
6132                                       asm, ".2d", ".2d", ".2d", ".d", []> {
6133     bits<1> idx;
6134     let Inst{11} = idx{0};
6135     let Inst{21} = 0;
6136   }
6137
6138
6139   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6140                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6141                                       asm, ".s", "", "", ".s", []> {
6142     bits<2> idx;
6143     let Inst{11} = idx{1};
6144     let Inst{21} = idx{0};
6145   }
6146
6147   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
6148                                       FPR64Op, FPR64Op, V128, VectorIndexD,
6149                                       asm, ".d", "", "", ".d", []> {
6150     bits<1> idx;
6151     let Inst{11} = idx{0};
6152     let Inst{21} = 0;
6153   }
6154 }
6155
6156 multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
6157                          SDPatternOperator OpNode> {
6158   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
6159                                       V128_lo, VectorIndexH,
6160                                       asm, ".4h", ".4h", ".4h", ".h",
6161     [(set (v4i16 V64:$Rd),
6162         (OpNode (v4i16 V64:$Rn),
6163          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6164     bits<3> idx;
6165     let Inst{11} = idx{2};
6166     let Inst{21} = idx{1};
6167     let Inst{20} = idx{0};
6168   }
6169
6170   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6171                                       V128, V128,
6172                                       V128_lo, VectorIndexH,
6173                                       asm, ".8h", ".8h", ".8h", ".h",
6174     [(set (v8i16 V128:$Rd),
6175        (OpNode (v8i16 V128:$Rn),
6176          (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6177     bits<3> idx;
6178     let Inst{11} = idx{2};
6179     let Inst{21} = idx{1};
6180     let Inst{20} = idx{0};
6181   }
6182
6183   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6184                                       V64, V64,
6185                                       V128, VectorIndexS,
6186                                       asm, ".2s", ".2s", ".2s",  ".s",
6187     [(set (v2i32 V64:$Rd),
6188        (OpNode (v2i32 V64:$Rn),
6189           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6190     bits<2> idx;
6191     let Inst{11} = idx{1};
6192     let Inst{21} = idx{0};
6193   }
6194
6195   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6196                                       V128, V128,
6197                                       V128, VectorIndexS,
6198                                       asm, ".4s", ".4s", ".4s", ".s",
6199     [(set (v4i32 V128:$Rd),
6200        (OpNode (v4i32 V128:$Rn),
6201           (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6202     bits<2> idx;
6203     let Inst{11} = idx{1};
6204     let Inst{21} = idx{0};
6205   }
6206
6207   def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6208                                       FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6209                                       asm, ".h", "", "", ".h", []> {
6210     bits<3> idx;
6211     let Inst{11} = idx{2};
6212     let Inst{21} = idx{1};
6213     let Inst{20} = idx{0};
6214   }
6215
6216   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6217                                       FPR32Op, FPR32Op, V128, VectorIndexS,
6218                                       asm, ".s", "", "", ".s",
6219       [(set (i32 FPR32Op:$Rd),
6220             (OpNode FPR32Op:$Rn,
6221                     (i32 (vector_extract (v4i32 V128:$Rm),
6222                                          VectorIndexS:$idx))))]> {
6223     bits<2> idx;
6224     let Inst{11} = idx{1};
6225     let Inst{21} = idx{0};
6226   }
6227 }
6228
6229 multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
6230                                SDPatternOperator OpNode> {
6231   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6232                                       V64, V64,
6233                                       V128_lo, VectorIndexH,
6234                                       asm, ".4h", ".4h", ".4h", ".h",
6235     [(set (v4i16 V64:$Rd),
6236         (OpNode (v4i16 V64:$Rn),
6237          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6238     bits<3> idx;
6239     let Inst{11} = idx{2};
6240     let Inst{21} = idx{1};
6241     let Inst{20} = idx{0};
6242   }
6243
6244   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6245                                       V128, V128,
6246                                       V128_lo, VectorIndexH,
6247                                       asm, ".8h", ".8h", ".8h", ".h",
6248     [(set (v8i16 V128:$Rd),
6249        (OpNode (v8i16 V128:$Rn),
6250          (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6251     bits<3> idx;
6252     let Inst{11} = idx{2};
6253     let Inst{21} = idx{1};
6254     let Inst{20} = idx{0};
6255   }
6256
6257   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6258                                       V64, V64,
6259                                       V128, VectorIndexS,
6260                                       asm, ".2s", ".2s", ".2s", ".s",
6261     [(set (v2i32 V64:$Rd),
6262        (OpNode (v2i32 V64:$Rn),
6263           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6264     bits<2> idx;
6265     let Inst{11} = idx{1};
6266     let Inst{21} = idx{0};
6267   }
6268
6269   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6270                                       V128, V128,
6271                                       V128, VectorIndexS,
6272                                       asm, ".4s", ".4s", ".4s", ".s",
6273     [(set (v4i32 V128:$Rd),
6274        (OpNode (v4i32 V128:$Rn),
6275           (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6276     bits<2> idx;
6277     let Inst{11} = idx{1};
6278     let Inst{21} = idx{0};
6279   }
6280 }
6281
6282 multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
6283                                    SDPatternOperator OpNode> {
6284   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
6285                                           V128_lo, VectorIndexH,
6286                                           asm, ".4h", ".4h", ".4h", ".h",
6287     [(set (v4i16 V64:$dst),
6288         (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
6289          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6290     bits<3> idx;
6291     let Inst{11} = idx{2};
6292     let Inst{21} = idx{1};
6293     let Inst{20} = idx{0};
6294   }
6295
6296   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6297                                       V128, V128,
6298                                       V128_lo, VectorIndexH,
6299                                       asm, ".8h", ".8h", ".8h", ".h",
6300     [(set (v8i16 V128:$dst),
6301        (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
6302          (v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6303     bits<3> idx;
6304     let Inst{11} = idx{2};
6305     let Inst{21} = idx{1};
6306     let Inst{20} = idx{0};
6307   }
6308
6309   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6310                                       V64, V64,
6311                                       V128, VectorIndexS,
6312                                       asm, ".2s", ".2s", ".2s", ".s",
6313     [(set (v2i32 V64:$dst),
6314        (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
6315           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6316     bits<2> idx;
6317     let Inst{11} = idx{1};
6318     let Inst{21} = idx{0};
6319   }
6320
6321   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6322                                       V128, V128,
6323                                       V128, VectorIndexS,
6324                                       asm, ".4s", ".4s", ".4s", ".s",
6325     [(set (v4i32 V128:$dst),
6326        (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
6327           (v4i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6328     bits<2> idx;
6329     let Inst{11} = idx{1};
6330     let Inst{21} = idx{0};
6331   }
6332 }
6333
6334 multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
6335                              SDPatternOperator OpNode> {
6336   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6337                                       V128, V64,
6338                                       V128_lo, VectorIndexH,
6339                                       asm, ".4s", ".4s", ".4h", ".h",
6340     [(set (v4i32 V128:$Rd),
6341         (OpNode (v4i16 V64:$Rn),
6342          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6343     bits<3> idx;
6344     let Inst{11} = idx{2};
6345     let Inst{21} = idx{1};
6346     let Inst{20} = idx{0};
6347   }
6348
6349   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6350                                       V128, V128,
6351                                       V128_lo, VectorIndexH,
6352                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6353     [(set (v4i32 V128:$Rd),
6354           (OpNode (extract_high_v8i16 V128:$Rn),
6355                   (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6356                                                       VectorIndexH:$idx))))]> {
6357
6358     bits<3> idx;
6359     let Inst{11} = idx{2};
6360     let Inst{21} = idx{1};
6361     let Inst{20} = idx{0};
6362   }
6363
6364   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6365                                       V128, V64,
6366                                       V128, VectorIndexS,
6367                                       asm, ".2d", ".2d", ".2s", ".s",
6368     [(set (v2i64 V128:$Rd),
6369         (OpNode (v2i32 V64:$Rn),
6370          (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6371     bits<2> idx;
6372     let Inst{11} = idx{1};
6373     let Inst{21} = idx{0};
6374   }
6375
6376   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6377                                       V128, V128,
6378                                       V128, VectorIndexS,
6379                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6380     [(set (v2i64 V128:$Rd),
6381           (OpNode (extract_high_v4i32 V128:$Rn),
6382                   (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6383                                                       VectorIndexS:$idx))))]> {
6384     bits<2> idx;
6385     let Inst{11} = idx{1};
6386     let Inst{21} = idx{0};
6387   }
6388
6389   def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
6390                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6391                                       asm, ".h", "", "", ".h", []> {
6392     bits<3> idx;
6393     let Inst{11} = idx{2};
6394     let Inst{21} = idx{1};
6395     let Inst{20} = idx{0};
6396   }
6397
6398   def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6399                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6400                                       asm, ".s", "", "", ".s", []> {
6401     bits<2> idx;
6402     let Inst{11} = idx{1};
6403     let Inst{21} = idx{0};
6404   }
6405 }
6406
6407 multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
6408                                        SDPatternOperator Accum> {
6409   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6410                                       V128, V64,
6411                                       V128_lo, VectorIndexH,
6412                                       asm, ".4s", ".4s", ".4h", ".h",
6413     [(set (v4i32 V128:$dst),
6414           (Accum (v4i32 V128:$Rd),
6415                  (v4i32 (int_arm64_neon_sqdmull
6416                              (v4i16 V64:$Rn),
6417                              (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6418                                                     VectorIndexH:$idx))))))]> {
6419     bits<3> idx;
6420     let Inst{11} = idx{2};
6421     let Inst{21} = idx{1};
6422     let Inst{20} = idx{0};
6423   }
6424
6425   // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
6426   // intermediate EXTRACT_SUBREG would be untyped.
6427   def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
6428                 (i32 (vector_extract (v4i32
6429                          (int_arm64_neon_sqdmull (v4i16 V64:$Rn),
6430                              (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6431                                                     VectorIndexH:$idx)))),
6432                          (i64 0))))),
6433             (EXTRACT_SUBREG
6434                 (!cast<Instruction>(NAME # v4i16_indexed)
6435                     (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
6436                     V128_lo:$Rm, VectorIndexH:$idx),
6437                 ssub)>;
6438
6439   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6440                                       V128, V128,
6441                                       V128_lo, VectorIndexH,
6442                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6443     [(set (v4i32 V128:$dst),
6444           (Accum (v4i32 V128:$Rd),
6445                  (v4i32 (int_arm64_neon_sqdmull
6446                             (extract_high_v8i16 V128:$Rn),
6447                             (extract_high_v8i16
6448                                 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6449                                                 VectorIndexH:$idx))))))]> {
6450     bits<3> idx;
6451     let Inst{11} = idx{2};
6452     let Inst{21} = idx{1};
6453     let Inst{20} = idx{0};
6454   }
6455
6456   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6457                                       V128, V64,
6458                                       V128, VectorIndexS,
6459                                       asm, ".2d", ".2d", ".2s", ".s",
6460     [(set (v2i64 V128:$dst),
6461         (Accum (v2i64 V128:$Rd),
6462                (v2i64 (int_arm64_neon_sqdmull
6463                           (v2i32 V64:$Rn),
6464                           (v2i32 (ARM64duplane32 (v4i32 V128:$Rm),
6465                                                  VectorIndexS:$idx))))))]> {
6466     bits<2> idx;
6467     let Inst{11} = idx{1};
6468     let Inst{21} = idx{0};
6469   }
6470
6471   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6472                                       V128, V128,
6473                                       V128, VectorIndexS,
6474                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6475     [(set (v2i64 V128:$dst),
6476           (Accum (v2i64 V128:$Rd),
6477                  (v2i64 (int_arm64_neon_sqdmull
6478                             (extract_high_v4i32 V128:$Rn),
6479                             (extract_high_v4i32
6480                                 (ARM64duplane32 (v4i32 V128:$Rm),
6481                                                 VectorIndexS:$idx))))))]> {
6482     bits<2> idx;
6483     let Inst{11} = idx{1};
6484     let Inst{21} = idx{0};
6485   }
6486
6487   def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
6488                                       FPR32Op, FPR16Op, V128_lo, VectorIndexH,
6489                                       asm, ".h", "", "", ".h", []> {
6490     bits<3> idx;
6491     let Inst{11} = idx{2};
6492     let Inst{21} = idx{1};
6493     let Inst{20} = idx{0};
6494   }
6495
6496
6497   def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
6498                                       FPR64Op, FPR32Op, V128, VectorIndexS,
6499                                       asm, ".s", "", "", ".s",
6500     [(set (i64 FPR64Op:$dst),
6501           (Accum (i64 FPR64Op:$Rd),
6502                  (i64 (int_arm64_neon_sqdmulls_scalar
6503                             (i32 FPR32Op:$Rn),
6504                             (i32 (vector_extract (v4i32 V128:$Rm),
6505                                                  VectorIndexS:$idx))))))]> {
6506
6507     bits<2> idx;
6508     let Inst{11} = idx{1};
6509     let Inst{21} = idx{0};
6510   }
6511 }
6512
6513 multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
6514                                    SDPatternOperator OpNode> {
6515   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6516   def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
6517                                       V128, V64,
6518                                       V128_lo, VectorIndexH,
6519                                       asm, ".4s", ".4s", ".4h", ".h",
6520     [(set (v4i32 V128:$Rd),
6521         (OpNode (v4i16 V64:$Rn),
6522          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6523     bits<3> idx;
6524     let Inst{11} = idx{2};
6525     let Inst{21} = idx{1};
6526     let Inst{20} = idx{0};
6527   }
6528
6529   def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
6530                                       V128, V128,
6531                                       V128_lo, VectorIndexH,
6532                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6533     [(set (v4i32 V128:$Rd),
6534           (OpNode (extract_high_v8i16 V128:$Rn),
6535                   (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6536                                                       VectorIndexH:$idx))))]> {
6537
6538     bits<3> idx;
6539     let Inst{11} = idx{2};
6540     let Inst{21} = idx{1};
6541     let Inst{20} = idx{0};
6542   }
6543
6544   def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6545                                       V128, V64,
6546                                       V128, VectorIndexS,
6547                                       asm, ".2d", ".2d", ".2s", ".s",
6548     [(set (v2i64 V128:$Rd),
6549         (OpNode (v2i32 V64:$Rn),
6550          (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6551     bits<2> idx;
6552     let Inst{11} = idx{1};
6553     let Inst{21} = idx{0};
6554   }
6555
6556   def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6557                                       V128, V128,
6558                                       V128, VectorIndexS,
6559                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6560     [(set (v2i64 V128:$Rd),
6561           (OpNode (extract_high_v4i32 V128:$Rn),
6562                   (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6563                                                       VectorIndexS:$idx))))]> {
6564     bits<2> idx;
6565     let Inst{11} = idx{1};
6566     let Inst{21} = idx{0};
6567   }
6568   }
6569 }
6570
6571 multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
6572                                        SDPatternOperator OpNode> {
6573   let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6574   def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
6575                                       V128, V64,
6576                                       V128_lo, VectorIndexH,
6577                                       asm, ".4s", ".4s", ".4h", ".h",
6578     [(set (v4i32 V128:$dst),
6579         (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
6580          (v4i16 (ARM64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6581     bits<3> idx;
6582     let Inst{11} = idx{2};
6583     let Inst{21} = idx{1};
6584     let Inst{20} = idx{0};
6585   }
6586
6587   def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
6588                                       V128, V128,
6589                                       V128_lo, VectorIndexH,
6590                                       asm#"2", ".4s", ".4s", ".8h", ".h",
6591     [(set (v4i32 V128:$dst),
6592           (OpNode (v4i32 V128:$Rd),
6593                   (extract_high_v8i16 V128:$Rn),
6594                   (extract_high_v8i16 (ARM64duplane16 (v8i16 V128_lo:$Rm),
6595                                                       VectorIndexH:$idx))))]> {
6596     bits<3> idx;
6597     let Inst{11} = idx{2};
6598     let Inst{21} = idx{1};
6599     let Inst{20} = idx{0};
6600   }
6601
6602   def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
6603                                       V128, V64,
6604                                       V128, VectorIndexS,
6605                                       asm, ".2d", ".2d", ".2s", ".s",
6606     [(set (v2i64 V128:$dst),
6607         (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
6608          (v2i32 (ARM64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
6609     bits<2> idx;
6610     let Inst{11} = idx{1};
6611     let Inst{21} = idx{0};
6612   }
6613
6614   def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6615                                       V128, V128,
6616                                       V128, VectorIndexS,
6617                                       asm#"2", ".2d", ".2d", ".4s", ".s",
6618     [(set (v2i64 V128:$dst),
6619           (OpNode (v2i64 V128:$Rd),
6620                   (extract_high_v4i32 V128:$Rn),
6621                   (extract_high_v4i32 (ARM64duplane32 (v4i32 V128:$Rm),
6622                                                       VectorIndexS:$idx))))]> {
6623     bits<2> idx;
6624     let Inst{11} = idx{1};
6625     let Inst{21} = idx{0};
6626   }
6627   }
6628 }
6629
6630 //----------------------------------------------------------------------------
6631 // AdvSIMD scalar shift by immediate
6632 //----------------------------------------------------------------------------
6633
6634 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6635 class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
6636                      RegisterClass regtype1, RegisterClass regtype2,
6637                      Operand immtype, string asm, list<dag> pattern>
6638   : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
6639       asm, "\t$Rd, $Rn, $imm", "", pattern>,
6640     Sched<[WriteV]> {
6641   bits<5> Rd;
6642   bits<5> Rn;
6643   bits<7> imm;
6644   let Inst{31-30} = 0b01;
6645   let Inst{29}    = U;
6646   let Inst{28-23} = 0b111110;
6647   let Inst{22-16} = fixed_imm;
6648   let Inst{15-11} = opc;
6649   let Inst{10}    = 1;
6650   let Inst{9-5} = Rn;
6651   let Inst{4-0} = Rd;
6652 }
6653
6654 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6655 class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
6656                      RegisterClass regtype1, RegisterClass regtype2,
6657                      Operand immtype, string asm, list<dag> pattern>
6658   : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
6659       asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
6660     Sched<[WriteV]> {
6661   bits<5> Rd;
6662   bits<5> Rn;
6663   bits<7> imm;
6664   let Inst{31-30} = 0b01;
6665   let Inst{29}    = U;
6666   let Inst{28-23} = 0b111110;
6667   let Inst{22-16} = fixed_imm;
6668   let Inst{15-11} = opc;
6669   let Inst{10}    = 1;
6670   let Inst{9-5} = Rn;
6671   let Inst{4-0} = Rd;
6672 }
6673
6674
6675 multiclass SIMDScalarRShiftSD<bit U, bits<5> opc, string asm> {
6676   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6677                               FPR32, FPR32, vecshiftR32, asm, []> {
6678     let Inst{20-16} = imm{4-0};
6679   }
6680
6681   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6682                               FPR64, FPR64, vecshiftR64, asm, []> {
6683     let Inst{21-16} = imm{5-0};
6684   }
6685 }
6686
6687 multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
6688                              SDPatternOperator OpNode> {
6689   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6690                               FPR64, FPR64, vecshiftR64, asm,
6691   [(set (i64 FPR64:$Rd),
6692      (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
6693     let Inst{21-16} = imm{5-0};
6694   }
6695
6696   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
6697             (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
6698 }
6699
6700 multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
6701                                  SDPatternOperator OpNode = null_frag> {
6702   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6703                               FPR64, FPR64, vecshiftR64, asm,
6704   [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
6705                                                    (i32 vecshiftR64:$imm)))]> {
6706     let Inst{21-16} = imm{5-0};
6707   }
6708
6709   def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
6710                            (i32 vecshiftR64:$imm))),
6711             (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
6712                                             vecshiftR64:$imm)>;
6713 }
6714
6715 multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
6716                              SDPatternOperator OpNode> {
6717   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6718                               FPR64, FPR64, vecshiftL64, asm,
6719     [(set (v1i64 FPR64:$Rd),
6720        (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
6721     let Inst{21-16} = imm{5-0};
6722   }
6723 }
6724
6725 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6726 multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
6727   def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
6728                               FPR64, FPR64, vecshiftL64, asm, []> {
6729     let Inst{21-16} = imm{5-0};
6730   }
6731 }
6732
6733 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6734 multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
6735                                SDPatternOperator OpNode = null_frag> {
6736   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6737                               FPR8, FPR16, vecshiftR8, asm, []> {
6738     let Inst{18-16} = imm{2-0};
6739   }
6740
6741   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6742                               FPR16, FPR32, vecshiftR16, asm, []> {
6743     let Inst{19-16} = imm{3-0};
6744   }
6745
6746   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6747                               FPR32, FPR64, vecshiftR32, asm,
6748     [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
6749     let Inst{20-16} = imm{4-0};
6750   }
6751 }
6752
6753 multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
6754                                 SDPatternOperator OpNode> {
6755   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6756                               FPR8, FPR8, vecshiftL8, asm, []> {
6757     let Inst{18-16} = imm{2-0};
6758   }
6759
6760   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6761                               FPR16, FPR16, vecshiftL16, asm, []> {
6762     let Inst{19-16} = imm{3-0};
6763   }
6764
6765   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6766                               FPR32, FPR32, vecshiftL32, asm,
6767     [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
6768     let Inst{20-16} = imm{4-0};
6769   }
6770
6771   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6772                               FPR64, FPR64, vecshiftL64, asm,
6773     [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn),
6774                                      (i32 vecshiftL64:$imm)))]> {
6775     let Inst{21-16} = imm{5-0};
6776   }
6777 }
6778
6779 multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
6780   def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
6781                               FPR8, FPR8, vecshiftR8, asm, []> {
6782     let Inst{18-16} = imm{2-0};
6783   }
6784
6785   def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
6786                               FPR16, FPR16, vecshiftR16, asm, []> {
6787     let Inst{19-16} = imm{3-0};
6788   }
6789
6790   def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
6791                               FPR32, FPR32, vecshiftR32, asm, []> {
6792     let Inst{20-16} = imm{4-0};
6793   }
6794
6795   def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
6796                               FPR64, FPR64, vecshiftR64, asm, []> {
6797     let Inst{21-16} = imm{5-0};
6798   }
6799 }
6800
6801 //----------------------------------------------------------------------------
6802 // AdvSIMD vector x indexed element
6803 //----------------------------------------------------------------------------
6804
6805 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6806 class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6807                      RegisterOperand dst_reg, RegisterOperand src_reg,
6808                      Operand immtype,
6809                      string asm, string dst_kind, string src_kind,
6810                      list<dag> pattern>
6811   : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
6812       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6813            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
6814     Sched<[WriteV]> {
6815   bits<5> Rd;
6816   bits<5> Rn;
6817   let Inst{31}    = 0;
6818   let Inst{30}    = Q;
6819   let Inst{29}    = U;
6820   let Inst{28-23} = 0b011110;
6821   let Inst{22-16} = fixed_imm;
6822   let Inst{15-11} = opc;
6823   let Inst{10}    = 1;
6824   let Inst{9-5}   = Rn;
6825   let Inst{4-0}   = Rd;
6826 }
6827
6828 let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6829 class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
6830                      RegisterOperand vectype1, RegisterOperand vectype2,
6831                      Operand immtype,
6832                      string asm, string dst_kind, string src_kind,
6833                      list<dag> pattern>
6834   : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
6835       asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
6836            "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
6837     Sched<[WriteV]> {
6838   bits<5> Rd;
6839   bits<5> Rn;
6840   let Inst{31}    = 0;
6841   let Inst{30}    = Q;
6842   let Inst{29}    = U;
6843   let Inst{28-23} = 0b011110;
6844   let Inst{22-16} = fixed_imm;
6845   let Inst{15-11} = opc;
6846   let Inst{10}    = 1;
6847   let Inst{9-5}   = Rn;
6848   let Inst{4-0}   = Rd;
6849 }
6850
6851 multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
6852                               Intrinsic OpNode> {
6853   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6854                                   V64, V64, vecshiftR32,
6855                                   asm, ".2s", ".2s",
6856       [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
6857     bits<5> imm;
6858     let Inst{20-16} = imm;
6859   }
6860
6861   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6862                                   V128, V128, vecshiftR32,
6863                                   asm, ".4s", ".4s",
6864       [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
6865     bits<5> imm;
6866     let Inst{20-16} = imm;
6867   }
6868
6869   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6870                                   V128, V128, vecshiftR64,
6871                                   asm, ".2d", ".2d",
6872       [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
6873     bits<6> imm;
6874     let Inst{21-16} = imm;
6875   }
6876 }
6877
6878 multiclass SIMDVectorRShiftSDToFP<bit U, bits<5> opc, string asm,
6879                                   Intrinsic OpNode> {
6880   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6881                                   V64, V64, vecshiftR32,
6882                                   asm, ".2s", ".2s",
6883       [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
6884     bits<5> imm;
6885     let Inst{20-16} = imm;
6886   }
6887
6888   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
6889                                   V128, V128, vecshiftR32,
6890                                   asm, ".4s", ".4s",
6891       [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
6892     bits<5> imm;
6893     let Inst{20-16} = imm;
6894   }
6895
6896   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
6897                                   V128, V128, vecshiftR64,
6898                                   asm, ".2d", ".2d",
6899       [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
6900     bits<6> imm;
6901     let Inst{21-16} = imm;
6902   }
6903 }
6904
6905 multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
6906                                      SDPatternOperator OpNode> {
6907   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6908                                   V64, V128, vecshiftR16Narrow,
6909                                   asm, ".8b", ".8h",
6910       [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
6911     bits<3> imm;
6912     let Inst{18-16} = imm;
6913   }
6914
6915   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
6916                                   V128, V128, vecshiftR16Narrow,
6917                                   asm#"2", ".16b", ".8h", []> {
6918     bits<3> imm;
6919     let Inst{18-16} = imm;
6920     let hasSideEffects = 0;
6921   }
6922
6923   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6924                                   V64, V128, vecshiftR32Narrow,
6925                                   asm, ".4h", ".4s",
6926       [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
6927     bits<4> imm;
6928     let Inst{19-16} = imm;
6929   }
6930
6931   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
6932                                   V128, V128, vecshiftR32Narrow,
6933                                   asm#"2", ".8h", ".4s", []> {
6934     bits<4> imm;
6935     let Inst{19-16} = imm;
6936     let hasSideEffects = 0;
6937   }
6938
6939   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
6940                                   V64, V128, vecshiftR64Narrow,
6941                                   asm, ".2s", ".2d",
6942       [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
6943     bits<5> imm;
6944     let Inst{20-16} = imm;
6945   }
6946
6947   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
6948                                   V128, V128, vecshiftR64Narrow,
6949                                   asm#"2", ".4s", ".2d", []> {
6950     bits<5> imm;
6951     let Inst{20-16} = imm;
6952     let hasSideEffects = 0;
6953   }
6954
6955   // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
6956   // themselves, so put them here instead.
6957
6958   // Patterns involving what's effectively an insert high and a normal
6959   // intrinsic, represented by CONCAT_VECTORS.
6960   def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
6961                                                    vecshiftR16Narrow:$imm)),
6962             (!cast<Instruction>(NAME # "v16i8_shift")
6963                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6964                 V128:$Rn, vecshiftR16Narrow:$imm)>;
6965   def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
6966                                                      vecshiftR32Narrow:$imm)),
6967             (!cast<Instruction>(NAME # "v8i16_shift")
6968                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6969                 V128:$Rn, vecshiftR32Narrow:$imm)>;
6970   def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
6971                                                      vecshiftR64Narrow:$imm)),
6972             (!cast<Instruction>(NAME # "v4i32_shift")
6973                 (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6974                 V128:$Rn, vecshiftR64Narrow:$imm)>;
6975 }
6976
6977 multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
6978                                 SDPatternOperator OpNode> {
6979   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
6980                                   V64, V64, vecshiftL8,
6981                                   asm, ".8b", ".8b",
6982                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
6983                        (i32 vecshiftL8:$imm)))]> {
6984     bits<3> imm;
6985     let Inst{18-16} = imm;
6986   }
6987
6988   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
6989                                   V128, V128, vecshiftL8,
6990                                   asm, ".16b", ".16b",
6991              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
6992                    (i32 vecshiftL8:$imm)))]> {
6993     bits<3> imm;
6994     let Inst{18-16} = imm;
6995   }
6996
6997   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
6998                                   V64, V64, vecshiftL16,
6999                                   asm, ".4h", ".4h",
7000               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7001                     (i32 vecshiftL16:$imm)))]> {
7002     bits<4> imm;
7003     let Inst{19-16} = imm;
7004   }
7005
7006   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7007                                   V128, V128, vecshiftL16,
7008                                   asm, ".8h", ".8h",
7009             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7010                   (i32 vecshiftL16:$imm)))]> {
7011     bits<4> imm;
7012     let Inst{19-16} = imm;
7013   }
7014
7015   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7016                                   V64, V64, vecshiftL32,
7017                                   asm, ".2s", ".2s",
7018               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7019                     (i32 vecshiftL32:$imm)))]> {
7020     bits<5> imm;
7021     let Inst{20-16} = imm;
7022   }
7023
7024   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7025                                   V128, V128, vecshiftL32,
7026                                   asm, ".4s", ".4s",
7027             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7028                   (i32 vecshiftL32:$imm)))]> {
7029     bits<5> imm;
7030     let Inst{20-16} = imm;
7031   }
7032
7033   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7034                                   V128, V128, vecshiftL64,
7035                                   asm, ".2d", ".2d",
7036             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7037                   (i32 vecshiftL64:$imm)))]> {
7038     bits<6> imm;
7039     let Inst{21-16} = imm;
7040   }
7041 }
7042
7043 multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7044                                 SDPatternOperator OpNode> {
7045   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7046                                   V64, V64, vecshiftR8,
7047                                   asm, ".8b", ".8b",
7048                  [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7049                        (i32 vecshiftR8:$imm)))]> {
7050     bits<3> imm;
7051     let Inst{18-16} = imm;
7052   }
7053
7054   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7055                                   V128, V128, vecshiftR8,
7056                                   asm, ".16b", ".16b",
7057              [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7058                    (i32 vecshiftR8:$imm)))]> {
7059     bits<3> imm;
7060     let Inst{18-16} = imm;
7061   }
7062
7063   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7064                                   V64, V64, vecshiftR16,
7065                                   asm, ".4h", ".4h",
7066               [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7067                     (i32 vecshiftR16:$imm)))]> {
7068     bits<4> imm;
7069     let Inst{19-16} = imm;
7070   }
7071
7072   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7073                                   V128, V128, vecshiftR16,
7074                                   asm, ".8h", ".8h",
7075             [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7076                   (i32 vecshiftR16:$imm)))]> {
7077     bits<4> imm;
7078     let Inst{19-16} = imm;
7079   }
7080
7081   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7082                                   V64, V64, vecshiftR32,
7083                                   asm, ".2s", ".2s",
7084               [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7085                     (i32 vecshiftR32:$imm)))]> {
7086     bits<5> imm;
7087     let Inst{20-16} = imm;
7088   }
7089
7090   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7091                                   V128, V128, vecshiftR32,
7092                                   asm, ".4s", ".4s",
7093             [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7094                   (i32 vecshiftR32:$imm)))]> {
7095     bits<5> imm;
7096     let Inst{20-16} = imm;
7097   }
7098
7099   def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7100                                   V128, V128, vecshiftR64,
7101                                   asm, ".2d", ".2d",
7102             [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7103                   (i32 vecshiftR64:$imm)))]> {
7104     bits<6> imm;
7105     let Inst{21-16} = imm;
7106   }
7107 }
7108
7109 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7110 multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
7111                                     SDPatternOperator OpNode = null_frag> {
7112   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7113                                   V64, V64, vecshiftR8, asm, ".8b", ".8b",
7114                  [(set (v8i8 V64:$dst),
7115                    (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7116                            (i32 vecshiftR8:$imm)))]> {
7117     bits<3> imm;
7118     let Inst{18-16} = imm;
7119   }
7120
7121   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7122                                   V128, V128, vecshiftR8, asm, ".16b", ".16b",
7123              [(set (v16i8 V128:$dst),
7124                (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7125                        (i32 vecshiftR8:$imm)))]> {
7126     bits<3> imm;
7127     let Inst{18-16} = imm;
7128   }
7129
7130   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7131                                   V64, V64, vecshiftR16, asm, ".4h", ".4h",
7132               [(set (v4i16 V64:$dst),
7133                 (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7134                         (i32 vecshiftR16:$imm)))]> {
7135     bits<4> imm;
7136     let Inst{19-16} = imm;
7137   }
7138
7139   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7140                                   V128, V128, vecshiftR16, asm, ".8h", ".8h",
7141             [(set (v8i16 V128:$dst),
7142               (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7143                       (i32 vecshiftR16:$imm)))]> {
7144     bits<4> imm;
7145     let Inst{19-16} = imm;
7146   }
7147
7148   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7149                                   V64, V64, vecshiftR32, asm, ".2s", ".2s",
7150               [(set (v2i32 V64:$dst),
7151                 (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7152                         (i32 vecshiftR32:$imm)))]> {
7153     bits<5> imm;
7154     let Inst{20-16} = imm;
7155   }
7156
7157   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7158                                   V128, V128, vecshiftR32, asm, ".4s", ".4s",
7159             [(set (v4i32 V128:$dst),
7160               (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7161                       (i32 vecshiftR32:$imm)))]> {
7162     bits<5> imm;
7163     let Inst{20-16} = imm;
7164   }
7165
7166   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7167                                   V128, V128, vecshiftR64,
7168                                   asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
7169               (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7170                       (i32 vecshiftR64:$imm)))]> {
7171     bits<6> imm;
7172     let Inst{21-16} = imm;
7173   }
7174 }
7175
7176 multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
7177                                     SDPatternOperator OpNode = null_frag> {
7178   def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
7179                                   V64, V64, vecshiftL8,
7180                                   asm, ".8b", ".8b",
7181                     [(set (v8i8 V64:$dst),
7182                           (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
7183                                   (i32 vecshiftL8:$imm)))]> {
7184     bits<3> imm;
7185     let Inst{18-16} = imm;
7186   }
7187
7188   def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7189                                   V128, V128, vecshiftL8,
7190                                   asm, ".16b", ".16b",
7191                     [(set (v16i8 V128:$dst),
7192                           (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
7193                                   (i32 vecshiftL8:$imm)))]> {
7194     bits<3> imm;
7195     let Inst{18-16} = imm;
7196   }
7197
7198   def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
7199                                   V64, V64, vecshiftL16,
7200                                   asm, ".4h", ".4h",
7201                     [(set (v4i16 V64:$dst),
7202                            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
7203                                    (i32 vecshiftL16:$imm)))]> {
7204     bits<4> imm;
7205     let Inst{19-16} = imm;
7206   }
7207
7208   def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7209                                   V128, V128, vecshiftL16,
7210                                   asm, ".8h", ".8h",
7211                     [(set (v8i16 V128:$dst),
7212                           (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7213                                   (i32 vecshiftL16:$imm)))]> {
7214     bits<4> imm;
7215     let Inst{19-16} = imm;
7216   }
7217
7218   def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
7219                                   V64, V64, vecshiftL32,
7220                                   asm, ".2s", ".2s",
7221                     [(set (v2i32 V64:$dst),
7222                           (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7223                                   (i32 vecshiftL32:$imm)))]> {
7224     bits<5> imm;
7225     let Inst{20-16} = imm;
7226   }
7227
7228   def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7229                                   V128, V128, vecshiftL32,
7230                                   asm, ".4s", ".4s",
7231                     [(set (v4i32 V128:$dst),
7232                           (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7233                                   (i32 vecshiftL32:$imm)))]> {
7234     bits<5> imm;
7235     let Inst{20-16} = imm;
7236   }
7237
7238   def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
7239                                   V128, V128, vecshiftL64,
7240                                   asm, ".2d", ".2d",
7241                     [(set (v2i64 V128:$dst),
7242                           (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
7243                                   (i32 vecshiftL64:$imm)))]> {
7244     bits<6> imm;
7245     let Inst{21-16} = imm;
7246   }
7247 }
7248
7249 multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
7250                                    SDPatternOperator OpNode> {
7251   def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7252                                   V128, V64, vecshiftL8, asm, ".8h", ".8b",
7253       [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
7254     bits<3> imm;
7255     let Inst{18-16} = imm;
7256   }
7257
7258   def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7259                                   V128, V128, vecshiftL8,
7260                                   asm#"2", ".8h", ".16b",
7261       [(set (v8i16 V128:$Rd),
7262             (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
7263     bits<3> imm;
7264     let Inst{18-16} = imm;
7265   }
7266
7267   def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7268                                   V128, V64, vecshiftL16, asm, ".4s", ".4h",
7269       [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
7270     bits<4> imm;
7271     let Inst{19-16} = imm;
7272   }
7273
7274   def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7275                                   V128, V128, vecshiftL16,
7276                                   asm#"2", ".4s", ".8h",
7277       [(set (v4i32 V128:$Rd),
7278             (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
7279
7280     bits<4> imm;
7281     let Inst{19-16} = imm;
7282   }
7283
7284   def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7285                                   V128, V64, vecshiftL32, asm, ".2d", ".2s",
7286       [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
7287     bits<5> imm;
7288     let Inst{20-16} = imm;
7289   }
7290
7291   def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7292                                   V128, V128, vecshiftL32,
7293                                   asm#"2", ".2d", ".4s",
7294       [(set (v2i64 V128:$Rd),
7295             (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
7296     bits<5> imm;
7297     let Inst{20-16} = imm;
7298   }
7299 }
7300
7301
7302 //---
7303 // Vector load/store
7304 //---
7305 // SIMD ldX/stX no-index memory references don't allow the optional
7306 // ", #0" constant and handle post-indexing explicitly, so we use
7307 // a more specialized parse method for them. Otherwise, it's the same as
7308 // the general am_noindex handling.
7309 def MemorySIMDNoIndexOperand : AsmOperandClass {
7310   let Name = "MemorySIMDNoIndex";
7311   let ParserMethod = "tryParseNoIndexMemory";
7312 }
7313 def am_simdnoindex : Operand<i64>,
7314                      ComplexPattern<i64, 1, "SelectAddrModeNoIndex", []> {
7315   let PrintMethod = "printAMNoIndex";
7316   let ParserMatchClass = MemorySIMDNoIndexOperand;
7317   let MIOperandInfo = (ops GPR64sp:$base);
7318   let DecoderMethod = "DecodeGPR64spRegisterClass";
7319 }
7320
7321 class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
7322                    string asm, dag oops, dag iops, list<dag> pattern>
7323   : I<oops, iops, asm, "\t$Vt, $vaddr", "", pattern> {
7324   bits<5> Vt;
7325   bits<5> vaddr;
7326   let Inst{31} = 0;
7327   let Inst{30} = Q;
7328   let Inst{29-23} = 0b0011000;
7329   let Inst{22} = L;
7330   let Inst{21-16} = 0b000000;
7331   let Inst{15-12} = opcode;
7332   let Inst{11-10} = size;
7333   let Inst{9-5} = vaddr;
7334   let Inst{4-0} = Vt;
7335 }
7336
7337 class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
7338                        string asm, dag oops, dag iops>
7339   : I<oops, iops, asm, "\t$Vt, $vaddr, $Xm", "", []> {
7340   bits<5> Vt;
7341   bits<5> vaddr;
7342   bits<5> Xm;
7343   let Inst{31} = 0;
7344   let Inst{30} = Q;
7345   let Inst{29-23} = 0b0011001;
7346   let Inst{22} = L;
7347   let Inst{21} = 0;
7348   let Inst{20-16} = Xm;
7349   let Inst{15-12} = opcode;
7350   let Inst{11-10} = size;
7351   let Inst{9-5} = vaddr;
7352   let Inst{4-0} = Vt;
7353   let DecoderMethod = "DecodeSIMDLdStPost";
7354 }
7355
7356 // The immediate form of AdvSIMD post-indexed addressing is encoded with
7357 // register post-index addressing from the zero register.
7358 multiclass SIMDLdStAliases<string asm, string layout, string Count,
7359                            int Offset, int Size> {
7360   // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
7361   //      "ld1\t$Vt, $vaddr, #16"
7362   // may get mapped to
7363   //      (LD1Twov8b_POST VecListTwo8b:$Vt, am_simdnoindex:$vaddr, XZR)
7364   def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7365                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7366                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7367                       am_simdnoindex:$vaddr, XZR), 1>;
7368
7369   // E.g. "ld1.8b { v0, v1 }, [x1], #16"
7370   //      "ld1.8b\t$Vt, $vaddr, #16"
7371   // may get mapped to
7372   //      (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, XZR)
7373   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7374                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7375                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7376                       am_simdnoindex:$vaddr, XZR), 0>;
7377
7378   // E.g. "ld1.8b { v0, v1 }, [x1]"
7379   //      "ld1\t$Vt, $vaddr"
7380   // may get mapped to
7381   //      (LD1Twov8b VecListTwo64:$Vt, am_simdnoindex:$vaddr)
7382   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7383                   (!cast<Instruction>(NAME # Count # "v" # layout)
7384                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7385                       am_simdnoindex:$vaddr), 0>;
7386
7387   // E.g. "ld1.8b { v0, v1 }, [x1], x2"
7388   //      "ld1\t$Vt, $vaddr, $Xm"
7389   // may get mapped to
7390   //      (LD1Twov8b_POST VecListTwo64:$Vt, am_simdnoindex:$vaddr, GPR64pi8:$Xm)
7391   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7392                   (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
7393                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7394                       am_simdnoindex:$vaddr,
7395                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7396 }
7397
7398 multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
7399                        int Offset64, bits<4> opcode> {
7400   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7401     def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
7402                            (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7403                            (ins am_simdnoindex:$vaddr), []>;
7404     def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
7405                            (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7406                            (ins am_simdnoindex:$vaddr), []>;
7407     def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
7408                            (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7409                            (ins am_simdnoindex:$vaddr), []>;
7410     def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
7411                            (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7412                            (ins am_simdnoindex:$vaddr), []>;
7413     def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
7414                            (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7415                            (ins am_simdnoindex:$vaddr), []>;
7416     def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
7417                            (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7418                            (ins am_simdnoindex:$vaddr), []>;
7419     def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
7420                            (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7421                            (ins am_simdnoindex:$vaddr), []>;
7422
7423
7424     def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
7425                        (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
7426                        (ins am_simdnoindex:$vaddr,
7427                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7428     def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
7429                        (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
7430                        (ins am_simdnoindex:$vaddr,
7431                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7432     def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
7433                        (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
7434                        (ins am_simdnoindex:$vaddr,
7435                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7436     def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
7437                        (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
7438                        (ins am_simdnoindex:$vaddr,
7439                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7440     def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
7441                        (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
7442                        (ins am_simdnoindex:$vaddr,
7443                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7444     def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
7445                        (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
7446                        (ins am_simdnoindex:$vaddr,
7447                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7448     def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
7449                        (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
7450                        (ins am_simdnoindex:$vaddr,
7451                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7452   }
7453
7454   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7455   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7456   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7457   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7458   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7459   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7460   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7461 }
7462
7463 // Only ld1/st1 has a v1d version.
7464 multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
7465                        int Offset64, bits<4> opcode> {
7466   let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
7467     def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
7468                             (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7469                                  am_simdnoindex:$vaddr), []>;
7470     def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
7471                            (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7472                                 am_simdnoindex:$vaddr), []>;
7473     def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
7474                            (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7475                                 am_simdnoindex:$vaddr), []>;
7476     def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
7477                            (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7478                                 am_simdnoindex:$vaddr), []>;
7479     def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
7480                            (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7481                                 am_simdnoindex:$vaddr), []>;
7482     def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
7483                            (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7484                                 am_simdnoindex:$vaddr), []>;
7485     def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
7486                            (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7487                                 am_simdnoindex:$vaddr), []>;
7488
7489     def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm, (outs),
7490                        (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
7491                             am_simdnoindex:$vaddr,
7492                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7493     def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm, (outs),
7494                        (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
7495                             am_simdnoindex:$vaddr,
7496                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7497     def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm, (outs),
7498                        (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
7499                             am_simdnoindex:$vaddr,
7500                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7501     def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm, (outs),
7502                        (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
7503                             am_simdnoindex:$vaddr,
7504                             !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
7505     def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm, (outs),
7506                        (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
7507                             am_simdnoindex:$vaddr,
7508                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7509     def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm, (outs),
7510                        (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
7511                             am_simdnoindex:$vaddr,
7512                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7513     def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm, (outs),
7514                        (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
7515                             am_simdnoindex:$vaddr,
7516                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7517   }
7518
7519   defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
7520   defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
7521   defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
7522   defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
7523   defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
7524   defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
7525   defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
7526 }
7527
7528 multiclass BaseSIMDLd1<string Count, string asm, string veclist,
7529                        int Offset128, int Offset64, bits<4> opcode>
7530   : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
7531
7532   // LD1 instructions have extra "1d" variants.
7533   let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
7534     def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
7535                            (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7536                            (ins am_simdnoindex:$vaddr), []>;
7537
7538     def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
7539                        (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
7540                        (ins am_simdnoindex:$vaddr,
7541                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7542   }
7543
7544   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7545 }
7546
7547 multiclass BaseSIMDSt1<string Count, string asm, string veclist,
7548                        int Offset128, int Offset64, bits<4> opcode>
7549   : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
7550
7551   // ST1 instructions have extra "1d" variants.
7552   let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
7553     def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
7554                            (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7555                                 am_simdnoindex:$vaddr), []>;
7556
7557     def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm, (outs),
7558                        (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
7559                             am_simdnoindex:$vaddr,
7560                             !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
7561   }
7562
7563   defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
7564 }
7565
7566 multiclass SIMDLd1Multiple<string asm> {
7567   defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
7568   defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7569   defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7570   defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7571 }
7572
7573 multiclass SIMDSt1Multiple<string asm> {
7574   defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
7575   defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
7576   defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
7577   defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
7578 }
7579
7580 multiclass SIMDLd2Multiple<string asm> {
7581   defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7582 }
7583
7584 multiclass SIMDSt2Multiple<string asm> {
7585   defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
7586 }
7587
7588 multiclass SIMDLd3Multiple<string asm> {
7589   defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7590 }
7591
7592 multiclass SIMDSt3Multiple<string asm> {
7593   defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
7594 }
7595
7596 multiclass SIMDLd4Multiple<string asm> {
7597   defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7598 }
7599
7600 multiclass SIMDSt4Multiple<string asm> {
7601   defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
7602 }
7603
7604 //---
7605 // AdvSIMD Load/store single-element
7606 //---
7607
7608 class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
7609                          string asm, string operands, dag oops, dag iops,
7610                          list<dag> pattern>
7611   : I<oops, iops, asm, operands, "", pattern> {
7612   bits<5> Vt;
7613   bits<5> vaddr;
7614   let Inst{31} = 0;
7615   let Inst{29-24} = 0b001101;
7616   let Inst{22} = L;
7617   let Inst{21} = R;
7618   let Inst{15-13} = opcode;
7619   let Inst{9-5} = vaddr;
7620   let Inst{4-0} = Vt;
7621   let DecoderMethod = "DecodeSIMDLdStSingle";
7622 }
7623
7624 class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
7625                          string asm, string operands, dag oops, dag iops,
7626                          list<dag> pattern>
7627   : I<oops, iops, asm, operands, "$Vt = $dst", pattern> {
7628   bits<5> Vt;
7629   bits<5> vaddr;
7630   let Inst{31} = 0;
7631   let Inst{29-24} = 0b001101;
7632   let Inst{22} = L;
7633   let Inst{21} = R;
7634   let Inst{15-13} = opcode;
7635   let Inst{9-5} = vaddr;
7636   let Inst{4-0} = Vt;
7637   let DecoderMethod = "DecodeSIMDLdStSingleTied";
7638 }
7639
7640
7641 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7642 class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
7643                   Operand listtype>
7644   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr",
7645                        (outs listtype:$Vt), (ins am_simdnoindex:$vaddr), []> {
7646   let Inst{30} = Q;
7647   let Inst{23} = 0;
7648   let Inst{20-16} = 0b00000;
7649   let Inst{12} = S;
7650   let Inst{11-10} = size;
7651 }
7652 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7653 class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
7654                       string asm, Operand listtype, Operand GPR64pi>
7655   : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, $vaddr, $Xm",
7656                        (outs listtype:$Vt),
7657                        (ins am_simdnoindex:$vaddr, GPR64pi:$Xm), []> {
7658   bits<5> Xm;
7659   let Inst{30} = Q;
7660   let Inst{23} = 1;
7661   let Inst{20-16} = Xm;
7662   let Inst{12} = S;
7663   let Inst{11-10} = size;
7664 }
7665
7666 multiclass SIMDLdrAliases<string asm, string layout, string Count,
7667                           int Offset, int Size> {
7668   // E.g. "ld1r { v0.8b }, [x1], #1"
7669   //      "ld1r.8b\t$Vt, $vaddr, #1"
7670   // may get mapped to
7671   //      (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
7672   def : InstAlias<asm # "\t$Vt, $vaddr, #" # Offset,
7673                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
7674                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
7675                       am_simdnoindex:$vaddr, XZR), 1>;
7676
7677   // E.g. "ld1r.8b { v0 }, [x1], #1"
7678   //      "ld1r.8b\t$Vt, $vaddr, #1"
7679   // may get mapped to
7680   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
7681   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, #" # Offset,
7682                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
7683                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7684                       am_simdnoindex:$vaddr, XZR), 0>;
7685
7686   // E.g. "ld1r.8b { v0 }, [x1]"
7687   //      "ld1r.8b\t$Vt, $vaddr"
7688   // may get mapped to
7689   //      (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
7690   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr",
7691                   (!cast<Instruction>(NAME # "v" # layout)
7692                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7693                       am_simdnoindex:$vaddr), 0>;
7694
7695   // E.g. "ld1r.8b { v0 }, [x1], x2"
7696   //      "ld1r.8b\t$Vt, $vaddr, $Xm"
7697   // may get mapped to
7698   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
7699   def : InstAlias<asm # "." # layout # "\t$Vt, $vaddr, $Xm",
7700                   (!cast<Instruction>(NAME # "v" # layout # "_POST")
7701                       !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
7702                       am_simdnoindex:$vaddr,
7703                       !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
7704 }
7705
7706 multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
7707   int Offset1, int Offset2, int Offset4, int Offset8> {
7708   def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
7709                         !cast<Operand>("VecList" # Count # "8b")>;
7710   def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
7711                         !cast<Operand>("VecList" # Count #"16b")>;
7712   def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
7713                         !cast<Operand>("VecList" # Count #"4h")>;
7714   def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
7715                         !cast<Operand>("VecList" # Count #"8h")>;
7716   def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
7717                         !cast<Operand>("VecList" # Count #"2s")>;
7718   def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
7719                         !cast<Operand>("VecList" # Count #"4s")>;
7720   def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
7721                         !cast<Operand>("VecList" # Count #"1d")>;
7722   def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
7723                         !cast<Operand>("VecList" # Count #"2d")>;
7724
7725   def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
7726                                  !cast<Operand>("VecList" # Count # "8b"),
7727                                  !cast<Operand>("GPR64pi" # Offset1)>;
7728   def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
7729                                  !cast<Operand>("VecList" # Count # "16b"),
7730                                  !cast<Operand>("GPR64pi" # Offset1)>;
7731   def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
7732                                  !cast<Operand>("VecList" # Count # "4h"),
7733                                  !cast<Operand>("GPR64pi" # Offset2)>;
7734   def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
7735                                  !cast<Operand>("VecList" # Count # "8h"),
7736                                  !cast<Operand>("GPR64pi" # Offset2)>;
7737   def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
7738                                  !cast<Operand>("VecList" # Count # "2s"),
7739                                  !cast<Operand>("GPR64pi" # Offset4)>;
7740   def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
7741                                  !cast<Operand>("VecList" # Count # "4s"),
7742                                  !cast<Operand>("GPR64pi" # Offset4)>;
7743   def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
7744                                  !cast<Operand>("VecList" # Count # "1d"),
7745                                  !cast<Operand>("GPR64pi" # Offset8)>;
7746   def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
7747                                  !cast<Operand>("VecList" # Count # "2d"),
7748                                  !cast<Operand>("GPR64pi" # Offset8)>;
7749
7750   defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
7751   defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
7752   defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
7753   defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
7754   defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
7755   defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
7756   defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
7757   defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
7758 }
7759
7760 class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
7761                       dag oops, dag iops, list<dag> pattern>
7762   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7763                        pattern> {
7764   // idx encoded in Q:S:size fields.
7765   bits<4> idx;
7766   let Inst{30} = idx{3};
7767   let Inst{23} = 0;
7768   let Inst{20-16} = 0b00000;
7769   let Inst{12} = idx{2};
7770   let Inst{11-10} = idx{1-0};
7771 }
7772 class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
7773                       dag oops, dag iops, list<dag> pattern>
7774   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7775                        pattern> {
7776   // idx encoded in Q:S:size fields.
7777   bits<4> idx;
7778   let Inst{30} = idx{3};
7779   let Inst{23} = 0;
7780   let Inst{20-16} = 0b00000;
7781   let Inst{12} = idx{2};
7782   let Inst{11-10} = idx{1-0};
7783 }
7784 class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
7785                           dag oops, dag iops>
7786   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7787                        oops, iops, []> {
7788   // idx encoded in Q:S:size fields.
7789   bits<4> idx;
7790   bits<5> Xm;
7791   let Inst{30} = idx{3};
7792   let Inst{23} = 1;
7793   let Inst{20-16} = Xm;
7794   let Inst{12} = idx{2};
7795   let Inst{11-10} = idx{1-0};
7796 }
7797 class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
7798                           dag oops, dag iops>
7799   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7800                        oops, iops, []> {
7801   // idx encoded in Q:S:size fields.
7802   bits<4> idx;
7803   bits<5> Xm;
7804   let Inst{30} = idx{3};
7805   let Inst{23} = 1;
7806   let Inst{20-16} = Xm;
7807   let Inst{12} = idx{2};
7808   let Inst{11-10} = idx{1-0};
7809 }
7810
7811 class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
7812                       dag oops, dag iops, list<dag> pattern>
7813   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7814                        pattern> {
7815   // idx encoded in Q:S:size<1> fields.
7816   bits<3> idx;
7817   let Inst{30} = idx{2};
7818   let Inst{23} = 0;
7819   let Inst{20-16} = 0b00000;
7820   let Inst{12} = idx{1};
7821   let Inst{11} = idx{0};
7822   let Inst{10} = size;
7823 }
7824 class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
7825                       dag oops, dag iops, list<dag> pattern>
7826   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7827                        pattern> {
7828   // idx encoded in Q:S:size<1> fields.
7829   bits<3> idx;
7830   let Inst{30} = idx{2};
7831   let Inst{23} = 0;
7832   let Inst{20-16} = 0b00000;
7833   let Inst{12} = idx{1};
7834   let Inst{11} = idx{0};
7835   let Inst{10} = size;
7836 }
7837
7838 class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7839                           dag oops, dag iops>
7840   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7841                        oops, iops, []> {
7842   // idx encoded in Q:S:size<1> fields.
7843   bits<3> idx;
7844   bits<5> Xm;
7845   let Inst{30} = idx{2};
7846   let Inst{23} = 1;
7847   let Inst{20-16} = Xm;
7848   let Inst{12} = idx{1};
7849   let Inst{11} = idx{0};
7850   let Inst{10} = size;
7851 }
7852 class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
7853                           dag oops, dag iops>
7854   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7855                        oops, iops, []> {
7856   // idx encoded in Q:S:size<1> fields.
7857   bits<3> idx;
7858   bits<5> Xm;
7859   let Inst{30} = idx{2};
7860   let Inst{23} = 1;
7861   let Inst{20-16} = Xm;
7862   let Inst{12} = idx{1};
7863   let Inst{11} = idx{0};
7864   let Inst{10} = size;
7865 }
7866 class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7867                       dag oops, dag iops, list<dag> pattern>
7868   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7869                        pattern> {
7870   // idx encoded in Q:S fields.
7871   bits<2> idx;
7872   let Inst{30} = idx{1};
7873   let Inst{23} = 0;
7874   let Inst{20-16} = 0b00000;
7875   let Inst{12} = idx{0};
7876   let Inst{11-10} = size;
7877 }
7878 class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7879                       dag oops, dag iops, list<dag> pattern>
7880   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7881                        pattern> {
7882   // idx encoded in Q:S fields.
7883   bits<2> idx;
7884   let Inst{30} = idx{1};
7885   let Inst{23} = 0;
7886   let Inst{20-16} = 0b00000;
7887   let Inst{12} = idx{0};
7888   let Inst{11-10} = size;
7889 }
7890 class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
7891                           string asm, dag oops, dag iops>
7892   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7893                        oops, iops, []> {
7894   // idx encoded in Q:S fields.
7895   bits<2> idx;
7896   bits<5> Xm;
7897   let Inst{30} = idx{1};
7898   let Inst{23} = 1;
7899   let Inst{20-16} = Xm;
7900   let Inst{12} = idx{0};
7901   let Inst{11-10} = size;
7902 }
7903 class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7904                           string asm, dag oops, dag iops>
7905   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7906                        oops, iops, []> {
7907   // idx encoded in Q:S fields.
7908   bits<2> idx;
7909   bits<5> Xm;
7910   let Inst{30} = idx{1};
7911   let Inst{23} = 1;
7912   let Inst{20-16} = Xm;
7913   let Inst{12} = idx{0};
7914   let Inst{11-10} = size;
7915 }
7916 class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7917                       dag oops, dag iops, list<dag> pattern>
7918   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7919                        pattern> {
7920   // idx encoded in Q field.
7921   bits<1> idx;
7922   let Inst{30} = idx;
7923   let Inst{23} = 0;
7924   let Inst{20-16} = 0b00000;
7925   let Inst{12} = 0;
7926   let Inst{11-10} = size;
7927 }
7928 class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
7929                       dag oops, dag iops, list<dag> pattern>
7930   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr", oops, iops,
7931                        pattern> {
7932   // idx encoded in Q field.
7933   bits<1> idx;
7934   let Inst{30} = idx;
7935   let Inst{23} = 0;
7936   let Inst{20-16} = 0b00000;
7937   let Inst{12} = 0;
7938   let Inst{11-10} = size;
7939 }
7940 class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
7941                           string asm, dag oops, dag iops>
7942   : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7943                        oops, iops, []> {
7944   // idx encoded in Q field.
7945   bits<1> idx;
7946   bits<5> Xm;
7947   let Inst{30} = idx;
7948   let Inst{23} = 1;
7949   let Inst{20-16} = Xm;
7950   let Inst{12} = 0;
7951   let Inst{11-10} = size;
7952 }
7953 class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
7954                           string asm, dag oops, dag iops>
7955   : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, $vaddr, $Xm",
7956                        oops, iops, []> {
7957   // idx encoded in Q field.
7958   bits<1> idx;
7959   bits<5> Xm;
7960   let Inst{30} = idx;
7961   let Inst{23} = 1;
7962   let Inst{20-16} = Xm;
7963   let Inst{12} = 0;
7964   let Inst{11-10} = size;
7965 }
7966
7967 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7968 multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
7969                          RegisterOperand listtype,
7970                          RegisterOperand GPR64pi> {
7971   def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
7972                            (outs listtype:$dst),
7973                            (ins listtype:$Vt, VectorIndexB:$idx,
7974                                 am_simdnoindex:$vaddr), []>;
7975
7976   def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
7977                             (outs listtype:$dst),
7978                             (ins listtype:$Vt, VectorIndexB:$idx,
7979                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7980 }
7981 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7982 multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
7983                          RegisterOperand listtype,
7984                          RegisterOperand GPR64pi> {
7985   def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
7986                             (outs listtype:$dst),
7987                             (ins listtype:$Vt, VectorIndexH:$idx,
7988                                  am_simdnoindex:$vaddr), []>;
7989
7990   def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
7991                             (outs listtype:$dst),
7992                             (ins listtype:$Vt, VectorIndexH:$idx,
7993                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
7994 }
7995 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
7996 multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
7997                          RegisterOperand listtype,
7998                          RegisterOperand GPR64pi> {
7999   def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8000                             (outs listtype:$dst),
8001                             (ins listtype:$Vt, VectorIndexS:$idx,
8002                                  am_simdnoindex:$vaddr), []>;
8003
8004   def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8005                             (outs listtype:$dst),
8006                             (ins listtype:$Vt, VectorIndexS:$idx,
8007                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8008 }
8009 let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8010 multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8011                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8012   def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8013                             (outs listtype:$dst),
8014                             (ins listtype:$Vt, VectorIndexD:$idx,
8015                                  am_simdnoindex:$vaddr), []>;
8016
8017   def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8018                             (outs listtype:$dst),
8019                             (ins listtype:$Vt, VectorIndexD:$idx,
8020                                  am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8021 }
8022 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8023 multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8024                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8025   def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8026                            (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8027                                         am_simdnoindex:$vaddr), []>;
8028
8029   def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8030                             (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8031                                          am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8032 }
8033 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8034 multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8035                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8036   def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8037                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8038                                          am_simdnoindex:$vaddr), []>;
8039
8040   def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8041                             (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8042                                          am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8043 }
8044 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8045 multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8046                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8047   def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8048                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8049                                          am_simdnoindex:$vaddr), []>;
8050
8051   def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8052                             (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8053                                          am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8054 }
8055 let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8056 multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8057                          RegisterOperand listtype, RegisterOperand GPR64pi> {
8058   def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8059                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8060                                          am_simdnoindex:$vaddr), []>;
8061
8062   def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8063                             (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8064                                          am_simdnoindex:$vaddr, GPR64pi:$Xm)>;
8065 }
8066
8067 multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8068                                  string Count, int Offset, Operand idxtype> {
8069   // E.g. "ld1 { v0.8b }[0], [x1], #1"
8070   //      "ld1\t$Vt, $vaddr, #1"
8071   // may get mapped to
8072   //      (LD1Rv8b_POST VecListOne8b:$Vt, am_simdnoindex:$vaddr, XZR)
8073   def : InstAlias<asm # "\t$Vt$idx, $vaddr, #" # Offset,
8074                   (!cast<Instruction>(NAME # Type  # "_POST")
8075                       !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8076                       idxtype:$idx, am_simdnoindex:$vaddr, XZR), 1>;
8077
8078   // E.g. "ld1.8b { v0 }[0], [x1], #1"
8079   //      "ld1.8b\t$Vt, $vaddr, #1"
8080   // may get mapped to
8081   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, XZR)
8082   def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, #" # Offset,
8083                   (!cast<Instruction>(NAME # Type # "_POST")
8084                       !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8085                       idxtype:$idx, am_simdnoindex:$vaddr, XZR), 0>;
8086
8087   // E.g. "ld1.8b { v0 }[0], [x1]"
8088   //      "ld1.8b\t$Vt, $vaddr"
8089   // may get mapped to
8090   //      (LD1Rv8b VecListOne64:$Vt, am_simdnoindex:$vaddr)
8091   def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr",
8092                       (!cast<Instruction>(NAME # Type)
8093                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8094                          idxtype:$idx, am_simdnoindex:$vaddr), 0>;
8095
8096   // E.g. "ld1.8b { v0 }[0], [x1], x2"
8097   //      "ld1.8b\t$Vt, $vaddr, $Xm"
8098   // may get mapped to
8099   //      (LD1Rv8b_POST VecListOne64:$Vt, am_simdnoindex:$vaddr, GPR64pi1:$Xm)
8100   def : InstAlias<asm # "." # layout # "\t$Vt$idx, $vaddr, $Xm",
8101                       (!cast<Instruction>(NAME # Type # "_POST")
8102                          !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
8103                          idxtype:$idx, am_simdnoindex:$vaddr,
8104                          !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8105 }
8106
8107 multiclass SIMDLdSt1SingleAliases<string asm> {
8108   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
8109   defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
8110   defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
8111   defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
8112 }
8113
8114 multiclass SIMDLdSt2SingleAliases<string asm> {
8115   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
8116   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
8117   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
8118   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
8119 }
8120
8121 multiclass SIMDLdSt3SingleAliases<string asm> {
8122   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
8123   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
8124   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
8125   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
8126 }
8127
8128 multiclass SIMDLdSt4SingleAliases<string asm> {
8129   defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
8130   defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
8131   defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
8132   defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
8133 }
8134
8135 //----------------------------------------------------------------------------
8136 // Crypto extensions
8137 //----------------------------------------------------------------------------
8138
8139 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8140 class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
8141               list<dag> pat>
8142   : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
8143     Sched<[WriteV]>{
8144   bits<5> Rd;
8145   bits<5> Rn;
8146   let Inst{31-16} = 0b0100111000101000;
8147   let Inst{15-12} = opc;
8148   let Inst{11-10} = 0b10;
8149   let Inst{9-5}   = Rn;
8150   let Inst{4-0}   = Rd;
8151 }
8152
8153 class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
8154   : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
8155             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
8156
8157 class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
8158   : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
8159             "$Rd = $dst",
8160             [(set (v16i8 V128:$dst),
8161                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
8162
8163 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8164 class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
8165                      dag oops, dag iops, list<dag> pat>
8166   : I<oops, iops, asm,
8167       "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
8168       "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
8169     Sched<[WriteV]>{
8170   bits<5> Rd;
8171   bits<5> Rn;
8172   bits<5> Rm;
8173   let Inst{31-21} = 0b01011110000;
8174   let Inst{20-16} = Rm;
8175   let Inst{15}    = 0;
8176   let Inst{14-12} = opc;
8177   let Inst{11-10} = 0b00;
8178   let Inst{9-5}   = Rn;
8179   let Inst{4-0}   = Rd;
8180 }
8181
8182 class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
8183   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8184                    (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
8185                    [(set (v4i32 FPR128:$dst),
8186                          (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
8187                                  (v4i32 V128:$Rm)))]>;
8188
8189 class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
8190   : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
8191                    (ins V128:$Rd, V128:$Rn, V128:$Rm),
8192                    [(set (v4i32 V128:$dst),
8193                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8194                                  (v4i32 V128:$Rm)))]>;
8195
8196 class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
8197   : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
8198                    (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
8199                    [(set (v4i32 FPR128:$dst),
8200                          (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
8201                                  (v4i32 V128:$Rm)))]>;
8202
8203 let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8204 class SHA2OpInst<bits<4> opc, string asm, string kind,
8205                  string cstr, dag oops, dag iops,
8206                  list<dag> pat>
8207   : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
8208                        "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
8209     Sched<[WriteV]>{
8210   bits<5> Rd;
8211   bits<5> Rn;
8212   let Inst{31-16} = 0b0101111000101000;
8213   let Inst{15-12} = opc;
8214   let Inst{11-10} = 0b10;
8215   let Inst{9-5}   = Rn;
8216   let Inst{4-0}   = Rd;
8217 }
8218
8219 class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
8220   : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
8221                (ins V128:$Rd, V128:$Rn),
8222                [(set (v4i32 V128:$dst),
8223                      (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
8224
8225 class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
8226   : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
8227                [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
8228
8229 // Allow the size specifier tokens to be upper case, not just lower.
8230 def : TokenAlias<".8B", ".8b">;
8231 def : TokenAlias<".4H", ".4h">;
8232 def : TokenAlias<".2S", ".2s">;
8233 def : TokenAlias<".1D", ".1d">;
8234 def : TokenAlias<".16B", ".16b">;
8235 def : TokenAlias<".8H", ".8h">;
8236 def : TokenAlias<".4S", ".4s">;
8237 def : TokenAlias<".2D", ".2d">;
8238 def : TokenAlias<".1Q", ".1q">;
8239 def : TokenAlias<".B", ".b">;
8240 def : TokenAlias<".H", ".h">;
8241 def : TokenAlias<".S", ".s">;
8242 def : TokenAlias<".D", ".d">;
8243 def : TokenAlias<".Q", ".q">;