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