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