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