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