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
251def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
252def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
253def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
254def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
255def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
256
257class AsmImmRange<int Low, int High> : AsmOperandClass {
258  let Name = "Imm" # Low # "_" # High;
259  let DiagnosticType = "InvalidImm" # Low # "_" # High;
260}
261
262def Imm1_8Operand : AsmImmRange<1, 8>;
263def Imm1_16Operand : AsmImmRange<1, 16>;
264def Imm1_32Operand : AsmImmRange<1, 32>;
265def Imm1_64Operand : AsmImmRange<1, 64>;
266
267def MovZSymbolG3AsmOperand : AsmOperandClass {
268  let Name = "MovZSymbolG3";
269  let RenderMethod = "addImmOperands";
270}
271
272def movz_symbol_g3 : Operand<i32> {
273  let ParserMatchClass = MovZSymbolG3AsmOperand;
274}
275
276def MovZSymbolG2AsmOperand : AsmOperandClass {
277  let Name = "MovZSymbolG2";
278  let RenderMethod = "addImmOperands";
279}
280
281def movz_symbol_g2 : Operand<i32> {
282  let ParserMatchClass = MovZSymbolG2AsmOperand;
283}
284
285def MovZSymbolG1AsmOperand : AsmOperandClass {
286  let Name = "MovZSymbolG1";
287  let RenderMethod = "addImmOperands";
288}
289
290def movz_symbol_g1 : Operand<i32> {
291  let ParserMatchClass = MovZSymbolG1AsmOperand;
292}
293
294def MovZSymbolG0AsmOperand : AsmOperandClass {
295  let Name = "MovZSymbolG0";
296  let RenderMethod = "addImmOperands";
297}
298
299def movz_symbol_g0 : Operand<i32> {
300  let ParserMatchClass = MovZSymbolG0AsmOperand;
301}
302
303def MovKSymbolG3AsmOperand : AsmOperandClass {
304  let Name = "MovKSymbolG3";
305  let RenderMethod = "addImmOperands";
306}
307
308def movk_symbol_g3 : Operand<i32> {
309  let ParserMatchClass = MovKSymbolG3AsmOperand;
310}
311
312def MovKSymbolG2AsmOperand : AsmOperandClass {
313  let Name = "MovKSymbolG2";
314  let RenderMethod = "addImmOperands";
315}
316
317def movk_symbol_g2 : Operand<i32> {
318  let ParserMatchClass = MovKSymbolG2AsmOperand;
319}
320
321def MovKSymbolG1AsmOperand : AsmOperandClass {
322  let Name = "MovKSymbolG1";
323  let RenderMethod = "addImmOperands";
324}
325
326def movk_symbol_g1 : Operand<i32> {
327  let ParserMatchClass = MovKSymbolG1AsmOperand;
328}
329
330def MovKSymbolG0AsmOperand : AsmOperandClass {
331  let Name = "MovKSymbolG0";
332  let RenderMethod = "addImmOperands";
333}
334
335def movk_symbol_g0 : Operand<i32> {
336  let ParserMatchClass = MovKSymbolG0AsmOperand;
337}
338
339class fixedpoint_i32<ValueType FloatVT>
340  : Operand<FloatVT>,
341    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
342  let EncoderMethod = "getFixedPointScaleOpValue";
343  let DecoderMethod = "DecodeFixedPointScaleImm32";
344  let ParserMatchClass = Imm1_32Operand;
345}
346
347class fixedpoint_i64<ValueType FloatVT>
348  : Operand<FloatVT>,
349    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
350  let EncoderMethod = "getFixedPointScaleOpValue";
351  let DecoderMethod = "DecodeFixedPointScaleImm64";
352  let ParserMatchClass = Imm1_64Operand;
353}
354
355def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
356def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
357def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
358
359def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
360def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
361def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
362
363def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
364  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
365}]> {
366  let EncoderMethod = "getVecShiftR8OpValue";
367  let DecoderMethod = "DecodeVecShiftR8Imm";
368  let ParserMatchClass = Imm1_8Operand;
369}
370def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
371  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
372}]> {
373  let EncoderMethod = "getVecShiftR16OpValue";
374  let DecoderMethod = "DecodeVecShiftR16Imm";
375  let ParserMatchClass = Imm1_16Operand;
376}
377def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
378  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
379}]> {
380  let EncoderMethod = "getVecShiftR16OpValue";
381  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
382  let ParserMatchClass = Imm1_8Operand;
383}
384def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
385  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
386}]> {
387  let EncoderMethod = "getVecShiftR32OpValue";
388  let DecoderMethod = "DecodeVecShiftR32Imm";
389  let ParserMatchClass = Imm1_32Operand;
390}
391def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
392  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
393}]> {
394  let EncoderMethod = "getVecShiftR32OpValue";
395  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
396  let ParserMatchClass = Imm1_16Operand;
397}
398def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
399  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
400}]> {
401  let EncoderMethod = "getVecShiftR64OpValue";
402  let DecoderMethod = "DecodeVecShiftR64Imm";
403  let ParserMatchClass = Imm1_64Operand;
404}
405def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
406  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
407}]> {
408  let EncoderMethod = "getVecShiftR64OpValue";
409  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
410  let ParserMatchClass = Imm1_32Operand;
411}
412
413def Imm0_1Operand : AsmImmRange<0, 1>;
414def Imm0_7Operand : AsmImmRange<0, 7>;
415def Imm0_15Operand : AsmImmRange<0, 15>;
416def Imm0_31Operand : AsmImmRange<0, 31>;
417def Imm0_63Operand : AsmImmRange<0, 63>;
418
419def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
420  return (((uint32_t)Imm) < 8);
421}]> {
422  let EncoderMethod = "getVecShiftL8OpValue";
423  let DecoderMethod = "DecodeVecShiftL8Imm";
424  let ParserMatchClass = Imm0_7Operand;
425}
426def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
427  return (((uint32_t)Imm) < 16);
428}]> {
429  let EncoderMethod = "getVecShiftL16OpValue";
430  let DecoderMethod = "DecodeVecShiftL16Imm";
431  let ParserMatchClass = Imm0_15Operand;
432}
433def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
434  return (((uint32_t)Imm) < 32);
435}]> {
436  let EncoderMethod = "getVecShiftL32OpValue";
437  let DecoderMethod = "DecodeVecShiftL32Imm";
438  let ParserMatchClass = Imm0_31Operand;
439}
440def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
441  return (((uint32_t)Imm) < 64);
442}]> {
443  let EncoderMethod = "getVecShiftL64OpValue";
444  let DecoderMethod = "DecodeVecShiftL64Imm";
445  let ParserMatchClass = Imm0_63Operand;
446}
447
448
449// Crazy immediate formats used by 32-bit and 64-bit logical immediate
450// instructions for splatting repeating bit patterns across the immediate.
451def logical_imm32_XFORM : SDNodeXForm<imm, [{
452  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
453  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
454}]>;
455def logical_imm64_XFORM : SDNodeXForm<imm, [{
456  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
457  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
458}]>;
459
460let DiagnosticType = "LogicalSecondSource" in {
461  def LogicalImm32Operand : AsmOperandClass {
462    let Name = "LogicalImm32";
463  }
464  def LogicalImm64Operand : AsmOperandClass {
465    let Name = "LogicalImm64";
466  }
467  def LogicalImm32NotOperand : AsmOperandClass {
468    let Name = "LogicalImm32Not";
469  }
470  def LogicalImm64NotOperand : AsmOperandClass {
471    let Name = "LogicalImm64Not";
472  }
473}
474def logical_imm32 : Operand<i32>, PatLeaf<(imm), [{
475  return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 32);
476}], logical_imm32_XFORM> {
477  let PrintMethod = "printLogicalImm32";
478  let ParserMatchClass = LogicalImm32Operand;
479}
480def logical_imm64 : Operand<i64>, PatLeaf<(imm), [{
481  return AArch64_AM::isLogicalImmediate(N->getZExtValue(), 64);
482}], logical_imm64_XFORM> {
483  let PrintMethod = "printLogicalImm64";
484  let ParserMatchClass = LogicalImm64Operand;
485}
486def logical_imm32_not : Operand<i32> {
487  let ParserMatchClass = LogicalImm32NotOperand;
488}
489def logical_imm64_not : Operand<i64> {
490  let ParserMatchClass = LogicalImm64NotOperand;
491}
492
493// imm0_65535 predicate - True if the immediate is in the range [0,65535].
494def Imm0_65535Operand : AsmImmRange<0, 65535>;
495def imm0_65535 : Operand<i32>, ImmLeaf<i32, [{
496  return ((uint32_t)Imm) < 65536;
497}]> {
498  let ParserMatchClass = Imm0_65535Operand;
499  let PrintMethod = "printImmHex";
500}
501
502// imm0_255 predicate - True if the immediate is in the range [0,255].
503def Imm0_255Operand : AsmOperandClass { let Name = "Imm0_255"; }
504def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
505  return ((uint32_t)Imm) < 256;
506}]> {
507  let ParserMatchClass = Imm0_255Operand;
508  let PrintMethod = "printImm";
509}
510
511// imm0_127 predicate - True if the immediate is in the range [0,127]
512def Imm0_127Operand : AsmImmRange<0, 127>;
513def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
514  return ((uint32_t)Imm) < 128;
515}]> {
516  let ParserMatchClass = Imm0_127Operand;
517  let PrintMethod = "printImm";
518}
519
520// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
521// for all shift-amounts.
522
523// imm0_63 predicate - True if the immediate is in the range [0,63]
524def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
525  return ((uint64_t)Imm) < 64;
526}]> {
527  let ParserMatchClass = Imm0_63Operand;
528}
529
530// imm0_31 predicate - True if the immediate is in the range [0,31]
531def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
532  return ((uint64_t)Imm) < 32;
533}]> {
534  let ParserMatchClass = Imm0_31Operand;
535}
536
537// True if the 32-bit immediate is in the range [0,31]
538def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
539  return ((uint64_t)Imm) < 32;
540}]> {
541  let ParserMatchClass = Imm0_31Operand;
542}
543
544// imm0_1 predicate - True if the immediate is in the range [0,1]
545def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
546  return ((uint64_t)Imm) < 2;
547}]> {
548  let ParserMatchClass = Imm0_1Operand;
549}
550
551// imm0_15 predicate - True if the immediate is in the range [0,15]
552def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
553  return ((uint64_t)Imm) < 16;
554}]> {
555  let ParserMatchClass = Imm0_15Operand;
556}
557
558// imm0_7 predicate - True if the immediate is in the range [0,7]
559def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
560  return ((uint64_t)Imm) < 8;
561}]> {
562  let ParserMatchClass = Imm0_7Operand;
563}
564
565// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
566def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
567  return ((uint32_t)Imm) < 16;
568}]> {
569  let ParserMatchClass = Imm0_15Operand;
570}
571
572// An arithmetic shifter operand:
573//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
574//  {5-0} - imm6
575class arith_shift<ValueType Ty, int width> : Operand<Ty> {
576  let PrintMethod = "printShifter";
577  let ParserMatchClass = !cast<AsmOperandClass>(
578                         "ArithmeticShifterOperand" # width);
579}
580
581def arith_shift32 : arith_shift<i32, 32>;
582def arith_shift64 : arith_shift<i64, 64>;
583
584class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
585    : Operand<Ty>,
586      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
587  let PrintMethod = "printShiftedRegister";
588  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
589}
590
591def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
592def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
593
594// An arithmetic shifter operand:
595//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
596//  {5-0} - imm6
597class logical_shift<int width> : Operand<i32> {
598  let PrintMethod = "printShifter";
599  let ParserMatchClass = !cast<AsmOperandClass>(
600                         "LogicalShifterOperand" # width);
601}
602
603def logical_shift32 : logical_shift<32>;
604def logical_shift64 : logical_shift<64>;
605
606class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
607    : Operand<Ty>,
608      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
609  let PrintMethod = "printShiftedRegister";
610  let MIOperandInfo = (ops regclass, shiftop);
611}
612
613def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
614def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
615
616// A logical vector shifter operand:
617//  {7-6} - shift type: 00 = lsl
618//  {5-0} - imm6: #0, #8, #16, or #24
619def logical_vec_shift : Operand<i32> {
620  let PrintMethod = "printShifter";
621  let EncoderMethod = "getVecShifterOpValue";
622  let ParserMatchClass = LogicalVecShifterOperand;
623}
624
625// A logical vector half-word shifter operand:
626//  {7-6} - shift type: 00 = lsl
627//  {5-0} - imm6: #0 or #8
628def logical_vec_hw_shift : Operand<i32> {
629  let PrintMethod = "printShifter";
630  let EncoderMethod = "getVecShifterOpValue";
631  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
632}
633
634// A vector move shifter operand:
635//  {0} - imm1: #8 or #16
636def move_vec_shift : Operand<i32> {
637  let PrintMethod = "printShifter";
638  let EncoderMethod = "getMoveVecShifterOpValue";
639  let ParserMatchClass = MoveVecShifterOperand;
640}
641
642let DiagnosticType = "AddSubSecondSource" in {
643  def AddSubImmOperand : AsmOperandClass {
644    let Name = "AddSubImm";
645    let ParserMethod = "tryParseAddSubImm";
646  }
647  def AddSubImmNegOperand : AsmOperandClass {
648    let Name = "AddSubImmNeg";
649    let ParserMethod = "tryParseAddSubImm";
650  }
651}
652// An ADD/SUB immediate shifter operand:
653//  second operand:
654//  {7-6} - shift type: 00 = lsl
655//  {5-0} - imm6: #0 or #12
656class addsub_shifted_imm<ValueType Ty>
657    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
658  let PrintMethod = "printAddSubImm";
659  let EncoderMethod = "getAddSubImmOpValue";
660  let ParserMatchClass = AddSubImmOperand;
661  let MIOperandInfo = (ops i32imm, i32imm);
662}
663
664class addsub_shifted_imm_neg<ValueType Ty>
665    : Operand<Ty> {
666  let EncoderMethod = "getAddSubImmOpValue";
667  let ParserMatchClass = AddSubImmNegOperand;
668  let MIOperandInfo = (ops i32imm, i32imm);
669}
670
671def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
672def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
673def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
674def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
675
676class neg_addsub_shifted_imm<ValueType Ty>
677    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
678  let PrintMethod = "printAddSubImm";
679  let EncoderMethod = "getAddSubImmOpValue";
680  let ParserMatchClass = AddSubImmOperand;
681  let MIOperandInfo = (ops i32imm, i32imm);
682}
683
684def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
685def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
686
687// An extend operand:
688//  {5-3} - extend type
689//  {2-0} - imm3
690def arith_extend : Operand<i32> {
691  let PrintMethod = "printArithExtend";
692  let ParserMatchClass = ExtendOperand;
693}
694def arith_extend64 : Operand<i32> {
695  let PrintMethod = "printArithExtend";
696  let ParserMatchClass = ExtendOperand64;
697}
698
699// 'extend' that's a lsl of a 64-bit register.
700def arith_extendlsl64 : Operand<i32> {
701  let PrintMethod = "printArithExtend";
702  let ParserMatchClass = ExtendOperandLSL64;
703}
704
705class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
706                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
707  let PrintMethod = "printExtendedRegister";
708  let MIOperandInfo = (ops GPR32, arith_extend);
709}
710
711class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
712                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
713  let PrintMethod = "printExtendedRegister";
714  let MIOperandInfo = (ops GPR32, arith_extend64);
715}
716
717// Floating-point immediate.
718def fpimm16 : Operand<f16>,
719              PatLeaf<(f16 fpimm), [{
720      return AArch64_AM::getFP16Imm(N->getValueAPF()) != -1;
721    }], SDNodeXForm<fpimm, [{
722      APFloat InVal = N->getValueAPF();
723      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
724      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
725    }]>> {
726  let ParserMatchClass = FPImmOperand;
727  let PrintMethod = "printFPImmOperand";
728}
729def fpimm32 : Operand<f32>,
730              PatLeaf<(f32 fpimm), [{
731      return AArch64_AM::getFP32Imm(N->getValueAPF()) != -1;
732    }], SDNodeXForm<fpimm, [{
733      APFloat InVal = N->getValueAPF();
734      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
735      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
736    }]>> {
737  let ParserMatchClass = FPImmOperand;
738  let PrintMethod = "printFPImmOperand";
739}
740def fpimm64 : Operand<f64>,
741              PatLeaf<(f64 fpimm), [{
742      return AArch64_AM::getFP64Imm(N->getValueAPF()) != -1;
743    }], SDNodeXForm<fpimm, [{
744      APFloat InVal = N->getValueAPF();
745      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
746      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
747    }]>> {
748  let ParserMatchClass = FPImmOperand;
749  let PrintMethod = "printFPImmOperand";
750}
751
752def fpimm8 : Operand<i32> {
753  let ParserMatchClass = FPImmOperand;
754  let PrintMethod = "printFPImmOperand";
755}
756
757def fpimm0 : PatLeaf<(fpimm), [{
758  return N->isExactlyValue(+0.0);
759}]>;
760
761// Vector lane operands
762class AsmVectorIndex<string Suffix> : AsmOperandClass {
763  let Name = "VectorIndex" # Suffix;
764  let DiagnosticType = "InvalidIndex" # Suffix;
765}
766def VectorIndex1Operand : AsmVectorIndex<"1">;
767def VectorIndexBOperand : AsmVectorIndex<"B">;
768def VectorIndexHOperand : AsmVectorIndex<"H">;
769def VectorIndexSOperand : AsmVectorIndex<"S">;
770def VectorIndexDOperand : AsmVectorIndex<"D">;
771
772def VectorIndex1 : Operand<i64>, ImmLeaf<i64, [{
773  return ((uint64_t)Imm) == 1;
774}]> {
775  let ParserMatchClass = VectorIndex1Operand;
776  let PrintMethod = "printVectorIndex";
777  let MIOperandInfo = (ops i64imm);
778}
779def VectorIndexB : Operand<i64>, ImmLeaf<i64, [{
780  return ((uint64_t)Imm) < 16;
781}]> {
782  let ParserMatchClass = VectorIndexBOperand;
783  let PrintMethod = "printVectorIndex";
784  let MIOperandInfo = (ops i64imm);
785}
786def VectorIndexH : Operand<i64>, ImmLeaf<i64, [{
787  return ((uint64_t)Imm) < 8;
788}]> {
789  let ParserMatchClass = VectorIndexHOperand;
790  let PrintMethod = "printVectorIndex";
791  let MIOperandInfo = (ops i64imm);
792}
793def VectorIndexS : Operand<i64>, ImmLeaf<i64, [{
794  return ((uint64_t)Imm) < 4;
795}]> {
796  let ParserMatchClass = VectorIndexSOperand;
797  let PrintMethod = "printVectorIndex";
798  let MIOperandInfo = (ops i64imm);
799}
800def VectorIndexD : Operand<i64>, ImmLeaf<i64, [{
801  return ((uint64_t)Imm) < 2;
802}]> {
803  let ParserMatchClass = VectorIndexDOperand;
804  let PrintMethod = "printVectorIndex";
805  let MIOperandInfo = (ops i64imm);
806}
807
808// 8-bit immediate for AdvSIMD where 64-bit values of the form:
809// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
810// are encoded as the eight bit value 'abcdefgh'.
811def simdimmtype10 : Operand<i32>,
812                    PatLeaf<(f64 fpimm), [{
813      return AArch64_AM::isAdvSIMDModImmType10(N->getValueAPF()
814                                               .bitcastToAPInt()
815                                               .getZExtValue());
816    }], SDNodeXForm<fpimm, [{
817      APFloat InVal = N->getValueAPF();
818      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
819                                                           .bitcastToAPInt()
820                                                           .getZExtValue());
821      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
822    }]>> {
823  let ParserMatchClass = SIMDImmType10Operand;
824  let PrintMethod = "printSIMDType10Operand";
825}
826
827
828//---
829// System management
830//---
831
832// Base encoding for system instruction operands.
833let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
834class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
835                  list<dag> pattern = []>
836    : I<oops, iops, asm, operands, "", pattern> {
837  let Inst{31-22} = 0b1101010100;
838  let Inst{21}    = L;
839}
840
841// System instructions which do not have an Rt register.
842class SimpleSystemI<bit L, dag iops, string asm, string operands,
843                    list<dag> pattern = []>
844    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
845  let Inst{4-0} = 0b11111;
846}
847
848// System instructions which have an Rt register.
849class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
850    : BaseSystemI<L, oops, iops, asm, operands>,
851      Sched<[WriteSys]> {
852  bits<5> Rt;
853  let Inst{4-0} = Rt;
854}
855
856// Hint instructions that take both a CRm and a 3-bit immediate.
857// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
858// model patterns with sufficiently fine granularity
859let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
860  class HintI<string mnemonic>
861      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
862                      [(int_aarch64_hint imm0_127:$imm)]>,
863        Sched<[WriteHint]> {
864    bits <7> imm;
865    let Inst{20-12} = 0b000110010;
866    let Inst{11-5} = imm;
867  }
868
869// System instructions taking a single literal operand which encodes into
870// CRm. op2 differentiates the opcodes.
871def BarrierAsmOperand : AsmOperandClass {
872  let Name = "Barrier";
873  let ParserMethod = "tryParseBarrierOperand";
874}
875def barrier_op : Operand<i32> {
876  let PrintMethod = "printBarrierOption";
877  let ParserMatchClass = BarrierAsmOperand;
878}
879class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
880                 list<dag> pattern = []>
881    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
882      Sched<[WriteBarrier]> {
883  bits<4> CRm;
884  let Inst{20-12} = 0b000110011;
885  let Inst{11-8} = CRm;
886  let Inst{7-5} = opc;
887}
888
889// MRS/MSR system instructions. These have different operand classes because
890// a different subset of registers can be accessed through each instruction.
891def MRSSystemRegisterOperand : AsmOperandClass {
892  let Name = "MRSSystemRegister";
893  let ParserMethod = "tryParseSysReg";
894  let DiagnosticType = "MRS";
895}
896// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
897def mrs_sysreg_op : Operand<i32> {
898  let ParserMatchClass = MRSSystemRegisterOperand;
899  let DecoderMethod = "DecodeMRSSystemRegister";
900  let PrintMethod = "printMRSSystemRegister";
901}
902
903def MSRSystemRegisterOperand : AsmOperandClass {
904  let Name = "MSRSystemRegister";
905  let ParserMethod = "tryParseSysReg";
906  let DiagnosticType = "MSR";
907}
908def msr_sysreg_op : Operand<i32> {
909  let ParserMatchClass = MSRSystemRegisterOperand;
910  let DecoderMethod = "DecodeMSRSystemRegister";
911  let PrintMethod = "printMSRSystemRegister";
912}
913
914def PSBHintOperand : AsmOperandClass {
915  let Name = "PSBHint";
916  let ParserMethod = "tryParsePSBHint";
917}
918def psbhint_op : Operand<i32> {
919  let ParserMatchClass = PSBHintOperand;
920  let PrintMethod = "printPSBHintOp";
921  let MCOperandPredicate = [{
922    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
923    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
924    if (!MCOp.isImm())
925      return false;
926    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
927  }];
928}
929
930class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
931                       "mrs", "\t$Rt, $systemreg"> {
932  bits<16> systemreg;
933  let Inst{20-5} = systemreg;
934}
935
936// FIXME: Some of these def NZCV, others don't. Best way to model that?
937// Explicitly modeling each of the system register as a register class
938// would do it, but feels like overkill at this point.
939class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
940                       "msr", "\t$systemreg, $Rt"> {
941  bits<16> systemreg;
942  let Inst{20-5} = systemreg;
943}
944
945def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
946  let Name = "SystemPStateFieldWithImm0_15";
947  let ParserMethod = "tryParseSysReg";
948}
949def pstatefield4_op : Operand<i32> {
950  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
951  let PrintMethod = "printSystemPStateField";
952}
953
954let Defs = [NZCV] in
955class MSRpstateImm0_15
956  : SimpleSystemI<0, (ins pstatefield4_op:$pstatefield, imm0_15:$imm),
957                  "msr", "\t$pstatefield, $imm">,
958    Sched<[WriteSys]> {
959  bits<6> pstatefield;
960  bits<4> imm;
961  let Inst{20-19} = 0b00;
962  let Inst{18-16} = pstatefield{5-3};
963  let Inst{15-12} = 0b0100;
964  let Inst{11-8} = imm;
965  let Inst{7-5} = pstatefield{2-0};
966
967  let DecoderMethod = "DecodeSystemPStateInstruction";
968  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
969  // Fail the decoder should attempt to decode the instruction as MSRI.
970  let hasCompleteDecoder = 0;
971}
972
973def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
974  let Name = "SystemPStateFieldWithImm0_1";
975  let ParserMethod = "tryParseSysReg";
976}
977def pstatefield1_op : Operand<i32> {
978  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
979  let PrintMethod = "printSystemPStateField";
980}
981
982let Defs = [NZCV] in
983class MSRpstateImm0_1
984  : SimpleSystemI<0, (ins pstatefield1_op:$pstatefield, imm0_1:$imm),
985                  "msr", "\t$pstatefield, $imm">,
986    Sched<[WriteSys]> {
987  bits<6> pstatefield;
988  bit imm;
989  let Inst{20-19} = 0b00;
990  let Inst{18-16} = pstatefield{5-3};
991  let Inst{15-9} = 0b0100000;
992  let Inst{8} = imm;
993  let Inst{7-5} = pstatefield{2-0};
994
995  let DecoderMethod = "DecodeSystemPStateInstruction";
996  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
997  // Fail the decoder should attempt to decode the instruction as MSRI.
998  let hasCompleteDecoder = 0;
999}
1000
1001// SYS and SYSL generic system instructions.
1002def SysCRAsmOperand : AsmOperandClass {
1003  let Name = "SysCR";
1004  let ParserMethod = "tryParseSysCROperand";
1005}
1006
1007def sys_cr_op : Operand<i32> {
1008  let PrintMethod = "printSysCROperand";
1009  let ParserMatchClass = SysCRAsmOperand;
1010}
1011
1012class SystemXtI<bit L, string asm>
1013  : RtSystemI<L, (outs),
1014       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1015       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1016  bits<3> op1;
1017  bits<4> Cn;
1018  bits<4> Cm;
1019  bits<3> op2;
1020  let Inst{20-19} = 0b01;
1021  let Inst{18-16} = op1;
1022  let Inst{15-12} = Cn;
1023  let Inst{11-8}  = Cm;
1024  let Inst{7-5}   = op2;
1025}
1026
1027class SystemLXtI<bit L, string asm>
1028  : RtSystemI<L, (outs),
1029       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1030       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1031  bits<3> op1;
1032  bits<4> Cn;
1033  bits<4> Cm;
1034  bits<3> op2;
1035  let Inst{20-19} = 0b01;
1036  let Inst{18-16} = op1;
1037  let Inst{15-12} = Cn;
1038  let Inst{11-8}  = Cm;
1039  let Inst{7-5}   = op2;
1040}
1041
1042
1043// Branch (register) instructions:
1044//
1045//  case opc of
1046//    0001 blr
1047//    0000 br
1048//    0101 dret
1049//    0100 eret
1050//    0010 ret
1051//    otherwise UNDEFINED
1052class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1053                    string operands, list<dag> pattern>
1054    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1055  let Inst{31-25} = 0b1101011;
1056  let Inst{24-21} = opc;
1057  let Inst{20-16} = 0b11111;
1058  let Inst{15-10} = 0b000000;
1059  let Inst{4-0}   = 0b00000;
1060}
1061
1062class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1063    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1064  bits<5> Rn;
1065  let Inst{9-5} = Rn;
1066}
1067
1068let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1069class SpecialReturn<bits<4> opc, string asm>
1070    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1071  let Inst{9-5} = 0b11111;
1072}
1073
1074//---
1075// Conditional branch instruction.
1076//---
1077
1078// Condition code.
1079// 4-bit immediate. Pretty-printed as <cc>
1080def ccode : Operand<i32> {
1081  let PrintMethod = "printCondCode";
1082  let ParserMatchClass = CondCode;
1083}
1084def inv_ccode : Operand<i32> {
1085  // AL and NV are invalid in the aliases which use inv_ccode
1086  let PrintMethod = "printInverseCondCode";
1087  let ParserMatchClass = CondCode;
1088  let MCOperandPredicate = [{
1089    return MCOp.isImm() &&
1090           MCOp.getImm() != AArch64CC::AL &&
1091           MCOp.getImm() != AArch64CC::NV;
1092  }];
1093}
1094
1095// Conditional branch target. 19-bit immediate. The low two bits of the target
1096// offset are implied zero and so are not part of the immediate.
1097def PCRelLabel19Operand : AsmOperandClass {
1098  let Name = "PCRelLabel19";
1099  let DiagnosticType = "InvalidLabel";
1100}
1101def am_brcond : Operand<OtherVT> {
1102  let EncoderMethod = "getCondBranchTargetOpValue";
1103  let DecoderMethod = "DecodePCRelLabel19";
1104  let PrintMethod = "printAlignedLabel";
1105  let ParserMatchClass = PCRelLabel19Operand;
1106}
1107
1108class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1109                     "b", ".$cond\t$target", "",
1110                     [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1111                   Sched<[WriteBr]> {
1112  let isBranch = 1;
1113  let isTerminator = 1;
1114  let Uses = [NZCV];
1115
1116  bits<4> cond;
1117  bits<19> target;
1118  let Inst{31-24} = 0b01010100;
1119  let Inst{23-5} = target;
1120  let Inst{4} = 0;
1121  let Inst{3-0} = cond;
1122}
1123
1124//---
1125// Compare-and-branch instructions.
1126//---
1127class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1128    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1129         asm, "\t$Rt, $target", "",
1130         [(node regtype:$Rt, bb:$target)]>,
1131      Sched<[WriteBr]> {
1132  let isBranch = 1;
1133  let isTerminator = 1;
1134
1135  bits<5> Rt;
1136  bits<19> target;
1137  let Inst{30-25} = 0b011010;
1138  let Inst{24}    = op;
1139  let Inst{23-5}  = target;
1140  let Inst{4-0}   = Rt;
1141}
1142
1143multiclass CmpBranch<bit op, string asm, SDNode node> {
1144  def W : BaseCmpBranch<GPR32, op, asm, node> {
1145    let Inst{31} = 0;
1146  }
1147  def X : BaseCmpBranch<GPR64, op, asm, node> {
1148    let Inst{31} = 1;
1149  }
1150}
1151
1152//---
1153// Test-bit-and-branch instructions.
1154//---
1155// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1156// the target offset are implied zero and so are not part of the immediate.
1157def BranchTarget14Operand : AsmOperandClass {
1158  let Name = "BranchTarget14";
1159}
1160def am_tbrcond : Operand<OtherVT> {
1161  let EncoderMethod = "getTestBranchTargetOpValue";
1162  let PrintMethod = "printAlignedLabel";
1163  let ParserMatchClass = BranchTarget14Operand;
1164}
1165
1166// AsmOperand classes to emit (or not) special diagnostics
1167def TBZImm0_31Operand : AsmOperandClass {
1168  let Name = "TBZImm0_31";
1169  let PredicateMethod = "isImm0_31";
1170  let RenderMethod = "addImm0_31Operands";
1171}
1172def TBZImm32_63Operand : AsmOperandClass {
1173  let Name = "Imm32_63";
1174  let DiagnosticType = "InvalidImm0_63";
1175}
1176
1177class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1178  return (((uint32_t)Imm) < 32);
1179}]> {
1180  let ParserMatchClass = matcher;
1181}
1182
1183def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1184def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1185
1186def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1187  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1188}]> {
1189  let ParserMatchClass = TBZImm32_63Operand;
1190}
1191
1192class BaseTestBranch<RegisterClass regtype, Operand immtype,
1193                     bit op, string asm, SDNode node>
1194    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1195       asm, "\t$Rt, $bit_off, $target", "",
1196       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1197      Sched<[WriteBr]> {
1198  let isBranch = 1;
1199  let isTerminator = 1;
1200
1201  bits<5> Rt;
1202  bits<6> bit_off;
1203  bits<14> target;
1204
1205  let Inst{30-25} = 0b011011;
1206  let Inst{24}    = op;
1207  let Inst{23-19} = bit_off{4-0};
1208  let Inst{18-5}  = target;
1209  let Inst{4-0}   = Rt;
1210
1211  let DecoderMethod = "DecodeTestAndBranch";
1212}
1213
1214multiclass TestBranch<bit op, string asm, SDNode node> {
1215  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1216    let Inst{31} = 0;
1217  }
1218
1219  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1220    let Inst{31} = 1;
1221  }
1222
1223  // Alias X-reg with 0-31 imm to W-Reg.
1224  def : InstAlias<asm # "\t$Rd, $imm, $target",
1225                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1226                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1227  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1228            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1229            tbz_imm0_31_diag:$imm, bb:$target)>;
1230}
1231
1232//---
1233// Unconditional branch (immediate) instructions.
1234//---
1235def BranchTarget26Operand : AsmOperandClass {
1236  let Name = "BranchTarget26";
1237  let DiagnosticType = "InvalidLabel";
1238}
1239def am_b_target : Operand<OtherVT> {
1240  let EncoderMethod = "getBranchTargetOpValue";
1241  let PrintMethod = "printAlignedLabel";
1242  let ParserMatchClass = BranchTarget26Operand;
1243}
1244def am_bl_target : Operand<i64> {
1245  let EncoderMethod = "getBranchTargetOpValue";
1246  let PrintMethod = "printAlignedLabel";
1247  let ParserMatchClass = BranchTarget26Operand;
1248}
1249
1250class BImm<bit op, dag iops, string asm, list<dag> pattern>
1251    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1252  bits<26> addr;
1253  let Inst{31}    = op;
1254  let Inst{30-26} = 0b00101;
1255  let Inst{25-0}  = addr;
1256
1257  let DecoderMethod = "DecodeUnconditionalBranch";
1258}
1259
1260class BranchImm<bit op, string asm, list<dag> pattern>
1261    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1262class CallImm<bit op, string asm, list<dag> pattern>
1263    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1264
1265//---
1266// Basic one-operand data processing instructions.
1267//---
1268
1269let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1270class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1271                         SDPatternOperator node>
1272  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1273      [(set regtype:$Rd, (node regtype:$Rn))]>,
1274    Sched<[WriteI, ReadI]> {
1275  bits<5> Rd;
1276  bits<5> Rn;
1277
1278  let Inst{30-13} = 0b101101011000000000;
1279  let Inst{12-10} = opc;
1280  let Inst{9-5}   = Rn;
1281  let Inst{4-0}   = Rd;
1282}
1283
1284let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1285multiclass OneOperandData<bits<3> opc, string asm,
1286                          SDPatternOperator node = null_frag> {
1287  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1288    let Inst{31} = 0;
1289  }
1290
1291  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1292    let Inst{31} = 1;
1293  }
1294}
1295
1296class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1297    : BaseOneOperandData<opc, GPR32, asm, node> {
1298  let Inst{31} = 0;
1299}
1300
1301class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1302    : BaseOneOperandData<opc, GPR64, asm, node> {
1303  let Inst{31} = 1;
1304}
1305
1306//---
1307// Basic two-operand data processing instructions.
1308//---
1309class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1310                          list<dag> pattern>
1311    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1312        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1313      Sched<[WriteI, ReadI, ReadI]> {
1314  let Uses = [NZCV];
1315  bits<5> Rd;
1316  bits<5> Rn;
1317  bits<5> Rm;
1318  let Inst{30}    = isSub;
1319  let Inst{28-21} = 0b11010000;
1320  let Inst{20-16} = Rm;
1321  let Inst{15-10} = 0;
1322  let Inst{9-5}   = Rn;
1323  let Inst{4-0}   = Rd;
1324}
1325
1326class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1327                      SDNode OpNode>
1328    : BaseBaseAddSubCarry<isSub, regtype, asm,
1329        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1330
1331class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1332                              SDNode OpNode>
1333    : BaseBaseAddSubCarry<isSub, regtype, asm,
1334        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1335         (implicit NZCV)]> {
1336  let Defs = [NZCV];
1337}
1338
1339multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1340                       SDNode OpNode, SDNode OpNode_setflags> {
1341  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1342    let Inst{31} = 0;
1343    let Inst{29} = 0;
1344  }
1345  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1346    let Inst{31} = 1;
1347    let Inst{29} = 0;
1348  }
1349
1350  // Sets flags.
1351  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1352                                    OpNode_setflags> {
1353    let Inst{31} = 0;
1354    let Inst{29} = 1;
1355  }
1356  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1357                                    OpNode_setflags> {
1358    let Inst{31} = 1;
1359    let Inst{29} = 1;
1360  }
1361}
1362
1363class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1364                     SDPatternOperator OpNode>
1365  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1366      asm, "\t$Rd, $Rn, $Rm", "",
1367      [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]> {
1368  bits<5> Rd;
1369  bits<5> Rn;
1370  bits<5> Rm;
1371  let Inst{30-21} = 0b0011010110;
1372  let Inst{20-16} = Rm;
1373  let Inst{15-14} = 0b00;
1374  let Inst{13-10} = opc;
1375  let Inst{9-5}   = Rn;
1376  let Inst{4-0}   = Rd;
1377}
1378
1379class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1380              SDPatternOperator OpNode>
1381    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1382  let Inst{10}    = isSigned;
1383}
1384
1385multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1386  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1387           Sched<[WriteID32, ReadID, ReadID]> {
1388    let Inst{31} = 0;
1389  }
1390  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1391           Sched<[WriteID64, ReadID, ReadID]> {
1392    let Inst{31} = 1;
1393  }
1394}
1395
1396class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1397                SDPatternOperator OpNode = null_frag>
1398  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1399    Sched<[WriteIS, ReadI]> {
1400  let Inst{11-10} = shift_type;
1401}
1402
1403multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1404  def Wr : BaseShift<shift_type, GPR32, asm> {
1405    let Inst{31} = 0;
1406  }
1407
1408  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1409    let Inst{31} = 1;
1410  }
1411
1412  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1413            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1414                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1415
1416  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1417            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1418
1419  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1420            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1421
1422  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1423            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1424}
1425
1426class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1427    : InstAlias<asm#"\t$dst, $src1, $src2",
1428                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1429
1430class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1431                       RegisterClass addtype, string asm,
1432                       list<dag> pattern>
1433  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1434      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1435  bits<5> Rd;
1436  bits<5> Rn;
1437  bits<5> Rm;
1438  bits<5> Ra;
1439  let Inst{30-24} = 0b0011011;
1440  let Inst{23-21} = opc;
1441  let Inst{20-16} = Rm;
1442  let Inst{15}    = isSub;
1443  let Inst{14-10} = Ra;
1444  let Inst{9-5}   = Rn;
1445  let Inst{4-0}   = Rd;
1446}
1447
1448multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1449  // MADD/MSUB generation is decided by MachineCombiner.cpp
1450  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
1451      [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
1452      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1453    let Inst{31} = 0;
1454  }
1455
1456  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
1457      [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
1458      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
1459    let Inst{31} = 1;
1460  }
1461}
1462
1463class WideMulAccum<bit isSub, bits<3> opc, string asm,
1464                   SDNode AccNode, SDNode ExtNode>
1465  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
1466    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
1467                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
1468    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
1469  let Inst{31} = 1;
1470}
1471
1472class MulHi<bits<3> opc, string asm, SDNode OpNode>
1473  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
1474      asm, "\t$Rd, $Rn, $Rm", "",
1475      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
1476    Sched<[WriteIM64, ReadIM, ReadIM]> {
1477  bits<5> Rd;
1478  bits<5> Rn;
1479  bits<5> Rm;
1480  let Inst{31-24} = 0b10011011;
1481  let Inst{23-21} = opc;
1482  let Inst{20-16} = Rm;
1483  let Inst{15}    = 0;
1484  let Inst{9-5}   = Rn;
1485  let Inst{4-0}   = Rd;
1486
1487  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
1488  // (i.e. all bits 1) but is ignored by the processor.
1489  let PostEncoderMethod = "fixMulHigh";
1490}
1491
1492class MulAccumWAlias<string asm, Instruction inst>
1493    : InstAlias<asm#"\t$dst, $src1, $src2",
1494                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
1495class MulAccumXAlias<string asm, Instruction inst>
1496    : InstAlias<asm#"\t$dst, $src1, $src2",
1497                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
1498class WideMulAccumAlias<string asm, Instruction inst>
1499    : InstAlias<asm#"\t$dst, $src1, $src2",
1500                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
1501
1502class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
1503              SDPatternOperator OpNode, string asm>
1504  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
1505      asm, "\t$Rd, $Rn, $Rm", "",
1506      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
1507    Sched<[WriteISReg, ReadI, ReadISReg]> {
1508  bits<5> Rd;
1509  bits<5> Rn;
1510  bits<5> Rm;
1511
1512  let Inst{31} = sf;
1513  let Inst{30-21} = 0b0011010110;
1514  let Inst{20-16} = Rm;
1515  let Inst{15-13} = 0b010;
1516  let Inst{12} = C;
1517  let Inst{11-10} = sz;
1518  let Inst{9-5} = Rn;
1519  let Inst{4-0} = Rd;
1520  let Predicates = [HasCRC];
1521}
1522
1523//---
1524// Address generation.
1525//---
1526
1527class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
1528    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
1529        pattern>,
1530      Sched<[WriteI]> {
1531  bits<5>  Xd;
1532  bits<21> label;
1533  let Inst{31}    = page;
1534  let Inst{30-29} = label{1-0};
1535  let Inst{28-24} = 0b10000;
1536  let Inst{23-5}  = label{20-2};
1537  let Inst{4-0}   = Xd;
1538
1539  let DecoderMethod = "DecodeAdrInstruction";
1540}
1541
1542//---
1543// Move immediate.
1544//---
1545
1546def movimm32_imm : Operand<i32> {
1547  let ParserMatchClass = Imm0_65535Operand;
1548  let EncoderMethod = "getMoveWideImmOpValue";
1549  let PrintMethod = "printImm";
1550}
1551def movimm32_shift : Operand<i32> {
1552  let PrintMethod = "printShifter";
1553  let ParserMatchClass = MovImm32ShifterOperand;
1554}
1555def movimm64_shift : Operand<i32> {
1556  let PrintMethod = "printShifter";
1557  let ParserMatchClass = MovImm64ShifterOperand;
1558}
1559
1560let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1561class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1562                        string asm>
1563  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
1564       asm, "\t$Rd, $imm$shift", "", []>,
1565    Sched<[WriteImm]> {
1566  bits<5> Rd;
1567  bits<16> imm;
1568  bits<6> shift;
1569  let Inst{30-29} = opc;
1570  let Inst{28-23} = 0b100101;
1571  let Inst{22-21} = shift{5-4};
1572  let Inst{20-5}  = imm;
1573  let Inst{4-0}   = Rd;
1574
1575  let DecoderMethod = "DecodeMoveImmInstruction";
1576}
1577
1578multiclass MoveImmediate<bits<2> opc, string asm> {
1579  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
1580    let Inst{31} = 0;
1581  }
1582
1583  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
1584    let Inst{31} = 1;
1585  }
1586}
1587
1588let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1589class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
1590                          string asm>
1591  : I<(outs regtype:$Rd),
1592      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
1593       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
1594    Sched<[WriteI, ReadI]> {
1595  bits<5> Rd;
1596  bits<16> imm;
1597  bits<6> shift;
1598  let Inst{30-29} = opc;
1599  let Inst{28-23} = 0b100101;
1600  let Inst{22-21} = shift{5-4};
1601  let Inst{20-5}  = imm;
1602  let Inst{4-0}   = Rd;
1603
1604  let DecoderMethod = "DecodeMoveImmInstruction";
1605}
1606
1607multiclass InsertImmediate<bits<2> opc, string asm> {
1608  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
1609    let Inst{31} = 0;
1610  }
1611
1612  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
1613    let Inst{31} = 1;
1614  }
1615}
1616
1617//---
1618// Add/Subtract
1619//---
1620
1621class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
1622                    RegisterClass srcRegtype, addsub_shifted_imm immtype,
1623                    string asm, SDPatternOperator OpNode>
1624    : I<(outs dstRegtype:$Rd), (ins srcRegtype:$Rn, immtype:$imm),
1625        asm, "\t$Rd, $Rn, $imm", "",
1626        [(set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))]>,
1627      Sched<[WriteI, ReadI]>  {
1628  bits<5>  Rd;
1629  bits<5>  Rn;
1630  bits<14> imm;
1631  let Inst{30}    = isSub;
1632  let Inst{29}    = setFlags;
1633  let Inst{28-24} = 0b10001;
1634  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
1635  let Inst{21-10} = imm{11-0};
1636  let Inst{9-5}   = Rn;
1637  let Inst{4-0}   = Rd;
1638  let DecoderMethod = "DecodeBaseAddSubImm";
1639}
1640
1641class BaseAddSubRegPseudo<RegisterClass regtype,
1642                          SDPatternOperator OpNode>
1643    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1644             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
1645      Sched<[WriteI, ReadI, ReadI]>;
1646
1647class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
1648                     arith_shifted_reg shifted_regtype, string asm,
1649                     SDPatternOperator OpNode>
1650    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
1651        asm, "\t$Rd, $Rn, $Rm", "",
1652        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
1653      Sched<[WriteISReg, ReadI, ReadISReg]> {
1654  // The operands are in order to match the 'addr' MI operands, so we
1655  // don't need an encoder method and by-name matching. Just use the default
1656  // in-order handling. Since we're using by-order, make sure the names
1657  // do not match.
1658  bits<5> dst;
1659  bits<5> src1;
1660  bits<5> src2;
1661  bits<8> shift;
1662  let Inst{30}    = isSub;
1663  let Inst{29}    = setFlags;
1664  let Inst{28-24} = 0b01011;
1665  let Inst{23-22} = shift{7-6};
1666  let Inst{21}    = 0;
1667  let Inst{20-16} = src2;
1668  let Inst{15-10} = shift{5-0};
1669  let Inst{9-5}   = src1;
1670  let Inst{4-0}   = dst;
1671
1672  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
1673}
1674
1675class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
1676                     RegisterClass src1Regtype, Operand src2Regtype,
1677                     string asm, SDPatternOperator OpNode>
1678    : I<(outs dstRegtype:$R1),
1679        (ins src1Regtype:$R2, src2Regtype:$R3),
1680        asm, "\t$R1, $R2, $R3", "",
1681        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
1682      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1683  bits<5> Rd;
1684  bits<5> Rn;
1685  bits<5> Rm;
1686  bits<6> ext;
1687  let Inst{30}    = isSub;
1688  let Inst{29}    = setFlags;
1689  let Inst{28-24} = 0b01011;
1690  let Inst{23-21} = 0b001;
1691  let Inst{20-16} = Rm;
1692  let Inst{15-13} = ext{5-3};
1693  let Inst{12-10} = ext{2-0};
1694  let Inst{9-5}   = Rn;
1695  let Inst{4-0}   = Rd;
1696
1697  let DecoderMethod = "DecodeAddSubERegInstruction";
1698}
1699
1700let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1701class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
1702                       RegisterClass src1Regtype, RegisterClass src2Regtype,
1703                       Operand ext_op, string asm>
1704    : I<(outs dstRegtype:$Rd),
1705        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
1706        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
1707      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
1708  bits<5> Rd;
1709  bits<5> Rn;
1710  bits<5> Rm;
1711  bits<6> ext;
1712  let Inst{30}    = isSub;
1713  let Inst{29}    = setFlags;
1714  let Inst{28-24} = 0b01011;
1715  let Inst{23-21} = 0b001;
1716  let Inst{20-16} = Rm;
1717  let Inst{15}    = ext{5};
1718  let Inst{12-10} = ext{2-0};
1719  let Inst{9-5}   = Rn;
1720  let Inst{4-0}   = Rd;
1721
1722  let DecoderMethod = "DecodeAddSubERegInstruction";
1723}
1724
1725// Aliases for register+register add/subtract.
1726class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
1727                     RegisterClass src1Regtype, RegisterClass src2Regtype,
1728                     int shiftExt>
1729    : InstAlias<asm#"\t$dst, $src1, $src2",
1730                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
1731                      shiftExt)>;
1732
1733multiclass AddSub<bit isSub, string mnemonic, string alias,
1734                  SDPatternOperator OpNode = null_frag> {
1735  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
1736  // Add/Subtract immediate
1737  // Increase the weight of the immediate variant to try to match it before
1738  // the extended register variant.
1739  // We used to match the register variant before the immediate when the
1740  // register argument could be implicitly zero-extended.
1741  let AddedComplexity = 6 in
1742  def Wri  : BaseAddSubImm<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
1743                           mnemonic, OpNode> {
1744    let Inst{31} = 0;
1745  }
1746  let AddedComplexity = 6 in
1747  def Xri  : BaseAddSubImm<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
1748                           mnemonic, OpNode> {
1749    let Inst{31} = 1;
1750  }
1751
1752  // Add/Subtract register - Only used for CodeGen
1753  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1754  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1755
1756  // Add/Subtract shifted register
1757  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
1758                           OpNode> {
1759    let Inst{31} = 0;
1760  }
1761  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
1762                           OpNode> {
1763    let Inst{31} = 1;
1764  }
1765  }
1766
1767  // Add/Subtract extended register
1768  let AddedComplexity = 1, hasSideEffects = 0 in {
1769  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
1770                           arith_extended_reg32<i32>, mnemonic, OpNode> {
1771    let Inst{31} = 0;
1772  }
1773  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
1774                           arith_extended_reg32to64<i64>, mnemonic, OpNode> {
1775    let Inst{31} = 1;
1776  }
1777  }
1778
1779  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
1780                               arith_extendlsl64, mnemonic> {
1781    // UXTX and SXTX only.
1782    let Inst{14-13} = 0b11;
1783    let Inst{31} = 1;
1784  }
1785
1786  // add Rd, Rb, -imm -> sub Rd, Rn, imm
1787  def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1788                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
1789                      addsub_shifted_imm32_neg:$imm), 0>;
1790  def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1791                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
1792                       addsub_shifted_imm64_neg:$imm), 0>;
1793
1794  // Register/register aliases with no shift when SP is not used.
1795  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1796                       GPR32, GPR32, GPR32, 0>;
1797  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1798                       GPR64, GPR64, GPR64, 0>;
1799
1800  // Register/register aliases with no shift when either the destination or
1801  // first source register is SP.
1802  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1803                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
1804  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1805                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
1806  def : AddSubRegAlias<mnemonic,
1807                       !cast<Instruction>(NAME#"Xrx64"),
1808                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
1809  def : AddSubRegAlias<mnemonic,
1810                       !cast<Instruction>(NAME#"Xrx64"),
1811                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
1812}
1813
1814multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
1815                   string alias, string cmpAlias> {
1816  let isCompare = 1, Defs = [NZCV] in {
1817  // Add/Subtract immediate
1818  def Wri  : BaseAddSubImm<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
1819                           mnemonic, OpNode> {
1820    let Inst{31} = 0;
1821  }
1822  def Xri  : BaseAddSubImm<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
1823                           mnemonic, OpNode> {
1824    let Inst{31} = 1;
1825  }
1826
1827  // Add/Subtract register
1828  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
1829  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
1830
1831  // Add/Subtract shifted register
1832  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
1833                           OpNode> {
1834    let Inst{31} = 0;
1835  }
1836  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
1837                           OpNode> {
1838    let Inst{31} = 1;
1839  }
1840
1841  // Add/Subtract extended register
1842  let AddedComplexity = 1 in {
1843  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
1844                           arith_extended_reg32<i32>, mnemonic, OpNode> {
1845    let Inst{31} = 0;
1846  }
1847  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
1848                           arith_extended_reg32<i64>, mnemonic, OpNode> {
1849    let Inst{31} = 1;
1850  }
1851  }
1852
1853  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
1854                               arith_extendlsl64, mnemonic> {
1855    // UXTX and SXTX only.
1856    let Inst{14-13} = 0b11;
1857    let Inst{31} = 1;
1858  }
1859  } // Defs = [NZCV]
1860
1861  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
1862  def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1863                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
1864                      addsub_shifted_imm32_neg:$imm), 0>;
1865  def : InstAlias<alias#"\t$Rd, $Rn, $imm",
1866                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
1867                       addsub_shifted_imm64_neg:$imm), 0>;
1868
1869  // Compare aliases
1870  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1871                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
1872  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1873                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
1874  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
1875                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1876  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
1877                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
1878  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
1879                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
1880  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
1881                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
1882  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
1883                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
1884
1885  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
1886  def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
1887                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
1888  def : InstAlias<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
1889                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
1890
1891  // Compare shorthands
1892  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
1893                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
1894  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
1895                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
1896  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
1897                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
1898  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
1899                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
1900
1901  // Register/register aliases with no shift when SP is not used.
1902  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
1903                       GPR32, GPR32, GPR32, 0>;
1904  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
1905                       GPR64, GPR64, GPR64, 0>;
1906
1907  // Register/register aliases with no shift when the first source register
1908  // is SP.
1909  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
1910                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
1911  def : AddSubRegAlias<mnemonic,
1912                       !cast<Instruction>(NAME#"Xrx64"),
1913                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
1914}
1915
1916//---
1917// Extract
1918//---
1919def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
1920                                      SDTCisPtrTy<3>]>;
1921def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
1922
1923class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
1924                     list<dag> patterns>
1925    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
1926         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
1927      Sched<[WriteExtr, ReadExtrHi]> {
1928  bits<5> Rd;
1929  bits<5> Rn;
1930  bits<5> Rm;
1931  bits<6> imm;
1932
1933  let Inst{30-23} = 0b00100111;
1934  let Inst{21}    = 0;
1935  let Inst{20-16} = Rm;
1936  let Inst{15-10} = imm;
1937  let Inst{9-5}   = Rn;
1938  let Inst{4-0}   = Rd;
1939}
1940
1941multiclass ExtractImm<string asm> {
1942  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
1943                      [(set GPR32:$Rd,
1944                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
1945    let Inst{31} = 0;
1946    let Inst{22} = 0;
1947    // imm<5> must be zero.
1948    let imm{5}   = 0;
1949  }
1950  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
1951                      [(set GPR64:$Rd,
1952                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
1953
1954    let Inst{31} = 1;
1955    let Inst{22} = 1;
1956  }
1957}
1958
1959//---
1960// Bitfield
1961//---
1962
1963let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1964class BaseBitfieldImm<bits<2> opc,
1965                      RegisterClass regtype, Operand imm_type, string asm>
1966    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
1967         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
1968      Sched<[WriteIS, ReadI]> {
1969  bits<5> Rd;
1970  bits<5> Rn;
1971  bits<6> immr;
1972  bits<6> imms;
1973
1974  let Inst{30-29} = opc;
1975  let Inst{28-23} = 0b100110;
1976  let Inst{21-16} = immr;
1977  let Inst{15-10} = imms;
1978  let Inst{9-5}   = Rn;
1979  let Inst{4-0}   = Rd;
1980}
1981
1982multiclass BitfieldImm<bits<2> opc, string asm> {
1983  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
1984    let Inst{31} = 0;
1985    let Inst{22} = 0;
1986    // imms<5> and immr<5> must be zero, else ReservedValue().
1987    let Inst{21} = 0;
1988    let Inst{15} = 0;
1989  }
1990  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
1991    let Inst{31} = 1;
1992    let Inst{22} = 1;
1993  }
1994}
1995
1996let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1997class BaseBitfieldImmWith2RegArgs<bits<2> opc,
1998                      RegisterClass regtype, Operand imm_type, string asm>
1999    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2000                             imm_type:$imms),
2001         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2002      Sched<[WriteIS, ReadI]> {
2003  bits<5> Rd;
2004  bits<5> Rn;
2005  bits<6> immr;
2006  bits<6> imms;
2007
2008  let Inst{30-29} = opc;
2009  let Inst{28-23} = 0b100110;
2010  let Inst{21-16} = immr;
2011  let Inst{15-10} = imms;
2012  let Inst{9-5}   = Rn;
2013  let Inst{4-0}   = Rd;
2014}
2015
2016multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2017  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2018    let Inst{31} = 0;
2019    let Inst{22} = 0;
2020    // imms<5> and immr<5> must be zero, else ReservedValue().
2021    let Inst{21} = 0;
2022    let Inst{15} = 0;
2023  }
2024  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2025    let Inst{31} = 1;
2026    let Inst{22} = 1;
2027  }
2028}
2029
2030//---
2031// Logical
2032//---
2033
2034// Logical (immediate)
2035class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2036                     RegisterClass sregtype, Operand imm_type, string asm,
2037                     list<dag> pattern>
2038    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2039         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2040      Sched<[WriteI, ReadI]> {
2041  bits<5>  Rd;
2042  bits<5>  Rn;
2043  bits<13> imm;
2044  let Inst{30-29} = opc;
2045  let Inst{28-23} = 0b100100;
2046  let Inst{22}    = imm{12};
2047  let Inst{21-16} = imm{11-6};
2048  let Inst{15-10} = imm{5-0};
2049  let Inst{9-5}   = Rn;
2050  let Inst{4-0}   = Rd;
2051
2052  let DecoderMethod = "DecodeLogicalImmInstruction";
2053}
2054
2055// Logical (shifted register)
2056class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2057                      logical_shifted_reg shifted_regtype, string asm,
2058                      list<dag> pattern>
2059    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2060        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2061      Sched<[WriteISReg, ReadI, ReadISReg]> {
2062  // The operands are in order to match the 'addr' MI operands, so we
2063  // don't need an encoder method and by-name matching. Just use the default
2064  // in-order handling. Since we're using by-order, make sure the names
2065  // do not match.
2066  bits<5> dst;
2067  bits<5> src1;
2068  bits<5> src2;
2069  bits<8> shift;
2070  let Inst{30-29} = opc;
2071  let Inst{28-24} = 0b01010;
2072  let Inst{23-22} = shift{7-6};
2073  let Inst{21}    = N;
2074  let Inst{20-16} = src2;
2075  let Inst{15-10} = shift{5-0};
2076  let Inst{9-5}   = src1;
2077  let Inst{4-0}   = dst;
2078
2079  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2080}
2081
2082// Aliases for register+register logical instructions.
2083class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2084    : InstAlias<asm#"\t$dst, $src1, $src2",
2085                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2086
2087multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2088                      string Alias> {
2089  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2090  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2091                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2092                                               logical_imm32:$imm))]> {
2093    let Inst{31} = 0;
2094    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2095  }
2096  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2097  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2098                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2099                                               logical_imm64:$imm))]> {
2100    let Inst{31} = 1;
2101  }
2102
2103  def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2104                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2105                      logical_imm32_not:$imm), 0>;
2106  def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2107                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2108                       logical_imm64_not:$imm), 0>;
2109}
2110
2111multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2112                       string Alias> {
2113  let isCompare = 1, Defs = [NZCV] in {
2114  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2115      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2116    let Inst{31} = 0;
2117    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2118  }
2119  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2120      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2121    let Inst{31} = 1;
2122  }
2123  } // end Defs = [NZCV]
2124
2125  def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2126                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2127                      logical_imm32_not:$imm), 0>;
2128  def : InstAlias<Alias # "\t$Rd, $Rn, $imm",
2129                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2130                       logical_imm64_not:$imm), 0>;
2131}
2132
2133class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2134    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2135             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2136      Sched<[WriteI, ReadI, ReadI]>;
2137
2138// Split from LogicalImm as not all instructions have both.
2139multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2140                      SDPatternOperator OpNode> {
2141  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2142  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2143  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2144  }
2145
2146  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2147                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2148                                                 logical_shifted_reg32:$Rm))]> {
2149    let Inst{31} = 0;
2150  }
2151  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2152                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2153                                                 logical_shifted_reg64:$Rm))]> {
2154    let Inst{31} = 1;
2155  }
2156
2157  def : LogicalRegAlias<mnemonic,
2158                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2159  def : LogicalRegAlias<mnemonic,
2160                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2161}
2162
2163// Split from LogicalReg to allow setting NZCV Defs
2164multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2165                       SDPatternOperator OpNode = null_frag> {
2166  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2167  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2168  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2169
2170  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2171            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2172    let Inst{31} = 0;
2173  }
2174  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2175            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2176    let Inst{31} = 1;
2177  }
2178  } // Defs = [NZCV]
2179
2180  def : LogicalRegAlias<mnemonic,
2181                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2182  def : LogicalRegAlias<mnemonic,
2183                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2184}
2185
2186//---
2187// Conditionally set flags
2188//---
2189
2190let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2191class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2192                            string mnemonic, SDNode OpNode>
2193    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2194         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2195         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2196                             (i32 imm:$cond), NZCV))]>,
2197      Sched<[WriteI, ReadI]> {
2198  let Uses = [NZCV];
2199  let Defs = [NZCV];
2200
2201  bits<5> Rn;
2202  bits<5> imm;
2203  bits<4> nzcv;
2204  bits<4> cond;
2205
2206  let Inst{30}    = op;
2207  let Inst{29-21} = 0b111010010;
2208  let Inst{20-16} = imm;
2209  let Inst{15-12} = cond;
2210  let Inst{11-10} = 0b10;
2211  let Inst{9-5}   = Rn;
2212  let Inst{4}     = 0b0;
2213  let Inst{3-0}   = nzcv;
2214}
2215
2216let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2217class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2218                            SDNode OpNode>
2219    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2220         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2221         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2222                             (i32 imm:$cond), NZCV))]>,
2223      Sched<[WriteI, ReadI, ReadI]> {
2224  let Uses = [NZCV];
2225  let Defs = [NZCV];
2226
2227  bits<5> Rn;
2228  bits<5> Rm;
2229  bits<4> nzcv;
2230  bits<4> cond;
2231
2232  let Inst{30}    = op;
2233  let Inst{29-21} = 0b111010010;
2234  let Inst{20-16} = Rm;
2235  let Inst{15-12} = cond;
2236  let Inst{11-10} = 0b00;
2237  let Inst{9-5}   = Rn;
2238  let Inst{4}     = 0b0;
2239  let Inst{3-0}   = nzcv;
2240}
2241
2242multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2243  // immediate operand variants
2244  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2245    let Inst{31} = 0;
2246  }
2247  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2248    let Inst{31} = 1;
2249  }
2250  // register operand variants
2251  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2252    let Inst{31} = 0;
2253  }
2254  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2255    let Inst{31} = 1;
2256  }
2257}
2258
2259//---
2260// Conditional select
2261//---
2262
2263class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2264    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2265         asm, "\t$Rd, $Rn, $Rm, $cond", "",
2266         [(set regtype:$Rd,
2267               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2268      Sched<[WriteI, ReadI, ReadI]> {
2269  let Uses = [NZCV];
2270
2271  bits<5> Rd;
2272  bits<5> Rn;
2273  bits<5> Rm;
2274  bits<4> cond;
2275
2276  let Inst{30}    = op;
2277  let Inst{29-21} = 0b011010100;
2278  let Inst{20-16} = Rm;
2279  let Inst{15-12} = cond;
2280  let Inst{11-10} = op2;
2281  let Inst{9-5}   = Rn;
2282  let Inst{4-0}   = Rd;
2283}
2284
2285multiclass CondSelect<bit op, bits<2> op2, string asm> {
2286  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2287    let Inst{31} = 0;
2288  }
2289  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2290    let Inst{31} = 1;
2291  }
2292}
2293
2294class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2295                       PatFrag frag>
2296    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2297         asm, "\t$Rd, $Rn, $Rm, $cond", "",
2298         [(set regtype:$Rd,
2299               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2300               (i32 imm:$cond), NZCV))]>,
2301      Sched<[WriteI, ReadI, ReadI]> {
2302  let Uses = [NZCV];
2303
2304  bits<5> Rd;
2305  bits<5> Rn;
2306  bits<5> Rm;
2307  bits<4> cond;
2308
2309  let Inst{30}    = op;
2310  let Inst{29-21} = 0b011010100;
2311  let Inst{20-16} = Rm;
2312  let Inst{15-12} = cond;
2313  let Inst{11-10} = op2;
2314  let Inst{9-5}   = Rn;
2315  let Inst{4-0}   = Rd;
2316}
2317
2318def inv_cond_XFORM : SDNodeXForm<imm, [{
2319  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2320  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2321                                   MVT::i32);
2322}]>;
2323
2324multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2325  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2326    let Inst{31} = 0;
2327  }
2328  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2329    let Inst{31} = 1;
2330  }
2331
2332  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2333            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2334                                           (inv_cond_XFORM imm:$cond))>;
2335
2336  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2337            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2338                                           (inv_cond_XFORM imm:$cond))>;
2339}
2340
2341//---
2342// Special Mask Value
2343//---
2344def maski8_or_more : Operand<i32>,
2345  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2346}
2347def maski16_or_more : Operand<i32>,
2348  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2349}
2350
2351
2352//---
2353// Load/store
2354//---
2355
2356// (unsigned immediate)
2357// Indexed for 8-bit registers. offset is in range [0,4095].
2358def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2359def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2360def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2361def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2362def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2363
2364class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2365  let Name = "UImm12Offset" # Scale;
2366  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2367  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2368  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2369}
2370
2371def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2372def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2373def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2374def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2375def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2376
2377class uimm12_scaled<int Scale> : Operand<i64> {
2378  let ParserMatchClass
2379   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2380  let EncoderMethod
2381   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2382  let PrintMethod = "printUImm12Offset<" # Scale # ">";
2383}
2384
2385def uimm12s1 : uimm12_scaled<1>;
2386def uimm12s2 : uimm12_scaled<2>;
2387def uimm12s4 : uimm12_scaled<4>;
2388def uimm12s8 : uimm12_scaled<8>;
2389def uimm12s16 : uimm12_scaled<16>;
2390
2391class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2392                      string asm, list<dag> pattern>
2393    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2394  bits<5> Rt;
2395
2396  bits<5> Rn;
2397  bits<12> offset;
2398
2399  let Inst{31-30} = sz;
2400  let Inst{29-27} = 0b111;
2401  let Inst{26}    = V;
2402  let Inst{25-24} = 0b01;
2403  let Inst{23-22} = opc;
2404  let Inst{21-10} = offset;
2405  let Inst{9-5}   = Rn;
2406  let Inst{4-0}   = Rt;
2407
2408  let DecoderMethod = "DecodeUnsignedLdStInstruction";
2409}
2410
2411multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2412                  Operand indextype, string asm, list<dag> pattern> {
2413  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2414  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
2415                           (ins GPR64sp:$Rn, indextype:$offset),
2416                           asm, pattern>,
2417           Sched<[WriteLD]>;
2418
2419  def : InstAlias<asm # "\t$Rt, [$Rn]",
2420                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2421}
2422
2423multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2424             Operand indextype, string asm, list<dag> pattern> {
2425  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2426  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
2427                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
2428                           asm, pattern>,
2429           Sched<[WriteST]>;
2430
2431  def : InstAlias<asm # "\t$Rt, [$Rn]",
2432                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
2433}
2434
2435def PrefetchOperand : AsmOperandClass {
2436  let Name = "Prefetch";
2437  let ParserMethod = "tryParsePrefetch";
2438}
2439def prfop : Operand<i32> {
2440  let PrintMethod = "printPrefetchOp";
2441  let ParserMatchClass = PrefetchOperand;
2442}
2443
2444let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2445class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
2446    : BaseLoadStoreUI<sz, V, opc,
2447                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
2448                      asm, pat>,
2449      Sched<[WriteLD]>;
2450
2451//---
2452// Load literal
2453//---
2454
2455// Load literal address: 19-bit immediate. The low two bits of the target
2456// offset are implied zero and so are not part of the immediate.
2457def am_ldrlit : Operand<OtherVT> {
2458  let EncoderMethod = "getLoadLiteralOpValue";
2459  let DecoderMethod = "DecodePCRelLabel19";
2460  let PrintMethod = "printAlignedLabel";
2461  let ParserMatchClass = PCRelLabel19Operand;
2462}
2463
2464let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2465class LoadLiteral<bits<2> opc, bit V, RegisterClass regtype, string asm>
2466    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
2467        asm, "\t$Rt, $label", "", []>,
2468      Sched<[WriteLD]> {
2469  bits<5> Rt;
2470  bits<19> label;
2471  let Inst{31-30} = opc;
2472  let Inst{29-27} = 0b011;
2473  let Inst{26}    = V;
2474  let Inst{25-24} = 0b00;
2475  let Inst{23-5}  = label;
2476  let Inst{4-0}   = Rt;
2477}
2478
2479let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2480class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
2481    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
2482        asm, "\t$Rt, $label", "", pat>,
2483      Sched<[WriteLD]> {
2484  bits<5> Rt;
2485  bits<19> label;
2486  let Inst{31-30} = opc;
2487  let Inst{29-27} = 0b011;
2488  let Inst{26}    = V;
2489  let Inst{25-24} = 0b00;
2490  let Inst{23-5}  = label;
2491  let Inst{4-0}   = Rt;
2492}
2493
2494//---
2495// Load/store register offset
2496//---
2497
2498def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
2499def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
2500def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
2501def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
2502def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
2503
2504def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
2505def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
2506def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
2507def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
2508def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
2509
2510class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
2511  let Name = "Mem" # Reg # "Extend" # Width;
2512  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
2513  let RenderMethod = "addMemExtendOperands";
2514  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
2515}
2516
2517def MemWExtend8Operand : MemExtendOperand<"W", 8> {
2518  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2519  // the trivial shift.
2520  let RenderMethod = "addMemExtend8Operands";
2521}
2522def MemWExtend16Operand : MemExtendOperand<"W", 16>;
2523def MemWExtend32Operand : MemExtendOperand<"W", 32>;
2524def MemWExtend64Operand : MemExtendOperand<"W", 64>;
2525def MemWExtend128Operand : MemExtendOperand<"W", 128>;
2526
2527def MemXExtend8Operand : MemExtendOperand<"X", 8> {
2528  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
2529  // the trivial shift.
2530  let RenderMethod = "addMemExtend8Operands";
2531}
2532def MemXExtend16Operand : MemExtendOperand<"X", 16>;
2533def MemXExtend32Operand : MemExtendOperand<"X", 32>;
2534def MemXExtend64Operand : MemExtendOperand<"X", 64>;
2535def MemXExtend128Operand : MemExtendOperand<"X", 128>;
2536
2537class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
2538        : Operand<i32> {
2539  let ParserMatchClass = ParserClass;
2540  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
2541  let DecoderMethod = "DecodeMemExtend";
2542  let EncoderMethod = "getMemExtendOpValue";
2543  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
2544}
2545
2546def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
2547def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
2548def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
2549def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
2550def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
2551
2552def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
2553def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
2554def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
2555def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
2556def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
2557
2558class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
2559                  Operand wextend, Operand xextend>  {
2560  // CodeGen-level pattern covering the entire addressing mode.
2561  ComplexPattern Wpat = windex;
2562  ComplexPattern Xpat = xindex;
2563
2564  // Asm-level Operand covering the valid "uxtw #3" style syntax.
2565  Operand Wext = wextend;
2566  Operand Xext = xextend;
2567}
2568
2569def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
2570def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
2571def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
2572def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
2573def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
2574                       ro_Xextend128>;
2575
2576class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2577                      string asm, dag ins, dag outs, list<dag> pat>
2578    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2579  bits<5> Rt;
2580  bits<5> Rn;
2581  bits<5> Rm;
2582  bits<2> extend;
2583  let Inst{31-30} = sz;
2584  let Inst{29-27} = 0b111;
2585  let Inst{26}    = V;
2586  let Inst{25-24} = 0b00;
2587  let Inst{23-22} = opc;
2588  let Inst{21}    = 1;
2589  let Inst{20-16} = Rm;
2590  let Inst{15}    = extend{1}; // sign extend Rm?
2591  let Inst{14}    = 1;
2592  let Inst{12}    = extend{0}; // do shift?
2593  let Inst{11-10} = 0b10;
2594  let Inst{9-5}   = Rn;
2595  let Inst{4-0}   = Rt;
2596}
2597
2598class ROInstAlias<string asm, RegisterClass regtype, Instruction INST>
2599  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
2600              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2601
2602multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2603                   string asm, ValueType Ty, SDPatternOperator loadop> {
2604  let AddedComplexity = 10 in
2605  def roW : LoadStore8RO<sz, V, opc, regtype, asm,
2606                 (outs regtype:$Rt),
2607                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2608                 [(set (Ty regtype:$Rt),
2609                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2610                                             ro_Wextend8:$extend)))]>,
2611           Sched<[WriteLDIdx, ReadAdrBase]> {
2612    let Inst{13} = 0b0;
2613  }
2614
2615  let AddedComplexity = 10 in
2616  def roX : LoadStore8RO<sz, V, opc, regtype, asm,
2617                 (outs regtype:$Rt),
2618                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2619                 [(set (Ty regtype:$Rt),
2620                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2621                                             ro_Xextend8:$extend)))]>,
2622           Sched<[WriteLDIdx, ReadAdrBase]> {
2623    let Inst{13} = 0b1;
2624  }
2625
2626  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2627}
2628
2629multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2630                    string asm, ValueType Ty, SDPatternOperator storeop> {
2631  let AddedComplexity = 10 in
2632  def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2633                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
2634                 [(storeop (Ty regtype:$Rt),
2635                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
2636                                         ro_Wextend8:$extend))]>,
2637            Sched<[WriteSTIdx, ReadAdrBase]> {
2638    let Inst{13} = 0b0;
2639  }
2640
2641  let AddedComplexity = 10 in
2642  def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
2643                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
2644                 [(storeop (Ty regtype:$Rt),
2645                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
2646                                         ro_Xextend8:$extend))]>,
2647            Sched<[WriteSTIdx, ReadAdrBase]> {
2648    let Inst{13} = 0b1;
2649  }
2650
2651  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2652}
2653
2654class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2655                      string asm, dag ins, dag outs, list<dag> pat>
2656    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2657  bits<5> Rt;
2658  bits<5> Rn;
2659  bits<5> Rm;
2660  bits<2> extend;
2661  let Inst{31-30} = sz;
2662  let Inst{29-27} = 0b111;
2663  let Inst{26}    = V;
2664  let Inst{25-24} = 0b00;
2665  let Inst{23-22} = opc;
2666  let Inst{21}    = 1;
2667  let Inst{20-16} = Rm;
2668  let Inst{15}    = extend{1}; // sign extend Rm?
2669  let Inst{14}    = 1;
2670  let Inst{12}    = extend{0}; // do shift?
2671  let Inst{11-10} = 0b10;
2672  let Inst{9-5}   = Rn;
2673  let Inst{4-0}   = Rt;
2674}
2675
2676multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2677                    string asm, ValueType Ty, SDPatternOperator loadop> {
2678  let AddedComplexity = 10 in
2679  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2680                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2681                 [(set (Ty regtype:$Rt),
2682                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2683                                              ro_Wextend16:$extend)))]>,
2684            Sched<[WriteLDIdx, ReadAdrBase]> {
2685    let Inst{13} = 0b0;
2686  }
2687
2688  let AddedComplexity = 10 in
2689  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2690                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2691                 [(set (Ty regtype:$Rt),
2692                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2693                                             ro_Xextend16:$extend)))]>,
2694            Sched<[WriteLDIdx, ReadAdrBase]> {
2695    let Inst{13} = 0b1;
2696  }
2697
2698  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2699}
2700
2701multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2702                     string asm, ValueType Ty, SDPatternOperator storeop> {
2703  let AddedComplexity = 10 in
2704  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2705                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
2706                [(storeop (Ty regtype:$Rt),
2707                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
2708                                         ro_Wextend16:$extend))]>,
2709           Sched<[WriteSTIdx, ReadAdrBase]> {
2710    let Inst{13} = 0b0;
2711  }
2712
2713  let AddedComplexity = 10 in
2714  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
2715                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
2716                [(storeop (Ty regtype:$Rt),
2717                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
2718                                         ro_Xextend16:$extend))]>,
2719           Sched<[WriteSTIdx, ReadAdrBase]> {
2720    let Inst{13} = 0b1;
2721  }
2722
2723  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2724}
2725
2726class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2727                      string asm, dag ins, dag outs, list<dag> pat>
2728    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2729  bits<5> Rt;
2730  bits<5> Rn;
2731  bits<5> Rm;
2732  bits<2> extend;
2733  let Inst{31-30} = sz;
2734  let Inst{29-27} = 0b111;
2735  let Inst{26}    = V;
2736  let Inst{25-24} = 0b00;
2737  let Inst{23-22} = opc;
2738  let Inst{21}    = 1;
2739  let Inst{20-16} = Rm;
2740  let Inst{15}    = extend{1}; // sign extend Rm?
2741  let Inst{14}    = 1;
2742  let Inst{12}    = extend{0}; // do shift?
2743  let Inst{11-10} = 0b10;
2744  let Inst{9-5}   = Rn;
2745  let Inst{4-0}   = Rt;
2746}
2747
2748multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2749                    string asm, ValueType Ty, SDPatternOperator loadop> {
2750  let AddedComplexity = 10 in
2751  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2752                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2753                 [(set (Ty regtype:$Rt),
2754                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2755                                              ro_Wextend32:$extend)))]>,
2756           Sched<[WriteLDIdx, ReadAdrBase]> {
2757    let Inst{13} = 0b0;
2758  }
2759
2760  let AddedComplexity = 10 in
2761  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2762                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2763                 [(set (Ty regtype:$Rt),
2764                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2765                                              ro_Xextend32:$extend)))]>,
2766           Sched<[WriteLDIdx, ReadAdrBase]> {
2767    let Inst{13} = 0b1;
2768  }
2769
2770  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2771}
2772
2773multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2774                     string asm, ValueType Ty, SDPatternOperator storeop> {
2775  let AddedComplexity = 10 in
2776  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2777                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
2778                [(storeop (Ty regtype:$Rt),
2779                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
2780                                         ro_Wextend32:$extend))]>,
2781            Sched<[WriteSTIdx, ReadAdrBase]> {
2782    let Inst{13} = 0b0;
2783  }
2784
2785  let AddedComplexity = 10 in
2786  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
2787                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
2788                [(storeop (Ty regtype:$Rt),
2789                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
2790                                        ro_Xextend32:$extend))]>,
2791            Sched<[WriteSTIdx, ReadAdrBase]> {
2792    let Inst{13} = 0b1;
2793  }
2794
2795  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2796}
2797
2798class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2799                      string asm, dag ins, dag outs, list<dag> pat>
2800    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2801  bits<5> Rt;
2802  bits<5> Rn;
2803  bits<5> Rm;
2804  bits<2> extend;
2805  let Inst{31-30} = sz;
2806  let Inst{29-27} = 0b111;
2807  let Inst{26}    = V;
2808  let Inst{25-24} = 0b00;
2809  let Inst{23-22} = opc;
2810  let Inst{21}    = 1;
2811  let Inst{20-16} = Rm;
2812  let Inst{15}    = extend{1}; // sign extend Rm?
2813  let Inst{14}    = 1;
2814  let Inst{12}    = extend{0}; // do shift?
2815  let Inst{11-10} = 0b10;
2816  let Inst{9-5}   = Rn;
2817  let Inst{4-0}   = Rt;
2818}
2819
2820multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2821                    string asm, ValueType Ty, SDPatternOperator loadop> {
2822  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2823  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2824                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2825                [(set (Ty regtype:$Rt),
2826                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2827                                             ro_Wextend64:$extend)))]>,
2828           Sched<[WriteLDIdx, ReadAdrBase]> {
2829    let Inst{13} = 0b0;
2830  }
2831
2832  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2833  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2834                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2835                 [(set (Ty regtype:$Rt),
2836                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2837                                              ro_Xextend64:$extend)))]>,
2838           Sched<[WriteLDIdx, ReadAdrBase]> {
2839    let Inst{13} = 0b1;
2840  }
2841
2842  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2843}
2844
2845multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2846                     string asm, ValueType Ty, SDPatternOperator storeop> {
2847  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2848  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2849                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2850                [(storeop (Ty regtype:$Rt),
2851                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2852                                         ro_Wextend64:$extend))]>,
2853            Sched<[WriteSTIdx, ReadAdrBase]> {
2854    let Inst{13} = 0b0;
2855  }
2856
2857  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2858  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
2859                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2860                [(storeop (Ty regtype:$Rt),
2861                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2862                                         ro_Xextend64:$extend))]>,
2863            Sched<[WriteSTIdx, ReadAdrBase]> {
2864    let Inst{13} = 0b1;
2865  }
2866
2867  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2868}
2869
2870class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2871                      string asm, dag ins, dag outs, list<dag> pat>
2872    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
2873  bits<5> Rt;
2874  bits<5> Rn;
2875  bits<5> Rm;
2876  bits<2> extend;
2877  let Inst{31-30} = sz;
2878  let Inst{29-27} = 0b111;
2879  let Inst{26}    = V;
2880  let Inst{25-24} = 0b00;
2881  let Inst{23-22} = opc;
2882  let Inst{21}    = 1;
2883  let Inst{20-16} = Rm;
2884  let Inst{15}    = extend{1}; // sign extend Rm?
2885  let Inst{14}    = 1;
2886  let Inst{12}    = extend{0}; // do shift?
2887  let Inst{11-10} = 0b10;
2888  let Inst{9-5}   = Rn;
2889  let Inst{4-0}   = Rt;
2890}
2891
2892multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2893                     string asm, ValueType Ty, SDPatternOperator loadop> {
2894  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2895  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2896                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2897                 [(set (Ty regtype:$Rt),
2898                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2899                                               ro_Wextend128:$extend)))]>,
2900            Sched<[WriteLDIdx, ReadAdrBase]> {
2901    let Inst{13} = 0b0;
2902  }
2903
2904  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
2905  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
2906                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2907                 [(set (Ty regtype:$Rt),
2908                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2909                                               ro_Xextend128:$extend)))]>,
2910            Sched<[WriteLDIdx, ReadAdrBase]> {
2911    let Inst{13} = 0b1;
2912  }
2913
2914  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2915}
2916
2917multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
2918                      string asm, ValueType Ty, SDPatternOperator storeop> {
2919  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2920  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2921               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
2922                [(storeop (Ty regtype:$Rt),
2923                          (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
2924                                          ro_Wextend128:$extend))]>,
2925            Sched<[WriteSTIdx, ReadAdrBase]> {
2926    let Inst{13} = 0b0;
2927  }
2928
2929  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
2930  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
2931               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
2932                [(storeop (Ty regtype:$Rt),
2933                          (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
2934                                          ro_Xextend128:$extend))]>,
2935            Sched<[WriteSTIdx, ReadAdrBase]> {
2936    let Inst{13} = 0b1;
2937  }
2938
2939  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
2940}
2941
2942let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
2943class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
2944                     string asm, list<dag> pat>
2945    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
2946      Sched<[WriteLD]> {
2947  bits<5> Rt;
2948  bits<5> Rn;
2949  bits<5> Rm;
2950  bits<2> extend;
2951  let Inst{31-30} = sz;
2952  let Inst{29-27} = 0b111;
2953  let Inst{26}    = V;
2954  let Inst{25-24} = 0b00;
2955  let Inst{23-22} = opc;
2956  let Inst{21}    = 1;
2957  let Inst{20-16} = Rm;
2958  let Inst{15}    = extend{1}; // sign extend Rm?
2959  let Inst{14}    = 1;
2960  let Inst{12}    = extend{0}; // do shift?
2961  let Inst{11-10} = 0b10;
2962  let Inst{9-5}   = Rn;
2963  let Inst{4-0}   = Rt;
2964}
2965
2966multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
2967  def roW : BasePrefetchRO<sz, V, opc, (outs),
2968                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
2969                asm, [(AArch64Prefetch imm:$Rt,
2970                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
2971                                                    ro_Wextend64:$extend))]> {
2972    let Inst{13} = 0b0;
2973  }
2974
2975  def roX : BasePrefetchRO<sz, V, opc, (outs),
2976                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
2977                asm,  [(AArch64Prefetch imm:$Rt,
2978                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
2979                                                     ro_Xextend64:$extend))]> {
2980    let Inst{13} = 0b1;
2981  }
2982
2983  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
2984               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
2985                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
2986}
2987
2988//---
2989// Load/store unscaled immediate
2990//---
2991
2992def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
2993def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
2994def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
2995def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
2996def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
2997
2998class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2999                           string asm, list<dag> pattern>
3000    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3001  bits<5> Rt;
3002  bits<5> Rn;
3003  bits<9> offset;
3004  let Inst{31-30} = sz;
3005  let Inst{29-27} = 0b111;
3006  let Inst{26}    = V;
3007  let Inst{25-24} = 0b00;
3008  let Inst{23-22} = opc;
3009  let Inst{21}    = 0;
3010  let Inst{20-12} = offset;
3011  let Inst{11-10} = 0b00;
3012  let Inst{9-5}   = Rn;
3013  let Inst{4-0}   = Rt;
3014
3015  let DecoderMethod = "DecodeSignedLdStInstruction";
3016}
3017
3018multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3019                   string asm, list<dag> pattern> {
3020  let AddedComplexity = 1 in // try this before LoadUI
3021  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3022                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3023          Sched<[WriteLD]>;
3024
3025  def : InstAlias<asm # "\t$Rt, [$Rn]",
3026                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3027}
3028
3029multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3030                         string asm, list<dag> pattern> {
3031  let AddedComplexity = 1 in // try this before StoreUI
3032  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3033                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3034                               asm, pattern>,
3035          Sched<[WriteST]>;
3036
3037  def : InstAlias<asm # "\t$Rt, [$Rn]",
3038                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3039}
3040
3041multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3042                            list<dag> pat> {
3043  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3044  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3045                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3046                               asm, pat>,
3047          Sched<[WriteLD]>;
3048
3049  def : InstAlias<asm # "\t$Rt, [$Rn]",
3050                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3051}
3052
3053//---
3054// Load/store unscaled immediate, unprivileged
3055//---
3056
3057class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3058                                dag oops, dag iops, string asm>
3059    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3060  bits<5> Rt;
3061  bits<5> Rn;
3062  bits<9> offset;
3063  let Inst{31-30} = sz;
3064  let Inst{29-27} = 0b111;
3065  let Inst{26}    = V;
3066  let Inst{25-24} = 0b00;
3067  let Inst{23-22} = opc;
3068  let Inst{21}    = 0;
3069  let Inst{20-12} = offset;
3070  let Inst{11-10} = 0b10;
3071  let Inst{9-5}   = Rn;
3072  let Inst{4-0}   = Rt;
3073
3074  let DecoderMethod = "DecodeSignedLdStInstruction";
3075}
3076
3077multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3078                            RegisterClass regtype, string asm> {
3079  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3080  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3081                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
3082          Sched<[WriteLD]>;
3083
3084  def : InstAlias<asm # "\t$Rt, [$Rn]",
3085                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3086}
3087
3088multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3089                             RegisterClass regtype, string asm> {
3090  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3091  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3092                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3093                                 asm>,
3094          Sched<[WriteST]>;
3095
3096  def : InstAlias<asm # "\t$Rt, [$Rn]",
3097                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3098}
3099
3100//---
3101// Load/store pre-indexed
3102//---
3103
3104class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3105                          string asm, string cstr, list<dag> pat>
3106    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3107  bits<5> Rt;
3108  bits<5> Rn;
3109  bits<9> offset;
3110  let Inst{31-30} = sz;
3111  let Inst{29-27} = 0b111;
3112  let Inst{26}    = V;
3113  let Inst{25-24} = 0;
3114  let Inst{23-22} = opc;
3115  let Inst{21}    = 0;
3116  let Inst{20-12} = offset;
3117  let Inst{11-10} = 0b11;
3118  let Inst{9-5}   = Rn;
3119  let Inst{4-0}   = Rt;
3120
3121  let DecoderMethod = "DecodeSignedLdStInstruction";
3122}
3123
3124let hasSideEffects = 0 in {
3125let mayStore = 0, mayLoad = 1 in
3126class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3127             string asm>
3128    : BaseLoadStorePreIdx<sz, V, opc,
3129                     (outs GPR64sp:$wback, regtype:$Rt),
3130                     (ins GPR64sp:$Rn, simm9:$offset), asm,
3131                     "$Rn = $wback,@earlyclobber $wback", []>,
3132      Sched<[WriteLD, WriteAdr]>;
3133
3134let mayStore = 1, mayLoad = 0 in
3135class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3136                  string asm, SDPatternOperator storeop, ValueType Ty>
3137    : BaseLoadStorePreIdx<sz, V, opc,
3138                      (outs GPR64sp:$wback),
3139                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3140                      asm, "$Rn = $wback,@earlyclobber $wback",
3141      [(set GPR64sp:$wback,
3142            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3143      Sched<[WriteAdr, WriteST]>;
3144} // hasSideEffects = 0
3145
3146//---
3147// Load/store post-indexed
3148//---
3149
3150class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3151                          string asm, string cstr, list<dag> pat>
3152    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3153  bits<5> Rt;
3154  bits<5> Rn;
3155  bits<9> offset;
3156  let Inst{31-30} = sz;
3157  let Inst{29-27} = 0b111;
3158  let Inst{26}    = V;
3159  let Inst{25-24} = 0b00;
3160  let Inst{23-22} = opc;
3161  let Inst{21}    = 0b0;
3162  let Inst{20-12} = offset;
3163  let Inst{11-10} = 0b01;
3164  let Inst{9-5}   = Rn;
3165  let Inst{4-0}   = Rt;
3166
3167  let DecoderMethod = "DecodeSignedLdStInstruction";
3168}
3169
3170let hasSideEffects = 0 in {
3171let mayStore = 0, mayLoad = 1 in
3172class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3173             string asm>
3174    : BaseLoadStorePostIdx<sz, V, opc,
3175                      (outs GPR64sp:$wback, regtype:$Rt),
3176                      (ins GPR64sp:$Rn, simm9:$offset),
3177                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
3178      Sched<[WriteLD, WriteI]>;
3179
3180let mayStore = 1, mayLoad = 0 in
3181class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterClass regtype,
3182                   string asm, SDPatternOperator storeop, ValueType Ty>
3183    : BaseLoadStorePostIdx<sz, V, opc,
3184                      (outs GPR64sp:$wback),
3185                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3186                       asm, "$Rn = $wback,@earlyclobber $wback",
3187      [(set GPR64sp:$wback,
3188            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3189    Sched<[WriteAdr, WriteST, ReadAdrBase]>;
3190} // hasSideEffects = 0
3191
3192
3193//---
3194// Load/store pair
3195//---
3196
3197// (indexed, offset)
3198
3199class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3200                              string asm>
3201    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3202  bits<5> Rt;
3203  bits<5> Rt2;
3204  bits<5> Rn;
3205  bits<7> offset;
3206  let Inst{31-30} = opc;
3207  let Inst{29-27} = 0b101;
3208  let Inst{26}    = V;
3209  let Inst{25-23} = 0b010;
3210  let Inst{22}    = L;
3211  let Inst{21-15} = offset;
3212  let Inst{14-10} = Rt2;
3213  let Inst{9-5}   = Rn;
3214  let Inst{4-0}   = Rt;
3215
3216  let DecoderMethod = "DecodePairLdStInstruction";
3217}
3218
3219multiclass LoadPairOffset<bits<2> opc, bit V, RegisterClass regtype,
3220                          Operand indextype, string asm> {
3221  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3222  def i : BaseLoadStorePairOffset<opc, V, 1,
3223                                  (outs regtype:$Rt, regtype:$Rt2),
3224                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
3225          Sched<[WriteLD, WriteLDHi]>;
3226
3227  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3228                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3229                                                  GPR64sp:$Rn, 0)>;
3230}
3231
3232
3233multiclass StorePairOffset<bits<2> opc, bit V, RegisterClass regtype,
3234                           Operand indextype, string asm> {
3235  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3236  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3237                                  (ins regtype:$Rt, regtype:$Rt2,
3238                                       GPR64sp:$Rn, indextype:$offset),
3239                                  asm>,
3240          Sched<[WriteSTP]>;
3241
3242  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3243                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3244                                                  GPR64sp:$Rn, 0)>;
3245}
3246
3247// (pre-indexed)
3248class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3249                              string asm>
3250    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3251  bits<5> Rt;
3252  bits<5> Rt2;
3253  bits<5> Rn;
3254  bits<7> offset;
3255  let Inst{31-30} = opc;
3256  let Inst{29-27} = 0b101;
3257  let Inst{26}    = V;
3258  let Inst{25-23} = 0b011;
3259  let Inst{22}    = L;
3260  let Inst{21-15} = offset;
3261  let Inst{14-10} = Rt2;
3262  let Inst{9-5}   = Rn;
3263  let Inst{4-0}   = Rt;
3264
3265  let DecoderMethod = "DecodePairLdStInstruction";
3266}
3267
3268let hasSideEffects = 0 in {
3269let mayStore = 0, mayLoad = 1 in
3270class LoadPairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3271                     Operand indextype, string asm>
3272    : BaseLoadStorePairPreIdx<opc, V, 1,
3273                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3274                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
3275      Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3276
3277let mayStore = 1, mayLoad = 0 in
3278class StorePairPreIdx<bits<2> opc, bit V, RegisterClass regtype,
3279                      Operand indextype, string asm>
3280    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3281                             (ins regtype:$Rt, regtype:$Rt2,
3282                                  GPR64sp:$Rn, indextype:$offset),
3283                             asm>,
3284      Sched<[WriteAdr, WriteSTP]>;
3285} // hasSideEffects = 0
3286
3287// (post-indexed)
3288
3289class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3290                              string asm>
3291    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3292  bits<5> Rt;
3293  bits<5> Rt2;
3294  bits<5> Rn;
3295  bits<7> offset;
3296  let Inst{31-30} = opc;
3297  let Inst{29-27} = 0b101;
3298  let Inst{26}    = V;
3299  let Inst{25-23} = 0b001;
3300  let Inst{22}    = L;
3301  let Inst{21-15} = offset;
3302  let Inst{14-10} = Rt2;
3303  let Inst{9-5}   = Rn;
3304  let Inst{4-0}   = Rt;
3305
3306  let DecoderMethod = "DecodePairLdStInstruction";
3307}
3308
3309let hasSideEffects = 0 in {
3310let mayStore = 0, mayLoad = 1 in
3311class LoadPairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3312                      Operand idxtype, string asm>
3313    : BaseLoadStorePairPostIdx<opc, V, 1,
3314                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3315                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3316      Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3317
3318let mayStore = 1, mayLoad = 0 in
3319class StorePairPostIdx<bits<2> opc, bit V, RegisterClass regtype,
3320                       Operand idxtype, string asm>
3321    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
3322                             (ins regtype:$Rt, regtype:$Rt2,
3323                                  GPR64sp:$Rn, idxtype:$offset),
3324                             asm>,
3325      Sched<[WriteAdr, WriteSTP]>;
3326} // hasSideEffects = 0
3327
3328//  (no-allocate)
3329
3330class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
3331                              string asm>
3332    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3333  bits<5> Rt;
3334  bits<5> Rt2;
3335  bits<5> Rn;
3336  bits<7> offset;
3337  let Inst{31-30} = opc;
3338  let Inst{29-27} = 0b101;
3339  let Inst{26}    = V;
3340  let Inst{25-23} = 0b000;
3341  let Inst{22}    = L;
3342  let Inst{21-15} = offset;
3343  let Inst{14-10} = Rt2;
3344  let Inst{9-5}   = Rn;
3345  let Inst{4-0}   = Rt;
3346
3347  let DecoderMethod = "DecodePairLdStInstruction";
3348}
3349
3350multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3351                           Operand indextype, string asm> {
3352  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3353  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
3354                                   (outs regtype:$Rt, regtype:$Rt2),
3355                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
3356          Sched<[WriteLD, WriteLDHi]>;
3357
3358
3359  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3360                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3361                                                  GPR64sp:$Rn, 0)>;
3362}
3363
3364multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
3365                      Operand indextype, string asm> {
3366  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
3367  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
3368                                   (ins regtype:$Rt, regtype:$Rt2,
3369                                        GPR64sp:$Rn, indextype:$offset),
3370                                   asm>,
3371          Sched<[WriteSTP]>;
3372
3373  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3374                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3375                                                  GPR64sp:$Rn, 0)>;
3376}
3377
3378//---
3379// Load/store exclusive
3380//---
3381
3382// True exclusive operations write to and/or read from the system's exclusive
3383// monitors, which as far as a compiler is concerned can be modelled as a
3384// random shared memory address. Hence LoadExclusive mayStore.
3385//
3386// Since these instructions have the undefined register bits set to 1 in
3387// their canonical form, we need a post encoder method to set those bits
3388// to 1 when encoding these instructions. We do this using the
3389// fixLoadStoreExclusive function. This function has template parameters:
3390//
3391// fixLoadStoreExclusive<int hasRs, int hasRt2>
3392//
3393// hasRs indicates that the instruction uses the Rs field, so we won't set
3394// it to 1 (and the same for Rt2). We don't need template parameters for
3395// the other register fields since Rt and Rn are always used.
3396//
3397let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
3398class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3399                             dag oops, dag iops, string asm, string operands>
3400    : I<oops, iops, asm, operands, "", []> {
3401  let Inst{31-30} = sz;
3402  let Inst{29-24} = 0b001000;
3403  let Inst{23}    = o2;
3404  let Inst{22}    = L;
3405  let Inst{21}    = o1;
3406  let Inst{15}    = o0;
3407
3408  let DecoderMethod = "DecodeExclusiveLdStInstruction";
3409}
3410
3411// Neither Rs nor Rt2 operands.
3412class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3413                               dag oops, dag iops, string asm, string operands>
3414    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
3415  bits<5> Rt;
3416  bits<5> Rn;
3417  let Inst{20-16} = 0b11111;
3418  let Unpredictable{20-16} = 0b11111;
3419  let Inst{14-10} = 0b11111;
3420  let Unpredictable{14-10} = 0b11111;
3421  let Inst{9-5} = Rn;
3422  let Inst{4-0} = Rt;
3423
3424  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
3425}
3426
3427// Simple load acquires don't set the exclusive monitor
3428let mayLoad = 1, mayStore = 0 in
3429class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3430                  RegisterClass regtype, string asm>
3431    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3432                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3433      Sched<[WriteLD]>;
3434
3435class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3436                    RegisterClass regtype, string asm>
3437    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
3438                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
3439      Sched<[WriteLD]>;
3440
3441class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3442                       RegisterClass regtype, string asm>
3443    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3444                             (outs regtype:$Rt, regtype:$Rt2),
3445                             (ins GPR64sp0:$Rn), asm,
3446                             "\t$Rt, $Rt2, [$Rn]">,
3447      Sched<[WriteLD, WriteLDHi]> {
3448  bits<5> Rt;
3449  bits<5> Rt2;
3450  bits<5> Rn;
3451  let Inst{14-10} = Rt2;
3452  let Inst{9-5} = Rn;
3453  let Inst{4-0} = Rt;
3454
3455  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
3456}
3457
3458// Simple store release operations do not check the exclusive monitor.
3459let mayLoad = 0, mayStore = 1 in
3460class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3461                   RegisterClass regtype, string asm>
3462    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
3463                               (ins regtype:$Rt, GPR64sp0:$Rn),
3464                               asm, "\t$Rt, [$Rn]">,
3465      Sched<[WriteST]>;
3466
3467let mayLoad = 1, mayStore = 1 in
3468class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3469                     RegisterClass regtype, string asm>
3470    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
3471                             (ins regtype:$Rt, GPR64sp0:$Rn),
3472                             asm, "\t$Ws, $Rt, [$Rn]">,
3473      Sched<[WriteSTX]> {
3474  bits<5> Ws;
3475  bits<5> Rt;
3476  bits<5> Rn;
3477  let Inst{20-16} = Ws;
3478  let Inst{9-5} = Rn;
3479  let Inst{4-0} = Rt;
3480
3481  let Constraints = "@earlyclobber $Ws";
3482  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
3483}
3484
3485class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
3486                         RegisterClass regtype, string asm>
3487    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
3488                             (outs GPR32:$Ws),
3489                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
3490                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
3491      Sched<[WriteSTX]> {
3492  bits<5> Ws;
3493  bits<5> Rt;
3494  bits<5> Rt2;
3495  bits<5> Rn;
3496  let Inst{20-16} = Ws;
3497  let Inst{14-10} = Rt2;
3498  let Inst{9-5} = Rn;
3499  let Inst{4-0} = Rt;
3500
3501  let Constraints = "@earlyclobber $Ws";
3502}
3503
3504//---
3505// Exception generation
3506//---
3507
3508let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3509class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
3510    : I<(outs), (ins imm0_65535:$imm), asm, "\t$imm", "", []>,
3511      Sched<[WriteSys]> {
3512  bits<16> imm;
3513  let Inst{31-24} = 0b11010100;
3514  let Inst{23-21} = op1;
3515  let Inst{20-5}  = imm;
3516  let Inst{4-2}   = 0b000;
3517  let Inst{1-0}   = ll;
3518}
3519
3520let Predicates = [HasFPARMv8] in {
3521
3522//---
3523// Floating point to integer conversion
3524//---
3525
3526class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
3527                      RegisterClass srcType, RegisterClass dstType,
3528                      string asm, list<dag> pattern>
3529    : I<(outs dstType:$Rd), (ins srcType:$Rn),
3530         asm, "\t$Rd, $Rn", "", pattern>,
3531      Sched<[WriteFCvt]> {
3532  bits<5> Rd;
3533  bits<5> Rn;
3534  let Inst{30-29} = 0b00;
3535  let Inst{28-24} = 0b11110;
3536  let Inst{23-22} = type;
3537  let Inst{21}    = 1;
3538  let Inst{20-19} = rmode;
3539  let Inst{18-16} = opcode;
3540  let Inst{15-10} = 0;
3541  let Inst{9-5}   = Rn;
3542  let Inst{4-0}   = Rd;
3543}
3544
3545let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3546class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
3547                      RegisterClass srcType, RegisterClass dstType,
3548                      Operand immType, string asm, list<dag> pattern>
3549    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3550         asm, "\t$Rd, $Rn, $scale", "", pattern>,
3551      Sched<[WriteFCvt]> {
3552  bits<5> Rd;
3553  bits<5> Rn;
3554  bits<6> scale;
3555  let Inst{30-29} = 0b00;
3556  let Inst{28-24} = 0b11110;
3557  let Inst{23-22} = type;
3558  let Inst{21}    = 0;
3559  let Inst{20-19} = rmode;
3560  let Inst{18-16} = opcode;
3561  let Inst{15-10} = scale;
3562  let Inst{9-5}   = Rn;
3563  let Inst{4-0}   = Rd;
3564}
3565
3566multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
3567           SDPatternOperator OpN> {
3568  // Unscaled half-precision to 32-bit
3569  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
3570                                     [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
3571    let Inst{31} = 0; // 32-bit GPR flag
3572    let Predicates = [HasFullFP16];
3573  }
3574
3575  // Unscaled half-precision to 64-bit
3576  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
3577                                     [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
3578    let Inst{31} = 1; // 64-bit GPR flag
3579    let Predicates = [HasFullFP16];
3580  }
3581
3582  // Unscaled single-precision to 32-bit
3583  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
3584                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
3585    let Inst{31} = 0; // 32-bit GPR flag
3586  }
3587
3588  // Unscaled single-precision to 64-bit
3589  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
3590                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
3591    let Inst{31} = 1; // 64-bit GPR flag
3592  }
3593
3594  // Unscaled double-precision to 32-bit
3595  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
3596                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3597    let Inst{31} = 0; // 32-bit GPR flag
3598  }
3599
3600  // Unscaled double-precision to 64-bit
3601  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
3602                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
3603    let Inst{31} = 1; // 64-bit GPR flag
3604  }
3605}
3606
3607multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
3608                             SDPatternOperator OpN> {
3609  // Scaled half-precision to 32-bit
3610  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
3611                              fixedpoint_f16_i32, asm,
3612              [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
3613                                          fixedpoint_f16_i32:$scale)))]> {
3614    let Inst{31} = 0; // 32-bit GPR flag
3615    let scale{5} = 1;
3616    let Predicates = [HasFullFP16];
3617  }
3618
3619  // Scaled half-precision to 64-bit
3620  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
3621                              fixedpoint_f16_i64, asm,
3622              [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
3623                                          fixedpoint_f16_i64:$scale)))]> {
3624    let Inst{31} = 1; // 64-bit GPR flag
3625    let Predicates = [HasFullFP16];
3626  }
3627
3628  // Scaled single-precision to 32-bit
3629  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
3630                              fixedpoint_f32_i32, asm,
3631              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
3632                                          fixedpoint_f32_i32:$scale)))]> {
3633    let Inst{31} = 0; // 32-bit GPR flag
3634    let scale{5} = 1;
3635  }
3636
3637  // Scaled single-precision to 64-bit
3638  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
3639                              fixedpoint_f32_i64, asm,
3640              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
3641                                          fixedpoint_f32_i64:$scale)))]> {
3642    let Inst{31} = 1; // 64-bit GPR flag
3643  }
3644
3645  // Scaled double-precision to 32-bit
3646  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
3647                              fixedpoint_f64_i32, asm,
3648              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
3649                                          fixedpoint_f64_i32:$scale)))]> {
3650    let Inst{31} = 0; // 32-bit GPR flag
3651    let scale{5} = 1;
3652  }
3653
3654  // Scaled double-precision to 64-bit
3655  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
3656                              fixedpoint_f64_i64, asm,
3657              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
3658                                          fixedpoint_f64_i64:$scale)))]> {
3659    let Inst{31} = 1; // 64-bit GPR flag
3660  }
3661}
3662
3663//---
3664// Integer to floating point conversion
3665//---
3666
3667let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
3668class BaseIntegerToFP<bit isUnsigned,
3669                      RegisterClass srcType, RegisterClass dstType,
3670                      Operand immType, string asm, list<dag> pattern>
3671    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
3672         asm, "\t$Rd, $Rn, $scale", "", pattern>,
3673      Sched<[WriteFCvt]> {
3674  bits<5> Rd;
3675  bits<5> Rn;
3676  bits<6> scale;
3677  let Inst{30-24} = 0b0011110;
3678  let Inst{21-17} = 0b00001;
3679  let Inst{16}    = isUnsigned;
3680  let Inst{15-10} = scale;
3681  let Inst{9-5}   = Rn;
3682  let Inst{4-0}   = Rd;
3683}
3684
3685class BaseIntegerToFPUnscaled<bit isUnsigned,
3686                      RegisterClass srcType, RegisterClass dstType,
3687                      ValueType dvt, string asm, SDNode node>
3688    : I<(outs dstType:$Rd), (ins srcType:$Rn),
3689         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
3690      Sched<[WriteFCvt]> {
3691  bits<5> Rd;
3692  bits<5> Rn;
3693  bits<6> scale;
3694  let Inst{30-24} = 0b0011110;
3695  let Inst{21-17} = 0b10001;
3696  let Inst{16}    = isUnsigned;
3697  let Inst{15-10} = 0b000000;
3698  let Inst{9-5}   = Rn;
3699  let Inst{4-0}   = Rd;
3700}
3701
3702multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
3703  // Unscaled
3704  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
3705    let Inst{31} = 0; // 32-bit GPR flag
3706    let Inst{23-22} = 0b11; // 16-bit FPR flag
3707    let Predicates = [HasFullFP16];
3708  }
3709
3710  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
3711    let Inst{31} = 0; // 32-bit GPR flag
3712    let Inst{23-22} = 0b00; // 32-bit FPR flag
3713  }
3714
3715  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
3716    let Inst{31} = 0; // 32-bit GPR flag
3717    let Inst{23-22} = 0b01; // 64-bit FPR flag
3718  }
3719
3720  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
3721    let Inst{31} = 1; // 64-bit GPR flag
3722    let Inst{23-22} = 0b11; // 16-bit FPR flag
3723    let Predicates = [HasFullFP16];
3724  }
3725
3726  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
3727    let Inst{31} = 1; // 64-bit GPR flag
3728    let Inst{23-22} = 0b00; // 32-bit FPR flag
3729  }
3730
3731  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
3732    let Inst{31} = 1; // 64-bit GPR flag
3733    let Inst{23-22} = 0b01; // 64-bit FPR flag
3734  }
3735
3736  // Scaled
3737  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
3738                             [(set FPR16:$Rd,
3739                                   (fdiv (node GPR32:$Rn),
3740                                         fixedpoint_f16_i32:$scale))]> {
3741    let Inst{31} = 0; // 32-bit GPR flag
3742    let Inst{23-22} = 0b11; // 16-bit FPR flag
3743    let scale{5} = 1;
3744    let Predicates = [HasFullFP16];
3745  }
3746
3747  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
3748                             [(set FPR32:$Rd,
3749                                   (fdiv (node GPR32:$Rn),
3750                                         fixedpoint_f32_i32:$scale))]> {
3751    let Inst{31} = 0; // 32-bit GPR flag
3752    let Inst{23-22} = 0b00; // 32-bit FPR flag
3753    let scale{5} = 1;
3754  }
3755
3756  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
3757                             [(set FPR64:$Rd,
3758                                   (fdiv (node GPR32:$Rn),
3759                                         fixedpoint_f64_i32:$scale))]> {
3760    let Inst{31} = 0; // 32-bit GPR flag
3761    let Inst{23-22} = 0b01; // 64-bit FPR flag
3762    let scale{5} = 1;
3763  }
3764
3765  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
3766                             [(set FPR16:$Rd,
3767                                   (fdiv (node GPR64:$Rn),
3768                                         fixedpoint_f16_i64:$scale))]> {
3769    let Inst{31} = 1; // 64-bit GPR flag
3770    let Inst{23-22} = 0b11; // 16-bit FPR flag
3771    let Predicates = [HasFullFP16];
3772  }
3773
3774  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
3775                             [(set FPR32:$Rd,
3776                                   (fdiv (node GPR64:$Rn),
3777                                         fixedpoint_f32_i64:$scale))]> {
3778    let Inst{31} = 1; // 64-bit GPR flag
3779    let Inst{23-22} = 0b00; // 32-bit FPR flag
3780  }
3781
3782  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
3783                             [(set FPR64:$Rd,
3784                                   (fdiv (node GPR64:$Rn),
3785                                         fixedpoint_f64_i64:$scale))]> {
3786    let Inst{31} = 1; // 64-bit GPR flag
3787    let Inst{23-22} = 0b01; // 64-bit FPR flag
3788  }
3789}
3790
3791//---
3792// Unscaled integer <-> floating point conversion (i.e. FMOV)
3793//---
3794
3795let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3796class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
3797                      RegisterClass srcType, RegisterClass dstType,
3798                      string asm>
3799    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
3800        // We use COPY_TO_REGCLASS for these bitconvert operations.
3801        // copyPhysReg() expands the resultant COPY instructions after
3802        // regalloc is done. This gives greater freedom for the allocator
3803        // and related passes (coalescing, copy propagation, et. al.) to
3804        // be more effective.
3805        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
3806      Sched<[WriteFCopy]> {
3807  bits<5> Rd;
3808  bits<5> Rn;
3809  let Inst{30-24} = 0b0011110;
3810  let Inst{21}    = 1;
3811  let Inst{20-19} = rmode;
3812  let Inst{18-16} = opcode;
3813  let Inst{15-10} = 0b000000;
3814  let Inst{9-5}   = Rn;
3815  let Inst{4-0}   = Rd;
3816}
3817
3818let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3819class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
3820                     RegisterClass srcType, RegisterOperand dstType, string asm,
3821                     string kind>
3822    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3823        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
3824      Sched<[WriteFCopy]> {
3825  bits<5> Rd;
3826  bits<5> Rn;
3827  let Inst{30-23} = 0b00111101;
3828  let Inst{21}    = 1;
3829  let Inst{20-19} = rmode;
3830  let Inst{18-16} = opcode;
3831  let Inst{15-10} = 0b000000;
3832  let Inst{9-5}   = Rn;
3833  let Inst{4-0}   = Rd;
3834
3835  let DecoderMethod =  "DecodeFMOVLaneInstruction";
3836}
3837
3838let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3839class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
3840                     RegisterOperand srcType, RegisterClass dstType, string asm,
3841                     string kind>
3842    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
3843        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
3844      Sched<[WriteFCopy]> {
3845  bits<5> Rd;
3846  bits<5> Rn;
3847  let Inst{30-23} = 0b00111101;
3848  let Inst{21}    = 1;
3849  let Inst{20-19} = rmode;
3850  let Inst{18-16} = opcode;
3851  let Inst{15-10} = 0b000000;
3852  let Inst{9-5}   = Rn;
3853  let Inst{4-0}   = Rd;
3854
3855  let DecoderMethod =  "DecodeFMOVLaneInstruction";
3856}
3857
3858
3859multiclass UnscaledConversion<string asm> {
3860  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
3861    let Inst{31} = 0; // 32-bit GPR flag
3862    let Inst{23-22} = 0b11; // 16-bit FPR flag
3863    let Predicates = [HasFullFP16];
3864  }
3865
3866  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
3867    let Inst{31} = 1; // 64-bit GPR flag
3868    let Inst{23-22} = 0b11; // 16-bit FPR flag
3869    let Predicates = [HasFullFP16];
3870  }
3871
3872  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
3873    let Inst{31} = 0; // 32-bit GPR flag
3874    let Inst{23-22} = 0b00; // 32-bit FPR flag
3875  }
3876
3877  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
3878    let Inst{31} = 1; // 64-bit GPR flag
3879    let Inst{23-22} = 0b01; // 64-bit FPR flag
3880  }
3881
3882  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
3883    let Inst{31} = 0; // 32-bit GPR flag
3884    let Inst{23-22} = 0b11; // 16-bit FPR flag
3885    let Predicates = [HasFullFP16];
3886  }
3887
3888  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
3889    let Inst{31} = 1; // 64-bit GPR flag
3890    let Inst{23-22} = 0b11; // 16-bit FPR flag
3891    let Predicates = [HasFullFP16];
3892  }
3893
3894  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
3895    let Inst{31} = 0; // 32-bit GPR flag
3896    let Inst{23-22} = 0b00; // 32-bit FPR flag
3897  }
3898
3899  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
3900    let Inst{31} = 1; // 64-bit GPR flag
3901    let Inst{23-22} = 0b01; // 64-bit FPR flag
3902  }
3903
3904  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
3905                                             asm, ".d"> {
3906    let Inst{31} = 1;
3907    let Inst{22} = 0;
3908  }
3909
3910  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
3911                                               asm, ".d"> {
3912    let Inst{31} = 1;
3913    let Inst{22} = 0;
3914  }
3915}
3916
3917//---
3918// Floating point conversion
3919//---
3920
3921class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
3922                       RegisterClass srcType, string asm, list<dag> pattern>
3923    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
3924      Sched<[WriteFCvt]> {
3925  bits<5> Rd;
3926  bits<5> Rn;
3927  let Inst{31-24} = 0b00011110;
3928  let Inst{23-22} = type;
3929  let Inst{21-17} = 0b10001;
3930  let Inst{16-15} = opcode;
3931  let Inst{14-10} = 0b10000;
3932  let Inst{9-5}   = Rn;
3933  let Inst{4-0}   = Rd;
3934}
3935
3936multiclass FPConversion<string asm> {
3937  // Double-precision to Half-precision
3938  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
3939                             [(set FPR16:$Rd, (fround FPR64:$Rn))]>;
3940
3941  // Double-precision to Single-precision
3942  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
3943                             [(set FPR32:$Rd, (fround FPR64:$Rn))]>;
3944
3945  // Half-precision to Double-precision
3946  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
3947                             [(set FPR64:$Rd, (fextend FPR16:$Rn))]>;
3948
3949  // Half-precision to Single-precision
3950  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
3951                             [(set FPR32:$Rd, (fextend FPR16:$Rn))]>;
3952
3953  // Single-precision to Double-precision
3954  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
3955                             [(set FPR64:$Rd, (fextend FPR32:$Rn))]>;
3956
3957  // Single-precision to Half-precision
3958  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
3959                             [(set FPR16:$Rd, (fround FPR32:$Rn))]>;
3960}
3961
3962//---
3963// Single operand floating point data processing
3964//---
3965
3966let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3967class BaseSingleOperandFPData<bits<4> opcode, RegisterClass regtype,
3968                              ValueType vt, string asm, SDPatternOperator node>
3969    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
3970         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
3971      Sched<[WriteF]> {
3972  bits<5> Rd;
3973  bits<5> Rn;
3974  let Inst{31-24} = 0b00011110;
3975  let Inst{21-19} = 0b100;
3976  let Inst{18-15} = opcode;
3977  let Inst{14-10} = 0b10000;
3978  let Inst{9-5}   = Rn;
3979  let Inst{4-0}   = Rd;
3980}
3981
3982multiclass SingleOperandFPData<bits<4> opcode, string asm,
3983                               SDPatternOperator node = null_frag> {
3984  def Hr : BaseSingleOperandFPData<opcode, FPR16, f16, asm, node> {
3985    let Inst{23-22} = 0b11; // 16-bit size flag
3986    let Predicates = [HasFullFP16];
3987  }
3988
3989  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
3990    let Inst{23-22} = 0b00; // 32-bit size flag
3991  }
3992
3993  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
3994    let Inst{23-22} = 0b01; // 64-bit size flag
3995  }
3996}
3997
3998//---
3999// Two operand floating point data processing
4000//---
4001
4002let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4003class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4004                           string asm, list<dag> pat>
4005    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4006         asm, "\t$Rd, $Rn, $Rm", "", pat>,
4007      Sched<[WriteF]> {
4008  bits<5> Rd;
4009  bits<5> Rn;
4010  bits<5> Rm;
4011  let Inst{31-24} = 0b00011110;
4012  let Inst{21}    = 1;
4013  let Inst{20-16} = Rm;
4014  let Inst{15-12} = opcode;
4015  let Inst{11-10} = 0b10;
4016  let Inst{9-5}   = Rn;
4017  let Inst{4-0}   = Rd;
4018}
4019
4020multiclass TwoOperandFPData<bits<4> opcode, string asm,
4021                            SDPatternOperator node = null_frag> {
4022  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4023                         [(set (f16 FPR16:$Rd),
4024                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4025    let Inst{23-22} = 0b11; // 16-bit size flag
4026    let Predicates = [HasFullFP16];
4027  }
4028
4029  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4030                         [(set (f32 FPR32:$Rd),
4031                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4032    let Inst{23-22} = 0b00; // 32-bit size flag
4033  }
4034
4035  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4036                         [(set (f64 FPR64:$Rd),
4037                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4038    let Inst{23-22} = 0b01; // 64-bit size flag
4039  }
4040}
4041
4042multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4043  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4044                  [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4045    let Inst{23-22} = 0b11; // 16-bit size flag
4046    let Predicates = [HasFullFP16];
4047  }
4048
4049  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4050                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4051    let Inst{23-22} = 0b00; // 32-bit size flag
4052  }
4053
4054  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4055                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4056    let Inst{23-22} = 0b01; // 64-bit size flag
4057  }
4058}
4059
4060
4061//---
4062// Three operand floating point data processing
4063//---
4064
4065class BaseThreeOperandFPData<bit isNegated, bit isSub,
4066                             RegisterClass regtype, string asm, list<dag> pat>
4067    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4068         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4069      Sched<[WriteFMul]> {
4070  bits<5> Rd;
4071  bits<5> Rn;
4072  bits<5> Rm;
4073  bits<5> Ra;
4074  let Inst{31-24} = 0b00011111;
4075  let Inst{21}    = isNegated;
4076  let Inst{20-16} = Rm;
4077  let Inst{15}    = isSub;
4078  let Inst{14-10} = Ra;
4079  let Inst{9-5}   = Rn;
4080  let Inst{4-0}   = Rd;
4081}
4082
4083multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4084                              SDPatternOperator node> {
4085  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4086            [(set FPR16:$Rd,
4087                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4088    let Inst{23-22} = 0b11; // 16-bit size flag
4089    let Predicates = [HasFullFP16];
4090  }
4091
4092  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4093            [(set FPR32:$Rd,
4094                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4095    let Inst{23-22} = 0b00; // 32-bit size flag
4096  }
4097
4098  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4099            [(set FPR64:$Rd,
4100                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4101    let Inst{23-22} = 0b01; // 64-bit size flag
4102  }
4103}
4104
4105//---
4106// Floating point data comparisons
4107//---
4108
4109let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4110class BaseOneOperandFPComparison<bit signalAllNans,
4111                                 RegisterClass regtype, string asm,
4112                                 list<dag> pat>
4113    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4114      Sched<[WriteFCmp]> {
4115  bits<5> Rn;
4116  let Inst{31-24} = 0b00011110;
4117  let Inst{21}    = 1;
4118
4119  let Inst{15-10} = 0b001000;
4120  let Inst{9-5}   = Rn;
4121  let Inst{4}     = signalAllNans;
4122  let Inst{3-0}   = 0b1000;
4123
4124  // Rm should be 0b00000 canonically, but we need to accept any value.
4125  let PostEncoderMethod = "fixOneOperandFPComparison";
4126}
4127
4128let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4129class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4130                                string asm, list<dag> pat>
4131    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4132      Sched<[WriteFCmp]> {
4133  bits<5> Rm;
4134  bits<5> Rn;
4135  let Inst{31-24} = 0b00011110;
4136  let Inst{21}    = 1;
4137  let Inst{20-16} = Rm;
4138  let Inst{15-10} = 0b001000;
4139  let Inst{9-5}   = Rn;
4140  let Inst{4}     = signalAllNans;
4141  let Inst{3-0}   = 0b0000;
4142}
4143
4144multiclass FPComparison<bit signalAllNans, string asm,
4145                        SDPatternOperator OpNode = null_frag> {
4146  let Defs = [NZCV] in {
4147  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4148      [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4149    let Inst{23-22} = 0b11;
4150    let Predicates = [HasFullFP16];
4151  }
4152
4153  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4154      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4155    let Inst{23-22} = 0b11;
4156    let Predicates = [HasFullFP16];
4157  }
4158
4159  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4160      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4161    let Inst{23-22} = 0b00;
4162  }
4163
4164  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4165      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4166    let Inst{23-22} = 0b00;
4167  }
4168
4169  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4170      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4171    let Inst{23-22} = 0b01;
4172  }
4173
4174  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4175      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4176    let Inst{23-22} = 0b01;
4177  }
4178  } // Defs = [NZCV]
4179}
4180
4181//---
4182// Floating point conditional comparisons
4183//---
4184
4185let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4186class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4187                           string mnemonic, list<dag> pat>
4188    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4189         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4190      Sched<[WriteFCmp]> {
4191  let Uses = [NZCV];
4192  let Defs = [NZCV];
4193
4194  bits<5> Rn;
4195  bits<5> Rm;
4196  bits<4> nzcv;
4197  bits<4> cond;
4198
4199  let Inst{31-24} = 0b00011110;
4200  let Inst{21}    = 1;
4201  let Inst{20-16} = Rm;
4202  let Inst{15-12} = cond;
4203  let Inst{11-10} = 0b01;
4204  let Inst{9-5}   = Rn;
4205  let Inst{4}     = signalAllNans;
4206  let Inst{3-0}   = nzcv;
4207}
4208
4209multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4210                            SDPatternOperator OpNode = null_frag> {
4211  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic, []> {
4212    let Inst{23-22} = 0b11;
4213    let Predicates = [HasFullFP16];
4214  }
4215
4216  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
4217      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
4218                          (i32 imm:$cond), NZCV))]> {
4219    let Inst{23-22} = 0b00;
4220  }
4221
4222  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
4223      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
4224                          (i32 imm:$cond), NZCV))]> {
4225    let Inst{23-22} = 0b01;
4226  }
4227}
4228
4229//---
4230// Floating point conditional select
4231//---
4232
4233class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
4234    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
4235         asm, "\t$Rd, $Rn, $Rm, $cond", "",
4236         [(set regtype:$Rd,
4237               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
4238                          (i32 imm:$cond), NZCV))]>,
4239      Sched<[WriteF]> {
4240  bits<5> Rd;
4241  bits<5> Rn;
4242  bits<5> Rm;
4243  bits<4> cond;
4244
4245  let Inst{31-24} = 0b00011110;
4246  let Inst{21}    = 1;
4247  let Inst{20-16} = Rm;
4248  let Inst{15-12} = cond;
4249  let Inst{11-10} = 0b11;
4250  let Inst{9-5}   = Rn;
4251  let Inst{4-0}   = Rd;
4252}
4253
4254multiclass FPCondSelect<string asm> {
4255  let Uses = [NZCV] in {
4256  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
4257    let Inst{23-22} = 0b11;
4258    let Predicates = [HasFullFP16];
4259  }
4260
4261  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
4262    let Inst{23-22} = 0b00;
4263  }
4264
4265  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
4266    let Inst{23-22} = 0b01;
4267  }
4268  } // Uses = [NZCV]
4269}
4270
4271//---
4272// Floating move immediate
4273//---
4274
4275class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
4276  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
4277      [(set regtype:$Rd, fpimmtype:$imm)]>,
4278    Sched<[WriteFImm]> {
4279  bits<5> Rd;
4280  bits<8> imm;
4281  let Inst{31-24} = 0b00011110;
4282  let Inst{21}    = 1;
4283  let Inst{20-13} = imm;
4284  let Inst{12-5}  = 0b10000000;
4285  let Inst{4-0}   = Rd;
4286}
4287
4288multiclass FPMoveImmediate<string asm> {
4289  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
4290    let Inst{23-22} = 0b11;
4291    let Predicates = [HasFullFP16];
4292  }
4293
4294  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
4295    let Inst{23-22} = 0b00;
4296  }
4297
4298  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
4299    let Inst{23-22} = 0b01;
4300  }
4301}
4302} // end of 'let Predicates = [HasFPARMv8]'
4303
4304//----------------------------------------------------------------------------
4305// AdvSIMD
4306//----------------------------------------------------------------------------
4307
4308let Predicates = [HasNEON] in {
4309
4310//----------------------------------------------------------------------------
4311// AdvSIMD three register vector instructions
4312//----------------------------------------------------------------------------
4313
4314let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4315class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
4316                        RegisterOperand regtype, string asm, string kind,
4317                        list<dag> pattern>
4318  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
4319      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4320      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
4321    Sched<[WriteV]> {
4322  bits<5> Rd;
4323  bits<5> Rn;
4324  bits<5> Rm;
4325  let Inst{31}    = 0;
4326  let Inst{30}    = Q;
4327  let Inst{29}    = U;
4328  let Inst{28-24} = 0b01110;
4329  let Inst{23-21} = size;
4330  let Inst{20-16} = Rm;
4331  let Inst{15-11} = opcode;
4332  let Inst{10}    = 1;
4333  let Inst{9-5}   = Rn;
4334  let Inst{4-0}   = Rd;
4335}
4336
4337let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4338class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
4339                        RegisterOperand regtype, string asm, string kind,
4340                        list<dag> pattern>
4341  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
4342      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
4343      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
4344    Sched<[WriteV]> {
4345  bits<5> Rd;
4346  bits<5> Rn;
4347  bits<5> Rm;
4348  let Inst{31}    = 0;
4349  let Inst{30}    = Q;
4350  let Inst{29}    = U;
4351  let Inst{28-24} = 0b01110;
4352  let Inst{23-21} = size;
4353  let Inst{20-16} = Rm;
4354  let Inst{15-11} = opcode;
4355  let Inst{10}    = 1;
4356  let Inst{9-5}   = Rn;
4357  let Inst{4-0}   = Rd;
4358}
4359
4360// All operand sizes distinguished in the encoding.
4361multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
4362                               SDPatternOperator OpNode> {
4363  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4364                                      asm, ".8b",
4365         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4366  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4367                                      asm, ".16b",
4368         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4369  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4370                                      asm, ".4h",
4371         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4372  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4373                                      asm, ".8h",
4374         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4375  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4376                                      asm, ".2s",
4377         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4378  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4379                                      asm, ".4s",
4380         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4381  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
4382                                      asm, ".2d",
4383         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
4384}
4385
4386// As above, but D sized elements unsupported.
4387multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
4388                                  SDPatternOperator OpNode> {
4389  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4390                                      asm, ".8b",
4391        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
4392  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4393                                      asm, ".16b",
4394        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
4395  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4396                                      asm, ".4h",
4397        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
4398  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4399                                      asm, ".8h",
4400        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
4401  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4402                                      asm, ".2s",
4403        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
4404  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4405                                      asm, ".4s",
4406        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
4407}
4408
4409multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
4410                                  SDPatternOperator OpNode> {
4411  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
4412                                      asm, ".8b",
4413      [(set (v8i8 V64:$dst),
4414            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4415  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
4416                                      asm, ".16b",
4417      [(set (v16i8 V128:$dst),
4418            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4419  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
4420                                      asm, ".4h",
4421      [(set (v4i16 V64:$dst),
4422            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4423  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
4424                                      asm, ".8h",
4425      [(set (v8i16 V128:$dst),
4426            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4427  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
4428                                      asm, ".2s",
4429      [(set (v2i32 V64:$dst),
4430            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4431  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
4432                                      asm, ".4s",
4433      [(set (v4i32 V128:$dst),
4434            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4435}
4436
4437// As above, but only B sized elements supported.
4438multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
4439                                SDPatternOperator OpNode> {
4440  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
4441                                      asm, ".8b",
4442    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4443  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
4444                                      asm, ".16b",
4445    [(set (v16i8 V128:$Rd),
4446          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
4447}
4448
4449// As above, but only floating point elements supported.
4450multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
4451                                 string asm, SDPatternOperator OpNode> {
4452  let Predicates = [HasNEON, HasFullFP16] in {
4453  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4454                                      asm, ".4h",
4455        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4456  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4457                                      asm, ".8h",
4458        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4459  } // Predicates = [HasNEON, HasFullFP16]
4460  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4461                                      asm, ".2s",
4462        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4463  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4464                                      asm, ".4s",
4465        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4466  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4467                                      asm, ".2d",
4468        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4469}
4470
4471multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
4472                                    string asm,
4473                                    SDPatternOperator OpNode> {
4474  let Predicates = [HasNEON, HasFullFP16] in {
4475  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
4476                                      asm, ".4h",
4477        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4478  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
4479                                      asm, ".8h",
4480        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4481  } // Predicates = [HasNEON, HasFullFP16]
4482  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
4483                                      asm, ".2s",
4484        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4485  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
4486                                      asm, ".4s",
4487        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4488  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
4489                                      asm, ".2d",
4490        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4491}
4492
4493multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
4494                                 string asm, SDPatternOperator OpNode> {
4495  let Predicates = [HasNEON, HasFullFP16] in {
4496  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
4497                                      asm, ".4h",
4498     [(set (v4f16 V64:$dst),
4499           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
4500  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
4501                                      asm, ".8h",
4502     [(set (v8f16 V128:$dst),
4503           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
4504  } // Predicates = [HasNEON, HasFullFP16]
4505  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
4506                                      asm, ".2s",
4507     [(set (v2f32 V64:$dst),
4508           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
4509  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
4510                                      asm, ".4s",
4511     [(set (v4f32 V128:$dst),
4512           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
4513  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
4514                                      asm, ".2d",
4515     [(set (v2f64 V128:$dst),
4516           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
4517}
4518
4519// As above, but D and B sized elements unsupported.
4520multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
4521                                SDPatternOperator OpNode> {
4522  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
4523                                      asm, ".4h",
4524        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
4525  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
4526                                      asm, ".8h",
4527        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
4528  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
4529                                      asm, ".2s",
4530        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
4531  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
4532                                      asm, ".4s",
4533        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
4534}
4535
4536// Logical three vector ops share opcode bits, and only use B sized elements.
4537multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
4538                                  SDPatternOperator OpNode = null_frag> {
4539  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
4540                                     asm, ".8b",
4541                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
4542  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
4543                                     asm, ".16b",
4544                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
4545
4546  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
4547          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4548  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
4549          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4550  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
4551          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
4552
4553  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
4554      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4555  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
4556      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4557  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
4558      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
4559}
4560
4561multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
4562                                  string asm, SDPatternOperator OpNode> {
4563  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
4564                                     asm, ".8b",
4565             [(set (v8i8 V64:$dst),
4566                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
4567  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
4568                                     asm, ".16b",
4569             [(set (v16i8 V128:$dst),
4570                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
4571                           (v16i8 V128:$Rm)))]>;
4572
4573  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
4574                           (v4i16 V64:$RHS))),
4575          (!cast<Instruction>(NAME#"v8i8")
4576            V64:$LHS, V64:$MHS, V64:$RHS)>;
4577  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
4578                           (v2i32 V64:$RHS))),
4579          (!cast<Instruction>(NAME#"v8i8")
4580            V64:$LHS, V64:$MHS, V64:$RHS)>;
4581  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
4582                           (v1i64 V64:$RHS))),
4583          (!cast<Instruction>(NAME#"v8i8")
4584            V64:$LHS, V64:$MHS, V64:$RHS)>;
4585
4586  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
4587                           (v8i16 V128:$RHS))),
4588      (!cast<Instruction>(NAME#"v16i8")
4589        V128:$LHS, V128:$MHS, V128:$RHS)>;
4590  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
4591                           (v4i32 V128:$RHS))),
4592      (!cast<Instruction>(NAME#"v16i8")
4593        V128:$LHS, V128:$MHS, V128:$RHS)>;
4594  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
4595                           (v2i64 V128:$RHS))),
4596      (!cast<Instruction>(NAME#"v16i8")
4597        V128:$LHS, V128:$MHS, V128:$RHS)>;
4598}
4599
4600
4601//----------------------------------------------------------------------------
4602// AdvSIMD two register vector instructions.
4603//----------------------------------------------------------------------------
4604
4605let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4606class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4607                            bits<2> size2, RegisterOperand regtype, string asm,
4608                            string dstkind, string srckind, list<dag> pattern>
4609  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
4610      "{\t$Rd" # dstkind # ", $Rn" # srckind #
4611      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
4612    Sched<[WriteV]> {
4613  bits<5> Rd;
4614  bits<5> Rn;
4615  let Inst{31}    = 0;
4616  let Inst{30}    = Q;
4617  let Inst{29}    = U;
4618  let Inst{28-24} = 0b01110;
4619  let Inst{23-22} = size;
4620  let Inst{21} = 0b1;
4621  let Inst{20-19} = size2;
4622  let Inst{18-17} = 0b00;
4623  let Inst{16-12} = opcode;
4624  let Inst{11-10} = 0b10;
4625  let Inst{9-5}   = Rn;
4626  let Inst{4-0}   = Rd;
4627}
4628
4629let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4630class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4631                                bits<2> size2, RegisterOperand regtype,
4632                                string asm, string dstkind, string srckind,
4633                                list<dag> pattern>
4634  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
4635      "{\t$Rd" # dstkind # ", $Rn" # srckind #
4636      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4637    Sched<[WriteV]> {
4638  bits<5> Rd;
4639  bits<5> Rn;
4640  let Inst{31}    = 0;
4641  let Inst{30}    = Q;
4642  let Inst{29}    = U;
4643  let Inst{28-24} = 0b01110;
4644  let Inst{23-22} = size;
4645  let Inst{21} = 0b1;
4646  let Inst{20-19} = size2;
4647  let Inst{18-17} = 0b00;
4648  let Inst{16-12} = opcode;
4649  let Inst{11-10} = 0b10;
4650  let Inst{9-5}   = Rn;
4651  let Inst{4-0}   = Rd;
4652}
4653
4654// Supports B, H, and S element sizes.
4655multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
4656                            SDPatternOperator OpNode> {
4657  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4658                                      asm, ".8b", ".8b",
4659                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4660  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4661                                      asm, ".16b", ".16b",
4662                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4663  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4664                                      asm, ".4h", ".4h",
4665                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4666  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4667                                      asm, ".8h", ".8h",
4668                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4669  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
4670                                      asm, ".2s", ".2s",
4671                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4672  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
4673                                      asm, ".4s", ".4s",
4674                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4675}
4676
4677class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
4678                            RegisterOperand regtype, string asm, string dstkind,
4679                            string srckind, string amount>
4680  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
4681      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
4682      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
4683    Sched<[WriteV]> {
4684  bits<5> Rd;
4685  bits<5> Rn;
4686  let Inst{31}    = 0;
4687  let Inst{30}    = Q;
4688  let Inst{29-24} = 0b101110;
4689  let Inst{23-22} = size;
4690  let Inst{21-10} = 0b100001001110;
4691  let Inst{9-5}   = Rn;
4692  let Inst{4-0}   = Rd;
4693}
4694
4695multiclass SIMDVectorLShiftLongBySizeBHS {
4696  let hasSideEffects = 0 in {
4697  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
4698                                             "shll", ".8h",  ".8b", "8">;
4699  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
4700                                             "shll2", ".8h", ".16b", "8">;
4701  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
4702                                             "shll", ".4s",  ".4h", "16">;
4703  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
4704                                             "shll2", ".4s", ".8h", "16">;
4705  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
4706                                             "shll", ".2d",  ".2s", "32">;
4707  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
4708                                             "shll2", ".2d", ".4s", "32">;
4709  }
4710}
4711
4712// Supports all element sizes.
4713multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
4714                             SDPatternOperator OpNode> {
4715  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4716                                      asm, ".4h", ".8b",
4717               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4718  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4719                                      asm, ".8h", ".16b",
4720               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4721  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4722                                      asm, ".2s", ".4h",
4723               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4724  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4725                                      asm, ".4s", ".8h",
4726               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4727  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
4728                                      asm, ".1d", ".2s",
4729               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4730  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
4731                                      asm, ".2d", ".4s",
4732               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4733}
4734
4735multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
4736                                 SDPatternOperator OpNode> {
4737  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
4738                                          asm, ".4h", ".8b",
4739      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
4740                                      (v8i8 V64:$Rn)))]>;
4741  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
4742                                          asm, ".8h", ".16b",
4743      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
4744                                      (v16i8 V128:$Rn)))]>;
4745  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
4746                                          asm, ".2s", ".4h",
4747      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
4748                                      (v4i16 V64:$Rn)))]>;
4749  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
4750                                          asm, ".4s", ".8h",
4751      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
4752                                      (v8i16 V128:$Rn)))]>;
4753  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
4754                                          asm, ".1d", ".2s",
4755      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
4756                                      (v2i32 V64:$Rn)))]>;
4757  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
4758                                          asm, ".2d", ".4s",
4759      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
4760                                      (v4i32 V128:$Rn)))]>;
4761}
4762
4763// Supports all element sizes, except 1xD.
4764multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
4765                                  SDPatternOperator OpNode> {
4766  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
4767                                    asm, ".8b", ".8b",
4768    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
4769  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
4770                                    asm, ".16b", ".16b",
4771    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
4772  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
4773                                    asm, ".4h", ".4h",
4774    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
4775  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
4776                                    asm, ".8h", ".8h",
4777    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
4778  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
4779                                    asm, ".2s", ".2s",
4780    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
4781  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
4782                                    asm, ".4s", ".4s",
4783    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
4784  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
4785                                    asm, ".2d", ".2d",
4786    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
4787}
4788
4789multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
4790                             SDPatternOperator OpNode = null_frag> {
4791  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4792                                asm, ".8b", ".8b",
4793    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4794  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4795                                asm, ".16b", ".16b",
4796    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4797  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4798                                asm, ".4h", ".4h",
4799    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4800  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4801                                asm, ".8h", ".8h",
4802    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4803  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
4804                                asm, ".2s", ".2s",
4805    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4806  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
4807                                asm, ".4s", ".4s",
4808    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4809  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
4810                                asm, ".2d", ".2d",
4811    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4812}
4813
4814
4815// Supports only B element sizes.
4816multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
4817                          SDPatternOperator OpNode> {
4818  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
4819                                asm, ".8b", ".8b",
4820                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
4821  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
4822                                asm, ".16b", ".16b",
4823                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
4824
4825}
4826
4827// Supports only B and H element sizes.
4828multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
4829                                SDPatternOperator OpNode> {
4830  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
4831                                asm, ".8b", ".8b",
4832                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
4833  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
4834                                asm, ".16b", ".16b",
4835                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
4836  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
4837                                asm, ".4h", ".4h",
4838                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
4839  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
4840                                asm, ".8h", ".8h",
4841                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
4842}
4843
4844// Supports only S and D element sizes, uses high bit of the size field
4845// as an extra opcode bit.
4846multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
4847                           SDPatternOperator OpNode> {
4848  let Predicates = [HasNEON, HasFullFP16] in {
4849  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
4850                                asm, ".4h", ".4h",
4851                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
4852  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
4853                                asm, ".8h", ".8h",
4854                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
4855  } // Predicates = [HasNEON, HasFullFP16]
4856  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4857                                asm, ".2s", ".2s",
4858                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4859  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4860                                asm, ".4s", ".4s",
4861                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4862  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
4863                                asm, ".2d", ".2d",
4864                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4865}
4866
4867// Supports only S element size.
4868multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
4869                           SDPatternOperator OpNode> {
4870  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4871                                asm, ".2s", ".2s",
4872                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4873  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4874                                asm, ".4s", ".4s",
4875                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4876}
4877
4878
4879multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
4880                           SDPatternOperator OpNode> {
4881  let Predicates = [HasNEON, HasFullFP16] in {
4882  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
4883                                asm, ".4h", ".4h",
4884                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
4885  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
4886                                asm, ".8h", ".8h",
4887                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
4888  } // Predicates = [HasNEON, HasFullFP16]
4889  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4890                                asm, ".2s", ".2s",
4891                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
4892  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4893                                asm, ".4s", ".4s",
4894                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
4895  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
4896                                asm, ".2d", ".2d",
4897                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
4898}
4899
4900multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
4901                           SDPatternOperator OpNode> {
4902  let Predicates = [HasNEON, HasFullFP16] in {
4903  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
4904                                asm, ".4h", ".4h",
4905                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
4906  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
4907                                asm, ".8h", ".8h",
4908                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4909  } // Predicates = [HasNEON, HasFullFP16]
4910  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
4911                                asm, ".2s", ".2s",
4912                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
4913  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
4914                                asm, ".4s", ".4s",
4915                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4916  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
4917                                asm, ".2d", ".2d",
4918                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4919}
4920
4921
4922class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
4923                           RegisterOperand inreg, RegisterOperand outreg,
4924                           string asm, string outkind, string inkind,
4925                           list<dag> pattern>
4926  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
4927      "{\t$Rd" # outkind # ", $Rn" # inkind #
4928      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
4929    Sched<[WriteV]> {
4930  bits<5> Rd;
4931  bits<5> Rn;
4932  let Inst{31}    = 0;
4933  let Inst{30}    = Q;
4934  let Inst{29}    = U;
4935  let Inst{28-24} = 0b01110;
4936  let Inst{23-22} = size;
4937  let Inst{21-17} = 0b10000;
4938  let Inst{16-12} = opcode;
4939  let Inst{11-10} = 0b10;
4940  let Inst{9-5}   = Rn;
4941  let Inst{4-0}   = Rd;
4942}
4943
4944class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
4945                           RegisterOperand inreg, RegisterOperand outreg,
4946                           string asm, string outkind, string inkind,
4947                           list<dag> pattern>
4948  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
4949      "{\t$Rd" # outkind # ", $Rn" # inkind #
4950      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
4951    Sched<[WriteV]> {
4952  bits<5> Rd;
4953  bits<5> Rn;
4954  let Inst{31}    = 0;
4955  let Inst{30}    = Q;
4956  let Inst{29}    = U;
4957  let Inst{28-24} = 0b01110;
4958  let Inst{23-22} = size;
4959  let Inst{21-17} = 0b10000;
4960  let Inst{16-12} = opcode;
4961  let Inst{11-10} = 0b10;
4962  let Inst{9-5}   = Rn;
4963  let Inst{4-0}   = Rd;
4964}
4965
4966multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
4967                              SDPatternOperator OpNode> {
4968  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
4969                                      asm, ".8b", ".8h",
4970        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
4971  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
4972                                      asm#"2", ".16b", ".8h", []>;
4973  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
4974                                      asm, ".4h", ".4s",
4975        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
4976  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
4977                                      asm#"2", ".8h", ".4s", []>;
4978  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
4979                                      asm, ".2s", ".2d",
4980        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
4981  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
4982                                      asm#"2", ".4s", ".2d", []>;
4983
4984  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
4985            (!cast<Instruction>(NAME # "v16i8")
4986                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4987  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
4988            (!cast<Instruction>(NAME # "v8i16")
4989                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4990  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
4991            (!cast<Instruction>(NAME # "v4i32")
4992                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
4993}
4994
4995class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
4996                           bits<5> opcode, RegisterOperand regtype, string asm,
4997                           string kind, string zero, ValueType dty,
4998                           ValueType sty, SDNode OpNode>
4999  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5000      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5001      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5002      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5003    Sched<[WriteV]> {
5004  bits<5> Rd;
5005  bits<5> Rn;
5006  let Inst{31}    = 0;
5007  let Inst{30}    = Q;
5008  let Inst{29}    = U;
5009  let Inst{28-24} = 0b01110;
5010  let Inst{23-22} = size;
5011  let Inst{21} = 0b1;
5012  let Inst{20-19} = size2;
5013  let Inst{18-17} = 0b00;
5014  let Inst{16-12} = opcode;
5015  let Inst{11-10} = 0b10;
5016  let Inst{9-5}   = Rn;
5017  let Inst{4-0}   = Rd;
5018}
5019
5020// Comparisons support all element sizes, except 1xD.
5021multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5022                            SDNode OpNode> {
5023  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5024                                     asm, ".8b", "0",
5025                                     v8i8, v8i8, OpNode>;
5026  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5027                                     asm, ".16b", "0",
5028                                     v16i8, v16i8, OpNode>;
5029  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5030                                     asm, ".4h", "0",
5031                                     v4i16, v4i16, OpNode>;
5032  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5033                                     asm, ".8h", "0",
5034                                     v8i16, v8i16, OpNode>;
5035  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5036                                     asm, ".2s", "0",
5037                                     v2i32, v2i32, OpNode>;
5038  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5039                                     asm, ".4s", "0",
5040                                     v4i32, v4i32, OpNode>;
5041  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5042                                     asm, ".2d", "0",
5043                                     v2i64, v2i64, OpNode>;
5044}
5045
5046// FP Comparisons support only S and D element sizes (and H for v8.2a).
5047multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5048                              string asm, SDNode OpNode> {
5049
5050  let Predicates = [HasNEON, HasFullFP16] in {
5051  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5052                                     asm, ".4h", "0.0",
5053                                     v4i16, v4f16, OpNode>;
5054  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5055                                     asm, ".8h", "0.0",
5056                                     v8i16, v8f16, OpNode>;
5057  } // Predicates = [HasNEON, HasFullFP16]
5058  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5059                                     asm, ".2s", "0.0",
5060                                     v2i32, v2f32, OpNode>;
5061  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5062                                     asm, ".4s", "0.0",
5063                                     v4i32, v4f32, OpNode>;
5064  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5065                                     asm, ".2d", "0.0",
5066                                     v2i64, v2f64, OpNode>;
5067
5068  let Predicates = [HasNEON, HasFullFP16] in {
5069  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5070                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5071  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5072                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5073  }
5074  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5075                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5076  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5077                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5078  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5079                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5080  let Predicates = [HasNEON, HasFullFP16] in {
5081  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5082                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5083  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5084                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5085  }
5086  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5087                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5088  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5089                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5090  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5091                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5092}
5093
5094let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5095class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5096                             RegisterOperand outtype, RegisterOperand intype,
5097                             string asm, string VdTy, string VnTy,
5098                             list<dag> pattern>
5099  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5100      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5101    Sched<[WriteV]> {
5102  bits<5> Rd;
5103  bits<5> Rn;
5104  let Inst{31}    = 0;
5105  let Inst{30}    = Q;
5106  let Inst{29}    = U;
5107  let Inst{28-24} = 0b01110;
5108  let Inst{23-22} = size;
5109  let Inst{21-17} = 0b10000;
5110  let Inst{16-12} = opcode;
5111  let Inst{11-10} = 0b10;
5112  let Inst{9-5}   = Rn;
5113  let Inst{4-0}   = Rd;
5114}
5115
5116class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5117                             RegisterOperand outtype, RegisterOperand intype,
5118                             string asm, string VdTy, string VnTy,
5119                             list<dag> pattern>
5120  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5121      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5122    Sched<[WriteV]> {
5123  bits<5> Rd;
5124  bits<5> Rn;
5125  let Inst{31}    = 0;
5126  let Inst{30}    = Q;
5127  let Inst{29}    = U;
5128  let Inst{28-24} = 0b01110;
5129  let Inst{23-22} = size;
5130  let Inst{21-17} = 0b10000;
5131  let Inst{16-12} = opcode;
5132  let Inst{11-10} = 0b10;
5133  let Inst{9-5}   = Rn;
5134  let Inst{4-0}   = Rd;
5135}
5136
5137multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
5138  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
5139                                    asm, ".4s", ".4h", []>;
5140  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
5141                                    asm#"2", ".4s", ".8h", []>;
5142  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
5143                                    asm, ".2d", ".2s", []>;
5144  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
5145                                    asm#"2", ".2d", ".4s", []>;
5146}
5147
5148multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
5149  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
5150                                    asm, ".4h", ".4s", []>;
5151  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
5152                                    asm#"2", ".8h", ".4s", []>;
5153  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5154                                    asm, ".2s", ".2d", []>;
5155  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5156                                    asm#"2", ".4s", ".2d", []>;
5157}
5158
5159multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
5160                                     Intrinsic OpNode> {
5161  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
5162                                     asm, ".2s", ".2d",
5163                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5164  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
5165                                    asm#"2", ".4s", ".2d", []>;
5166
5167  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
5168            (!cast<Instruction>(NAME # "v4f32")
5169                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5170}
5171
5172//----------------------------------------------------------------------------
5173// AdvSIMD three register different-size vector instructions.
5174//----------------------------------------------------------------------------
5175
5176let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5177class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
5178                      RegisterOperand outtype, RegisterOperand intype1,
5179                      RegisterOperand intype2, string asm,
5180                      string outkind, string inkind1, string inkind2,
5181                      list<dag> pattern>
5182  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
5183      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5184      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
5185    Sched<[WriteV]> {
5186  bits<5> Rd;
5187  bits<5> Rn;
5188  bits<5> Rm;
5189  let Inst{31}    = 0;
5190  let Inst{30}    = size{0};
5191  let Inst{29}    = U;
5192  let Inst{28-24} = 0b01110;
5193  let Inst{23-22} = size{2-1};
5194  let Inst{21}    = 1;
5195  let Inst{20-16} = Rm;
5196  let Inst{15-12} = opcode;
5197  let Inst{11-10} = 0b00;
5198  let Inst{9-5}   = Rn;
5199  let Inst{4-0}   = Rd;
5200}
5201
5202let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5203class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
5204                      RegisterOperand outtype, RegisterOperand intype1,
5205                      RegisterOperand intype2, string asm,
5206                      string outkind, string inkind1, string inkind2,
5207                      list<dag> pattern>
5208  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
5209      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
5210      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5211    Sched<[WriteV]> {
5212  bits<5> Rd;
5213  bits<5> Rn;
5214  bits<5> Rm;
5215  let Inst{31}    = 0;
5216  let Inst{30}    = size{0};
5217  let Inst{29}    = U;
5218  let Inst{28-24} = 0b01110;
5219  let Inst{23-22} = size{2-1};
5220  let Inst{21}    = 1;
5221  let Inst{20-16} = Rm;
5222  let Inst{15-12} = opcode;
5223  let Inst{11-10} = 0b00;
5224  let Inst{9-5}   = Rn;
5225  let Inst{4-0}   = Rd;
5226}
5227
5228// FIXME: TableGen doesn't know how to deal with expanded types that also
5229//        change the element count (in this case, placing the results in
5230//        the high elements of the result register rather than the low
5231//        elements). Until that's fixed, we can't code-gen those.
5232multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
5233                                    Intrinsic IntOp> {
5234  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5235                                                  V64, V128, V128,
5236                                                  asm, ".8b", ".8h", ".8h",
5237     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5238  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5239                                                  V128, V128, V128,
5240                                                  asm#"2", ".16b", ".8h", ".8h",
5241     []>;
5242  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5243                                                  V64, V128, V128,
5244                                                  asm, ".4h", ".4s", ".4s",
5245     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5246  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5247                                                  V128, V128, V128,
5248                                                  asm#"2", ".8h", ".4s", ".4s",
5249     []>;
5250  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5251                                                  V64, V128, V128,
5252                                                  asm, ".2s", ".2d", ".2d",
5253     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5254  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5255                                                  V128, V128, V128,
5256                                                  asm#"2", ".4s", ".2d", ".2d",
5257     []>;
5258
5259
5260  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
5261  // a version attached to an instruction.
5262  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
5263                                                   (v8i16 V128:$Rm))),
5264            (!cast<Instruction>(NAME # "v8i16_v16i8")
5265                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5266                V128:$Rn, V128:$Rm)>;
5267  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
5268                                                    (v4i32 V128:$Rm))),
5269            (!cast<Instruction>(NAME # "v4i32_v8i16")
5270                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5271                V128:$Rn, V128:$Rm)>;
5272  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
5273                                                    (v2i64 V128:$Rm))),
5274            (!cast<Instruction>(NAME # "v2i64_v4i32")
5275                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
5276                V128:$Rn, V128:$Rm)>;
5277}
5278
5279multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
5280                                      Intrinsic IntOp> {
5281  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5282                                            V128, V64, V64,
5283                                            asm, ".8h", ".8b", ".8b",
5284      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5285  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5286                                            V128, V128, V128,
5287                                            asm#"2", ".8h", ".16b", ".16b", []>;
5288  let Predicates = [HasCrypto] in {
5289    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
5290                                              V128, V64, V64,
5291                                              asm, ".1q", ".1d", ".1d", []>;
5292    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
5293                                              V128, V128, V128,
5294                                              asm#"2", ".1q", ".2d", ".2d", []>;
5295  }
5296
5297  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
5298                          (v8i8 (extract_high_v16i8 V128:$Rm)))),
5299      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
5300}
5301
5302multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
5303                                 SDPatternOperator OpNode> {
5304  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5305                                                  V128, V64, V64,
5306                                                  asm, ".4s", ".4h", ".4h",
5307      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5308  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5309                                                  V128, V128, V128,
5310                                                  asm#"2", ".4s", ".8h", ".8h",
5311      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5312                                      (extract_high_v8i16 V128:$Rm)))]>;
5313  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5314                                                  V128, V64, V64,
5315                                                  asm, ".2d", ".2s", ".2s",
5316      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5317  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5318                                                  V128, V128, V128,
5319                                                  asm#"2", ".2d", ".4s", ".4s",
5320      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5321                                      (extract_high_v4i32 V128:$Rm)))]>;
5322}
5323
5324multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
5325                                  SDPatternOperator OpNode = null_frag> {
5326  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5327                                                  V128, V64, V64,
5328                                                  asm, ".8h", ".8b", ".8b",
5329      [(set (v8i16 V128:$Rd),
5330            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
5331  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5332                                                 V128, V128, V128,
5333                                                 asm#"2", ".8h", ".16b", ".16b",
5334      [(set (v8i16 V128:$Rd),
5335            (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5336                                (extract_high_v16i8 V128:$Rm)))))]>;
5337  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5338                                                  V128, V64, V64,
5339                                                  asm, ".4s", ".4h", ".4h",
5340      [(set (v4i32 V128:$Rd),
5341            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
5342  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5343                                                  V128, V128, V128,
5344                                                  asm#"2", ".4s", ".8h", ".8h",
5345      [(set (v4i32 V128:$Rd),
5346            (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5347                                  (extract_high_v8i16 V128:$Rm)))))]>;
5348  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5349                                                  V128, V64, V64,
5350                                                  asm, ".2d", ".2s", ".2s",
5351      [(set (v2i64 V128:$Rd),
5352            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
5353  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5354                                                  V128, V128, V128,
5355                                                  asm#"2", ".2d", ".4s", ".4s",
5356      [(set (v2i64 V128:$Rd),
5357            (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5358                                 (extract_high_v4i32 V128:$Rm)))))]>;
5359}
5360
5361multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
5362                                          string asm,
5363                                          SDPatternOperator OpNode> {
5364  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5365                                                  V128, V64, V64,
5366                                                  asm, ".8h", ".8b", ".8b",
5367    [(set (v8i16 V128:$dst),
5368          (add (v8i16 V128:$Rd),
5369               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
5370  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5371                                                 V128, V128, V128,
5372                                                 asm#"2", ".8h", ".16b", ".16b",
5373    [(set (v8i16 V128:$dst),
5374          (add (v8i16 V128:$Rd),
5375               (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
5376                                   (extract_high_v16i8 V128:$Rm))))))]>;
5377  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5378                                                  V128, V64, V64,
5379                                                  asm, ".4s", ".4h", ".4h",
5380    [(set (v4i32 V128:$dst),
5381          (add (v4i32 V128:$Rd),
5382               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
5383  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5384                                                  V128, V128, V128,
5385                                                  asm#"2", ".4s", ".8h", ".8h",
5386    [(set (v4i32 V128:$dst),
5387          (add (v4i32 V128:$Rd),
5388               (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
5389                                    (extract_high_v8i16 V128:$Rm))))))]>;
5390  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5391                                                  V128, V64, V64,
5392                                                  asm, ".2d", ".2s", ".2s",
5393    [(set (v2i64 V128:$dst),
5394          (add (v2i64 V128:$Rd),
5395               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
5396  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5397                                                  V128, V128, V128,
5398                                                  asm#"2", ".2d", ".4s", ".4s",
5399    [(set (v2i64 V128:$dst),
5400          (add (v2i64 V128:$Rd),
5401               (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
5402                                    (extract_high_v4i32 V128:$Rm))))))]>;
5403}
5404
5405multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
5406                                  SDPatternOperator OpNode = null_frag> {
5407  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5408                                                  V128, V64, V64,
5409                                                  asm, ".8h", ".8b", ".8b",
5410      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5411  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5412                                                 V128, V128, V128,
5413                                                 asm#"2", ".8h", ".16b", ".16b",
5414      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
5415                                      (extract_high_v16i8 V128:$Rm)))]>;
5416  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5417                                                  V128, V64, V64,
5418                                                  asm, ".4s", ".4h", ".4h",
5419      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5420  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5421                                                  V128, V128, V128,
5422                                                  asm#"2", ".4s", ".8h", ".8h",
5423      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
5424                                      (extract_high_v8i16 V128:$Rm)))]>;
5425  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5426                                                  V128, V64, V64,
5427                                                  asm, ".2d", ".2s", ".2s",
5428      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5429  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5430                                                  V128, V128, V128,
5431                                                  asm#"2", ".2d", ".4s", ".4s",
5432      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
5433                                      (extract_high_v4i32 V128:$Rm)))]>;
5434}
5435
5436multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
5437                                      string asm,
5438                                      SDPatternOperator OpNode> {
5439  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
5440                                                  V128, V64, V64,
5441                                                  asm, ".8h", ".8b", ".8b",
5442    [(set (v8i16 V128:$dst),
5443          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5444  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
5445                                                 V128, V128, V128,
5446                                                 asm#"2", ".8h", ".16b", ".16b",
5447    [(set (v8i16 V128:$dst),
5448          (OpNode (v8i16 V128:$Rd),
5449                  (extract_high_v16i8 V128:$Rn),
5450                  (extract_high_v16i8 V128:$Rm)))]>;
5451  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5452                                                  V128, V64, V64,
5453                                                  asm, ".4s", ".4h", ".4h",
5454    [(set (v4i32 V128:$dst),
5455          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5456  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5457                                                  V128, V128, V128,
5458                                                  asm#"2", ".4s", ".8h", ".8h",
5459    [(set (v4i32 V128:$dst),
5460          (OpNode (v4i32 V128:$Rd),
5461                  (extract_high_v8i16 V128:$Rn),
5462                  (extract_high_v8i16 V128:$Rm)))]>;
5463  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5464                                                  V128, V64, V64,
5465                                                  asm, ".2d", ".2s", ".2s",
5466    [(set (v2i64 V128:$dst),
5467          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5468  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5469                                                  V128, V128, V128,
5470                                                  asm#"2", ".2d", ".4s", ".4s",
5471    [(set (v2i64 V128:$dst),
5472          (OpNode (v2i64 V128:$Rd),
5473                  (extract_high_v4i32 V128:$Rn),
5474                  (extract_high_v4i32 V128:$Rm)))]>;
5475}
5476
5477multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
5478                                           SDPatternOperator Accum> {
5479  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
5480                                                  V128, V64, V64,
5481                                                  asm, ".4s", ".4h", ".4h",
5482    [(set (v4i32 V128:$dst),
5483          (Accum (v4i32 V128:$Rd),
5484                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
5485                                                (v4i16 V64:$Rm)))))]>;
5486  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
5487                                                  V128, V128, V128,
5488                                                  asm#"2", ".4s", ".8h", ".8h",
5489    [(set (v4i32 V128:$dst),
5490          (Accum (v4i32 V128:$Rd),
5491                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
5492                                            (extract_high_v8i16 V128:$Rm)))))]>;
5493  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
5494                                                  V128, V64, V64,
5495                                                  asm, ".2d", ".2s", ".2s",
5496    [(set (v2i64 V128:$dst),
5497          (Accum (v2i64 V128:$Rd),
5498                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
5499                                                (v2i32 V64:$Rm)))))]>;
5500  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
5501                                                  V128, V128, V128,
5502                                                  asm#"2", ".2d", ".4s", ".4s",
5503    [(set (v2i64 V128:$dst),
5504          (Accum (v2i64 V128:$Rd),
5505                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
5506                                            (extract_high_v4i32 V128:$Rm)))))]>;
5507}
5508
5509multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
5510                                  SDPatternOperator OpNode> {
5511  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
5512                                                  V128, V128, V64,
5513                                                  asm, ".8h", ".8h", ".8b",
5514       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
5515  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
5516                                                  V128, V128, V128,
5517                                                  asm#"2", ".8h", ".8h", ".16b",
5518       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
5519                                       (extract_high_v16i8 V128:$Rm)))]>;
5520  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
5521                                                  V128, V128, V64,
5522                                                  asm, ".4s", ".4s", ".4h",
5523       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
5524  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
5525                                                  V128, V128, V128,
5526                                                  asm#"2", ".4s", ".4s", ".8h",
5527       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
5528                                       (extract_high_v8i16 V128:$Rm)))]>;
5529  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
5530                                                  V128, V128, V64,
5531                                                  asm, ".2d", ".2d", ".2s",
5532       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
5533  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
5534                                                  V128, V128, V128,
5535                                                  asm#"2", ".2d", ".2d", ".4s",
5536       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
5537                                       (extract_high_v4i32 V128:$Rm)))]>;
5538}
5539
5540//----------------------------------------------------------------------------
5541// AdvSIMD bitwise extract from vector
5542//----------------------------------------------------------------------------
5543
5544class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
5545                             string asm, string kind>
5546  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
5547      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
5548      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
5549      [(set (vty regtype:$Rd),
5550            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
5551    Sched<[WriteV]> {
5552  bits<5> Rd;
5553  bits<5> Rn;
5554  bits<5> Rm;
5555  bits<4> imm;
5556  let Inst{31}    = 0;
5557  let Inst{30}    = size;
5558  let Inst{29-21} = 0b101110000;
5559  let Inst{20-16} = Rm;
5560  let Inst{15}    = 0;
5561  let Inst{14-11} = imm;
5562  let Inst{10}    = 0;
5563  let Inst{9-5}   = Rn;
5564  let Inst{4-0}   = Rd;
5565}
5566
5567
5568multiclass SIMDBitwiseExtract<string asm> {
5569  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
5570    let imm{3} = 0;
5571  }
5572  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
5573}
5574
5575//----------------------------------------------------------------------------
5576// AdvSIMD zip vector
5577//----------------------------------------------------------------------------
5578
5579class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
5580                        string asm, string kind, SDNode OpNode, ValueType valty>
5581  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5582      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5583      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
5584      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
5585    Sched<[WriteV]> {
5586  bits<5> Rd;
5587  bits<5> Rn;
5588  bits<5> Rm;
5589  let Inst{31}    = 0;
5590  let Inst{30}    = size{0};
5591  let Inst{29-24} = 0b001110;
5592  let Inst{23-22} = size{2-1};
5593  let Inst{21}    = 0;
5594  let Inst{20-16} = Rm;
5595  let Inst{15}    = 0;
5596  let Inst{14-12} = opc;
5597  let Inst{11-10} = 0b10;
5598  let Inst{9-5}   = Rn;
5599  let Inst{4-0}   = Rd;
5600}
5601
5602multiclass SIMDZipVector<bits<3>opc, string asm,
5603                         SDNode OpNode> {
5604  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
5605      asm, ".8b", OpNode, v8i8>;
5606  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
5607      asm, ".16b", OpNode, v16i8>;
5608  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
5609      asm, ".4h", OpNode, v4i16>;
5610  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
5611      asm, ".8h", OpNode, v8i16>;
5612  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
5613      asm, ".2s", OpNode, v2i32>;
5614  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
5615      asm, ".4s", OpNode, v4i32>;
5616  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
5617      asm, ".2d", OpNode, v2i64>;
5618
5619  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
5620        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
5621  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
5622        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
5623  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
5624        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
5625  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
5626        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
5627  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
5628        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
5629}
5630
5631//----------------------------------------------------------------------------
5632// AdvSIMD three register scalar instructions
5633//----------------------------------------------------------------------------
5634
5635let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5636class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
5637                        RegisterClass regtype, string asm,
5638                        list<dag> pattern>
5639  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5640      "\t$Rd, $Rn, $Rm", "", pattern>,
5641    Sched<[WriteV]> {
5642  bits<5> Rd;
5643  bits<5> Rn;
5644  bits<5> Rm;
5645  let Inst{31-30} = 0b01;
5646  let Inst{29}    = U;
5647  let Inst{28-24} = 0b11110;
5648  let Inst{23-21} = size;
5649  let Inst{20-16} = Rm;
5650  let Inst{15-11} = opcode;
5651  let Inst{10}    = 1;
5652  let Inst{9-5}   = Rn;
5653  let Inst{4-0}   = Rd;
5654}
5655
5656let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
5657class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
5658                        dag oops, dag iops, string asm,
5659            list<dag> pattern>
5660  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
5661    Sched<[WriteV]> {
5662  bits<5> Rd;
5663  bits<5> Rn;
5664  bits<5> Rm;
5665  let Inst{31-30} = 0b01;
5666  let Inst{29}    = U;
5667  let Inst{28-24} = 0b11110;
5668  let Inst{23-22} = size;
5669  let Inst{21}    = R;
5670  let Inst{20-16} = Rm;
5671  let Inst{15-11} = opcode;
5672  let Inst{10}    = 1;
5673  let Inst{9-5}   = Rn;
5674  let Inst{4-0}   = Rd;
5675}
5676
5677multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
5678                            SDPatternOperator OpNode> {
5679  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
5680    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5681}
5682
5683multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
5684                               SDPatternOperator OpNode> {
5685  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
5686    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
5687  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
5688  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
5689  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
5690
5691  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
5692            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
5693  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
5694            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
5695}
5696
5697multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
5698                             SDPatternOperator OpNode> {
5699  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
5700                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5701  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
5702}
5703
5704multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
5705                                 SDPatternOperator OpNode = null_frag> {
5706  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
5707                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
5708                                     asm, []>;
5709  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
5710                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
5711                                     asm, []>;
5712}
5713
5714multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
5715                             SDPatternOperator OpNode = null_frag> {
5716  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5717    def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
5718      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5719    def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
5720      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
5721    let Predicates = [HasNEON, HasFullFP16] in {
5722    def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
5723      [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
5724    } // Predicates = [HasNEON, HasFullFP16]
5725  }
5726
5727  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5728            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5729}
5730
5731multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
5732                                SDPatternOperator OpNode = null_frag> {
5733  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5734    def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
5735      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
5736    def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
5737      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
5738    let Predicates = [HasNEON, HasFullFP16] in {
5739    def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
5740      []>;
5741    } // Predicates = [HasNEON, HasFullFP16]
5742  }
5743
5744  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
5745            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
5746}
5747
5748class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
5749              dag oops, dag iops, string asm, string cstr, list<dag> pat>
5750  : I<oops, iops, asm,
5751      "\t$Rd, $Rn, $Rm", cstr, pat>,
5752    Sched<[WriteV]> {
5753  bits<5> Rd;
5754  bits<5> Rn;
5755  bits<5> Rm;
5756  let Inst{31-30} = 0b01;
5757  let Inst{29}    = U;
5758  let Inst{28-24} = 0b11110;
5759  let Inst{23-22} = size;
5760  let Inst{21}    = 1;
5761  let Inst{20-16} = Rm;
5762  let Inst{15-11} = opcode;
5763  let Inst{10}    = 0;
5764  let Inst{9-5}   = Rn;
5765  let Inst{4-0}   = Rd;
5766}
5767
5768let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5769multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
5770                                  SDPatternOperator OpNode = null_frag> {
5771  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5772                                      (outs FPR32:$Rd),
5773                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
5774  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5775                                      (outs FPR64:$Rd),
5776                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
5777            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5778}
5779
5780let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5781multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
5782                                  SDPatternOperator OpNode = null_frag> {
5783  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
5784                                      (outs FPR32:$dst),
5785                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
5786                                      asm, "$Rd = $dst", []>;
5787  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
5788                                      (outs FPR64:$dst),
5789                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
5790                                      asm, "$Rd = $dst",
5791            [(set (i64 FPR64:$dst),
5792                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
5793}
5794
5795//----------------------------------------------------------------------------
5796// AdvSIMD two register scalar instructions
5797//----------------------------------------------------------------------------
5798
5799let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5800class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
5801                        RegisterClass regtype, RegisterClass regtype2,
5802                        string asm, list<dag> pat>
5803  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
5804      "\t$Rd, $Rn", "", pat>,
5805    Sched<[WriteV]> {
5806  bits<5> Rd;
5807  bits<5> Rn;
5808  let Inst{31-30} = 0b01;
5809  let Inst{29}    = U;
5810  let Inst{28-24} = 0b11110;
5811  let Inst{23-22} = size;
5812  let Inst{21} = 0b1;
5813  let Inst{20-19} = size2;
5814  let Inst{18-17} = 0b00;
5815  let Inst{16-12} = opcode;
5816  let Inst{11-10} = 0b10;
5817  let Inst{9-5}   = Rn;
5818  let Inst{4-0}   = Rd;
5819}
5820
5821let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5822class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
5823                        RegisterClass regtype, RegisterClass regtype2,
5824                        string asm, list<dag> pat>
5825  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
5826      "\t$Rd, $Rn", "$Rd = $dst", pat>,
5827    Sched<[WriteV]> {
5828  bits<5> Rd;
5829  bits<5> Rn;
5830  let Inst{31-30} = 0b01;
5831  let Inst{29}    = U;
5832  let Inst{28-24} = 0b11110;
5833  let Inst{23-22} = size;
5834  let Inst{21-17} = 0b10000;
5835  let Inst{16-12} = opcode;
5836  let Inst{11-10} = 0b10;
5837  let Inst{9-5}   = Rn;
5838  let Inst{4-0}   = Rd;
5839}
5840
5841
5842let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5843class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
5844                        RegisterClass regtype, string asm, string zero>
5845  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5846      "\t$Rd, $Rn, #" # zero, "", []>,
5847    Sched<[WriteV]> {
5848  bits<5> Rd;
5849  bits<5> Rn;
5850  let Inst{31-30} = 0b01;
5851  let Inst{29}    = U;
5852  let Inst{28-24} = 0b11110;
5853  let Inst{23-22} = size;
5854  let Inst{21} = 0b1;
5855  let Inst{20-19} = size2;
5856  let Inst{18-17} = 0b00;
5857  let Inst{16-12} = opcode;
5858  let Inst{11-10} = 0b10;
5859  let Inst{9-5}   = Rn;
5860  let Inst{4-0}   = Rd;
5861}
5862
5863class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
5864  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
5865     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
5866    Sched<[WriteV]> {
5867  bits<5> Rd;
5868  bits<5> Rn;
5869  let Inst{31-17} = 0b011111100110000;
5870  let Inst{16-12} = opcode;
5871  let Inst{11-10} = 0b10;
5872  let Inst{9-5}   = Rn;
5873  let Inst{4-0}   = Rd;
5874}
5875
5876multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
5877                             SDPatternOperator OpNode> {
5878  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
5879
5880  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
5881            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5882}
5883
5884multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
5885                              SDPatternOperator OpNode> {
5886  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
5887  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
5888  let Predicates = [HasNEON, HasFullFP16] in {
5889  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
5890  }
5891
5892  def : InstAlias<asm # "\t$Rd, $Rn, #0",
5893                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
5894  def : InstAlias<asm # "\t$Rd, $Rn, #0",
5895                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
5896  let Predicates = [HasNEON, HasFullFP16] in {
5897  def : InstAlias<asm # "\t$Rd, $Rn, #0",
5898                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
5899  }
5900
5901  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
5902            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
5903}
5904
5905multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
5906                          SDPatternOperator OpNode = null_frag> {
5907  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
5908    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
5909
5910  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
5911            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
5912}
5913
5914multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
5915  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
5916  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
5917  let Predicates = [HasNEON, HasFullFP16] in {
5918  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
5919  }
5920}
5921
5922multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
5923                              SDPatternOperator OpNode> {
5924  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
5925                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
5926  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
5927                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
5928  let Predicates = [HasNEON, HasFullFP16] in {
5929  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
5930                                [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
5931  }
5932}
5933
5934multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
5935                             SDPatternOperator OpNode = null_frag> {
5936  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5937    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
5938           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5939    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
5940           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
5941    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
5942    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
5943  }
5944
5945  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
5946            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
5947}
5948
5949multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
5950                                 Intrinsic OpNode> {
5951  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
5952    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
5953        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
5954    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
5955        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
5956    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
5957    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
5958  }
5959
5960  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
5961            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
5962}
5963
5964
5965
5966let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5967multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
5968                                 SDPatternOperator OpNode = null_frag> {
5969  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
5970        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
5971  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
5972  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
5973}
5974
5975//----------------------------------------------------------------------------
5976// AdvSIMD scalar pairwise instructions
5977//----------------------------------------------------------------------------
5978
5979let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5980class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
5981                        RegisterOperand regtype, RegisterOperand vectype,
5982                        string asm, string kind>
5983  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
5984      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
5985    Sched<[WriteV]> {
5986  bits<5> Rd;
5987  bits<5> Rn;
5988  let Inst{31-30} = 0b01;
5989  let Inst{29}    = U;
5990  let Inst{28-24} = 0b11110;
5991  let Inst{23-22} = size;
5992  let Inst{21-17} = 0b11000;
5993  let Inst{16-12} = opcode;
5994  let Inst{11-10} = 0b10;
5995  let Inst{9-5}   = Rn;
5996  let Inst{4-0}   = Rd;
5997}
5998
5999multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6000  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6001                                      asm, ".2d">;
6002}
6003
6004multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6005  let Predicates = [HasNEON, HasFullFP16] in {
6006  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6007                                      asm, ".2h">;
6008  }
6009  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6010                                      asm, ".2s">;
6011  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6012                                      asm, ".2d">;
6013}
6014
6015//----------------------------------------------------------------------------
6016// AdvSIMD across lanes instructions
6017//----------------------------------------------------------------------------
6018
6019let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6020class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6021                          RegisterClass regtype, RegisterOperand vectype,
6022                          string asm, string kind, list<dag> pattern>
6023  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6024      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6025    Sched<[WriteV]> {
6026  bits<5> Rd;
6027  bits<5> Rn;
6028  let Inst{31}    = 0;
6029  let Inst{30}    = Q;
6030  let Inst{29}    = U;
6031  let Inst{28-24} = 0b01110;
6032  let Inst{23-22} = size;
6033  let Inst{21-17} = 0b11000;
6034  let Inst{16-12} = opcode;
6035  let Inst{11-10} = 0b10;
6036  let Inst{9-5}   = Rn;
6037  let Inst{4-0}   = Rd;
6038}
6039
6040multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6041                              string asm> {
6042  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
6043                                   asm, ".8b", []>;
6044  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
6045                                   asm, ".16b", []>;
6046  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6047                                   asm, ".4h", []>;
6048  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6049                                   asm, ".8h", []>;
6050  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6051                                   asm, ".4s", []>;
6052}
6053
6054multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6055  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6056                                   asm, ".8b", []>;
6057  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6058                                   asm, ".16b", []>;
6059  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6060                                   asm, ".4h", []>;
6061  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6062                                   asm, ".8h", []>;
6063  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6064                                   asm, ".4s", []>;
6065}
6066
6067multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6068                            Intrinsic intOp> {
6069  let Predicates = [HasNEON, HasFullFP16] in {
6070  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6071                                   asm, ".4h",
6072        [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6073  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6074                                   asm, ".8h",
6075        [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6076  } // Predicates = [HasNEON, HasFullFP16]
6077  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6078                                   asm, ".4s",
6079        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6080}
6081
6082//----------------------------------------------------------------------------
6083// AdvSIMD INS/DUP instructions
6084//----------------------------------------------------------------------------
6085
6086// FIXME: There has got to be a better way to factor these. ugh.
6087
6088class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6089                     string operands, string constraints, list<dag> pattern>
6090  : I<outs, ins, asm, operands, constraints, pattern>,
6091    Sched<[WriteV]> {
6092  bits<5> Rd;
6093  bits<5> Rn;
6094  let Inst{31} = 0;
6095  let Inst{30} = Q;
6096  let Inst{29} = op;
6097  let Inst{28-21} = 0b01110000;
6098  let Inst{15} = 0;
6099  let Inst{10} = 1;
6100  let Inst{9-5} = Rn;
6101  let Inst{4-0} = Rd;
6102}
6103
6104class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6105                      RegisterOperand vecreg, RegisterClass regtype>
6106  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6107                   "{\t$Rd" # size # ", $Rn" #
6108                   "|" # size # "\t$Rd, $Rn}", "",
6109                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6110  let Inst{20-16} = imm5;
6111  let Inst{14-11} = 0b0001;
6112}
6113
6114class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6115                         ValueType vectype, ValueType insreg,
6116                         RegisterOperand vecreg, Operand idxtype,
6117                         ValueType elttype, SDNode OpNode>
6118  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6119                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6120                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6121                 [(set (vectype vecreg:$Rd),
6122                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6123  let Inst{14-11} = 0b0000;
6124}
6125
6126class SIMDDup64FromElement
6127  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6128                       VectorIndexD, i64, AArch64duplane64> {
6129  bits<1> idx;
6130  let Inst{20} = idx;
6131  let Inst{19-16} = 0b1000;
6132}
6133
6134class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
6135                           RegisterOperand vecreg>
6136  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
6137                       VectorIndexS, i64, AArch64duplane32> {
6138  bits<2> idx;
6139  let Inst{20-19} = idx;
6140  let Inst{18-16} = 0b100;
6141}
6142
6143class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
6144                           RegisterOperand vecreg>
6145  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
6146                       VectorIndexH, i64, AArch64duplane16> {
6147  bits<3> idx;
6148  let Inst{20-18} = idx;
6149  let Inst{17-16} = 0b10;
6150}
6151
6152class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
6153                          RegisterOperand vecreg>
6154  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
6155                       VectorIndexB, i64, AArch64duplane8> {
6156  bits<4> idx;
6157  let Inst{20-17} = idx;
6158  let Inst{16} = 1;
6159}
6160
6161class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
6162                  Operand idxtype, string asm, list<dag> pattern>
6163  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
6164                   "{\t$Rd, $Rn" # size # "$idx" #
6165                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
6166  let Inst{14-11} = imm4;
6167}
6168
6169class SIMDSMov<bit Q, string size, RegisterClass regtype,
6170               Operand idxtype>
6171  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
6172class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
6173               Operand idxtype>
6174  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
6175      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
6176
6177class SIMDMovAlias<string asm, string size, Instruction inst,
6178                   RegisterClass regtype, Operand idxtype>
6179    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
6180                    "|" # size # "\t$dst, $src$idx}",
6181                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
6182
6183multiclass SMov {
6184  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
6185    bits<4> idx;
6186    let Inst{20-17} = idx;
6187    let Inst{16} = 1;
6188  }
6189  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
6190    bits<4> idx;
6191    let Inst{20-17} = idx;
6192    let Inst{16} = 1;
6193  }
6194  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
6195    bits<3> idx;
6196    let Inst{20-18} = idx;
6197    let Inst{17-16} = 0b10;
6198  }
6199  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
6200    bits<3> idx;
6201    let Inst{20-18} = idx;
6202    let Inst{17-16} = 0b10;
6203  }
6204  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
6205    bits<2> idx;
6206    let Inst{20-19} = idx;
6207    let Inst{18-16} = 0b100;
6208  }
6209}
6210
6211multiclass UMov {
6212  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
6213    bits<4> idx;
6214    let Inst{20-17} = idx;
6215    let Inst{16} = 1;
6216  }
6217  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
6218    bits<3> idx;
6219    let Inst{20-18} = idx;
6220    let Inst{17-16} = 0b10;
6221  }
6222  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
6223    bits<2> idx;
6224    let Inst{20-19} = idx;
6225    let Inst{18-16} = 0b100;
6226  }
6227  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
6228    bits<1> idx;
6229    let Inst{20} = idx;
6230    let Inst{19-16} = 0b1000;
6231  }
6232  def : SIMDMovAlias<"mov", ".s",
6233                     !cast<Instruction>(NAME#"vi32"),
6234                     GPR32, VectorIndexS>;
6235  def : SIMDMovAlias<"mov", ".d",
6236                     !cast<Instruction>(NAME#"vi64"),
6237                     GPR64, VectorIndexD>;
6238}
6239
6240class SIMDInsFromMain<string size, ValueType vectype,
6241                      RegisterClass regtype, Operand idxtype>
6242  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
6243                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
6244                   "{\t$Rd" # size # "$idx, $Rn" #
6245                   "|" # size # "\t$Rd$idx, $Rn}",
6246                   "$Rd = $dst",
6247            [(set V128:$dst,
6248              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
6249  let Inst{14-11} = 0b0011;
6250}
6251
6252class SIMDInsFromElement<string size, ValueType vectype,
6253                         ValueType elttype, Operand idxtype>
6254  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
6255                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
6256                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
6257                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
6258                   "$Rd = $dst",
6259         [(set V128:$dst,
6260               (vector_insert
6261                 (vectype V128:$Rd),
6262                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
6263                 idxtype:$idx))]>;
6264
6265class SIMDInsMainMovAlias<string size, Instruction inst,
6266                          RegisterClass regtype, Operand idxtype>
6267    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
6268                        "|" # size #"\t$dst$idx, $src}",
6269                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
6270class SIMDInsElementMovAlias<string size, Instruction inst,
6271                             Operand idxtype>
6272    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
6273                      # "|" # size #"\t$dst$idx, $src$idx2}",
6274                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
6275
6276
6277multiclass SIMDIns {
6278  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
6279    bits<4> idx;
6280    let Inst{20-17} = idx;
6281    let Inst{16} = 1;
6282  }
6283  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
6284    bits<3> idx;
6285    let Inst{20-18} = idx;
6286    let Inst{17-16} = 0b10;
6287  }
6288  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
6289    bits<2> idx;
6290    let Inst{20-19} = idx;
6291    let Inst{18-16} = 0b100;
6292  }
6293  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
6294    bits<1> idx;
6295    let Inst{20} = idx;
6296    let Inst{19-16} = 0b1000;
6297  }
6298
6299  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
6300    bits<4> idx;
6301    bits<4> idx2;
6302    let Inst{20-17} = idx;
6303    let Inst{16} = 1;
6304    let Inst{14-11} = idx2;
6305  }
6306  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
6307    bits<3> idx;
6308    bits<3> idx2;
6309    let Inst{20-18} = idx;
6310    let Inst{17-16} = 0b10;
6311    let Inst{14-12} = idx2;
6312    let Inst{11} = {?};
6313  }
6314  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
6315    bits<2> idx;
6316    bits<2> idx2;
6317    let Inst{20-19} = idx;
6318    let Inst{18-16} = 0b100;
6319    let Inst{14-13} = idx2;
6320    let Inst{12-11} = {?,?};
6321  }
6322  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
6323    bits<1> idx;
6324    bits<1> idx2;
6325    let Inst{20} = idx;
6326    let Inst{19-16} = 0b1000;
6327    let Inst{14} = idx2;
6328    let Inst{13-11} = {?,?,?};
6329  }
6330
6331  // For all forms of the INS instruction, the "mov" mnemonic is the
6332  // preferred alias. Why they didn't just call the instruction "mov" in
6333  // the first place is a very good question indeed...
6334  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
6335                         GPR32, VectorIndexB>;
6336  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
6337                         GPR32, VectorIndexH>;
6338  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
6339                         GPR32, VectorIndexS>;
6340  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
6341                         GPR64, VectorIndexD>;
6342
6343  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
6344                         VectorIndexB>;
6345  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
6346                         VectorIndexH>;
6347  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
6348                         VectorIndexS>;
6349  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
6350                         VectorIndexD>;
6351}
6352
6353//----------------------------------------------------------------------------
6354// AdvSIMD TBL/TBX
6355//----------------------------------------------------------------------------
6356
6357let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6358class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6359                          RegisterOperand listtype, string asm, string kind>
6360  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
6361       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
6362    Sched<[WriteV]> {
6363  bits<5> Vd;
6364  bits<5> Vn;
6365  bits<5> Vm;
6366  let Inst{31}    = 0;
6367  let Inst{30}    = Q;
6368  let Inst{29-21} = 0b001110000;
6369  let Inst{20-16} = Vm;
6370  let Inst{15}    = 0;
6371  let Inst{14-13} = len;
6372  let Inst{12}    = op;
6373  let Inst{11-10} = 0b00;
6374  let Inst{9-5}   = Vn;
6375  let Inst{4-0}   = Vd;
6376}
6377
6378let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6379class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
6380                          RegisterOperand listtype, string asm, string kind>
6381  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
6382       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
6383    Sched<[WriteV]> {
6384  bits<5> Vd;
6385  bits<5> Vn;
6386  bits<5> Vm;
6387  let Inst{31}    = 0;
6388  let Inst{30}    = Q;
6389  let Inst{29-21} = 0b001110000;
6390  let Inst{20-16} = Vm;
6391  let Inst{15}    = 0;
6392  let Inst{14-13} = len;
6393  let Inst{12}    = op;
6394  let Inst{11-10} = 0b00;
6395  let Inst{9-5}   = Vn;
6396  let Inst{4-0}   = Vd;
6397}
6398
6399class SIMDTableLookupAlias<string asm, Instruction inst,
6400                          RegisterOperand vectype, RegisterOperand listtype>
6401    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
6402                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
6403
6404multiclass SIMDTableLookup<bit op, string asm> {
6405  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
6406                                      asm, ".8b">;
6407  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
6408                                      asm, ".8b">;
6409  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
6410                                      asm, ".8b">;
6411  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
6412                                      asm, ".8b">;
6413  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
6414                                      asm, ".16b">;
6415  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
6416                                      asm, ".16b">;
6417  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
6418                                      asm, ".16b">;
6419  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
6420                                      asm, ".16b">;
6421
6422  def : SIMDTableLookupAlias<asm # ".8b",
6423                         !cast<Instruction>(NAME#"v8i8One"),
6424                         V64, VecListOne128>;
6425  def : SIMDTableLookupAlias<asm # ".8b",
6426                         !cast<Instruction>(NAME#"v8i8Two"),
6427                         V64, VecListTwo128>;
6428  def : SIMDTableLookupAlias<asm # ".8b",
6429                         !cast<Instruction>(NAME#"v8i8Three"),
6430                         V64, VecListThree128>;
6431  def : SIMDTableLookupAlias<asm # ".8b",
6432                         !cast<Instruction>(NAME#"v8i8Four"),
6433                         V64, VecListFour128>;
6434  def : SIMDTableLookupAlias<asm # ".16b",
6435                         !cast<Instruction>(NAME#"v16i8One"),
6436                         V128, VecListOne128>;
6437  def : SIMDTableLookupAlias<asm # ".16b",
6438                         !cast<Instruction>(NAME#"v16i8Two"),
6439                         V128, VecListTwo128>;
6440  def : SIMDTableLookupAlias<asm # ".16b",
6441                         !cast<Instruction>(NAME#"v16i8Three"),
6442                         V128, VecListThree128>;
6443  def : SIMDTableLookupAlias<asm # ".16b",
6444                         !cast<Instruction>(NAME#"v16i8Four"),
6445                         V128, VecListFour128>;
6446}
6447
6448multiclass SIMDTableLookupTied<bit op, string asm> {
6449  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
6450                                      asm, ".8b">;
6451  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
6452                                      asm, ".8b">;
6453  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
6454                                      asm, ".8b">;
6455  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
6456                                      asm, ".8b">;
6457  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
6458                                      asm, ".16b">;
6459  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
6460                                      asm, ".16b">;
6461  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
6462                                      asm, ".16b">;
6463  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
6464                                      asm, ".16b">;
6465
6466  def : SIMDTableLookupAlias<asm # ".8b",
6467                         !cast<Instruction>(NAME#"v8i8One"),
6468                         V64, VecListOne128>;
6469  def : SIMDTableLookupAlias<asm # ".8b",
6470                         !cast<Instruction>(NAME#"v8i8Two"),
6471                         V64, VecListTwo128>;
6472  def : SIMDTableLookupAlias<asm # ".8b",
6473                         !cast<Instruction>(NAME#"v8i8Three"),
6474                         V64, VecListThree128>;
6475  def : SIMDTableLookupAlias<asm # ".8b",
6476                         !cast<Instruction>(NAME#"v8i8Four"),
6477                         V64, VecListFour128>;
6478  def : SIMDTableLookupAlias<asm # ".16b",
6479                         !cast<Instruction>(NAME#"v16i8One"),
6480                         V128, VecListOne128>;
6481  def : SIMDTableLookupAlias<asm # ".16b",
6482                         !cast<Instruction>(NAME#"v16i8Two"),
6483                         V128, VecListTwo128>;
6484  def : SIMDTableLookupAlias<asm # ".16b",
6485                         !cast<Instruction>(NAME#"v16i8Three"),
6486                         V128, VecListThree128>;
6487  def : SIMDTableLookupAlias<asm # ".16b",
6488                         !cast<Instruction>(NAME#"v16i8Four"),
6489                         V128, VecListFour128>;
6490}
6491
6492
6493//----------------------------------------------------------------------------
6494// AdvSIMD scalar CPY
6495//----------------------------------------------------------------------------
6496let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6497class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
6498                        string kind, Operand idxtype>
6499  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
6500       "{\t$dst, $src" # kind # "$idx" #
6501       "|\t$dst, $src$idx}", "", []>,
6502    Sched<[WriteV]> {
6503  bits<5> dst;
6504  bits<5> src;
6505  let Inst{31-21} = 0b01011110000;
6506  let Inst{15-10} = 0b000001;
6507  let Inst{9-5}   = src;
6508  let Inst{4-0}   = dst;
6509}
6510
6511class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
6512      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
6513    : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
6514                    # "|\t$dst, $src$index}",
6515                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
6516
6517
6518multiclass SIMDScalarCPY<string asm> {
6519  def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
6520    bits<4> idx;
6521    let Inst{20-17} = idx;
6522    let Inst{16} = 1;
6523  }
6524  def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
6525    bits<3> idx;
6526    let Inst{20-18} = idx;
6527    let Inst{17-16} = 0b10;
6528  }
6529  def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
6530    bits<2> idx;
6531    let Inst{20-19} = idx;
6532    let Inst{18-16} = 0b100;
6533  }
6534  def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
6535    bits<1> idx;
6536    let Inst{20} = idx;
6537    let Inst{19-16} = 0b1000;
6538  }
6539
6540  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
6541                                                          VectorIndexD:$idx)))),
6542            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
6543
6544  // 'DUP' mnemonic aliases.
6545  def : SIMDScalarCPYAlias<"dup", ".b",
6546                           !cast<Instruction>(NAME#"i8"),
6547                           FPR8, V128, VectorIndexB>;
6548  def : SIMDScalarCPYAlias<"dup", ".h",
6549                           !cast<Instruction>(NAME#"i16"),
6550                           FPR16, V128, VectorIndexH>;
6551  def : SIMDScalarCPYAlias<"dup", ".s",
6552                           !cast<Instruction>(NAME#"i32"),
6553                           FPR32, V128, VectorIndexS>;
6554  def : SIMDScalarCPYAlias<"dup", ".d",
6555                           !cast<Instruction>(NAME#"i64"),
6556                           FPR64, V128, VectorIndexD>;
6557}
6558
6559//----------------------------------------------------------------------------
6560// AdvSIMD modified immediate instructions
6561//----------------------------------------------------------------------------
6562
6563class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
6564                          string asm, string op_string,
6565                          string cstr, list<dag> pattern>
6566  : I<oops, iops, asm, op_string, cstr, pattern>,
6567    Sched<[WriteV]> {
6568  bits<5> Rd;
6569  bits<8> imm8;
6570  let Inst{31}    = 0;
6571  let Inst{30}    = Q;
6572  let Inst{29}    = op;
6573  let Inst{28-19} = 0b0111100000;
6574  let Inst{18-16} = imm8{7-5};
6575  let Inst{11} = op2;
6576  let Inst{10} = 1;
6577  let Inst{9-5}   = imm8{4-0};
6578  let Inst{4-0}   = Rd;
6579}
6580
6581class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
6582                                Operand immtype, dag opt_shift_iop,
6583                                string opt_shift, string asm, string kind,
6584                                list<dag> pattern>
6585  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
6586                        !con((ins immtype:$imm8), opt_shift_iop), asm,
6587                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
6588                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6589                        "", pattern> {
6590  let DecoderMethod = "DecodeModImmInstruction";
6591}
6592
6593class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
6594                                Operand immtype, dag opt_shift_iop,
6595                                string opt_shift, string asm, string kind,
6596                                list<dag> pattern>
6597  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
6598                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
6599                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
6600                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
6601                        "$Rd = $dst", pattern> {
6602  let DecoderMethod = "DecodeModImmTiedInstruction";
6603}
6604
6605class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
6606                                     RegisterOperand vectype, string asm,
6607                                     string kind, list<dag> pattern>
6608  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
6609                              (ins logical_vec_shift:$shift),
6610                              "$shift", asm, kind, pattern> {
6611  bits<2> shift;
6612  let Inst{15}    = b15_b12{1};
6613  let Inst{14-13} = shift;
6614  let Inst{12}    = b15_b12{0};
6615}
6616
6617class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
6618                                     RegisterOperand vectype, string asm,
6619                                     string kind, list<dag> pattern>
6620  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6621                              (ins logical_vec_shift:$shift),
6622                              "$shift", asm, kind, pattern> {
6623  bits<2> shift;
6624  let Inst{15}    = b15_b12{1};
6625  let Inst{14-13} = shift;
6626  let Inst{12}    = b15_b12{0};
6627}
6628
6629
6630class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
6631                                         RegisterOperand vectype, string asm,
6632                                         string kind, list<dag> pattern>
6633  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
6634                              (ins logical_vec_hw_shift:$shift),
6635                              "$shift", asm, kind, pattern> {
6636  bits<2> shift;
6637  let Inst{15} = b15_b12{1};
6638  let Inst{14} = 0;
6639  let Inst{13} = shift{0};
6640  let Inst{12} = b15_b12{0};
6641}
6642
6643class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
6644                                         RegisterOperand vectype, string asm,
6645                                         string kind, list<dag> pattern>
6646  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
6647                              (ins logical_vec_hw_shift:$shift),
6648                              "$shift", asm, kind, pattern> {
6649  bits<2> shift;
6650  let Inst{15} = b15_b12{1};
6651  let Inst{14} = 0;
6652  let Inst{13} = shift{0};
6653  let Inst{12} = b15_b12{0};
6654}
6655
6656multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
6657                                      string asm> {
6658  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
6659                                                 asm, ".4h", []>;
6660  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
6661                                                 asm, ".8h", []>;
6662
6663  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
6664                                             asm, ".2s", []>;
6665  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
6666                                             asm, ".4s", []>;
6667}
6668
6669multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
6670                                      bits<2> w_cmode, string asm,
6671                                      SDNode OpNode> {
6672  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
6673                                                 asm, ".4h",
6674             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
6675                                             imm0_255:$imm8,
6676                                             (i32 imm:$shift)))]>;
6677  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
6678                                                 asm, ".8h",
6679             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
6680                                              imm0_255:$imm8,
6681                                              (i32 imm:$shift)))]>;
6682
6683  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
6684                                             asm, ".2s",
6685             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
6686                                             imm0_255:$imm8,
6687                                             (i32 imm:$shift)))]>;
6688  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
6689                                             asm, ".4s",
6690             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
6691                                              imm0_255:$imm8,
6692                                              (i32 imm:$shift)))]>;
6693}
6694
6695class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
6696                             RegisterOperand vectype, string asm,
6697                             string kind, list<dag> pattern>
6698  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
6699                              (ins move_vec_shift:$shift),
6700                              "$shift", asm, kind, pattern> {
6701  bits<1> shift;
6702  let Inst{15-13} = cmode{3-1};
6703  let Inst{12}    = shift;
6704}
6705
6706class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
6707                                   RegisterOperand vectype,
6708                                   Operand imm_type, string asm,
6709                                   string kind, list<dag> pattern>
6710  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
6711                              asm, kind, pattern> {
6712  let Inst{15-12} = cmode;
6713}
6714
6715class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
6716                                   list<dag> pattern>
6717  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
6718                        "\t$Rd, $imm8", "", pattern> {
6719  let Inst{15-12} = cmode;
6720  let DecoderMethod = "DecodeModImmInstruction";
6721}
6722
6723//----------------------------------------------------------------------------
6724// AdvSIMD indexed element
6725//----------------------------------------------------------------------------
6726
6727let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6728class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6729                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
6730                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
6731                      string apple_kind, string dst_kind, string lhs_kind,
6732                      string rhs_kind, list<dag> pattern>
6733  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
6734      asm,
6735      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6736      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
6737    Sched<[WriteV]> {
6738  bits<5> Rd;
6739  bits<5> Rn;
6740  bits<5> Rm;
6741
6742  let Inst{31}    = 0;
6743  let Inst{30}    = Q;
6744  let Inst{29}    = U;
6745  let Inst{28}    = Scalar;
6746  let Inst{27-24} = 0b1111;
6747  let Inst{23-22} = size;
6748  // Bit 21 must be set by the derived class.
6749  let Inst{20-16} = Rm;
6750  let Inst{15-12} = opc;
6751  // Bit 11 must be set by the derived class.
6752  let Inst{10}    = 0;
6753  let Inst{9-5}   = Rn;
6754  let Inst{4-0}   = Rd;
6755}
6756
6757let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6758class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
6759                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
6760                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
6761                      string apple_kind, string dst_kind, string lhs_kind,
6762                      string rhs_kind, list<dag> pattern>
6763  : I<(outs dst_reg:$dst),
6764      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
6765      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
6766      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
6767    Sched<[WriteV]> {
6768  bits<5> Rd;
6769  bits<5> Rn;
6770  bits<5> Rm;
6771
6772  let Inst{31}    = 0;
6773  let Inst{30}    = Q;
6774  let Inst{29}    = U;
6775  let Inst{28}    = Scalar;
6776  let Inst{27-24} = 0b1111;
6777  let Inst{23-22} = size;
6778  // Bit 21 must be set by the derived class.
6779  let Inst{20-16} = Rm;
6780  let Inst{15-12} = opc;
6781  // Bit 11 must be set by the derived class.
6782  let Inst{10}    = 0;
6783  let Inst{9-5}   = Rn;
6784  let Inst{4-0}   = Rd;
6785}
6786
6787multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
6788                         SDPatternOperator OpNode> {
6789  let Predicates = [HasNEON, HasFullFP16] in {
6790  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
6791                                      V64, V64,
6792                                      V128_lo, VectorIndexH,
6793                                      asm, ".4h", ".4h", ".4h", ".h",
6794    [(set (v4f16 V64:$Rd),
6795        (OpNode (v4f16 V64:$Rn),
6796         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6797    bits<3> idx;
6798    let Inst{11} = idx{2};
6799    let Inst{21} = idx{1};
6800    let Inst{20} = idx{0};
6801  }
6802
6803  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
6804                                      V128, V128,
6805                                      V128_lo, VectorIndexH,
6806                                      asm, ".8h", ".8h", ".8h", ".h",
6807    [(set (v8f16 V128:$Rd),
6808        (OpNode (v8f16 V128:$Rn),
6809         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
6810    bits<3> idx;
6811    let Inst{11} = idx{2};
6812    let Inst{21} = idx{1};
6813    let Inst{20} = idx{0};
6814  }
6815  } // Predicates = [HasNEON, HasFullFP16]
6816
6817  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
6818                                      V64, V64,
6819                                      V128, VectorIndexS,
6820                                      asm, ".2s", ".2s", ".2s", ".s",
6821    [(set (v2f32 V64:$Rd),
6822        (OpNode (v2f32 V64:$Rn),
6823         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6824    bits<2> idx;
6825    let Inst{11} = idx{1};
6826    let Inst{21} = idx{0};
6827  }
6828
6829  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
6830                                      V128, V128,
6831                                      V128, VectorIndexS,
6832                                      asm, ".4s", ".4s", ".4s", ".s",
6833    [(set (v4f32 V128:$Rd),
6834        (OpNode (v4f32 V128:$Rn),
6835         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
6836    bits<2> idx;
6837    let Inst{11} = idx{1};
6838    let Inst{21} = idx{0};
6839  }
6840
6841  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
6842                                      V128, V128,
6843                                      V128, VectorIndexD,
6844                                      asm, ".2d", ".2d", ".2d", ".d",
6845    [(set (v2f64 V128:$Rd),
6846        (OpNode (v2f64 V128:$Rn),
6847         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
6848    bits<1> idx;
6849    let Inst{11} = idx{0};
6850    let Inst{21} = 0;
6851  }
6852
6853  let Predicates = [HasNEON, HasFullFP16] in {
6854  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
6855                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6856                                      asm, ".h", "", "", ".h",
6857    [(set (f16 FPR16Op:$Rd),
6858          (OpNode (f16 FPR16Op:$Rn),
6859                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
6860                                       VectorIndexH:$idx))))]> {
6861    bits<3> idx;
6862    let Inst{11} = idx{2};
6863    let Inst{21} = idx{1};
6864    let Inst{20} = idx{0};
6865  }
6866  } // Predicates = [HasNEON, HasFullFP16]
6867
6868  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
6869                                      FPR32Op, FPR32Op, V128, VectorIndexS,
6870                                      asm, ".s", "", "", ".s",
6871    [(set (f32 FPR32Op:$Rd),
6872          (OpNode (f32 FPR32Op:$Rn),
6873                  (f32 (vector_extract (v4f32 V128:$Rm),
6874                                       VectorIndexS:$idx))))]> {
6875    bits<2> idx;
6876    let Inst{11} = idx{1};
6877    let Inst{21} = idx{0};
6878  }
6879
6880  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
6881                                      FPR64Op, FPR64Op, V128, VectorIndexD,
6882                                      asm, ".d", "", "", ".d",
6883    [(set (f64 FPR64Op:$Rd),
6884          (OpNode (f64 FPR64Op:$Rn),
6885                  (f64 (vector_extract (v2f64 V128:$Rm),
6886                                       VectorIndexD:$idx))))]> {
6887    bits<1> idx;
6888    let Inst{11} = idx{0};
6889    let Inst{21} = 0;
6890  }
6891}
6892
6893multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
6894  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
6895  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6896                           (AArch64duplane32 (v4f32 V128:$Rm),
6897                                           VectorIndexS:$idx))),
6898            (!cast<Instruction>(INST # v2i32_indexed)
6899                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6900  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
6901                           (AArch64dup (f32 FPR32Op:$Rm)))),
6902            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
6903                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6904
6905
6906  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
6907  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6908                           (AArch64duplane32 (v4f32 V128:$Rm),
6909                                           VectorIndexS:$idx))),
6910            (!cast<Instruction>(INST # "v4i32_indexed")
6911                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6912  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
6913                           (AArch64dup (f32 FPR32Op:$Rm)))),
6914            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
6915                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
6916
6917  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
6918  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6919                           (AArch64duplane64 (v2f64 V128:$Rm),
6920                                           VectorIndexD:$idx))),
6921            (!cast<Instruction>(INST # "v2i64_indexed")
6922                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
6923  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
6924                           (AArch64dup (f64 FPR64Op:$Rm)))),
6925            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
6926                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
6927
6928  // 2 variants for 32-bit scalar version: extract from .2s or from .4s
6929  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6930                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
6931            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6932                V128:$Rm, VectorIndexS:$idx)>;
6933  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
6934                         (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
6935            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
6936                (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
6937
6938  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
6939  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
6940                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
6941            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
6942                V128:$Rm, VectorIndexD:$idx)>;
6943}
6944
6945multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
6946  let Predicates = [HasNEON, HasFullFP16] in {
6947  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
6948                                          V128_lo, VectorIndexH,
6949                                          asm, ".4h", ".4h", ".4h", ".h", []> {
6950    bits<3> idx;
6951    let Inst{11} = idx{2};
6952    let Inst{21} = idx{1};
6953    let Inst{20} = idx{0};
6954  }
6955
6956  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
6957                                          V128, V128,
6958                                          V128_lo, VectorIndexH,
6959                                          asm, ".8h", ".8h", ".8h", ".h", []> {
6960    bits<3> idx;
6961    let Inst{11} = idx{2};
6962    let Inst{21} = idx{1};
6963    let Inst{20} = idx{0};
6964  }
6965  } // Predicates = [HasNEON, HasFullFP16]
6966
6967  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
6968                                          V128, VectorIndexS,
6969                                          asm, ".2s", ".2s", ".2s", ".s", []> {
6970    bits<2> idx;
6971    let Inst{11} = idx{1};
6972    let Inst{21} = idx{0};
6973  }
6974
6975  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
6976                                      V128, V128,
6977                                      V128, VectorIndexS,
6978                                      asm, ".4s", ".4s", ".4s", ".s", []> {
6979    bits<2> idx;
6980    let Inst{11} = idx{1};
6981    let Inst{21} = idx{0};
6982  }
6983
6984  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
6985                                      V128, V128,
6986                                      V128, VectorIndexD,
6987                                      asm, ".2d", ".2d", ".2d", ".d", []> {
6988    bits<1> idx;
6989    let Inst{11} = idx{0};
6990    let Inst{21} = 0;
6991  }
6992
6993  let Predicates = [HasNEON, HasFullFP16] in {
6994  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
6995                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
6996                                      asm, ".h", "", "", ".h", []> {
6997    bits<3> idx;
6998    let Inst{11} = idx{2};
6999    let Inst{21} = idx{1};
7000    let Inst{20} = idx{0};
7001  }
7002  } // Predicates = [HasNEON, HasFullFP16]
7003
7004  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7005                                      FPR32Op, FPR32Op, V128, VectorIndexS,
7006                                      asm, ".s", "", "", ".s", []> {
7007    bits<2> idx;
7008    let Inst{11} = idx{1};
7009    let Inst{21} = idx{0};
7010  }
7011
7012  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7013                                      FPR64Op, FPR64Op, V128, VectorIndexD,
7014                                      asm, ".d", "", "", ".d", []> {
7015    bits<1> idx;
7016    let Inst{11} = idx{0};
7017    let Inst{21} = 0;
7018  }
7019}
7020
7021multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7022                         SDPatternOperator OpNode> {
7023  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7024                                      V128_lo, VectorIndexH,
7025                                      asm, ".4h", ".4h", ".4h", ".h",
7026    [(set (v4i16 V64:$Rd),
7027        (OpNode (v4i16 V64:$Rn),
7028         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7029    bits<3> idx;
7030    let Inst{11} = idx{2};
7031    let Inst{21} = idx{1};
7032    let Inst{20} = idx{0};
7033  }
7034
7035  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7036                                      V128, V128,
7037                                      V128_lo, VectorIndexH,
7038                                      asm, ".8h", ".8h", ".8h", ".h",
7039    [(set (v8i16 V128:$Rd),
7040       (OpNode (v8i16 V128:$Rn),
7041         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7042    bits<3> idx;
7043    let Inst{11} = idx{2};
7044    let Inst{21} = idx{1};
7045    let Inst{20} = idx{0};
7046  }
7047
7048  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7049                                      V64, V64,
7050                                      V128, VectorIndexS,
7051                                      asm, ".2s", ".2s", ".2s",  ".s",
7052    [(set (v2i32 V64:$Rd),
7053       (OpNode (v2i32 V64:$Rn),
7054          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7055    bits<2> idx;
7056    let Inst{11} = idx{1};
7057    let Inst{21} = idx{0};
7058  }
7059
7060  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7061                                      V128, V128,
7062                                      V128, VectorIndexS,
7063                                      asm, ".4s", ".4s", ".4s", ".s",
7064    [(set (v4i32 V128:$Rd),
7065       (OpNode (v4i32 V128:$Rn),
7066          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7067    bits<2> idx;
7068    let Inst{11} = idx{1};
7069    let Inst{21} = idx{0};
7070  }
7071
7072  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7073                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7074                                      asm, ".h", "", "", ".h", []> {
7075    bits<3> idx;
7076    let Inst{11} = idx{2};
7077    let Inst{21} = idx{1};
7078    let Inst{20} = idx{0};
7079  }
7080
7081  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7082                                      FPR32Op, FPR32Op, V128, VectorIndexS,
7083                                      asm, ".s", "", "", ".s",
7084      [(set (i32 FPR32Op:$Rd),
7085            (OpNode FPR32Op:$Rn,
7086                    (i32 (vector_extract (v4i32 V128:$Rm),
7087                                         VectorIndexS:$idx))))]> {
7088    bits<2> idx;
7089    let Inst{11} = idx{1};
7090    let Inst{21} = idx{0};
7091  }
7092}
7093
7094multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
7095                               SDPatternOperator OpNode> {
7096  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7097                                      V64, V64,
7098                                      V128_lo, VectorIndexH,
7099                                      asm, ".4h", ".4h", ".4h", ".h",
7100    [(set (v4i16 V64:$Rd),
7101        (OpNode (v4i16 V64:$Rn),
7102         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7103    bits<3> idx;
7104    let Inst{11} = idx{2};
7105    let Inst{21} = idx{1};
7106    let Inst{20} = idx{0};
7107  }
7108
7109  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7110                                      V128, V128,
7111                                      V128_lo, VectorIndexH,
7112                                      asm, ".8h", ".8h", ".8h", ".h",
7113    [(set (v8i16 V128:$Rd),
7114       (OpNode (v8i16 V128:$Rn),
7115         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7116    bits<3> idx;
7117    let Inst{11} = idx{2};
7118    let Inst{21} = idx{1};
7119    let Inst{20} = idx{0};
7120  }
7121
7122  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7123                                      V64, V64,
7124                                      V128, VectorIndexS,
7125                                      asm, ".2s", ".2s", ".2s", ".s",
7126    [(set (v2i32 V64:$Rd),
7127       (OpNode (v2i32 V64:$Rn),
7128          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7129    bits<2> idx;
7130    let Inst{11} = idx{1};
7131    let Inst{21} = idx{0};
7132  }
7133
7134  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7135                                      V128, V128,
7136                                      V128, VectorIndexS,
7137                                      asm, ".4s", ".4s", ".4s", ".s",
7138    [(set (v4i32 V128:$Rd),
7139       (OpNode (v4i32 V128:$Rn),
7140          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7141    bits<2> idx;
7142    let Inst{11} = idx{1};
7143    let Inst{21} = idx{0};
7144  }
7145}
7146
7147multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
7148                                   SDPatternOperator OpNode> {
7149  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
7150                                          V128_lo, VectorIndexH,
7151                                          asm, ".4h", ".4h", ".4h", ".h",
7152    [(set (v4i16 V64:$dst),
7153        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
7154         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7155    bits<3> idx;
7156    let Inst{11} = idx{2};
7157    let Inst{21} = idx{1};
7158    let Inst{20} = idx{0};
7159  }
7160
7161  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7162                                      V128, V128,
7163                                      V128_lo, VectorIndexH,
7164                                      asm, ".8h", ".8h", ".8h", ".h",
7165    [(set (v8i16 V128:$dst),
7166       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
7167         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7168    bits<3> idx;
7169    let Inst{11} = idx{2};
7170    let Inst{21} = idx{1};
7171    let Inst{20} = idx{0};
7172  }
7173
7174  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7175                                      V64, V64,
7176                                      V128, VectorIndexS,
7177                                      asm, ".2s", ".2s", ".2s", ".s",
7178    [(set (v2i32 V64:$dst),
7179       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
7180          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7181    bits<2> idx;
7182    let Inst{11} = idx{1};
7183    let Inst{21} = idx{0};
7184  }
7185
7186  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7187                                      V128, V128,
7188                                      V128, VectorIndexS,
7189                                      asm, ".4s", ".4s", ".4s", ".s",
7190    [(set (v4i32 V128:$dst),
7191       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
7192          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7193    bits<2> idx;
7194    let Inst{11} = idx{1};
7195    let Inst{21} = idx{0};
7196  }
7197}
7198
7199multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
7200                             SDPatternOperator OpNode> {
7201  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7202                                      V128, V64,
7203                                      V128_lo, VectorIndexH,
7204                                      asm, ".4s", ".4s", ".4h", ".h",
7205    [(set (v4i32 V128:$Rd),
7206        (OpNode (v4i16 V64:$Rn),
7207         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7208    bits<3> idx;
7209    let Inst{11} = idx{2};
7210    let Inst{21} = idx{1};
7211    let Inst{20} = idx{0};
7212  }
7213
7214  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7215                                      V128, V128,
7216                                      V128_lo, VectorIndexH,
7217                                      asm#"2", ".4s", ".4s", ".8h", ".h",
7218    [(set (v4i32 V128:$Rd),
7219          (OpNode (extract_high_v8i16 V128:$Rn),
7220                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7221                                                      VectorIndexH:$idx))))]> {
7222
7223    bits<3> idx;
7224    let Inst{11} = idx{2};
7225    let Inst{21} = idx{1};
7226    let Inst{20} = idx{0};
7227  }
7228
7229  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7230                                      V128, V64,
7231                                      V128, VectorIndexS,
7232                                      asm, ".2d", ".2d", ".2s", ".s",
7233    [(set (v2i64 V128:$Rd),
7234        (OpNode (v2i32 V64:$Rn),
7235         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7236    bits<2> idx;
7237    let Inst{11} = idx{1};
7238    let Inst{21} = idx{0};
7239  }
7240
7241  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7242                                      V128, V128,
7243                                      V128, VectorIndexS,
7244                                      asm#"2", ".2d", ".2d", ".4s", ".s",
7245    [(set (v2i64 V128:$Rd),
7246          (OpNode (extract_high_v4i32 V128:$Rn),
7247                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7248                                                      VectorIndexS:$idx))))]> {
7249    bits<2> idx;
7250    let Inst{11} = idx{1};
7251    let Inst{21} = idx{0};
7252  }
7253
7254  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7255                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7256                                      asm, ".h", "", "", ".h", []> {
7257    bits<3> idx;
7258    let Inst{11} = idx{2};
7259    let Inst{21} = idx{1};
7260    let Inst{20} = idx{0};
7261  }
7262
7263  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7264                                      FPR64Op, FPR32Op, V128, VectorIndexS,
7265                                      asm, ".s", "", "", ".s", []> {
7266    bits<2> idx;
7267    let Inst{11} = idx{1};
7268    let Inst{21} = idx{0};
7269  }
7270}
7271
7272multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
7273                                       SDPatternOperator Accum> {
7274  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7275                                      V128, V64,
7276                                      V128_lo, VectorIndexH,
7277                                      asm, ".4s", ".4s", ".4h", ".h",
7278    [(set (v4i32 V128:$dst),
7279          (Accum (v4i32 V128:$Rd),
7280                 (v4i32 (int_aarch64_neon_sqdmull
7281                             (v4i16 V64:$Rn),
7282                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7283                                                    VectorIndexH:$idx))))))]> {
7284    bits<3> idx;
7285    let Inst{11} = idx{2};
7286    let Inst{21} = idx{1};
7287    let Inst{20} = idx{0};
7288  }
7289
7290  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
7291  // intermediate EXTRACT_SUBREG would be untyped.
7292  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
7293                (i32 (vector_extract (v4i32
7294                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7295                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7296                                                    VectorIndexH:$idx)))),
7297                         (i64 0))))),
7298            (EXTRACT_SUBREG
7299                (!cast<Instruction>(NAME # v4i16_indexed)
7300                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
7301                    V128_lo:$Rm, VectorIndexH:$idx),
7302                ssub)>;
7303
7304  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7305                                      V128, V128,
7306                                      V128_lo, VectorIndexH,
7307                                      asm#"2", ".4s", ".4s", ".8h", ".h",
7308    [(set (v4i32 V128:$dst),
7309          (Accum (v4i32 V128:$Rd),
7310                 (v4i32 (int_aarch64_neon_sqdmull
7311                            (extract_high_v8i16 V128:$Rn),
7312                            (extract_high_v8i16
7313                                (AArch64duplane16 (v8i16 V128_lo:$Rm),
7314                                                VectorIndexH:$idx))))))]> {
7315    bits<3> idx;
7316    let Inst{11} = idx{2};
7317    let Inst{21} = idx{1};
7318    let Inst{20} = idx{0};
7319  }
7320
7321  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7322                                      V128, V64,
7323                                      V128, VectorIndexS,
7324                                      asm, ".2d", ".2d", ".2s", ".s",
7325    [(set (v2i64 V128:$dst),
7326        (Accum (v2i64 V128:$Rd),
7327               (v2i64 (int_aarch64_neon_sqdmull
7328                          (v2i32 V64:$Rn),
7329                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
7330                                                 VectorIndexS:$idx))))))]> {
7331    bits<2> idx;
7332    let Inst{11} = idx{1};
7333    let Inst{21} = idx{0};
7334  }
7335
7336  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7337                                      V128, V128,
7338                                      V128, VectorIndexS,
7339                                      asm#"2", ".2d", ".2d", ".4s", ".s",
7340    [(set (v2i64 V128:$dst),
7341          (Accum (v2i64 V128:$Rd),
7342                 (v2i64 (int_aarch64_neon_sqdmull
7343                            (extract_high_v4i32 V128:$Rn),
7344                            (extract_high_v4i32
7345                                (AArch64duplane32 (v4i32 V128:$Rm),
7346                                                VectorIndexS:$idx))))))]> {
7347    bits<2> idx;
7348    let Inst{11} = idx{1};
7349    let Inst{21} = idx{0};
7350  }
7351
7352  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
7353                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
7354                                      asm, ".h", "", "", ".h", []> {
7355    bits<3> idx;
7356    let Inst{11} = idx{2};
7357    let Inst{21} = idx{1};
7358    let Inst{20} = idx{0};
7359  }
7360
7361
7362  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7363                                      FPR64Op, FPR32Op, V128, VectorIndexS,
7364                                      asm, ".s", "", "", ".s",
7365    [(set (i64 FPR64Op:$dst),
7366          (Accum (i64 FPR64Op:$Rd),
7367                 (i64 (int_aarch64_neon_sqdmulls_scalar
7368                            (i32 FPR32Op:$Rn),
7369                            (i32 (vector_extract (v4i32 V128:$Rm),
7370                                                 VectorIndexS:$idx))))))]> {
7371
7372    bits<2> idx;
7373    let Inst{11} = idx{1};
7374    let Inst{21} = idx{0};
7375  }
7376}
7377
7378multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
7379                                   SDPatternOperator OpNode> {
7380  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7381  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
7382                                      V128, V64,
7383                                      V128_lo, VectorIndexH,
7384                                      asm, ".4s", ".4s", ".4h", ".h",
7385    [(set (v4i32 V128:$Rd),
7386        (OpNode (v4i16 V64:$Rn),
7387         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7388    bits<3> idx;
7389    let Inst{11} = idx{2};
7390    let Inst{21} = idx{1};
7391    let Inst{20} = idx{0};
7392  }
7393
7394  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7395                                      V128, V128,
7396                                      V128_lo, VectorIndexH,
7397                                      asm#"2", ".4s", ".4s", ".8h", ".h",
7398    [(set (v4i32 V128:$Rd),
7399          (OpNode (extract_high_v8i16 V128:$Rn),
7400                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7401                                                      VectorIndexH:$idx))))]> {
7402
7403    bits<3> idx;
7404    let Inst{11} = idx{2};
7405    let Inst{21} = idx{1};
7406    let Inst{20} = idx{0};
7407  }
7408
7409  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7410                                      V128, V64,
7411                                      V128, VectorIndexS,
7412                                      asm, ".2d", ".2d", ".2s", ".s",
7413    [(set (v2i64 V128:$Rd),
7414        (OpNode (v2i32 V64:$Rn),
7415         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7416    bits<2> idx;
7417    let Inst{11} = idx{1};
7418    let Inst{21} = idx{0};
7419  }
7420
7421  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7422                                      V128, V128,
7423                                      V128, VectorIndexS,
7424                                      asm#"2", ".2d", ".2d", ".4s", ".s",
7425    [(set (v2i64 V128:$Rd),
7426          (OpNode (extract_high_v4i32 V128:$Rn),
7427                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7428                                                      VectorIndexS:$idx))))]> {
7429    bits<2> idx;
7430    let Inst{11} = idx{1};
7431    let Inst{21} = idx{0};
7432  }
7433  }
7434}
7435
7436multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
7437                                       SDPatternOperator OpNode> {
7438  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7439  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
7440                                      V128, V64,
7441                                      V128_lo, VectorIndexH,
7442                                      asm, ".4s", ".4s", ".4h", ".h",
7443    [(set (v4i32 V128:$dst),
7444        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
7445         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7446    bits<3> idx;
7447    let Inst{11} = idx{2};
7448    let Inst{21} = idx{1};
7449    let Inst{20} = idx{0};
7450  }
7451
7452  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
7453                                      V128, V128,
7454                                      V128_lo, VectorIndexH,
7455                                      asm#"2", ".4s", ".4s", ".8h", ".h",
7456    [(set (v4i32 V128:$dst),
7457          (OpNode (v4i32 V128:$Rd),
7458                  (extract_high_v8i16 V128:$Rn),
7459                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
7460                                                      VectorIndexH:$idx))))]> {
7461    bits<3> idx;
7462    let Inst{11} = idx{2};
7463    let Inst{21} = idx{1};
7464    let Inst{20} = idx{0};
7465  }
7466
7467  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
7468                                      V128, V64,
7469                                      V128, VectorIndexS,
7470                                      asm, ".2d", ".2d", ".2s", ".s",
7471    [(set (v2i64 V128:$dst),
7472        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
7473         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7474    bits<2> idx;
7475    let Inst{11} = idx{1};
7476    let Inst{21} = idx{0};
7477  }
7478
7479  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7480                                      V128, V128,
7481                                      V128, VectorIndexS,
7482                                      asm#"2", ".2d", ".2d", ".4s", ".s",
7483    [(set (v2i64 V128:$dst),
7484          (OpNode (v2i64 V128:$Rd),
7485                  (extract_high_v4i32 V128:$Rn),
7486                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
7487                                                      VectorIndexS:$idx))))]> {
7488    bits<2> idx;
7489    let Inst{11} = idx{1};
7490    let Inst{21} = idx{0};
7491  }
7492  }
7493}
7494
7495//----------------------------------------------------------------------------
7496// AdvSIMD scalar shift by immediate
7497//----------------------------------------------------------------------------
7498
7499let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7500class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
7501                     RegisterClass regtype1, RegisterClass regtype2,
7502                     Operand immtype, string asm, list<dag> pattern>
7503  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
7504      asm, "\t$Rd, $Rn, $imm", "", pattern>,
7505    Sched<[WriteV]> {
7506  bits<5> Rd;
7507  bits<5> Rn;
7508  bits<7> imm;
7509  let Inst{31-30} = 0b01;
7510  let Inst{29}    = U;
7511  let Inst{28-23} = 0b111110;
7512  let Inst{22-16} = fixed_imm;
7513  let Inst{15-11} = opc;
7514  let Inst{10}    = 1;
7515  let Inst{9-5} = Rn;
7516  let Inst{4-0} = Rd;
7517}
7518
7519let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7520class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
7521                     RegisterClass regtype1, RegisterClass regtype2,
7522                     Operand immtype, string asm, list<dag> pattern>
7523  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
7524      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
7525    Sched<[WriteV]> {
7526  bits<5> Rd;
7527  bits<5> Rn;
7528  bits<7> imm;
7529  let Inst{31-30} = 0b01;
7530  let Inst{29}    = U;
7531  let Inst{28-23} = 0b111110;
7532  let Inst{22-16} = fixed_imm;
7533  let Inst{15-11} = opc;
7534  let Inst{10}    = 1;
7535  let Inst{9-5} = Rn;
7536  let Inst{4-0} = Rd;
7537}
7538
7539
7540multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
7541  let Predicates = [HasNEON, HasFullFP16] in {
7542  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7543                              FPR16, FPR16, vecshiftR16, asm, []> {
7544    let Inst{19-16} = imm{3-0};
7545  }
7546  } // Predicates = [HasNEON, HasFullFP16]
7547  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7548                              FPR32, FPR32, vecshiftR32, asm, []> {
7549    let Inst{20-16} = imm{4-0};
7550  }
7551
7552  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7553                              FPR64, FPR64, vecshiftR64, asm, []> {
7554    let Inst{21-16} = imm{5-0};
7555  }
7556}
7557
7558multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
7559                             SDPatternOperator OpNode> {
7560  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7561                              FPR64, FPR64, vecshiftR64, asm,
7562  [(set (i64 FPR64:$Rd),
7563     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
7564    let Inst{21-16} = imm{5-0};
7565  }
7566
7567  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
7568            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
7569}
7570
7571multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
7572                                 SDPatternOperator OpNode = null_frag> {
7573  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7574                              FPR64, FPR64, vecshiftR64, asm,
7575  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
7576                                                   (i32 vecshiftR64:$imm)))]> {
7577    let Inst{21-16} = imm{5-0};
7578  }
7579
7580  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
7581                           (i32 vecshiftR64:$imm))),
7582            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
7583                                            vecshiftR64:$imm)>;
7584}
7585
7586multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
7587                             SDPatternOperator OpNode> {
7588  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7589                              FPR64, FPR64, vecshiftL64, asm,
7590    [(set (v1i64 FPR64:$Rd),
7591       (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7592    let Inst{21-16} = imm{5-0};
7593  }
7594}
7595
7596let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7597multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
7598  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
7599                              FPR64, FPR64, vecshiftL64, asm, []> {
7600    let Inst{21-16} = imm{5-0};
7601  }
7602}
7603
7604let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7605multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
7606                               SDPatternOperator OpNode = null_frag> {
7607  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7608                              FPR8, FPR16, vecshiftR8, asm, []> {
7609    let Inst{18-16} = imm{2-0};
7610  }
7611
7612  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7613                              FPR16, FPR32, vecshiftR16, asm, []> {
7614    let Inst{19-16} = imm{3-0};
7615  }
7616
7617  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7618                              FPR32, FPR64, vecshiftR32, asm,
7619    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
7620    let Inst{20-16} = imm{4-0};
7621  }
7622}
7623
7624multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
7625                                SDPatternOperator OpNode> {
7626  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7627                              FPR8, FPR8, vecshiftL8, asm, []> {
7628    let Inst{18-16} = imm{2-0};
7629  }
7630
7631  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7632                              FPR16, FPR16, vecshiftL16, asm, []> {
7633    let Inst{19-16} = imm{3-0};
7634  }
7635
7636  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7637                              FPR32, FPR32, vecshiftL32, asm,
7638    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
7639    let Inst{20-16} = imm{4-0};
7640  }
7641
7642  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7643                              FPR64, FPR64, vecshiftL64, asm,
7644    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
7645    let Inst{21-16} = imm{5-0};
7646  }
7647
7648  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
7649            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
7650}
7651
7652multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
7653  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
7654                              FPR8, FPR8, vecshiftR8, asm, []> {
7655    let Inst{18-16} = imm{2-0};
7656  }
7657
7658  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
7659                              FPR16, FPR16, vecshiftR16, asm, []> {
7660    let Inst{19-16} = imm{3-0};
7661  }
7662
7663  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
7664                              FPR32, FPR32, vecshiftR32, asm, []> {
7665    let Inst{20-16} = imm{4-0};
7666  }
7667
7668  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
7669                              FPR64, FPR64, vecshiftR64, asm, []> {
7670    let Inst{21-16} = imm{5-0};
7671  }
7672}
7673
7674//----------------------------------------------------------------------------
7675// AdvSIMD vector x indexed element
7676//----------------------------------------------------------------------------
7677
7678let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7679class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7680                     RegisterOperand dst_reg, RegisterOperand src_reg,
7681                     Operand immtype,
7682                     string asm, string dst_kind, string src_kind,
7683                     list<dag> pattern>
7684  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
7685      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7686           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
7687    Sched<[WriteV]> {
7688  bits<5> Rd;
7689  bits<5> Rn;
7690  let Inst{31}    = 0;
7691  let Inst{30}    = Q;
7692  let Inst{29}    = U;
7693  let Inst{28-23} = 0b011110;
7694  let Inst{22-16} = fixed_imm;
7695  let Inst{15-11} = opc;
7696  let Inst{10}    = 1;
7697  let Inst{9-5}   = Rn;
7698  let Inst{4-0}   = Rd;
7699}
7700
7701let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7702class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
7703                     RegisterOperand vectype1, RegisterOperand vectype2,
7704                     Operand immtype,
7705                     string asm, string dst_kind, string src_kind,
7706                     list<dag> pattern>
7707  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
7708      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
7709           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
7710    Sched<[WriteV]> {
7711  bits<5> Rd;
7712  bits<5> Rn;
7713  let Inst{31}    = 0;
7714  let Inst{30}    = Q;
7715  let Inst{29}    = U;
7716  let Inst{28-23} = 0b011110;
7717  let Inst{22-16} = fixed_imm;
7718  let Inst{15-11} = opc;
7719  let Inst{10}    = 1;
7720  let Inst{9-5}   = Rn;
7721  let Inst{4-0}   = Rd;
7722}
7723
7724multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
7725                              Intrinsic OpNode> {
7726  let Predicates = [HasNEON, HasFullFP16] in {
7727  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7728                                  V64, V64, vecshiftR16,
7729                                  asm, ".4h", ".4h",
7730      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
7731    bits<4> imm;
7732    let Inst{19-16} = imm;
7733  }
7734
7735  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7736                                  V128, V128, vecshiftR16,
7737                                  asm, ".8h", ".8h",
7738      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
7739    bits<4> imm;
7740    let Inst{19-16} = imm;
7741  }
7742  } // Predicates = [HasNEON, HasFullFP16]
7743  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7744                                  V64, V64, vecshiftR32,
7745                                  asm, ".2s", ".2s",
7746      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
7747    bits<5> imm;
7748    let Inst{20-16} = imm;
7749  }
7750
7751  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7752                                  V128, V128, vecshiftR32,
7753                                  asm, ".4s", ".4s",
7754      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
7755    bits<5> imm;
7756    let Inst{20-16} = imm;
7757  }
7758
7759  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7760                                  V128, V128, vecshiftR64,
7761                                  asm, ".2d", ".2d",
7762      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
7763    bits<6> imm;
7764    let Inst{21-16} = imm;
7765  }
7766}
7767
7768multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
7769                                  Intrinsic OpNode> {
7770  let Predicates = [HasNEON, HasFullFP16] in {
7771  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7772                                  V64, V64, vecshiftR16,
7773                                  asm, ".4h", ".4h",
7774      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
7775    bits<4> imm;
7776    let Inst{19-16} = imm;
7777  }
7778
7779  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7780                                  V128, V128, vecshiftR16,
7781                                  asm, ".8h", ".8h",
7782      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
7783    bits<4> imm;
7784    let Inst{19-16} = imm;
7785  }
7786  } // Predicates = [HasNEON, HasFullFP16]
7787
7788  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7789                                  V64, V64, vecshiftR32,
7790                                  asm, ".2s", ".2s",
7791      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
7792    bits<5> imm;
7793    let Inst{20-16} = imm;
7794  }
7795
7796  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7797                                  V128, V128, vecshiftR32,
7798                                  asm, ".4s", ".4s",
7799      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
7800    bits<5> imm;
7801    let Inst{20-16} = imm;
7802  }
7803
7804  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7805                                  V128, V128, vecshiftR64,
7806                                  asm, ".2d", ".2d",
7807      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
7808    bits<6> imm;
7809    let Inst{21-16} = imm;
7810  }
7811}
7812
7813multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
7814                                     SDPatternOperator OpNode> {
7815  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7816                                  V64, V128, vecshiftR16Narrow,
7817                                  asm, ".8b", ".8h",
7818      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
7819    bits<3> imm;
7820    let Inst{18-16} = imm;
7821  }
7822
7823  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
7824                                  V128, V128, vecshiftR16Narrow,
7825                                  asm#"2", ".16b", ".8h", []> {
7826    bits<3> imm;
7827    let Inst{18-16} = imm;
7828    let hasSideEffects = 0;
7829  }
7830
7831  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7832                                  V64, V128, vecshiftR32Narrow,
7833                                  asm, ".4h", ".4s",
7834      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
7835    bits<4> imm;
7836    let Inst{19-16} = imm;
7837  }
7838
7839  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
7840                                  V128, V128, vecshiftR32Narrow,
7841                                  asm#"2", ".8h", ".4s", []> {
7842    bits<4> imm;
7843    let Inst{19-16} = imm;
7844    let hasSideEffects = 0;
7845  }
7846
7847  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7848                                  V64, V128, vecshiftR64Narrow,
7849                                  asm, ".2s", ".2d",
7850      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
7851    bits<5> imm;
7852    let Inst{20-16} = imm;
7853  }
7854
7855  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
7856                                  V128, V128, vecshiftR64Narrow,
7857                                  asm#"2", ".4s", ".2d", []> {
7858    bits<5> imm;
7859    let Inst{20-16} = imm;
7860    let hasSideEffects = 0;
7861  }
7862
7863  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
7864  // themselves, so put them here instead.
7865
7866  // Patterns involving what's effectively an insert high and a normal
7867  // intrinsic, represented by CONCAT_VECTORS.
7868  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
7869                                                   vecshiftR16Narrow:$imm)),
7870            (!cast<Instruction>(NAME # "v16i8_shift")
7871                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7872                V128:$Rn, vecshiftR16Narrow:$imm)>;
7873  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
7874                                                     vecshiftR32Narrow:$imm)),
7875            (!cast<Instruction>(NAME # "v8i16_shift")
7876                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7877                V128:$Rn, vecshiftR32Narrow:$imm)>;
7878  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
7879                                                     vecshiftR64Narrow:$imm)),
7880            (!cast<Instruction>(NAME # "v4i32_shift")
7881                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
7882                V128:$Rn, vecshiftR64Narrow:$imm)>;
7883}
7884
7885multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
7886                                SDPatternOperator OpNode> {
7887  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7888                                  V64, V64, vecshiftL8,
7889                                  asm, ".8b", ".8b",
7890                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7891                       (i32 vecshiftL8:$imm)))]> {
7892    bits<3> imm;
7893    let Inst{18-16} = imm;
7894  }
7895
7896  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7897                                  V128, V128, vecshiftL8,
7898                                  asm, ".16b", ".16b",
7899             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7900                   (i32 vecshiftL8:$imm)))]> {
7901    bits<3> imm;
7902    let Inst{18-16} = imm;
7903  }
7904
7905  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7906                                  V64, V64, vecshiftL16,
7907                                  asm, ".4h", ".4h",
7908              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7909                    (i32 vecshiftL16:$imm)))]> {
7910    bits<4> imm;
7911    let Inst{19-16} = imm;
7912  }
7913
7914  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7915                                  V128, V128, vecshiftL16,
7916                                  asm, ".8h", ".8h",
7917            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7918                  (i32 vecshiftL16:$imm)))]> {
7919    bits<4> imm;
7920    let Inst{19-16} = imm;
7921  }
7922
7923  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7924                                  V64, V64, vecshiftL32,
7925                                  asm, ".2s", ".2s",
7926              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7927                    (i32 vecshiftL32:$imm)))]> {
7928    bits<5> imm;
7929    let Inst{20-16} = imm;
7930  }
7931
7932  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7933                                  V128, V128, vecshiftL32,
7934                                  asm, ".4s", ".4s",
7935            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7936                  (i32 vecshiftL32:$imm)))]> {
7937    bits<5> imm;
7938    let Inst{20-16} = imm;
7939  }
7940
7941  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
7942                                  V128, V128, vecshiftL64,
7943                                  asm, ".2d", ".2d",
7944            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7945                  (i32 vecshiftL64:$imm)))]> {
7946    bits<6> imm;
7947    let Inst{21-16} = imm;
7948  }
7949}
7950
7951multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
7952                                SDPatternOperator OpNode> {
7953  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
7954                                  V64, V64, vecshiftR8,
7955                                  asm, ".8b", ".8b",
7956                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
7957                       (i32 vecshiftR8:$imm)))]> {
7958    bits<3> imm;
7959    let Inst{18-16} = imm;
7960  }
7961
7962  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
7963                                  V128, V128, vecshiftR8,
7964                                  asm, ".16b", ".16b",
7965             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
7966                   (i32 vecshiftR8:$imm)))]> {
7967    bits<3> imm;
7968    let Inst{18-16} = imm;
7969  }
7970
7971  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
7972                                  V64, V64, vecshiftR16,
7973                                  asm, ".4h", ".4h",
7974              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
7975                    (i32 vecshiftR16:$imm)))]> {
7976    bits<4> imm;
7977    let Inst{19-16} = imm;
7978  }
7979
7980  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
7981                                  V128, V128, vecshiftR16,
7982                                  asm, ".8h", ".8h",
7983            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7984                  (i32 vecshiftR16:$imm)))]> {
7985    bits<4> imm;
7986    let Inst{19-16} = imm;
7987  }
7988
7989  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
7990                                  V64, V64, vecshiftR32,
7991                                  asm, ".2s", ".2s",
7992              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
7993                    (i32 vecshiftR32:$imm)))]> {
7994    bits<5> imm;
7995    let Inst{20-16} = imm;
7996  }
7997
7998  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
7999                                  V128, V128, vecshiftR32,
8000                                  asm, ".4s", ".4s",
8001            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8002                  (i32 vecshiftR32:$imm)))]> {
8003    bits<5> imm;
8004    let Inst{20-16} = imm;
8005  }
8006
8007  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8008                                  V128, V128, vecshiftR64,
8009                                  asm, ".2d", ".2d",
8010            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8011                  (i32 vecshiftR64:$imm)))]> {
8012    bits<6> imm;
8013    let Inst{21-16} = imm;
8014  }
8015}
8016
8017let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8018multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8019                                    SDPatternOperator OpNode = null_frag> {
8020  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8021                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
8022                 [(set (v8i8 V64:$dst),
8023                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8024                           (i32 vecshiftR8:$imm)))]> {
8025    bits<3> imm;
8026    let Inst{18-16} = imm;
8027  }
8028
8029  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8030                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
8031             [(set (v16i8 V128:$dst),
8032               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8033                       (i32 vecshiftR8:$imm)))]> {
8034    bits<3> imm;
8035    let Inst{18-16} = imm;
8036  }
8037
8038  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8039                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
8040              [(set (v4i16 V64:$dst),
8041                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8042                        (i32 vecshiftR16:$imm)))]> {
8043    bits<4> imm;
8044    let Inst{19-16} = imm;
8045  }
8046
8047  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8048                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
8049            [(set (v8i16 V128:$dst),
8050              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8051                      (i32 vecshiftR16:$imm)))]> {
8052    bits<4> imm;
8053    let Inst{19-16} = imm;
8054  }
8055
8056  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8057                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
8058              [(set (v2i32 V64:$dst),
8059                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8060                        (i32 vecshiftR32:$imm)))]> {
8061    bits<5> imm;
8062    let Inst{20-16} = imm;
8063  }
8064
8065  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8066                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
8067            [(set (v4i32 V128:$dst),
8068              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8069                      (i32 vecshiftR32:$imm)))]> {
8070    bits<5> imm;
8071    let Inst{20-16} = imm;
8072  }
8073
8074  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8075                                  V128, V128, vecshiftR64,
8076                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8077              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8078                      (i32 vecshiftR64:$imm)))]> {
8079    bits<6> imm;
8080    let Inst{21-16} = imm;
8081  }
8082}
8083
8084multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
8085                                    SDPatternOperator OpNode = null_frag> {
8086  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8087                                  V64, V64, vecshiftL8,
8088                                  asm, ".8b", ".8b",
8089                    [(set (v8i8 V64:$dst),
8090                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8091                                  (i32 vecshiftL8:$imm)))]> {
8092    bits<3> imm;
8093    let Inst{18-16} = imm;
8094  }
8095
8096  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8097                                  V128, V128, vecshiftL8,
8098                                  asm, ".16b", ".16b",
8099                    [(set (v16i8 V128:$dst),
8100                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8101                                  (i32 vecshiftL8:$imm)))]> {
8102    bits<3> imm;
8103    let Inst{18-16} = imm;
8104  }
8105
8106  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8107                                  V64, V64, vecshiftL16,
8108                                  asm, ".4h", ".4h",
8109                    [(set (v4i16 V64:$dst),
8110                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8111                                   (i32 vecshiftL16:$imm)))]> {
8112    bits<4> imm;
8113    let Inst{19-16} = imm;
8114  }
8115
8116  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8117                                  V128, V128, vecshiftL16,
8118                                  asm, ".8h", ".8h",
8119                    [(set (v8i16 V128:$dst),
8120                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8121                                  (i32 vecshiftL16:$imm)))]> {
8122    bits<4> imm;
8123    let Inst{19-16} = imm;
8124  }
8125
8126  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8127                                  V64, V64, vecshiftL32,
8128                                  asm, ".2s", ".2s",
8129                    [(set (v2i32 V64:$dst),
8130                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8131                                  (i32 vecshiftL32:$imm)))]> {
8132    bits<5> imm;
8133    let Inst{20-16} = imm;
8134  }
8135
8136  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8137                                  V128, V128, vecshiftL32,
8138                                  asm, ".4s", ".4s",
8139                    [(set (v4i32 V128:$dst),
8140                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8141                                  (i32 vecshiftL32:$imm)))]> {
8142    bits<5> imm;
8143    let Inst{20-16} = imm;
8144  }
8145
8146  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8147                                  V128, V128, vecshiftL64,
8148                                  asm, ".2d", ".2d",
8149                    [(set (v2i64 V128:$dst),
8150                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8151                                  (i32 vecshiftL64:$imm)))]> {
8152    bits<6> imm;
8153    let Inst{21-16} = imm;
8154  }
8155}
8156
8157multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
8158                                   SDPatternOperator OpNode> {
8159  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8160                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
8161      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
8162    bits<3> imm;
8163    let Inst{18-16} = imm;
8164  }
8165
8166  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8167                                  V128, V128, vecshiftL8,
8168                                  asm#"2", ".8h", ".16b",
8169      [(set (v8i16 V128:$Rd),
8170            (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
8171    bits<3> imm;
8172    let Inst{18-16} = imm;
8173  }
8174
8175  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8176                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
8177      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
8178    bits<4> imm;
8179    let Inst{19-16} = imm;
8180  }
8181
8182  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8183                                  V128, V128, vecshiftL16,
8184                                  asm#"2", ".4s", ".8h",
8185      [(set (v4i32 V128:$Rd),
8186            (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
8187
8188    bits<4> imm;
8189    let Inst{19-16} = imm;
8190  }
8191
8192  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8193                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
8194      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
8195    bits<5> imm;
8196    let Inst{20-16} = imm;
8197  }
8198
8199  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8200                                  V128, V128, vecshiftL32,
8201                                  asm#"2", ".2d", ".4s",
8202      [(set (v2i64 V128:$Rd),
8203            (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
8204    bits<5> imm;
8205    let Inst{20-16} = imm;
8206  }
8207}
8208
8209
8210//---
8211// Vector load/store
8212//---
8213// SIMD ldX/stX no-index memory references don't allow the optional
8214// ", #0" constant and handle post-indexing explicitly, so we use
8215// a more specialized parse method for them. Otherwise, it's the same as
8216// the general GPR64sp handling.
8217
8218class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
8219                   string asm, dag oops, dag iops, list<dag> pattern>
8220  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
8221  bits<5> Vt;
8222  bits<5> Rn;
8223  let Inst{31} = 0;
8224  let Inst{30} = Q;
8225  let Inst{29-23} = 0b0011000;
8226  let Inst{22} = L;
8227  let Inst{21-16} = 0b000000;
8228  let Inst{15-12} = opcode;
8229  let Inst{11-10} = size;
8230  let Inst{9-5} = Rn;
8231  let Inst{4-0} = Vt;
8232}
8233
8234class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
8235                       string asm, dag oops, dag iops>
8236  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
8237  bits<5> Vt;
8238  bits<5> Rn;
8239  bits<5> Xm;
8240  let Inst{31} = 0;
8241  let Inst{30} = Q;
8242  let Inst{29-23} = 0b0011001;
8243  let Inst{22} = L;
8244  let Inst{21} = 0;
8245  let Inst{20-16} = Xm;
8246  let Inst{15-12} = opcode;
8247  let Inst{11-10} = size;
8248  let Inst{9-5} = Rn;
8249  let Inst{4-0} = Vt;
8250}
8251
8252// The immediate form of AdvSIMD post-indexed addressing is encoded with
8253// register post-index addressing from the zero register.
8254multiclass SIMDLdStAliases<string asm, string layout, string Count,
8255                           int Offset, int Size> {
8256  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
8257  //      "ld1\t$Vt, [$Rn], #16"
8258  // may get mapped to
8259  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
8260  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8261                  (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8262                      GPR64sp:$Rn,
8263                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8264                      XZR), 1>;
8265
8266  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
8267  //      "ld1.8b\t$Vt, [$Rn], #16"
8268  // may get mapped to
8269  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
8270  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8271                  (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8272                      GPR64sp:$Rn,
8273                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8274                      XZR), 0>;
8275
8276  // E.g. "ld1.8b { v0, v1 }, [x1]"
8277  //      "ld1\t$Vt, [$Rn]"
8278  // may get mapped to
8279  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
8280  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8281                  (!cast<Instruction>(NAME # Count # "v" # layout)
8282                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8283                      GPR64sp:$Rn), 0>;
8284
8285  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
8286  //      "ld1\t$Vt, [$Rn], $Xm"
8287  // may get mapped to
8288  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
8289  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8290                  (!cast<Instruction>(NAME # Count # "v" # layout # "_POST")
8291                      GPR64sp:$Rn,
8292                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8293                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8294}
8295
8296multiclass BaseSIMDLdN<string Count, string asm, string veclist, int Offset128,
8297                       int Offset64, bits<4> opcode> {
8298  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8299    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
8300                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
8301                           (ins GPR64sp:$Rn), []>;
8302    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
8303                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
8304                           (ins GPR64sp:$Rn), []>;
8305    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
8306                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
8307                           (ins GPR64sp:$Rn), []>;
8308    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
8309                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
8310                           (ins GPR64sp:$Rn), []>;
8311    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
8312                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
8313                           (ins GPR64sp:$Rn), []>;
8314    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
8315                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
8316                           (ins GPR64sp:$Rn), []>;
8317    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
8318                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
8319                           (ins GPR64sp:$Rn), []>;
8320
8321
8322    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
8323                       (outs GPR64sp:$wback,
8324                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
8325                       (ins GPR64sp:$Rn,
8326                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8327    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
8328                       (outs GPR64sp:$wback,
8329                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
8330                       (ins GPR64sp:$Rn,
8331                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8332    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
8333                       (outs GPR64sp:$wback,
8334                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
8335                       (ins GPR64sp:$Rn,
8336                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8337    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
8338                       (outs GPR64sp:$wback,
8339                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
8340                       (ins GPR64sp:$Rn,
8341                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8342    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
8343                       (outs GPR64sp:$wback,
8344                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
8345                       (ins GPR64sp:$Rn,
8346                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8347    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
8348                       (outs GPR64sp:$wback,
8349                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
8350                       (ins GPR64sp:$Rn,
8351                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8352    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
8353                       (outs GPR64sp:$wback,
8354                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
8355                       (ins GPR64sp:$Rn,
8356                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8357  }
8358
8359  defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8360  defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8361  defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8362  defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8363  defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8364  defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8365  defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8366}
8367
8368// Only ld1/st1 has a v1d version.
8369multiclass BaseSIMDStN<string Count, string asm, string veclist, int Offset128,
8370                       int Offset64, bits<4> opcode> {
8371  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
8372    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
8373                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8374                                 GPR64sp:$Rn), []>;
8375    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
8376                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8377                                GPR64sp:$Rn), []>;
8378    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
8379                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8380                                GPR64sp:$Rn), []>;
8381    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
8382                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8383                                GPR64sp:$Rn), []>;
8384    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
8385                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8386                                GPR64sp:$Rn), []>;
8387    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
8388                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8389                                GPR64sp:$Rn), []>;
8390    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
8391                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8392                                GPR64sp:$Rn), []>;
8393
8394    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
8395                       (outs GPR64sp:$wback),
8396                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
8397                            GPR64sp:$Rn,
8398                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8399    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
8400                       (outs GPR64sp:$wback),
8401                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
8402                            GPR64sp:$Rn,
8403                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8404    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
8405                       (outs GPR64sp:$wback),
8406                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
8407                            GPR64sp:$Rn,
8408                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8409    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
8410                       (outs GPR64sp:$wback),
8411                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
8412                            GPR64sp:$Rn,
8413                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
8414    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
8415                       (outs GPR64sp:$wback),
8416                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
8417                            GPR64sp:$Rn,
8418                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8419    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
8420                       (outs GPR64sp:$wback),
8421                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
8422                            GPR64sp:$Rn,
8423                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8424    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
8425                       (outs GPR64sp:$wback),
8426                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
8427                            GPR64sp:$Rn,
8428                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8429  }
8430
8431  defm : SIMDLdStAliases<asm, "16b", Count, Offset128, 128>;
8432  defm : SIMDLdStAliases<asm, "8h", Count, Offset128, 128>;
8433  defm : SIMDLdStAliases<asm, "4s", Count, Offset128, 128>;
8434  defm : SIMDLdStAliases<asm, "2d", Count, Offset128, 128>;
8435  defm : SIMDLdStAliases<asm, "8b", Count, Offset64, 64>;
8436  defm : SIMDLdStAliases<asm, "4h", Count, Offset64, 64>;
8437  defm : SIMDLdStAliases<asm, "2s", Count, Offset64, 64>;
8438}
8439
8440multiclass BaseSIMDLd1<string Count, string asm, string veclist,
8441                       int Offset128, int Offset64, bits<4> opcode>
8442  : BaseSIMDLdN<Count, asm, veclist, Offset128, Offset64, opcode> {
8443
8444  // LD1 instructions have extra "1d" variants.
8445  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
8446    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
8447                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
8448                           (ins GPR64sp:$Rn), []>;
8449
8450    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
8451                       (outs GPR64sp:$wback,
8452                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
8453                       (ins GPR64sp:$Rn,
8454                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8455  }
8456
8457  defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8458}
8459
8460multiclass BaseSIMDSt1<string Count, string asm, string veclist,
8461                       int Offset128, int Offset64, bits<4> opcode>
8462  : BaseSIMDStN<Count, asm, veclist, Offset128, Offset64, opcode> {
8463
8464  // ST1 instructions have extra "1d" variants.
8465  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
8466    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
8467                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8468                                GPR64sp:$Rn), []>;
8469
8470    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
8471                       (outs GPR64sp:$wback),
8472                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
8473                            GPR64sp:$Rn,
8474                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
8475  }
8476
8477  defm : SIMDLdStAliases<asm, "1d", Count, Offset64, 64>;
8478}
8479
8480multiclass SIMDLd1Multiple<string asm> {
8481  defm One   : BaseSIMDLd1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8482  defm Two   : BaseSIMDLd1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8483  defm Three : BaseSIMDLd1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8484  defm Four  : BaseSIMDLd1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8485}
8486
8487multiclass SIMDSt1Multiple<string asm> {
8488  defm One   : BaseSIMDSt1<"One", asm, "VecListOne", 16, 8,  0b0111>;
8489  defm Two   : BaseSIMDSt1<"Two", asm, "VecListTwo", 32, 16, 0b1010>;
8490  defm Three : BaseSIMDSt1<"Three", asm, "VecListThree", 48, 24, 0b0110>;
8491  defm Four  : BaseSIMDSt1<"Four", asm, "VecListFour", 64, 32, 0b0010>;
8492}
8493
8494multiclass SIMDLd2Multiple<string asm> {
8495  defm Two : BaseSIMDLdN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8496}
8497
8498multiclass SIMDSt2Multiple<string asm> {
8499  defm Two : BaseSIMDStN<"Two", asm, "VecListTwo", 32, 16, 0b1000>;
8500}
8501
8502multiclass SIMDLd3Multiple<string asm> {
8503  defm Three : BaseSIMDLdN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8504}
8505
8506multiclass SIMDSt3Multiple<string asm> {
8507  defm Three : BaseSIMDStN<"Three", asm, "VecListThree", 48, 24, 0b0100>;
8508}
8509
8510multiclass SIMDLd4Multiple<string asm> {
8511  defm Four : BaseSIMDLdN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8512}
8513
8514multiclass SIMDSt4Multiple<string asm> {
8515  defm Four : BaseSIMDStN<"Four", asm, "VecListFour", 64, 32, 0b0000>;
8516}
8517
8518//---
8519// AdvSIMD Load/store single-element
8520//---
8521
8522class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
8523                         string asm, string operands, string cst,
8524                         dag oops, dag iops, list<dag> pattern>
8525  : I<oops, iops, asm, operands, cst, pattern> {
8526  bits<5> Vt;
8527  bits<5> Rn;
8528  let Inst{31} = 0;
8529  let Inst{29-24} = 0b001101;
8530  let Inst{22} = L;
8531  let Inst{21} = R;
8532  let Inst{15-13} = opcode;
8533  let Inst{9-5} = Rn;
8534  let Inst{4-0} = Vt;
8535}
8536
8537class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
8538                         string asm, string operands, string cst,
8539                         dag oops, dag iops, list<dag> pattern>
8540  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
8541  bits<5> Vt;
8542  bits<5> Rn;
8543  let Inst{31} = 0;
8544  let Inst{29-24} = 0b001101;
8545  let Inst{22} = L;
8546  let Inst{21} = R;
8547  let Inst{15-13} = opcode;
8548  let Inst{9-5} = Rn;
8549  let Inst{4-0} = Vt;
8550}
8551
8552
8553let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8554class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
8555                  Operand listtype>
8556  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
8557                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
8558                       []> {
8559  let Inst{30} = Q;
8560  let Inst{23} = 0;
8561  let Inst{20-16} = 0b00000;
8562  let Inst{12} = S;
8563  let Inst{11-10} = size;
8564}
8565let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8566class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
8567                      string asm, Operand listtype, Operand GPR64pi>
8568  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
8569                       "$Rn = $wback",
8570                       (outs GPR64sp:$wback, listtype:$Vt),
8571                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
8572  bits<5> Xm;
8573  let Inst{30} = Q;
8574  let Inst{23} = 1;
8575  let Inst{20-16} = Xm;
8576  let Inst{12} = S;
8577  let Inst{11-10} = size;
8578}
8579
8580multiclass SIMDLdrAliases<string asm, string layout, string Count,
8581                          int Offset, int Size> {
8582  // E.g. "ld1r { v0.8b }, [x1], #1"
8583  //      "ld1r.8b\t$Vt, [$Rn], #1"
8584  // may get mapped to
8585  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8586  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
8587                  (!cast<Instruction>(NAME # "v" # layout # "_POST")
8588                      GPR64sp:$Rn,
8589                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8590                      XZR), 1>;
8591
8592  // E.g. "ld1r.8b { v0 }, [x1], #1"
8593  //      "ld1r.8b\t$Vt, [$Rn], #1"
8594  // may get mapped to
8595  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
8596  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
8597                  (!cast<Instruction>(NAME # "v" # layout # "_POST")
8598                      GPR64sp:$Rn,
8599                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8600                      XZR), 0>;
8601
8602  // E.g. "ld1r.8b { v0 }, [x1]"
8603  //      "ld1r.8b\t$Vt, [$Rn]"
8604  // may get mapped to
8605  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
8606  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
8607                  (!cast<Instruction>(NAME # "v" # layout)
8608                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8609                      GPR64sp:$Rn), 0>;
8610
8611  // E.g. "ld1r.8b { v0 }, [x1], x2"
8612  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
8613  // may get mapped to
8614  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
8615  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
8616                  (!cast<Instruction>(NAME # "v" # layout # "_POST")
8617                      GPR64sp:$Rn,
8618                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
8619                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
8620}
8621
8622multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
8623  int Offset1, int Offset2, int Offset4, int Offset8> {
8624  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
8625                        !cast<Operand>("VecList" # Count # "8b")>;
8626  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
8627                        !cast<Operand>("VecList" # Count #"16b")>;
8628  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
8629                        !cast<Operand>("VecList" # Count #"4h")>;
8630  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
8631                        !cast<Operand>("VecList" # Count #"8h")>;
8632  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
8633                        !cast<Operand>("VecList" # Count #"2s")>;
8634  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
8635                        !cast<Operand>("VecList" # Count #"4s")>;
8636  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
8637                        !cast<Operand>("VecList" # Count #"1d")>;
8638  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
8639                        !cast<Operand>("VecList" # Count #"2d")>;
8640
8641  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
8642                                 !cast<Operand>("VecList" # Count # "8b"),
8643                                 !cast<Operand>("GPR64pi" # Offset1)>;
8644  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
8645                                 !cast<Operand>("VecList" # Count # "16b"),
8646                                 !cast<Operand>("GPR64pi" # Offset1)>;
8647  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
8648                                 !cast<Operand>("VecList" # Count # "4h"),
8649                                 !cast<Operand>("GPR64pi" # Offset2)>;
8650  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
8651                                 !cast<Operand>("VecList" # Count # "8h"),
8652                                 !cast<Operand>("GPR64pi" # Offset2)>;
8653  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
8654                                 !cast<Operand>("VecList" # Count # "2s"),
8655                                 !cast<Operand>("GPR64pi" # Offset4)>;
8656  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
8657                                 !cast<Operand>("VecList" # Count # "4s"),
8658                                 !cast<Operand>("GPR64pi" # Offset4)>;
8659  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
8660                                 !cast<Operand>("VecList" # Count # "1d"),
8661                                 !cast<Operand>("GPR64pi" # Offset8)>;
8662  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
8663                                 !cast<Operand>("VecList" # Count # "2d"),
8664                                 !cast<Operand>("GPR64pi" # Offset8)>;
8665
8666  defm : SIMDLdrAliases<asm, "8b",  Count, Offset1,  64>;
8667  defm : SIMDLdrAliases<asm, "16b", Count, Offset1, 128>;
8668  defm : SIMDLdrAliases<asm, "4h",  Count, Offset2,  64>;
8669  defm : SIMDLdrAliases<asm, "8h",  Count, Offset2, 128>;
8670  defm : SIMDLdrAliases<asm, "2s",  Count, Offset4,  64>;
8671  defm : SIMDLdrAliases<asm, "4s",  Count, Offset4, 128>;
8672  defm : SIMDLdrAliases<asm, "1d",  Count, Offset8,  64>;
8673  defm : SIMDLdrAliases<asm, "2d",  Count, Offset8, 128>;
8674}
8675
8676class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
8677                      dag oops, dag iops, list<dag> pattern>
8678  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8679                       pattern> {
8680  // idx encoded in Q:S:size fields.
8681  bits<4> idx;
8682  let Inst{30} = idx{3};
8683  let Inst{23} = 0;
8684  let Inst{20-16} = 0b00000;
8685  let Inst{12} = idx{2};
8686  let Inst{11-10} = idx{1-0};
8687}
8688class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
8689                      dag oops, dag iops, list<dag> pattern>
8690  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8691                           oops, iops, pattern> {
8692  // idx encoded in Q:S:size fields.
8693  bits<4> idx;
8694  let Inst{30} = idx{3};
8695  let Inst{23} = 0;
8696  let Inst{20-16} = 0b00000;
8697  let Inst{12} = idx{2};
8698  let Inst{11-10} = idx{1-0};
8699}
8700class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
8701                          dag oops, dag iops>
8702  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8703                       "$Rn = $wback", oops, iops, []> {
8704  // idx encoded in Q:S:size fields.
8705  bits<4> idx;
8706  bits<5> Xm;
8707  let Inst{30} = idx{3};
8708  let Inst{23} = 1;
8709  let Inst{20-16} = Xm;
8710  let Inst{12} = idx{2};
8711  let Inst{11-10} = idx{1-0};
8712}
8713class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
8714                          dag oops, dag iops>
8715  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8716                           "$Rn = $wback", oops, iops, []> {
8717  // idx encoded in Q:S:size fields.
8718  bits<4> idx;
8719  bits<5> Xm;
8720  let Inst{30} = idx{3};
8721  let Inst{23} = 1;
8722  let Inst{20-16} = Xm;
8723  let Inst{12} = idx{2};
8724  let Inst{11-10} = idx{1-0};
8725}
8726
8727class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
8728                      dag oops, dag iops, list<dag> pattern>
8729  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8730                       pattern> {
8731  // idx encoded in Q:S:size<1> fields.
8732  bits<3> idx;
8733  let Inst{30} = idx{2};
8734  let Inst{23} = 0;
8735  let Inst{20-16} = 0b00000;
8736  let Inst{12} = idx{1};
8737  let Inst{11} = idx{0};
8738  let Inst{10} = size;
8739}
8740class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
8741                      dag oops, dag iops, list<dag> pattern>
8742  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8743                           oops, iops, pattern> {
8744  // idx encoded in Q:S:size<1> fields.
8745  bits<3> idx;
8746  let Inst{30} = idx{2};
8747  let Inst{23} = 0;
8748  let Inst{20-16} = 0b00000;
8749  let Inst{12} = idx{1};
8750  let Inst{11} = idx{0};
8751  let Inst{10} = size;
8752}
8753
8754class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8755                          dag oops, dag iops>
8756  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8757                       "$Rn = $wback", oops, iops, []> {
8758  // idx encoded in Q:S:size<1> fields.
8759  bits<3> idx;
8760  bits<5> Xm;
8761  let Inst{30} = idx{2};
8762  let Inst{23} = 1;
8763  let Inst{20-16} = Xm;
8764  let Inst{12} = idx{1};
8765  let Inst{11} = idx{0};
8766  let Inst{10} = size;
8767}
8768class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
8769                          dag oops, dag iops>
8770  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8771                           "$Rn = $wback", oops, iops, []> {
8772  // idx encoded in Q:S:size<1> fields.
8773  bits<3> idx;
8774  bits<5> Xm;
8775  let Inst{30} = idx{2};
8776  let Inst{23} = 1;
8777  let Inst{20-16} = Xm;
8778  let Inst{12} = idx{1};
8779  let Inst{11} = idx{0};
8780  let Inst{10} = size;
8781}
8782class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8783                      dag oops, dag iops, list<dag> pattern>
8784  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8785                       pattern> {
8786  // idx encoded in Q:S fields.
8787  bits<2> idx;
8788  let Inst{30} = idx{1};
8789  let Inst{23} = 0;
8790  let Inst{20-16} = 0b00000;
8791  let Inst{12} = idx{0};
8792  let Inst{11-10} = size;
8793}
8794class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8795                      dag oops, dag iops, list<dag> pattern>
8796  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8797                           oops, iops, pattern> {
8798  // idx encoded in Q:S fields.
8799  bits<2> idx;
8800  let Inst{30} = idx{1};
8801  let Inst{23} = 0;
8802  let Inst{20-16} = 0b00000;
8803  let Inst{12} = idx{0};
8804  let Inst{11-10} = size;
8805}
8806class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
8807                          string asm, dag oops, dag iops>
8808  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8809                       "$Rn = $wback", oops, iops, []> {
8810  // idx encoded in Q:S fields.
8811  bits<2> idx;
8812  bits<5> Xm;
8813  let Inst{30} = idx{1};
8814  let Inst{23} = 1;
8815  let Inst{20-16} = Xm;
8816  let Inst{12} = idx{0};
8817  let Inst{11-10} = size;
8818}
8819class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8820                          string asm, dag oops, dag iops>
8821  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8822                           "$Rn = $wback", oops, iops, []> {
8823  // idx encoded in Q:S fields.
8824  bits<2> idx;
8825  bits<5> Xm;
8826  let Inst{30} = idx{1};
8827  let Inst{23} = 1;
8828  let Inst{20-16} = Xm;
8829  let Inst{12} = idx{0};
8830  let Inst{11-10} = size;
8831}
8832class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8833                      dag oops, dag iops, list<dag> pattern>
8834  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
8835                       pattern> {
8836  // idx encoded in Q field.
8837  bits<1> idx;
8838  let Inst{30} = idx;
8839  let Inst{23} = 0;
8840  let Inst{20-16} = 0b00000;
8841  let Inst{12} = 0;
8842  let Inst{11-10} = size;
8843}
8844class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
8845                      dag oops, dag iops, list<dag> pattern>
8846  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
8847                           oops, iops, pattern> {
8848  // idx encoded in Q field.
8849  bits<1> idx;
8850  let Inst{30} = idx;
8851  let Inst{23} = 0;
8852  let Inst{20-16} = 0b00000;
8853  let Inst{12} = 0;
8854  let Inst{11-10} = size;
8855}
8856class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
8857                          string asm, dag oops, dag iops>
8858  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8859                       "$Rn = $wback", oops, iops, []> {
8860  // idx encoded in Q field.
8861  bits<1> idx;
8862  bits<5> Xm;
8863  let Inst{30} = idx;
8864  let Inst{23} = 1;
8865  let Inst{20-16} = Xm;
8866  let Inst{12} = 0;
8867  let Inst{11-10} = size;
8868}
8869class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
8870                          string asm, dag oops, dag iops>
8871  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
8872                           "$Rn = $wback", oops, iops, []> {
8873  // idx encoded in Q field.
8874  bits<1> idx;
8875  bits<5> Xm;
8876  let Inst{30} = idx;
8877  let Inst{23} = 1;
8878  let Inst{20-16} = Xm;
8879  let Inst{12} = 0;
8880  let Inst{11-10} = size;
8881}
8882
8883let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8884multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
8885                         RegisterOperand listtype,
8886                         RegisterOperand GPR64pi> {
8887  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
8888                           (outs listtype:$dst),
8889                           (ins listtype:$Vt, VectorIndexB:$idx,
8890                                GPR64sp:$Rn), []>;
8891
8892  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
8893                            (outs GPR64sp:$wback, listtype:$dst),
8894                            (ins listtype:$Vt, VectorIndexB:$idx,
8895                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
8896}
8897let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8898multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
8899                         RegisterOperand listtype,
8900                         RegisterOperand GPR64pi> {
8901  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
8902                            (outs listtype:$dst),
8903                            (ins listtype:$Vt, VectorIndexH:$idx,
8904                                 GPR64sp:$Rn), []>;
8905
8906  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
8907                            (outs GPR64sp:$wback, listtype:$dst),
8908                            (ins listtype:$Vt, VectorIndexH:$idx,
8909                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
8910}
8911let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8912multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
8913                         RegisterOperand listtype,
8914                         RegisterOperand GPR64pi> {
8915  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
8916                            (outs listtype:$dst),
8917                            (ins listtype:$Vt, VectorIndexS:$idx,
8918                                 GPR64sp:$Rn), []>;
8919
8920  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
8921                            (outs GPR64sp:$wback, listtype:$dst),
8922                            (ins listtype:$Vt, VectorIndexS:$idx,
8923                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
8924}
8925let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
8926multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
8927                         RegisterOperand listtype, RegisterOperand GPR64pi> {
8928  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
8929                            (outs listtype:$dst),
8930                            (ins listtype:$Vt, VectorIndexD:$idx,
8931                                 GPR64sp:$Rn), []>;
8932
8933  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
8934                            (outs GPR64sp:$wback, listtype:$dst),
8935                            (ins listtype:$Vt, VectorIndexD:$idx,
8936                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
8937}
8938let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8939multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
8940                         RegisterOperand listtype, RegisterOperand GPR64pi> {
8941  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
8942                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
8943                                        GPR64sp:$Rn), []>;
8944
8945  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
8946                                    (outs GPR64sp:$wback),
8947                                    (ins listtype:$Vt, VectorIndexB:$idx,
8948                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
8949}
8950let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8951multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
8952                         RegisterOperand listtype, RegisterOperand GPR64pi> {
8953  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
8954                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
8955                                         GPR64sp:$Rn), []>;
8956
8957  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
8958                            (outs GPR64sp:$wback),
8959                            (ins listtype:$Vt, VectorIndexH:$idx,
8960                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
8961}
8962let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8963multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
8964                         RegisterOperand listtype, RegisterOperand GPR64pi> {
8965  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
8966                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
8967                                         GPR64sp:$Rn), []>;
8968
8969  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
8970                            (outs GPR64sp:$wback),
8971                            (ins listtype:$Vt, VectorIndexS:$idx,
8972                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
8973}
8974let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
8975multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
8976                         RegisterOperand listtype, RegisterOperand GPR64pi> {
8977  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
8978                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
8979                                         GPR64sp:$Rn), []>;
8980
8981  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
8982                            (outs GPR64sp:$wback),
8983                            (ins listtype:$Vt, VectorIndexD:$idx,
8984                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
8985}
8986
8987multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
8988                                 string Count, int Offset, Operand idxtype> {
8989  // E.g. "ld1 { v0.8b }[0], [x1], #1"
8990  //      "ld1\t$Vt, [$Rn], #1"
8991  // may get mapped to
8992  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
8993  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
8994                  (!cast<Instruction>(NAME # Type  # "_POST")
8995                      GPR64sp:$Rn,
8996                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
8997                      idxtype:$idx, XZR), 1>;
8998
8999  // E.g. "ld1.8b { v0 }[0], [x1], #1"
9000  //      "ld1.8b\t$Vt, [$Rn], #1"
9001  // may get mapped to
9002  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9003  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9004                  (!cast<Instruction>(NAME # Type # "_POST")
9005                      GPR64sp:$Rn,
9006                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9007                      idxtype:$idx, XZR), 0>;
9008
9009  // E.g. "ld1.8b { v0 }[0], [x1]"
9010  //      "ld1.8b\t$Vt, [$Rn]"
9011  // may get mapped to
9012  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9013  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9014                      (!cast<Instruction>(NAME # Type)
9015                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9016                         idxtype:$idx, GPR64sp:$Rn), 0>;
9017
9018  // E.g. "ld1.8b { v0 }[0], [x1], x2"
9019  //      "ld1.8b\t$Vt, [$Rn], $Xm"
9020  // may get mapped to
9021  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9022  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9023                      (!cast<Instruction>(NAME # Type # "_POST")
9024                         GPR64sp:$Rn,
9025                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9026                         idxtype:$idx,
9027                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9028}
9029
9030multiclass SIMDLdSt1SingleAliases<string asm> {
9031  defm : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
9032  defm : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9033  defm : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9034  defm : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9035}
9036
9037multiclass SIMDLdSt2SingleAliases<string asm> {
9038  defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
9039  defm : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
9040  defm : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
9041  defm : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9042}
9043
9044multiclass SIMDLdSt3SingleAliases<string asm> {
9045  defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
9046  defm : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
9047  defm : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9048  defm : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9049}
9050
9051multiclass SIMDLdSt4SingleAliases<string asm> {
9052  defm : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
9053  defm : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
9054  defm : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9055  defm : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9056}
9057} // end of 'let Predicates = [HasNEON]'
9058
9059//----------------------------------------------------------------------------
9060// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9061//----------------------------------------------------------------------------
9062
9063let Predicates = [HasNEON, HasV8_1a] in {
9064
9065class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9066                                    RegisterOperand regtype, string asm,
9067                                    string kind, list<dag> pattern>
9068  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9069                                pattern> {
9070}
9071multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9072                                             SDPatternOperator Accum> {
9073  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9074    [(set (v4i16 V64:$dst),
9075          (Accum (v4i16 V64:$Rd),
9076                 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9077                                                   (v4i16 V64:$Rm)))))]>;
9078  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
9079    [(set (v8i16 V128:$dst),
9080          (Accum (v8i16 V128:$Rd),
9081                 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
9082                                                   (v8i16 V128:$Rm)))))]>;
9083  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
9084    [(set (v2i32 V64:$dst),
9085          (Accum (v2i32 V64:$Rd),
9086                 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
9087                                                   (v2i32 V64:$Rm)))))]>;
9088  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
9089    [(set (v4i32 V128:$dst),
9090          (Accum (v4i32 V128:$Rd),
9091                 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
9092                                                   (v4i32 V128:$Rm)))))]>;
9093}
9094
9095multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
9096                                     SDPatternOperator Accum> {
9097  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9098                                          V64, V64, V128_lo, VectorIndexH,
9099                                          asm, ".4h", ".4h", ".4h", ".h",
9100    [(set (v4i16 V64:$dst),
9101          (Accum (v4i16 V64:$Rd),
9102                 (v4i16 (int_aarch64_neon_sqrdmulh
9103                          (v4i16 V64:$Rn),
9104                          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9105                                                    VectorIndexH:$idx))))))]> {
9106    bits<3> idx;
9107    let Inst{11} = idx{2};
9108    let Inst{21} = idx{1};
9109    let Inst{20} = idx{0};
9110  }
9111
9112  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9113                                          V128, V128, V128_lo, VectorIndexH,
9114                                          asm, ".8h", ".8h", ".8h", ".h",
9115    [(set (v8i16 V128:$dst),
9116          (Accum (v8i16 V128:$Rd),
9117                 (v8i16 (int_aarch64_neon_sqrdmulh
9118                          (v8i16 V128:$Rn),
9119                          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
9120                                                   VectorIndexH:$idx))))))]> {
9121    bits<3> idx;
9122    let Inst{11} = idx{2};
9123    let Inst{21} = idx{1};
9124    let Inst{20} = idx{0};
9125  }
9126
9127  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9128                                          V64, V64, V128, VectorIndexS,
9129                                          asm, ".2s", ".2s", ".2s", ".s",
9130    [(set (v2i32 V64:$dst),
9131        (Accum (v2i32 V64:$Rd),
9132               (v2i32 (int_aarch64_neon_sqrdmulh
9133                        (v2i32 V64:$Rn),
9134                        (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
9135                                                 VectorIndexS:$idx))))))]> {
9136    bits<2> idx;
9137    let Inst{11} = idx{1};
9138    let Inst{21} = idx{0};
9139  }
9140
9141  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9142  // an intermediate EXTRACT_SUBREG would be untyped.
9143  // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
9144  // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
9145  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9146                       (i32 (vector_extract
9147                               (v4i32 (insert_subvector
9148                                       (undef),
9149                                        (v2i32 (int_aarch64_neon_sqrdmulh
9150                                                 (v2i32 V64:$Rn),
9151                                                 (v2i32 (AArch64duplane32
9152                                                          (v4i32 V128:$Rm),
9153                                                          VectorIndexS:$idx)))),
9154                                      (i32 0))),
9155                               (i64 0))))),
9156            (EXTRACT_SUBREG
9157                (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
9158                          (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
9159                                                FPR32Op:$Rd,
9160                                                ssub)),
9161                          V64:$Rn,
9162                          V128:$Rm,
9163                          VectorIndexS:$idx)),
9164                ssub)>;
9165
9166  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9167                                          V128, V128, V128, VectorIndexS,
9168                                          asm, ".4s", ".4s", ".4s", ".s",
9169    [(set (v4i32 V128:$dst),
9170          (Accum (v4i32 V128:$Rd),
9171                 (v4i32 (int_aarch64_neon_sqrdmulh
9172                          (v4i32 V128:$Rn),
9173                          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
9174                                                   VectorIndexS:$idx))))))]> {
9175    bits<2> idx;
9176    let Inst{11} = idx{1};
9177    let Inst{21} = idx{0};
9178  }
9179
9180  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
9181  // an intermediate EXTRACT_SUBREG would be untyped.
9182  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9183                        (i32 (vector_extract
9184                               (v4i32 (int_aarch64_neon_sqrdmulh
9185                                        (v4i32 V128:$Rn),
9186                                        (v4i32 (AArch64duplane32
9187                                                 (v4i32 V128:$Rm),
9188                                                 VectorIndexS:$idx)))),
9189                               (i64 0))))),
9190            (EXTRACT_SUBREG
9191                (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
9192                         (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
9193                                               FPR32Op:$Rd,
9194                                               ssub)),
9195                         V128:$Rn,
9196                         V128:$Rm,
9197                         VectorIndexS:$idx)),
9198                ssub)>;
9199
9200  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9201                                        FPR16Op, FPR16Op, V128_lo,
9202                                        VectorIndexH, asm, ".h", "", "", ".h",
9203                                        []> {
9204    bits<3> idx;
9205    let Inst{11} = idx{2};
9206    let Inst{21} = idx{1};
9207    let Inst{20} = idx{0};
9208  }
9209
9210  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9211                                        FPR32Op, FPR32Op, V128, VectorIndexS,
9212                                        asm, ".s", "", "", ".s",
9213    [(set (i32 FPR32Op:$dst),
9214          (Accum (i32 FPR32Op:$Rd),
9215                 (i32 (int_aarch64_neon_sqrdmulh
9216                        (i32 FPR32Op:$Rn),
9217                        (i32 (vector_extract (v4i32 V128:$Rm),
9218                                             VectorIndexS:$idx))))))]> {
9219    bits<2> idx;
9220    let Inst{11} = idx{1};
9221    let Inst{21} = idx{0};
9222  }
9223}
9224} // let Predicates = [HasNeon, HasV8_1a]
9225
9226//----------------------------------------------------------------------------
9227// Crypto extensions
9228//----------------------------------------------------------------------------
9229
9230let Predicates = [HasCrypto] in {
9231let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9232class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
9233              list<dag> pat>
9234  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
9235    Sched<[WriteV]>{
9236  bits<5> Rd;
9237  bits<5> Rn;
9238  let Inst{31-16} = 0b0100111000101000;
9239  let Inst{15-12} = opc;
9240  let Inst{11-10} = 0b10;
9241  let Inst{9-5}   = Rn;
9242  let Inst{4-0}   = Rd;
9243}
9244
9245class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
9246  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
9247            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
9248
9249class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
9250  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
9251            "$Rd = $dst",
9252            [(set (v16i8 V128:$dst),
9253                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
9254
9255let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9256class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
9257                     dag oops, dag iops, list<dag> pat>
9258  : I<oops, iops, asm,
9259      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
9260      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
9261    Sched<[WriteV]>{
9262  bits<5> Rd;
9263  bits<5> Rn;
9264  bits<5> Rm;
9265  let Inst{31-21} = 0b01011110000;
9266  let Inst{20-16} = Rm;
9267  let Inst{15}    = 0;
9268  let Inst{14-12} = opc;
9269  let Inst{11-10} = 0b00;
9270  let Inst{9-5}   = Rn;
9271  let Inst{4-0}   = Rd;
9272}
9273
9274class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
9275  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9276                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
9277                   [(set (v4i32 FPR128:$dst),
9278                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
9279                                 (v4i32 V128:$Rm)))]>;
9280
9281class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
9282  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
9283                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
9284                   [(set (v4i32 V128:$dst),
9285                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9286                                 (v4i32 V128:$Rm)))]>;
9287
9288class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
9289  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
9290                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
9291                   [(set (v4i32 FPR128:$dst),
9292                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
9293                                 (v4i32 V128:$Rm)))]>;
9294
9295let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9296class SHA2OpInst<bits<4> opc, string asm, string kind,
9297                 string cstr, dag oops, dag iops,
9298                 list<dag> pat>
9299  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
9300                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
9301    Sched<[WriteV]>{
9302  bits<5> Rd;
9303  bits<5> Rn;
9304  let Inst{31-16} = 0b0101111000101000;
9305  let Inst{15-12} = opc;
9306  let Inst{11-10} = 0b10;
9307  let Inst{9-5}   = Rn;
9308  let Inst{4-0}   = Rd;
9309}
9310
9311class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
9312  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
9313               (ins V128:$Rd, V128:$Rn),
9314               [(set (v4i32 V128:$dst),
9315                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
9316
9317class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
9318  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
9319               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
9320} // end of 'let Predicates = [HasCrypto]'
9321
9322//----------------------------------------------------------------------------
9323// v8.1 atomic instructions extension:
9324// * CAS
9325// * CASP
9326// * SWP
9327// * LDOPregister<OP>, and aliases STOPregister<OP>
9328
9329// Instruction encodings:
9330//
9331//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
9332// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
9333// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
9334// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
9335// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
9336// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
9337
9338// Instruction syntax:
9339//
9340// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9341// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
9342// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
9343// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
9344// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9345// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
9346// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
9347// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
9348// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
9349// ST<OP>{<order>} <Xs>, [<Xn|SP>]
9350
9351let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9352class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
9353                      string cstr, list<dag> pattern>
9354      : I<oops, iops, asm, operands, cstr, pattern> {
9355  bits<2> Sz;
9356  bit NP;
9357  bit Acq;
9358  bit Rel;
9359  bits<5> Rs;
9360  bits<5> Rn;
9361  bits<5> Rt;
9362  let Inst{31-30} = Sz;
9363  let Inst{29-24} = 0b001000;
9364  let Inst{23} = NP;
9365  let Inst{22} = Acq;
9366  let Inst{21} = 0b1;
9367  let Inst{20-16} = Rs;
9368  let Inst{15} = Rel;
9369  let Inst{14-10} = 0b11111;
9370  let Inst{9-5} = Rn;
9371  let Inst{4-0} = Rt;
9372}
9373
9374class BaseCAS<string order, string size, RegisterClass RC>
9375      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9376                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
9377                        "$out = $Rs",[]>,
9378        Sched<[WriteAtomic]> {
9379  let NP = 1;
9380}
9381
9382multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
9383  let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseCAS<order, "b", GPR32>;
9384  let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseCAS<order, "h", GPR32>;
9385  let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseCAS<order, "", GPR32>;
9386  let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseCAS<order, "", GPR64>;
9387}
9388
9389class BaseCASP<string order, string size, RegisterOperand RC>
9390      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
9391                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
9392                        "$out = $Rs",[]>,
9393        Sched<[WriteAtomic]> {
9394  let NP = 0;
9395}
9396
9397multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
9398  let Sz = 0b00, Acq = Acq, Rel = Rel in
9399    def s : BaseCASP<order, "", WSeqPairClassOperand>;
9400  let Sz = 0b01, Acq = Acq, Rel = Rel in
9401    def d : BaseCASP<order, "", XSeqPairClassOperand>;
9402}
9403
9404let Predicates = [HasV8_1a] in
9405class BaseSWP<string order, string size, RegisterClass RC>
9406      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
9407          "\t$Rs, $Rt, [$Rn]","",[]>,
9408        Sched<[WriteAtomic]> {
9409  bits<2> Sz;
9410  bit Acq;
9411  bit Rel;
9412  bits<5> Rs;
9413  bits<3> opc = 0b000;
9414  bits<5> Rn;
9415  bits<5> Rt;
9416  let Inst{31-30} = Sz;
9417  let Inst{29-24} = 0b111000;
9418  let Inst{23} = Acq;
9419  let Inst{22} = Rel;
9420  let Inst{21} = 0b1;
9421  let Inst{20-16} = Rs;
9422  let Inst{15} = 0b1;
9423  let Inst{14-12} = opc;
9424  let Inst{11-10} = 0b00;
9425  let Inst{9-5} = Rn;
9426  let Inst{4-0} = Rt;
9427}
9428
9429multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
9430  let Sz = 0b00, Acq = Acq, Rel = Rel in def b : BaseSWP<order, "b", GPR32>;
9431  let Sz = 0b01, Acq = Acq, Rel = Rel in def h : BaseSWP<order, "h", GPR32>;
9432  let Sz = 0b10, Acq = Acq, Rel = Rel in def s : BaseSWP<order, "", GPR32>;
9433  let Sz = 0b11, Acq = Acq, Rel = Rel in def d : BaseSWP<order, "", GPR64>;
9434}
9435
9436let Predicates = [HasV8_1a], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
9437class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
9438      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
9439          "\t$Rs, $Rt, [$Rn]","",[]>,
9440        Sched<[WriteAtomic]> {
9441  bits<2> Sz;
9442  bit Acq;
9443  bit Rel;
9444  bits<5> Rs;
9445  bits<3> opc;
9446  bits<5> Rn;
9447  bits<5> Rt;
9448  let Inst{31-30} = Sz;
9449  let Inst{29-24} = 0b111000;
9450  let Inst{23} = Acq;
9451  let Inst{22} = Rel;
9452  let Inst{21} = 0b1;
9453  let Inst{20-16} = Rs;
9454  let Inst{15} = 0b0;
9455  let Inst{14-12} = opc;
9456  let Inst{11-10} = 0b00;
9457  let Inst{9-5} = Rn;
9458  let Inst{4-0} = Rt;
9459}
9460
9461multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
9462                        string order> {
9463  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
9464    def b : BaseLDOPregister<op, order, "b", GPR32>;
9465  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
9466    def h : BaseLDOPregister<op, order, "h", GPR32>;
9467  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
9468    def s : BaseLDOPregister<op, order, "", GPR32>;
9469  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
9470    def d : BaseLDOPregister<op, order, "", GPR64>;
9471}
9472
9473let Predicates = [HasV8_1a] in
9474class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
9475                        Instruction inst> :
9476      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
9477
9478multiclass STOPregister<string asm, string instr> {
9479  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
9480                    !cast<Instruction>(instr # "Lb")>;
9481  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
9482                    !cast<Instruction>(instr # "Lh")>;
9483  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
9484                    !cast<Instruction>(instr # "Ls")>;
9485  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
9486                    !cast<Instruction>(instr # "Ld")>;
9487  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
9488                    !cast<Instruction>(instr # "b")>;
9489  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
9490                    !cast<Instruction>(instr # "h")>;
9491  def : BaseSTOPregister<asm,        GPR32, WZR,
9492                    !cast<Instruction>(instr # "s")>;
9493  def : BaseSTOPregister<asm,        GPR64, XZR,
9494                    !cast<Instruction>(instr # "d")>;
9495}
9496
9497//----------------------------------------------------------------------------
9498// Allow the size specifier tokens to be upper case, not just lower.
9499def : TokenAlias<".8B", ".8b">;
9500def : TokenAlias<".4H", ".4h">;
9501def : TokenAlias<".2S", ".2s">;
9502def : TokenAlias<".1D", ".1d">;
9503def : TokenAlias<".16B", ".16b">;
9504def : TokenAlias<".8H", ".8h">;
9505def : TokenAlias<".4S", ".4s">;
9506def : TokenAlias<".2D", ".2d">;
9507def : TokenAlias<".1Q", ".1q">;
9508def : TokenAlias<".2H", ".2h">;
9509def : TokenAlias<".B", ".b">;
9510def : TokenAlias<".H", ".h">;
9511def : TokenAlias<".S", ".s">;
9512def : TokenAlias<".D", ".d">;
9513def : TokenAlias<".Q", ".q">;
9514