1//===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9//===----------------------------------------------------------------------===//
10//  Describe AArch64 instructions format here
11//
12
13// Format specifies the encoding used by the instruction.  This is part of the
14// ad-hoc solution used to emit machine instruction encodings by our machine
15// code emitter.
16class Format<bits<2> val> {
17  bits<2> Value = val;
18}
19
20def PseudoFrm   : Format<0>;
21def NormalFrm   : Format<1>; // Do we need any others?
22
23// Enum describing whether an instruction is
24// destructive in its first source operand.
25class DestructiveInstTypeEnum<bits<4> val> {
26  bits<4> Value = val;
27}
28def NotDestructive                : DestructiveInstTypeEnum<0>;
29// Destructive in its first operand and can be MOVPRFX'd, but has no other
30// special properties.
31def DestructiveOther              : DestructiveInstTypeEnum<1>;
32def DestructiveUnary              : DestructiveInstTypeEnum<2>;
33def DestructiveBinaryImm          : DestructiveInstTypeEnum<3>;
34def DestructiveBinaryShImmUnpred  : DestructiveInstTypeEnum<4>;
35def DestructiveBinary             : DestructiveInstTypeEnum<5>;
36def DestructiveBinaryComm         : DestructiveInstTypeEnum<6>;
37def DestructiveBinaryCommWithRev  : DestructiveInstTypeEnum<7>;
38def DestructiveTernaryCommWithRev : DestructiveInstTypeEnum<8>;
39
40class FalseLanesEnum<bits<2> val> {
41  bits<2> Value = val;
42}
43def FalseLanesNone  : FalseLanesEnum<0>;
44def FalseLanesZero  : FalseLanesEnum<1>;
45def FalseLanesUndef : FalseLanesEnum<2>;
46
47// AArch64 Instruction Format
48class AArch64Inst<Format f, string cstr> : Instruction {
49  field bits<32> Inst; // Instruction encoding.
50  // Mask of bits that cause an encoding to be UNPREDICTABLE.
51  // If a bit is set, then if the corresponding bit in the
52  // target encoding differs from its value in the "Inst" field,
53  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
54  field bits<32> Unpredictable = 0;
55  // SoftFail is the generic name for this field, but we alias it so
56  // as to make it more obvious what it means in ARM-land.
57  field bits<32> SoftFail = Unpredictable;
58  let Namespace   = "AArch64";
59  Format F        = f;
60  bits<2> Form    = F.Value;
61
62  // Defaults
63  bit isWhile = 0;
64  bit isPTestLike = 0;
65  FalseLanesEnum FalseLanes = FalseLanesNone;
66  DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
67  ElementSizeEnum ElementSize = ElementSizeNone;
68
69  let TSFlags{10}  = isPTestLike;
70  let TSFlags{9}   = isWhile;
71  let TSFlags{8-7} = FalseLanes.Value;
72  let TSFlags{6-3} = DestructiveInstType.Value;
73  let TSFlags{2-0} = ElementSize.Value;
74
75  let Pattern     = [];
76  let Constraints = cstr;
77}
78
79class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
80  : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
81
82// Pseudo instructions (don't have encoding information)
83class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
84    : AArch64Inst<PseudoFrm, cstr> {
85  dag OutOperandList = oops;
86  dag InOperandList  = iops;
87  let Pattern        = pattern;
88  let isCodeGenOnly  = 1;
89  let isPseudo       = 1;
90}
91
92// Real instructions (have encoding information)
93class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
94  let Pattern = pattern;
95  let Size = 4;
96}
97
98// Normal instructions
99class I<dag oops, dag iops, string asm, string operands, string cstr,
100        list<dag> pattern>
101    : EncodedI<cstr, pattern> {
102  dag OutOperandList = oops;
103  dag InOperandList  = iops;
104  let AsmString      = !strconcat(asm, operands);
105}
106
107class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
108class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
109class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
110
111// Helper fragment for an extract of the high portion of a 128-bit vector.
112def extract_high_v16i8 :
113   UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
114def extract_high_v8i16 :
115   UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
116def extract_high_v4i32 :
117   UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
118def extract_high_v2i64 :
119   UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
120
121//===----------------------------------------------------------------------===//
122// Asm Operand Classes.
123//
124
125// Shifter operand for arithmetic shifted encodings.
126def ShifterOperand : AsmOperandClass {
127  let Name = "Shifter";
128}
129
130// Shifter operand for mov immediate encodings.
131def MovImm32ShifterOperand : AsmOperandClass {
132  let SuperClasses = [ShifterOperand];
133  let Name = "MovImm32Shifter";
134  let RenderMethod = "addShifterOperands";
135  let DiagnosticType = "InvalidMovImm32Shift";
136}
137def MovImm64ShifterOperand : AsmOperandClass {
138  let SuperClasses = [ShifterOperand];
139  let Name = "MovImm64Shifter";
140  let RenderMethod = "addShifterOperands";
141  let DiagnosticType = "InvalidMovImm64Shift";
142}
143
144// Shifter operand for arithmetic register shifted encodings.
145class ArithmeticShifterOperand<int width> : AsmOperandClass {
146  let SuperClasses = [ShifterOperand];
147  let Name = "ArithmeticShifter" # width;
148  let PredicateMethod = "isArithmeticShifter<" # width # ">";
149  let RenderMethod = "addShifterOperands";
150  let DiagnosticType = "AddSubRegShift" # width;
151}
152
153def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
154def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
155
156// Shifter operand for logical register shifted encodings.
157class LogicalShifterOperand<int width> : AsmOperandClass {
158  let SuperClasses = [ShifterOperand];
159  let Name = "LogicalShifter" # width;
160  let PredicateMethod = "isLogicalShifter<" # width # ">";
161  let RenderMethod = "addShifterOperands";
162  let DiagnosticType = "AddSubRegShift" # width;
163}
164
165def LogicalShifterOperand32 : LogicalShifterOperand<32>;
166def LogicalShifterOperand64 : LogicalShifterOperand<64>;
167
168// Shifter operand for logical vector 128/64-bit shifted encodings.
169def LogicalVecShifterOperand : AsmOperandClass {
170  let SuperClasses = [ShifterOperand];
171  let Name = "LogicalVecShifter";
172  let RenderMethod = "addShifterOperands";
173}
174def LogicalVecHalfWordShifterOperand : AsmOperandClass {
175  let SuperClasses = [LogicalVecShifterOperand];
176  let Name = "LogicalVecHalfWordShifter";
177  let RenderMethod = "addShifterOperands";
178}
179
180// The "MSL" shifter on the vector MOVI instruction.
181def MoveVecShifterOperand : AsmOperandClass {
182  let SuperClasses = [ShifterOperand];
183  let Name = "MoveVecShifter";
184  let RenderMethod = "addShifterOperands";
185}
186
187// Extend operand for arithmetic encodings.
188def ExtendOperand : AsmOperandClass {
189  let Name = "Extend";
190  let DiagnosticType = "AddSubRegExtendLarge";
191}
192def ExtendOperand64 : AsmOperandClass {
193  let SuperClasses = [ExtendOperand];
194  let Name = "Extend64";
195  let DiagnosticType = "AddSubRegExtendSmall";
196}
197// 'extend' that's a lsl of a 64-bit register.
198def ExtendOperandLSL64 : AsmOperandClass {
199  let SuperClasses = [ExtendOperand];
200  let Name = "ExtendLSL64";
201  let RenderMethod = "addExtend64Operands";
202  let DiagnosticType = "AddSubRegExtendLarge";
203}
204
205// 8-bit floating-point immediate encodings.
206def FPImmOperand : AsmOperandClass {
207  let Name = "FPImm";
208  let ParserMethod = "tryParseFPImm<true>";
209  let DiagnosticType = "InvalidFPImm";
210}
211
212def CondCode : AsmOperandClass {
213  let Name = "CondCode";
214  let DiagnosticType = "InvalidCondCode";
215}
216
217// A 32-bit register pasrsed as 64-bit
218def GPR32as64Operand : AsmOperandClass {
219  let Name = "GPR32as64";
220  let ParserMethod =
221      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
222}
223def GPR32as64 : RegisterOperand<GPR32> {
224  let ParserMatchClass = GPR32as64Operand;
225}
226
227// A 64-bit register pasrsed as 32-bit
228def GPR64as32Operand : AsmOperandClass {
229  let Name = "GPR64as32";
230  let ParserMethod =
231      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
232}
233def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
234  let ParserMatchClass = GPR64as32Operand;
235}
236
237// 8-bit immediate for AdvSIMD where 64-bit values of the form:
238// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
239// are encoded as the eight bit value 'abcdefgh'.
240def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
241
242class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
243  let Name = "UImm" # Width # "s" # Scale;
244  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
245  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
246  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
247}
248
249class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
250  let Name = "SImm" # Width # "s" # Scale;
251  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
252  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
253  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
254}
255
256//===----------------------------------------------------------------------===//
257// Operand Definitions.
258//
259
260// ADR[P] instruction labels.
261def AdrpOperand : AsmOperandClass {
262  let Name = "AdrpLabel";
263  let ParserMethod = "tryParseAdrpLabel";
264  let DiagnosticType = "InvalidLabel";
265}
266def adrplabel : Operand<i64> {
267  let EncoderMethod = "getAdrLabelOpValue";
268  let PrintMethod = "printAdrpLabel";
269  let ParserMatchClass = AdrpOperand;
270  let OperandType = "OPERAND_PCREL";
271}
272
273def AdrOperand : AsmOperandClass {
274  let Name = "AdrLabel";
275  let ParserMethod = "tryParseAdrLabel";
276  let DiagnosticType = "InvalidLabel";
277}
278def adrlabel : Operand<i64> {
279  let EncoderMethod = "getAdrLabelOpValue";
280  let ParserMatchClass = AdrOperand;
281}
282
283class SImmOperand<int width> : AsmOperandClass {
284  let Name = "SImm" # width;
285  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
286  let RenderMethod = "addImmOperands";
287  let PredicateMethod = "isSImm<" # width # ">";
288}
289
290
291class AsmImmRange<int Low, int High> : AsmOperandClass {
292  let Name = "Imm" # Low # "_" # High;
293  let DiagnosticType = "InvalidImm" # Low # "_" # High;
294  let RenderMethod = "addImmOperands";
295  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
296}
297
298// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
299def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
300def simm10Scaled : Operand<i64> {
301  let ParserMatchClass = SImm10s8Operand;
302  let DecoderMethod = "DecodeSImm<10>";
303  let PrintMethod = "printImmScale<8>";
304}
305
306def simm9s16 : Operand<i64> {
307  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
308  let DecoderMethod = "DecodeSImm<9>";
309  let PrintMethod = "printImmScale<16>";
310}
311
312// uimm6 predicate - True if the immediate is in the range [0, 63].
313def UImm6Operand : AsmOperandClass {
314  let Name = "UImm6";
315  let DiagnosticType = "InvalidImm0_63";
316}
317
318def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
319  let ParserMatchClass = UImm6Operand;
320}
321
322def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
323  let ParserMatchClass = AsmImmRange<0, 65535>;
324}
325
326def SImm9Operand : SImmOperand<9>;
327def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
328  let ParserMatchClass = SImm9Operand;
329  let DecoderMethod = "DecodeSImm<9>";
330}
331
332def SImm8Operand : SImmOperand<8>;
333def simm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
334  let ParserMatchClass = SImm8Operand;
335  let DecoderMethod = "DecodeSImm<8>";
336}
337
338def SImm6Operand : SImmOperand<6>;
339def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
340  let ParserMatchClass = SImm6Operand;
341  let DecoderMethod = "DecodeSImm<6>";
342}
343
344def SImm5Operand : SImmOperand<5>;
345def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
346  let ParserMatchClass = SImm5Operand;
347  let DecoderMethod = "DecodeSImm<5>";
348}
349
350def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
351  let ParserMatchClass = SImm5Operand;
352  let DecoderMethod = "DecodeSImm<5>";
353}
354
355def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
356  let ParserMatchClass = SImm5Operand;
357  let DecoderMethod = "DecodeSImm<5>";
358  let PrintMethod = "printSImm<8>";
359}
360
361def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
362  let ParserMatchClass = SImm5Operand;
363  let DecoderMethod = "DecodeSImm<5>";
364  let PrintMethod = "printSImm<16>";
365}
366
367// simm7sN predicate - True if the immediate is a multiple of N in the range
368// [-64 * N, 63 * N].
369
370def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
371def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
372def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
373
374def simm7s4 : Operand<i32> {
375  let ParserMatchClass = SImm7s4Operand;
376  let PrintMethod = "printImmScale<4>";
377}
378
379def simm7s8 : Operand<i32> {
380  let ParserMatchClass = SImm7s8Operand;
381  let PrintMethod = "printImmScale<8>";
382}
383
384def simm7s16 : Operand<i32> {
385  let ParserMatchClass = SImm7s16Operand;
386  let PrintMethod = "printImmScale<16>";
387}
388
389def am_sve_fi : ComplexPattern<i64, 2, "SelectAddrModeFrameIndexSVE", []>;
390
391def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
392def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
393def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
394def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
395def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
396
397def am_indexedu6s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedU6S128", []>;
398def am_indexeds9s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedS9S128", []>;
399
400def UImmS1XForm : SDNodeXForm<imm, [{
401  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
402}]>;
403def UImmS2XForm : SDNodeXForm<imm, [{
404  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
405}]>;
406def UImmS4XForm : SDNodeXForm<imm, [{
407  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
408}]>;
409def UImmS8XForm : SDNodeXForm<imm, [{
410  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
411}]>;
412
413// uimm5sN predicate - True if the immediate is a multiple of N in the range
414// [0 * N, 32 * N].
415def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
416def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
417def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
418
419def uimm5s2 : Operand<i64>, ImmLeaf<i64,
420                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
421                UImmS2XForm> {
422  let ParserMatchClass = UImm5s2Operand;
423  let PrintMethod = "printImmScale<2>";
424}
425def uimm5s4 : Operand<i64>, ImmLeaf<i64,
426                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
427                UImmS4XForm> {
428  let ParserMatchClass = UImm5s4Operand;
429  let PrintMethod = "printImmScale<4>";
430}
431def uimm5s8 : Operand<i64>, ImmLeaf<i64,
432                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
433                UImmS8XForm> {
434  let ParserMatchClass = UImm5s8Operand;
435  let PrintMethod = "printImmScale<8>";
436}
437
438// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
439// instead of ImmLeaf (Constant)
440def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
441                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
442                UImmS2XForm> {
443  let ParserMatchClass = UImm5s2Operand;
444  let PrintMethod = "printImmScale<2>";
445}
446def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
447                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
448                UImmS4XForm> {
449  let ParserMatchClass = UImm5s4Operand;
450  let PrintMethod = "printImmScale<4>";
451}
452def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
453                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
454                UImmS8XForm> {
455  let ParserMatchClass = UImm5s8Operand;
456  let PrintMethod = "printImmScale<8>";
457}
458
459// uimm6sN predicate - True if the immediate is a multiple of N in the range
460// [0 * N, 64 * N].
461def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
462def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
463def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
464def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
465def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
466
467def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
468  let ParserMatchClass = UImm6s1Operand;
469}
470def uimm6s2 : Operand<i64>, ImmLeaf<i64,
471[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
472  let PrintMethod = "printImmScale<2>";
473  let ParserMatchClass = UImm6s2Operand;
474}
475def uimm6s4 : Operand<i64>, ImmLeaf<i64,
476[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
477  let PrintMethod = "printImmScale<4>";
478  let ParserMatchClass = UImm6s4Operand;
479}
480def uimm6s8 : Operand<i64>, ImmLeaf<i64,
481[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
482  let PrintMethod = "printImmScale<8>";
483  let ParserMatchClass = UImm6s8Operand;
484}
485def uimm6s16 : Operand<i64>, ImmLeaf<i64,
486[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
487  let PrintMethod = "printImmScale<16>";
488  let ParserMatchClass = UImm6s16Operand;
489}
490
491def SImmS2XForm : SDNodeXForm<imm, [{
492  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
493}]>;
494def SImmS3XForm : SDNodeXForm<imm, [{
495  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
496}]>;
497def SImmS4XForm : SDNodeXForm<imm, [{
498  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
499}]>;
500def SImmS16XForm : SDNodeXForm<imm, [{
501  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
502}]>;
503def SImmS32XForm : SDNodeXForm<imm, [{
504  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
505}]>;
506
507// simm6sN predicate - True if the immediate is a multiple of N in the range
508// [-32 * N, 31 * N].
509def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
510def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
511  let ParserMatchClass = SImm6s1Operand;
512  let DecoderMethod = "DecodeSImm<6>";
513}
514
515// simm4sN predicate - True if the immediate is a multiple of N in the range
516// [ -8* N, 7 * N].
517def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
518def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
519def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
520def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
521def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
522def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
523
524def simm4s1 : Operand<i64>, ImmLeaf<i64,
525[{ return Imm >=-8  && Imm <= 7; }]> {
526  let ParserMatchClass = SImm4s1Operand;
527  let DecoderMethod = "DecodeSImm<4>";
528}
529
530def simm4s2 : Operand<i64>, ImmLeaf<i64,
531[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
532  let PrintMethod = "printImmScale<2>";
533  let ParserMatchClass = SImm4s2Operand;
534  let DecoderMethod = "DecodeSImm<4>";
535}
536
537def simm4s3 : Operand<i64>, ImmLeaf<i64,
538[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
539  let PrintMethod = "printImmScale<3>";
540  let ParserMatchClass = SImm4s3Operand;
541  let DecoderMethod = "DecodeSImm<4>";
542}
543
544def simm4s4 : Operand<i64>, ImmLeaf<i64,
545[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
546  let PrintMethod = "printImmScale<4>";
547  let ParserMatchClass = SImm4s4Operand;
548  let DecoderMethod = "DecodeSImm<4>";
549}
550def simm4s16 : Operand<i64>, ImmLeaf<i64,
551[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
552  let PrintMethod = "printImmScale<16>";
553  let ParserMatchClass = SImm4s16Operand;
554  let DecoderMethod = "DecodeSImm<4>";
555}
556def simm4s32 : Operand<i64>, ImmLeaf<i64,
557[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
558  let PrintMethod = "printImmScale<32>";
559  let ParserMatchClass = SImm4s32Operand;
560  let DecoderMethod = "DecodeSImm<4>";
561}
562
563def Imm1_8Operand : AsmImmRange<1, 8>;
564def Imm1_16Operand : AsmImmRange<1, 16>;
565def Imm1_32Operand : AsmImmRange<1, 32>;
566def Imm1_64Operand : AsmImmRange<1, 64>;
567
568class BranchTarget<int N> : AsmOperandClass {
569  let Name = "BranchTarget" # N;
570  let DiagnosticType = "InvalidLabel";
571  let PredicateMethod = "isBranchTarget<" # N # ">";
572}
573
574class PCRelLabel<int N> : BranchTarget<N> {
575  let Name = "PCRelLabel" # N;
576}
577
578def BranchTarget14Operand : BranchTarget<14>;
579def BranchTarget26Operand : BranchTarget<26>;
580def PCRelLabel19Operand   : PCRelLabel<19>;
581
582def MovWSymbolG3AsmOperand : AsmOperandClass {
583  let Name = "MovWSymbolG3";
584  let RenderMethod = "addImmOperands";
585}
586
587def movw_symbol_g3 : Operand<i32> {
588  let ParserMatchClass = MovWSymbolG3AsmOperand;
589}
590
591def MovWSymbolG2AsmOperand : AsmOperandClass {
592  let Name = "MovWSymbolG2";
593  let RenderMethod = "addImmOperands";
594}
595
596def movw_symbol_g2 : Operand<i32> {
597  let ParserMatchClass = MovWSymbolG2AsmOperand;
598}
599
600def MovWSymbolG1AsmOperand : AsmOperandClass {
601  let Name = "MovWSymbolG1";
602  let RenderMethod = "addImmOperands";
603}
604
605def movw_symbol_g1 : Operand<i32> {
606  let ParserMatchClass = MovWSymbolG1AsmOperand;
607}
608
609def MovWSymbolG0AsmOperand : AsmOperandClass {
610  let Name = "MovWSymbolG0";
611  let RenderMethod = "addImmOperands";
612}
613
614def movw_symbol_g0 : Operand<i32> {
615  let ParserMatchClass = MovWSymbolG0AsmOperand;
616}
617
618class fixedpoint_i32<ValueType FloatVT>
619  : Operand<FloatVT>,
620    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
621  let EncoderMethod = "getFixedPointScaleOpValue";
622  let DecoderMethod = "DecodeFixedPointScaleImm32";
623  let ParserMatchClass = Imm1_32Operand;
624}
625
626class fixedpoint_i64<ValueType FloatVT>
627  : Operand<FloatVT>,
628    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
629  let EncoderMethod = "getFixedPointScaleOpValue";
630  let DecoderMethod = "DecodeFixedPointScaleImm64";
631  let ParserMatchClass = Imm1_64Operand;
632}
633
634def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
635def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
636def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
637
638def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
639def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
640def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
641
642def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
643  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
644}]> {
645  let EncoderMethod = "getVecShiftR8OpValue";
646  let DecoderMethod = "DecodeVecShiftR8Imm";
647  let ParserMatchClass = Imm1_8Operand;
648}
649def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
650  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
651}]> {
652  let EncoderMethod = "getVecShiftR16OpValue";
653  let DecoderMethod = "DecodeVecShiftR16Imm";
654  let ParserMatchClass = Imm1_16Operand;
655}
656def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
657  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
658}]> {
659  let EncoderMethod = "getVecShiftR16OpValue";
660  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
661  let ParserMatchClass = Imm1_8Operand;
662}
663def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
664  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
665}]> {
666  let EncoderMethod = "getVecShiftR32OpValue";
667  let DecoderMethod = "DecodeVecShiftR32Imm";
668  let ParserMatchClass = Imm1_32Operand;
669}
670def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
671  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
672}]> {
673  let EncoderMethod = "getVecShiftR32OpValue";
674  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
675  let ParserMatchClass = Imm1_16Operand;
676}
677def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
678  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
679}]> {
680  let EncoderMethod = "getVecShiftR64OpValue";
681  let DecoderMethod = "DecodeVecShiftR64Imm";
682  let ParserMatchClass = Imm1_64Operand;
683}
684def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
685  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
686}]> {
687  let EncoderMethod = "getVecShiftR64OpValue";
688  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
689  let ParserMatchClass = Imm1_32Operand;
690}
691
692// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
693// (ImmLeaf)
694def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
695  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
696}]> {
697  let EncoderMethod = "getVecShiftR8OpValue";
698  let DecoderMethod = "DecodeVecShiftR8Imm";
699  let ParserMatchClass = Imm1_8Operand;
700}
701def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
702  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
703}]> {
704  let EncoderMethod = "getVecShiftR16OpValue";
705  let DecoderMethod = "DecodeVecShiftR16Imm";
706  let ParserMatchClass = Imm1_16Operand;
707}
708def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
709  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
710}]> {
711  let EncoderMethod = "getVecShiftR32OpValue";
712  let DecoderMethod = "DecodeVecShiftR32Imm";
713  let ParserMatchClass = Imm1_32Operand;
714}
715def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
716  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
717}]> {
718  let EncoderMethod = "getVecShiftR64OpValue";
719  let DecoderMethod = "DecodeVecShiftR64Imm";
720  let ParserMatchClass = Imm1_64Operand;
721}
722
723def Imm0_1Operand : AsmImmRange<0, 1>;
724def Imm0_7Operand : AsmImmRange<0, 7>;
725def Imm0_15Operand : AsmImmRange<0, 15>;
726def Imm0_31Operand : AsmImmRange<0, 31>;
727def Imm0_63Operand : AsmImmRange<0, 63>;
728
729def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
730  return (((uint32_t)Imm) < 8);
731}]> {
732  let EncoderMethod = "getVecShiftL8OpValue";
733  let DecoderMethod = "DecodeVecShiftL8Imm";
734  let ParserMatchClass = Imm0_7Operand;
735}
736def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
737  return (((uint32_t)Imm) < 16);
738}]> {
739  let EncoderMethod = "getVecShiftL16OpValue";
740  let DecoderMethod = "DecodeVecShiftL16Imm";
741  let ParserMatchClass = Imm0_15Operand;
742}
743def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
744  return (((uint32_t)Imm) < 32);
745}]> {
746  let EncoderMethod = "getVecShiftL32OpValue";
747  let DecoderMethod = "DecodeVecShiftL32Imm";
748  let ParserMatchClass = Imm0_31Operand;
749}
750def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
751  return (((uint32_t)Imm) < 64);
752}]> {
753  let EncoderMethod = "getVecShiftL64OpValue";
754  let DecoderMethod = "DecodeVecShiftL64Imm";
755  let ParserMatchClass = Imm0_63Operand;
756}
757
758// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
759// (ImmLeaf)
760def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
761  return (((uint32_t)Imm) < 8);
762}]> {
763  let EncoderMethod = "getVecShiftL8OpValue";
764  let DecoderMethod = "DecodeVecShiftL8Imm";
765  let ParserMatchClass = Imm0_7Operand;
766}
767def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
768  return (((uint32_t)Imm) < 16);
769}]> {
770  let EncoderMethod = "getVecShiftL16OpValue";
771  let DecoderMethod = "DecodeVecShiftL16Imm";
772  let ParserMatchClass = Imm0_15Operand;
773}
774def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
775  return (((uint32_t)Imm) < 32);
776}]> {
777  let EncoderMethod = "getVecShiftL32OpValue";
778  let DecoderMethod = "DecodeVecShiftL32Imm";
779  let ParserMatchClass = Imm0_31Operand;
780}
781def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
782  return (((uint32_t)Imm) < 64);
783}]> {
784  let EncoderMethod = "getVecShiftL64OpValue";
785  let DecoderMethod = "DecodeVecShiftL64Imm";
786  let ParserMatchClass = Imm0_63Operand;
787}
788
789// Crazy immediate formats used by 32-bit and 64-bit logical immediate
790// instructions for splatting repeating bit patterns across the immediate.
791def logical_imm32_XFORM : SDNodeXForm<imm, [{
792  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
793  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
794}]>;
795def logical_imm64_XFORM : SDNodeXForm<imm, [{
796  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
797  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
798}]>;
799
800def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
801  GISDNodeXFormEquiv<logical_imm32_XFORM>;
802def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
803  GISDNodeXFormEquiv<logical_imm64_XFORM>;
804
805let DiagnosticType = "LogicalSecondSource" in {
806  def LogicalImm32Operand : AsmOperandClass {
807    let Name = "LogicalImm32";
808    let PredicateMethod = "isLogicalImm<int32_t>";
809    let RenderMethod = "addLogicalImmOperands<int32_t>";
810  }
811  def LogicalImm64Operand : AsmOperandClass {
812    let Name = "LogicalImm64";
813    let PredicateMethod = "isLogicalImm<int64_t>";
814    let RenderMethod = "addLogicalImmOperands<int64_t>";
815  }
816  def LogicalImm32NotOperand : AsmOperandClass {
817    let Name = "LogicalImm32Not";
818    let PredicateMethod = "isLogicalImm<int32_t>";
819    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
820  }
821  def LogicalImm64NotOperand : AsmOperandClass {
822    let Name = "LogicalImm64Not";
823    let PredicateMethod = "isLogicalImm<int64_t>";
824    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
825  }
826}
827def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
828  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
829}], logical_imm32_XFORM> {
830  let PrintMethod = "printLogicalImm<int32_t>";
831  let ParserMatchClass = LogicalImm32Operand;
832}
833def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
834  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
835}], logical_imm64_XFORM> {
836  let PrintMethod = "printLogicalImm<int64_t>";
837  let ParserMatchClass = LogicalImm64Operand;
838}
839def logical_imm32_not : Operand<i32> {
840  let ParserMatchClass = LogicalImm32NotOperand;
841}
842def logical_imm64_not : Operand<i64> {
843  let ParserMatchClass = LogicalImm64NotOperand;
844}
845
846// iXX_imm0_65535 predicates - True if the immediate is in the range [0,65535].
847let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
848def i32_imm0_65535 : Operand<i32>, TImmLeaf<i32, [{
849  return ((uint32_t)Imm) < 65536;
850}]>;
851
852def i64_imm0_65535 : Operand<i64>, TImmLeaf<i64, [{
853  return ((uint64_t)Imm) < 65536;
854}]>;
855}
856
857// imm0_255 predicate - True if the immediate is in the range [0,255].
858def Imm0_255Operand : AsmImmRange<0,255>;
859
860def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
861  return ((uint32_t)Imm) < 256;
862}]> {
863  let ParserMatchClass = Imm0_255Operand;
864  let PrintMethod = "printImm";
865}
866
867// imm0_127 predicate - True if the immediate is in the range [0,127]
868def Imm0_127Operand : AsmImmRange<0, 127>;
869def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
870  return ((uint32_t)Imm) < 128;
871}]> {
872  let ParserMatchClass = Imm0_127Operand;
873  let PrintMethod = "printImm";
874}
875
876def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
877  return ((uint64_t)Imm) < 128;
878}]> {
879  let ParserMatchClass = Imm0_127Operand;
880  let PrintMethod = "printImm";
881}
882
883// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
884// for all shift-amounts.
885
886// imm0_63 predicate - True if the immediate is in the range [0,63]
887def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
888  return ((uint64_t)Imm) < 64;
889}]> {
890  let ParserMatchClass = Imm0_63Operand;
891}
892
893// imm0_31 predicate - True if the immediate is in the range [0,31]
894def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
895  return ((uint64_t)Imm) < 32;
896}]> {
897  let ParserMatchClass = Imm0_31Operand;
898}
899
900// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
901// instead of Constant (ImmLeaf)
902def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
903  return ((uint64_t)Imm) < 32;
904}]> {
905  let ParserMatchClass = Imm0_31Operand;
906}
907
908// True if the 32-bit immediate is in the range [0,31]
909def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
910  return ((uint64_t)Imm) < 32;
911}]> {
912  let ParserMatchClass = Imm0_31Operand;
913}
914
915// imm0_1 predicate - True if the immediate is in the range [0,1]
916def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
917  return ((uint64_t)Imm) < 2;
918}]> {
919  let ParserMatchClass = Imm0_1Operand;
920}
921
922// timm0_1 - as above, but use TargetConstant (TImmLeaf)
923def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
924  return ((uint64_t)Imm) < 2;
925}]> {
926  let ParserMatchClass = Imm0_1Operand;
927}
928
929// imm0_15 predicate - True if the immediate is in the range [0,15]
930def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
931  return ((uint64_t)Imm) < 16;
932}]> {
933  let ParserMatchClass = Imm0_15Operand;
934}
935
936// imm0_7 predicate - True if the immediate is in the range [0,7]
937def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
938  return ((uint64_t)Imm) < 8;
939}]> {
940  let ParserMatchClass = Imm0_7Operand;
941}
942
943// imm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
944def imm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
945  return ((uint32_t)Imm) < 8;
946}]> {
947  let ParserMatchClass = Imm0_7Operand;
948}
949
950// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
951def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
952  return ((uint32_t)Imm) < 16;
953}]> {
954  let ParserMatchClass = Imm0_15Operand;
955}
956
957// An arithmetic shifter operand:
958//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
959//  {5-0} - imm6
960class arith_shift<ValueType Ty, int width> : Operand<Ty> {
961  let PrintMethod = "printShifter";
962  let ParserMatchClass = !cast<AsmOperandClass>(
963                         "ArithmeticShifterOperand" # width);
964}
965
966def arith_shift32 : arith_shift<i32, 32>;
967def arith_shift64 : arith_shift<i64, 64>;
968
969class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
970    : Operand<Ty>,
971      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
972  let PrintMethod = "printShiftedRegister";
973  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
974}
975
976def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
977def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
978
979def gi_arith_shifted_reg32 :
980  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
981  GIComplexPatternEquiv<arith_shifted_reg32>;
982
983def gi_arith_shifted_reg64 :
984  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
985  GIComplexPatternEquiv<arith_shifted_reg64>;
986
987// An arithmetic shifter operand:
988//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
989//  {5-0} - imm6
990class logical_shift<int width> : Operand<i32> {
991  let PrintMethod = "printShifter";
992  let ParserMatchClass = !cast<AsmOperandClass>(
993                         "LogicalShifterOperand" # width);
994}
995
996def logical_shift32 : logical_shift<32>;
997def logical_shift64 : logical_shift<64>;
998
999class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1000    : Operand<Ty>,
1001      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1002  let PrintMethod = "printShiftedRegister";
1003  let MIOperandInfo = (ops regclass, shiftop);
1004}
1005
1006def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1007def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1008
1009def gi_logical_shifted_reg32 :
1010  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1011  GIComplexPatternEquiv<logical_shifted_reg32>;
1012
1013def gi_logical_shifted_reg64 :
1014  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1015  GIComplexPatternEquiv<logical_shifted_reg64>;
1016
1017// A logical vector shifter operand:
1018//  {7-6} - shift type: 00 = lsl
1019//  {5-0} - imm6: #0, #8, #16, or #24
1020def logical_vec_shift : Operand<i32> {
1021  let PrintMethod = "printShifter";
1022  let EncoderMethod = "getVecShifterOpValue";
1023  let ParserMatchClass = LogicalVecShifterOperand;
1024}
1025
1026// A logical vector half-word shifter operand:
1027//  {7-6} - shift type: 00 = lsl
1028//  {5-0} - imm6: #0 or #8
1029def logical_vec_hw_shift : Operand<i32> {
1030  let PrintMethod = "printShifter";
1031  let EncoderMethod = "getVecShifterOpValue";
1032  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1033}
1034
1035// A vector move shifter operand:
1036//  {0} - imm1: #8 or #16
1037def move_vec_shift : Operand<i32> {
1038  let PrintMethod = "printShifter";
1039  let EncoderMethod = "getMoveVecShifterOpValue";
1040  let ParserMatchClass = MoveVecShifterOperand;
1041}
1042
1043let DiagnosticType = "AddSubSecondSource" in {
1044  def AddSubImmOperand : AsmOperandClass {
1045    let Name = "AddSubImm";
1046    let ParserMethod = "tryParseImmWithOptionalShift";
1047    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1048  }
1049  def AddSubImmNegOperand : AsmOperandClass {
1050    let Name = "AddSubImmNeg";
1051    let ParserMethod = "tryParseImmWithOptionalShift";
1052    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1053  }
1054}
1055// An ADD/SUB immediate shifter operand:
1056//  second operand:
1057//  {7-6} - shift type: 00 = lsl
1058//  {5-0} - imm6: #0 or #12
1059class addsub_shifted_imm<ValueType Ty>
1060    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1061  let PrintMethod = "printAddSubImm";
1062  let EncoderMethod = "getAddSubImmOpValue";
1063  let ParserMatchClass = AddSubImmOperand;
1064  let MIOperandInfo = (ops i32imm, i32imm);
1065}
1066
1067class addsub_shifted_imm_neg<ValueType Ty>
1068    : Operand<Ty> {
1069  let EncoderMethod = "getAddSubImmOpValue";
1070  let ParserMatchClass = AddSubImmNegOperand;
1071  let MIOperandInfo = (ops i32imm, i32imm);
1072}
1073
1074def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1075def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1076def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1077def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1078
1079def gi_addsub_shifted_imm32 :
1080    GIComplexOperandMatcher<s32, "selectArithImmed">,
1081    GIComplexPatternEquiv<addsub_shifted_imm32>;
1082
1083def gi_addsub_shifted_imm64 :
1084    GIComplexOperandMatcher<s64, "selectArithImmed">,
1085    GIComplexPatternEquiv<addsub_shifted_imm64>;
1086
1087class neg_addsub_shifted_imm<ValueType Ty>
1088    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1089  let PrintMethod = "printAddSubImm";
1090  let EncoderMethod = "getAddSubImmOpValue";
1091  let ParserMatchClass = AddSubImmOperand;
1092  let MIOperandInfo = (ops i32imm, i32imm);
1093}
1094
1095def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1096def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1097
1098def gi_neg_addsub_shifted_imm32 :
1099    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1100    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1101
1102def gi_neg_addsub_shifted_imm64 :
1103    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1104    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1105
1106// An extend operand:
1107//  {5-3} - extend type
1108//  {2-0} - imm3
1109def arith_extend : Operand<i32> {
1110  let PrintMethod = "printArithExtend";
1111  let ParserMatchClass = ExtendOperand;
1112}
1113def arith_extend64 : Operand<i32> {
1114  let PrintMethod = "printArithExtend";
1115  let ParserMatchClass = ExtendOperand64;
1116}
1117
1118// 'extend' that's a lsl of a 64-bit register.
1119def arith_extendlsl64 : Operand<i32> {
1120  let PrintMethod = "printArithExtend";
1121  let ParserMatchClass = ExtendOperandLSL64;
1122}
1123
1124class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1125                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1126  let PrintMethod = "printExtendedRegister";
1127  let MIOperandInfo = (ops GPR32, arith_extend);
1128}
1129
1130class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1131                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1132  let PrintMethod = "printExtendedRegister";
1133  let MIOperandInfo = (ops GPR32, arith_extend64);
1134}
1135
1136def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1137def gi_arith_extended_reg32_i32 :
1138    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1139    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1140
1141def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1142def gi_arith_extended_reg32_i64 :
1143    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1144    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1145
1146def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1147def gi_arith_extended_reg32to64_i64 :
1148    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1149    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1150
1151// Floating-point immediate.
1152def fpimm16 : Operand<f16>,
1153              FPImmLeaf<f16, [{
1154      return AArch64_AM::getFP16Imm(Imm) != -1;
1155    }], SDNodeXForm<fpimm, [{
1156      APFloat InVal = N->getValueAPF();
1157      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1158      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1159    }]>> {
1160  let ParserMatchClass = FPImmOperand;
1161  let PrintMethod = "printFPImmOperand";
1162}
1163def fpimm32 : Operand<f32>,
1164              FPImmLeaf<f32, [{
1165      return AArch64_AM::getFP32Imm(Imm) != -1;
1166    }], SDNodeXForm<fpimm, [{
1167      APFloat InVal = N->getValueAPF();
1168      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1169      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1170    }]>> {
1171  let ParserMatchClass = FPImmOperand;
1172  let PrintMethod = "printFPImmOperand";
1173}
1174def fpimm64 : Operand<f64>,
1175              FPImmLeaf<f64, [{
1176      return AArch64_AM::getFP64Imm(Imm) != -1;
1177    }], SDNodeXForm<fpimm, [{
1178      APFloat InVal = N->getValueAPF();
1179      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1180      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1181    }]>> {
1182  let ParserMatchClass = FPImmOperand;
1183  let PrintMethod = "printFPImmOperand";
1184}
1185
1186def fpimm8 : Operand<i32> {
1187  let ParserMatchClass = FPImmOperand;
1188  let PrintMethod = "printFPImmOperand";
1189}
1190
1191def fpimm0 : FPImmLeaf<fAny, [{
1192  return Imm.isExactlyValue(+0.0);
1193}]>;
1194
1195// Vector lane operands
1196class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1197  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1198  let DiagnosticType = "Invalid" # Name;
1199  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1200  let RenderMethod = "addVectorIndexOperands";
1201}
1202
1203class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1204    : Operand<ty> {
1205  let ParserMatchClass = mc;
1206  let PrintMethod = "printVectorIndex";
1207}
1208
1209multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1210  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1211  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1212}
1213
1214def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1215def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1216def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1217def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1218def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1219
1220defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1221                                [{ return ((uint64_t)Imm) == 1; }]>;
1222defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1223                                [{ return ((uint64_t)Imm) < 16; }]>;
1224defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1225                                [{ return ((uint64_t)Imm) < 8; }]>;
1226defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1227                                [{ return ((uint64_t)Imm) < 4; }]>;
1228defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1229                                [{ return ((uint64_t)Imm) < 2; }]>;
1230
1231defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1232                                   [{ return ((uint64_t)Imm) == 1; }]>;
1233defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1234                                   [{ return ((uint64_t)Imm) < 16; }]>;
1235defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1236                                   [{ return ((uint64_t)Imm) < 8; }]>;
1237defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1238                                   [{ return ((uint64_t)Imm) < 4; }]>;
1239defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1240                                   [{ return ((uint64_t)Imm) < 2; }]>;
1241
1242def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1243def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1244def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1245def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1246def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1247
1248defm sve_elm_idx_extdup_b
1249  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1250                [{ return ((uint64_t)Imm) < 64; }]>;
1251defm sve_elm_idx_extdup_h
1252  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1253                [{ return ((uint64_t)Imm) < 32; }]>;
1254defm sve_elm_idx_extdup_s
1255  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1256                [{ return ((uint64_t)Imm) < 16; }]>;
1257defm sve_elm_idx_extdup_d
1258  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1259                [{ return ((uint64_t)Imm) < 8; }]>;
1260defm sve_elm_idx_extdup_q
1261  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1262                [{ return ((uint64_t)Imm) < 4; }]>;
1263
1264// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1265// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1266// are encoded as the eight bit value 'abcdefgh'.
1267def simdimmtype10 : Operand<i32>,
1268                    FPImmLeaf<f64, [{
1269      return AArch64_AM::isAdvSIMDModImmType10(
1270                 Imm.bitcastToAPInt().getZExtValue());
1271    }], SDNodeXForm<fpimm, [{
1272      APFloat InVal = N->getValueAPF();
1273      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1274                                                           .bitcastToAPInt()
1275                                                           .getZExtValue());
1276      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1277    }]>> {
1278  let ParserMatchClass = SIMDImmType10Operand;
1279  let PrintMethod = "printSIMDType10Operand";
1280}
1281
1282
1283//---
1284// System management
1285//---
1286
1287// Base encoding for system instruction operands.
1288let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1289class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1290                  list<dag> pattern = []>
1291    : I<oops, iops, asm, operands, "", pattern> {
1292  let Inst{31-22} = 0b1101010100;
1293  let Inst{21}    = L;
1294}
1295
1296// System instructions which do not have an Rt register.
1297class SimpleSystemI<bit L, dag iops, string asm, string operands,
1298                    list<dag> pattern = []>
1299    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1300  let Inst{4-0} = 0b11111;
1301}
1302
1303// System instructions which have an Rt register.
1304class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1305                list<dag> pattern = []>
1306    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1307      Sched<[WriteSys]> {
1308  bits<5> Rt;
1309  let Inst{4-0} = Rt;
1310}
1311
1312// System instructions for transactional memory extension
1313class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1314                    string asm, string operands, list<dag> pattern>
1315    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1316      Sched<[WriteSys]> {
1317  let Inst{20-12} = 0b000110011;
1318  let Inst{11-8} = CRm;
1319  let Inst{7-5} = op2;
1320  let DecoderMethod = "";
1321
1322  let mayLoad = 1;
1323  let mayStore = 1;
1324}
1325
1326// System instructions for transactional memory - single input operand
1327class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1328    : TMBaseSystemI<0b1, CRm, 0b011,
1329                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1330  bits<5> Rt;
1331  let Inst{4-0} = Rt;
1332}
1333
1334// System instructions that pass a register argument
1335// This class assumes the register is for input rather than output.
1336class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1337                      list<dag> pattern = []>
1338    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1339  let Inst{20-12} = 0b000110001;
1340  let Inst{11-8} = CRm;
1341  let Inst{7-5} = Op2;
1342}
1343
1344// System instructions for transactional memory - no operand
1345class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1346    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1347  let Inst{4-0} = 0b11111;
1348}
1349
1350// System instructions for exit from transactions
1351class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1352    : I<(outs), (ins i64_imm0_65535:$imm), asm, "\t$imm", "", pattern>,
1353      Sched<[WriteSys]> {
1354  bits<16> imm;
1355  let Inst{31-24} = 0b11010100;
1356  let Inst{23-21} = op1;
1357  let Inst{20-5}  = imm;
1358  let Inst{4-0}   = 0b00000;
1359}
1360
1361// Hint instructions that take both a CRm and a 3-bit immediate.
1362// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1363// model patterns with sufficiently fine granularity
1364let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1365  class HintI<string mnemonic>
1366      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1367                      [(int_aarch64_hint imm0_127:$imm)]>,
1368        Sched<[WriteHint]> {
1369    bits <7> imm;
1370    let Inst{20-12} = 0b000110010;
1371    let Inst{11-5} = imm;
1372  }
1373
1374// System instructions taking a single literal operand which encodes into
1375// CRm. op2 differentiates the opcodes.
1376def BarrierAsmOperand : AsmOperandClass {
1377  let Name = "Barrier";
1378  let ParserMethod = "tryParseBarrierOperand";
1379}
1380def barrier_op : Operand<i32> {
1381  let PrintMethod = "printBarrierOption";
1382  let ParserMatchClass = BarrierAsmOperand;
1383}
1384def BarriernXSAsmOperand : AsmOperandClass {
1385  let Name = "BarriernXS";
1386  let ParserMethod = "tryParseBarriernXSOperand";
1387}
1388def barrier_nxs_op : Operand<i32> {
1389  let PrintMethod = "printBarriernXSOption";
1390  let ParserMatchClass = BarriernXSAsmOperand;
1391}
1392class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1393                 list<dag> pattern = []>
1394    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1395      Sched<[WriteBarrier]> {
1396  bits<4> CRm;
1397  let Inst{20-12} = 0b000110011;
1398  let Inst{11-8} = CRm;
1399  let Inst{7-5} = opc;
1400}
1401
1402class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1403    : SimpleSystemI<0, (ins), asm, "", pattern>,
1404      Sched<[]> {
1405  bits<4> CRm;
1406  let CRm = 0b0011;
1407  let Inst{31-12} = 0b11010101000000110010;
1408  let Inst{11-8} = CRm;
1409  let Inst{7-5} = op2;
1410  let Inst{4-0} = 0b11111;
1411}
1412
1413// MRS/MSR system instructions. These have different operand classes because
1414// a different subset of registers can be accessed through each instruction.
1415def MRSSystemRegisterOperand : AsmOperandClass {
1416  let Name = "MRSSystemRegister";
1417  let ParserMethod = "tryParseSysReg";
1418  let DiagnosticType = "MRS";
1419}
1420// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1421def mrs_sysreg_op : Operand<i32> {
1422  let ParserMatchClass = MRSSystemRegisterOperand;
1423  let DecoderMethod = "DecodeMRSSystemRegister";
1424  let PrintMethod = "printMRSSystemRegister";
1425}
1426
1427def MSRSystemRegisterOperand : AsmOperandClass {
1428  let Name = "MSRSystemRegister";
1429  let ParserMethod = "tryParseSysReg";
1430  let DiagnosticType = "MSR";
1431}
1432def msr_sysreg_op : Operand<i32> {
1433  let ParserMatchClass = MSRSystemRegisterOperand;
1434  let DecoderMethod = "DecodeMSRSystemRegister";
1435  let PrintMethod = "printMSRSystemRegister";
1436}
1437
1438def PSBHintOperand : AsmOperandClass {
1439  let Name = "PSBHint";
1440  let ParserMethod = "tryParsePSBHint";
1441}
1442def psbhint_op : Operand<i32> {
1443  let ParserMatchClass = PSBHintOperand;
1444  let PrintMethod = "printPSBHintOp";
1445  let MCOperandPredicate = [{
1446    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1447    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1448    if (!MCOp.isImm())
1449      return false;
1450    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1451  }];
1452}
1453
1454def BTIHintOperand : AsmOperandClass {
1455  let Name = "BTIHint";
1456  let ParserMethod = "tryParseBTIHint";
1457}
1458def btihint_op : Operand<i32> {
1459  let ParserMatchClass = BTIHintOperand;
1460  let PrintMethod = "printBTIHintOp";
1461  let MCOperandPredicate = [{
1462    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1463    if (!MCOp.isImm())
1464      return false;
1465    return AArch64BTIHint::lookupBTIByEncoding((MCOp.getImm() ^ 32) >> 1) != nullptr;
1466  }];
1467}
1468
1469class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1470                       "mrs", "\t$Rt, $systemreg"> {
1471  bits<16> systemreg;
1472  let Inst{20-5} = systemreg;
1473  let DecoderNamespace = "Fallback";
1474}
1475
1476// FIXME: Some of these def NZCV, others don't. Best way to model that?
1477// Explicitly modeling each of the system register as a register class
1478// would do it, but feels like overkill at this point.
1479class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1480                       "msr", "\t$systemreg, $Rt"> {
1481  bits<16> systemreg;
1482  let Inst{20-5} = systemreg;
1483  let DecoderNamespace = "Fallback";
1484}
1485
1486def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1487  let Name = "SystemPStateFieldWithImm0_15";
1488  let ParserMethod = "tryParseSysReg";
1489}
1490def pstatefield4_op : Operand<i32> {
1491  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1492  let PrintMethod = "printSystemPStateField";
1493}
1494
1495// Instructions to modify PSTATE, no input reg
1496let Defs = [NZCV] in
1497class PstateWriteSimple<dag iops, string asm, string operands>
1498  : SimpleSystemI<0, iops, asm, operands> {
1499
1500  let Inst{20-19} = 0b00;
1501  let Inst{15-12} = 0b0100;
1502}
1503
1504class MSRpstateImm0_15
1505  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1506                  "\t$pstatefield, $imm">,
1507    Sched<[WriteSys]> {
1508
1509  bits<6> pstatefield;
1510  bits<4> imm;
1511  let Inst{18-16} = pstatefield{5-3};
1512  let Inst{11-8} = imm;
1513  let Inst{7-5} = pstatefield{2-0};
1514
1515  let DecoderMethod = "DecodeSystemPStateInstruction";
1516  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1517  // Fail the decoder should attempt to decode the instruction as MSRI.
1518  let hasCompleteDecoder = 0;
1519}
1520
1521def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1522  let Name = "SystemPStateFieldWithImm0_1";
1523  let ParserMethod = "tryParseSysReg";
1524}
1525def pstatefield1_op : Operand<i32> {
1526  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1527  let PrintMethod = "printSystemPStateField";
1528}
1529
1530class MSRpstateImm0_1
1531  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1532                 "\t$pstatefield, $imm">,
1533    Sched<[WriteSys]> {
1534
1535  bits<6> pstatefield;
1536  bit imm;
1537  let Inst{18-16} = pstatefield{5-3};
1538  let Inst{11-9} = 0b000;
1539  let Inst{8} = imm;
1540  let Inst{7-5} = pstatefield{2-0};
1541
1542  let DecoderMethod = "DecodeSystemPStateInstruction";
1543  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1544  // Fail the decoder should attempt to decode the instruction as MSRI.
1545  let hasCompleteDecoder = 0;
1546}
1547
1548// SYS and SYSL generic system instructions.
1549def SysCRAsmOperand : AsmOperandClass {
1550  let Name = "SysCR";
1551  let ParserMethod = "tryParseSysCROperand";
1552}
1553
1554def sys_cr_op : Operand<i32> {
1555  let PrintMethod = "printSysCROperand";
1556  let ParserMatchClass = SysCRAsmOperand;
1557}
1558
1559class SystemXtI<bit L, string asm>
1560  : RtSystemI<L, (outs),
1561       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1562       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1563  bits<3> op1;
1564  bits<4> Cn;
1565  bits<4> Cm;
1566  bits<3> op2;
1567  let Inst{20-19} = 0b01;
1568  let Inst{18-16} = op1;
1569  let Inst{15-12} = Cn;
1570  let Inst{11-8}  = Cm;
1571  let Inst{7-5}   = op2;
1572}
1573
1574class SystemLXtI<bit L, string asm>
1575  : RtSystemI<L, (outs),
1576       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1577       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1578  bits<3> op1;
1579  bits<4> Cn;
1580  bits<4> Cm;
1581  bits<3> op2;
1582  let Inst{20-19} = 0b01;
1583  let Inst{18-16} = op1;
1584  let Inst{15-12} = Cn;
1585  let Inst{11-8}  = Cm;
1586  let Inst{7-5}   = op2;
1587}
1588
1589
1590// Branch (register) instructions:
1591//
1592//  case opc of
1593//    0001 blr
1594//    0000 br
1595//    0101 dret
1596//    0100 eret
1597//    0010 ret
1598//    otherwise UNDEFINED
1599class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1600                    string operands, list<dag> pattern>
1601    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1602  let Inst{31-25} = 0b1101011;
1603  let Inst{24-21} = opc;
1604  let Inst{20-16} = 0b11111;
1605  let Inst{15-10} = 0b000000;
1606  let Inst{4-0}   = 0b00000;
1607}
1608
1609class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1610    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1611  bits<5> Rn;
1612  let Inst{9-5} = Rn;
1613}
1614
1615let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1616class SpecialReturn<bits<4> opc, string asm>
1617    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1618  let Inst{9-5} = 0b11111;
1619}
1620
1621let mayLoad = 1 in
1622class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1623  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1624  Sched<[]> {
1625  bits<5> Rn;
1626  bits<5> Rt;
1627  let Inst{31-30} = sz;
1628  let Inst{29-10} = 0b11100010111111110000;
1629  let Inst{9-5} = Rn;
1630  let Inst{4-0} = Rt;
1631}
1632
1633class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1634               list<dag> pattern>
1635  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1636  let isAuthenticated = 1;
1637  let Inst{31-25} = 0b1101011;
1638  let Inst{20-11} = 0b1111100001;
1639  let Inst{10} = M;
1640  let Inst{4-0} = 0b11111;
1641}
1642
1643class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1644  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1645  bits<5> Rn;
1646  bits<5> Rm;
1647  let Inst{24-22} = 0b100;
1648  let Inst{21} = op;
1649  let Inst{9-5} = Rn;
1650  let Inst{4-0} = Rm;
1651}
1652
1653class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1654  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1655  bits<5> Rn;
1656  let Inst{24} = 0;
1657  let Inst{23-21} = opc;
1658  let Inst{9-5} = Rn;
1659}
1660
1661let Uses = [LR,SP] in
1662class AuthReturn<bits<3> op, bits<1> M, string asm>
1663  : AuthBase<M, (outs), (ins), asm, "", []> {
1664  let Inst{24} = 0;
1665  let Inst{23-21} = op;
1666  let Inst{9-0} = 0b1111111111;
1667}
1668
1669let mayLoad = 1 in
1670class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1671                   string operands, string cstr, Operand opr>
1672  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1673  bits<10> offset;
1674  bits<5> Rn;
1675  bits<5> Rt;
1676  let isAuthenticated = 1;
1677  let Inst{31-24} = 0b11111000;
1678  let Inst{23} = M;
1679  let Inst{22} = offset{9};
1680  let Inst{21} = 1;
1681  let Inst{20-12} = offset{8-0};
1682  let Inst{11} = W;
1683  let Inst{10} = 1;
1684  let Inst{9-5} = Rn;
1685  let Inst{4-0} = Rt;
1686
1687  let DecoderMethod = "DecodeAuthLoadInstruction";
1688}
1689
1690multiclass AuthLoad<bit M, string asm, Operand opr> {
1691  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1692                               (ins GPR64sp:$Rn, opr:$offset),
1693                               asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1694  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1695                               (ins GPR64sp:$Rn, opr:$offset),
1696                               asm, "\t$Rt, [$Rn, $offset]!",
1697                               "$Rn = $wback,@earlyclobber $wback", opr>;
1698
1699  def : InstAlias<asm # "\t$Rt, [$Rn]",
1700                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1701
1702  def : InstAlias<asm # "\t$Rt, [$wback]!",
1703                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1704}
1705
1706//---
1707// Conditional branch instruction.
1708//---
1709
1710// Condition code.
1711// 4-bit immediate. Pretty-printed as <cc>
1712def ccode : Operand<i32> {
1713  let PrintMethod = "printCondCode";
1714  let ParserMatchClass = CondCode;
1715}
1716def inv_ccode : Operand<i32> {
1717  // AL and NV are invalid in the aliases which use inv_ccode
1718  let PrintMethod = "printInverseCondCode";
1719  let ParserMatchClass = CondCode;
1720  let MCOperandPredicate = [{
1721    return MCOp.isImm() &&
1722           MCOp.getImm() != AArch64CC::AL &&
1723           MCOp.getImm() != AArch64CC::NV;
1724  }];
1725}
1726
1727// Conditional branch target. 19-bit immediate. The low two bits of the target
1728// offset are implied zero and so are not part of the immediate.
1729def am_brcond : Operand<OtherVT> {
1730  let EncoderMethod = "getCondBranchTargetOpValue";
1731  let DecoderMethod = "DecodePCRelLabel19";
1732  let PrintMethod = "printAlignedLabel";
1733  let ParserMatchClass = PCRelLabel19Operand;
1734  let OperandType = "OPERAND_PCREL";
1735}
1736
1737class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1738                     "b", ".$cond\t$target", "",
1739                     [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1740                   Sched<[WriteBr]> {
1741  let isBranch = 1;
1742  let isTerminator = 1;
1743  let Uses = [NZCV];
1744
1745  bits<4> cond;
1746  bits<19> target;
1747  let Inst{31-24} = 0b01010100;
1748  let Inst{23-5} = target;
1749  let Inst{4} = 0;
1750  let Inst{3-0} = cond;
1751}
1752
1753//---
1754// Compare-and-branch instructions.
1755//---
1756class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1757    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1758         asm, "\t$Rt, $target", "",
1759         [(node regtype:$Rt, bb:$target)]>,
1760      Sched<[WriteBr]> {
1761  let isBranch = 1;
1762  let isTerminator = 1;
1763
1764  bits<5> Rt;
1765  bits<19> target;
1766  let Inst{30-25} = 0b011010;
1767  let Inst{24}    = op;
1768  let Inst{23-5}  = target;
1769  let Inst{4-0}   = Rt;
1770}
1771
1772multiclass CmpBranch<bit op, string asm, SDNode node> {
1773  def W : BaseCmpBranch<GPR32, op, asm, node> {
1774    let Inst{31} = 0;
1775  }
1776  def X : BaseCmpBranch<GPR64, op, asm, node> {
1777    let Inst{31} = 1;
1778  }
1779}
1780
1781//---
1782// Test-bit-and-branch instructions.
1783//---
1784// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1785// the target offset are implied zero and so are not part of the immediate.
1786def am_tbrcond : Operand<OtherVT> {
1787  let EncoderMethod = "getTestBranchTargetOpValue";
1788  let PrintMethod = "printAlignedLabel";
1789  let ParserMatchClass = BranchTarget14Operand;
1790  let OperandType = "OPERAND_PCREL";
1791}
1792
1793// AsmOperand classes to emit (or not) special diagnostics
1794def TBZImm0_31Operand : AsmOperandClass {
1795  let Name = "TBZImm0_31";
1796  let PredicateMethod = "isImmInRange<0,31>";
1797  let RenderMethod = "addImmOperands";
1798}
1799def TBZImm32_63Operand : AsmOperandClass {
1800  let Name = "Imm32_63";
1801  let PredicateMethod = "isImmInRange<32,63>";
1802  let DiagnosticType = "InvalidImm0_63";
1803  let RenderMethod = "addImmOperands";
1804}
1805
1806class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1807  return (((uint32_t)Imm) < 32);
1808}]> {
1809  let ParserMatchClass = matcher;
1810}
1811
1812def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1813def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1814
1815def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1816  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1817}]> {
1818  let ParserMatchClass = TBZImm32_63Operand;
1819}
1820
1821class BaseTestBranch<RegisterClass regtype, Operand immtype,
1822                     bit op, string asm, SDNode node>
1823    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1824       asm, "\t$Rt, $bit_off, $target", "",
1825       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1826      Sched<[WriteBr]> {
1827  let isBranch = 1;
1828  let isTerminator = 1;
1829
1830  bits<5> Rt;
1831  bits<6> bit_off;
1832  bits<14> target;
1833
1834  let Inst{30-25} = 0b011011;
1835  let Inst{24}    = op;
1836  let Inst{23-19} = bit_off{4-0};
1837  let Inst{18-5}  = target;
1838  let Inst{4-0}   = Rt;
1839
1840  let DecoderMethod = "DecodeTestAndBranch";
1841}
1842
1843multiclass TestBranch<bit op, string asm, SDNode node> {
1844  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1845    let Inst{31} = 0;
1846  }
1847
1848  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1849    let Inst{31} = 1;
1850  }
1851
1852  // Alias X-reg with 0-31 imm to W-Reg.
1853  def : InstAlias<asm # "\t$Rd, $imm, $target",
1854                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1855                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1856  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1857            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1858            tbz_imm0_31_diag:$imm, bb:$target)>;
1859}
1860
1861//---
1862// Unconditional branch (immediate) instructions.
1863//---
1864def am_b_target : Operand<OtherVT> {
1865  let EncoderMethod = "getBranchTargetOpValue";
1866  let PrintMethod = "printAlignedLabel";
1867  let ParserMatchClass = BranchTarget26Operand;
1868  let OperandType = "OPERAND_PCREL";
1869}
1870def am_bl_target : Operand<i64> {
1871  let EncoderMethod = "getBranchTargetOpValue";
1872  let PrintMethod = "printAlignedLabel";
1873  let ParserMatchClass = BranchTarget26Operand;
1874  let OperandType = "OPERAND_PCREL";
1875}
1876
1877class BImm<bit op, dag iops, string asm, list<dag> pattern>
1878    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1879  bits<26> addr;
1880  let Inst{31}    = op;
1881  let Inst{30-26} = 0b00101;
1882  let Inst{25-0}  = addr;
1883
1884  let DecoderMethod = "DecodeUnconditionalBranch";
1885}
1886
1887class BranchImm<bit op, string asm, list<dag> pattern>
1888    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1889class CallImm<bit op, string asm, list<dag> pattern>
1890    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1891
1892//---
1893// Basic one-operand data processing instructions.
1894//---
1895
1896let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1897class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1898                         SDPatternOperator node>
1899  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1900      [(set regtype:$Rd, (node regtype:$Rn))]>,
1901    Sched<[WriteI, ReadI]> {
1902  bits<5> Rd;
1903  bits<5> Rn;
1904
1905  let Inst{30-13} = 0b101101011000000000;
1906  let Inst{12-10} = opc;
1907  let Inst{9-5}   = Rn;
1908  let Inst{4-0}   = Rd;
1909}
1910
1911let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1912multiclass OneOperandData<bits<3> opc, string asm,
1913                          SDPatternOperator node = null_frag> {
1914  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1915    let Inst{31} = 0;
1916  }
1917
1918  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1919    let Inst{31} = 1;
1920  }
1921}
1922
1923class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1924    : BaseOneOperandData<opc, GPR32, asm, node> {
1925  let Inst{31} = 0;
1926}
1927
1928class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1929    : BaseOneOperandData<opc, GPR64, asm, node> {
1930  let Inst{31} = 1;
1931}
1932
1933class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1934  : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1935      []>,
1936    Sched<[WriteI, ReadI]> {
1937  bits<5> Rd;
1938  bits<5> Rn;
1939  let Inst{31-15} = 0b11011010110000010;
1940  let Inst{14-12} = opcode_prefix;
1941  let Inst{11-10} = opcode;
1942  let Inst{9-5} = Rn;
1943  let Inst{4-0} = Rd;
1944}
1945
1946class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1947  : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1948  bits<5> Rd;
1949  let Inst{31-15} = 0b11011010110000010;
1950  let Inst{14-12} = opcode_prefix;
1951  let Inst{11-10} = opcode;
1952  let Inst{9-5} = 0b11111;
1953  let Inst{4-0} = Rd;
1954}
1955
1956class SignAuthTwoOperand<bits<4> opc, string asm,
1957                         SDPatternOperator OpNode>
1958  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1959      asm, "\t$Rd, $Rn, $Rm", "",
1960      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1961    Sched<[WriteI, ReadI, ReadI]> {
1962  bits<5> Rd;
1963  bits<5> Rn;
1964  bits<5> Rm;
1965  let Inst{31-21} = 0b10011010110;
1966  let Inst{20-16} = Rm;
1967  let Inst{15-14} = 0b00;
1968  let Inst{13-10} = opc;
1969  let Inst{9-5}   = Rn;
1970  let Inst{4-0}   = Rd;
1971}
1972
1973class ClearAuth<bits<1> data, string asm>
1974  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
1975  bits<5> Rd;
1976  let Inst{31-11} = 0b110110101100000101000;
1977  let Inst{10} = data;
1978  let Inst{9-5} = 0b11111;
1979  let Inst{4-0} = Rd;
1980}
1981
1982// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1983class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1984    : I<(outs), iops, asm, ops, "", []>,
1985      Sched<[WriteI, ReadI, ReadI]> {
1986  let Uses = [NZCV];
1987  let Defs = [NZCV];
1988  bits<5> Rn;
1989  let Inst{31}    = sf;
1990  let Inst{30-15} = 0b0111010000000000;
1991  let Inst{14}    = sz;
1992  let Inst{13-10} = 0b0010;
1993  let Inst{9-5}   = Rn;
1994  let Inst{4-0}   = 0b01101;
1995}
1996
1997class FlagRotate<dag iops, string asm, string ops>
1998    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1999  bits<6> imm;
2000  bits<4> mask;
2001  let Inst{20-15} = imm;
2002  let Inst{13-10} = 0b0001;
2003  let Inst{4}     = 0b0;
2004  let Inst{3-0}   = mask;
2005}
2006
2007//---
2008// Basic two-operand data processing instructions.
2009//---
2010class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2011                          list<dag> pattern>
2012    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2013        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2014      Sched<[WriteI, ReadI, ReadI]> {
2015  let Uses = [NZCV];
2016  bits<5> Rd;
2017  bits<5> Rn;
2018  bits<5> Rm;
2019  let Inst{30}    = isSub;
2020  let Inst{28-21} = 0b11010000;
2021  let Inst{20-16} = Rm;
2022  let Inst{15-10} = 0;
2023  let Inst{9-5}   = Rn;
2024  let Inst{4-0}   = Rd;
2025}
2026
2027class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2028                      SDNode OpNode>
2029    : BaseBaseAddSubCarry<isSub, regtype, asm,
2030        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2031
2032class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2033                              SDNode OpNode>
2034    : BaseBaseAddSubCarry<isSub, regtype, asm,
2035        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2036         (implicit NZCV)]> {
2037  let Defs = [NZCV];
2038}
2039
2040multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2041                       SDNode OpNode, SDNode OpNode_setflags> {
2042  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2043    let Inst{31} = 0;
2044    let Inst{29} = 0;
2045  }
2046  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2047    let Inst{31} = 1;
2048    let Inst{29} = 0;
2049  }
2050
2051  // Sets flags.
2052  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2053                                    OpNode_setflags> {
2054    let Inst{31} = 0;
2055    let Inst{29} = 1;
2056  }
2057  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2058                                    OpNode_setflags> {
2059    let Inst{31} = 1;
2060    let Inst{29} = 1;
2061  }
2062}
2063
2064class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
2065                     SDPatternOperator OpNode,
2066                     RegisterClass in1regtype = regtype,
2067                     RegisterClass in2regtype = regtype>
2068  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2069      asm, "\t$Rd, $Rn, $Rm", "",
2070      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2071  bits<5> Rd;
2072  bits<5> Rn;
2073  bits<5> Rm;
2074  let Inst{30-21} = 0b0011010110;
2075  let Inst{20-16} = Rm;
2076  let Inst{15-14} = 0b00;
2077  let Inst{13-10} = opc;
2078  let Inst{9-5}   = Rn;
2079  let Inst{4-0}   = Rd;
2080}
2081
2082class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
2083              SDPatternOperator OpNode>
2084    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
2085  let Inst{10}    = isSigned;
2086}
2087
2088multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2089  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
2090           Sched<[WriteID32, ReadID, ReadID]> {
2091    let Inst{31} = 0;
2092  }
2093  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
2094           Sched<[WriteID64, ReadID, ReadID]> {
2095    let Inst{31} = 1;
2096  }
2097}
2098
2099class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
2100                SDPatternOperator OpNode = null_frag>
2101  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
2102    Sched<[WriteIS, ReadI]> {
2103  let Inst{11-10} = shift_type;
2104}
2105
2106multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2107  def Wr : BaseShift<shift_type, GPR32, asm> {
2108    let Inst{31} = 0;
2109  }
2110
2111  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
2112    let Inst{31} = 1;
2113  }
2114
2115  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2116            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2117                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2118
2119  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2120            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2121
2122  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2123            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2124
2125  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2126            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2127
2128  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2129            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2130                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2131
2132  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2133            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2134                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2135}
2136
2137class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2138    : InstAlias<asm#"\t$dst, $src1, $src2",
2139                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2140
2141class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2142                       RegisterClass addtype, string asm,
2143                       list<dag> pattern>
2144  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2145      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2146  bits<5> Rd;
2147  bits<5> Rn;
2148  bits<5> Rm;
2149  bits<5> Ra;
2150  let Inst{30-24} = 0b0011011;
2151  let Inst{23-21} = opc;
2152  let Inst{20-16} = Rm;
2153  let Inst{15}    = isSub;
2154  let Inst{14-10} = Ra;
2155  let Inst{9-5}   = Rn;
2156  let Inst{4-0}   = Rd;
2157}
2158
2159multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
2160  // MADD/MSUB generation is decided by MachineCombiner.cpp
2161  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
2162      [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
2163      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2164    let Inst{31} = 0;
2165  }
2166
2167  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
2168      [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
2169      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2170    let Inst{31} = 1;
2171  }
2172}
2173
2174class WideMulAccum<bit isSub, bits<3> opc, string asm,
2175                   SDNode AccNode, SDNode ExtNode>
2176  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2177    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2178                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2179    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2180  let Inst{31} = 1;
2181}
2182
2183class MulHi<bits<3> opc, string asm, SDNode OpNode>
2184  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2185      asm, "\t$Rd, $Rn, $Rm", "",
2186      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2187    Sched<[WriteIM64, ReadIM, ReadIM]> {
2188  bits<5> Rd;
2189  bits<5> Rn;
2190  bits<5> Rm;
2191  let Inst{31-24} = 0b10011011;
2192  let Inst{23-21} = opc;
2193  let Inst{20-16} = Rm;
2194  let Inst{15}    = 0;
2195  let Inst{9-5}   = Rn;
2196  let Inst{4-0}   = Rd;
2197
2198  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2199  // (i.e. all bits 1) but is ignored by the processor.
2200  let PostEncoderMethod = "fixMulHigh";
2201}
2202
2203class MulAccumWAlias<string asm, Instruction inst>
2204    : InstAlias<asm#"\t$dst, $src1, $src2",
2205                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2206class MulAccumXAlias<string asm, Instruction inst>
2207    : InstAlias<asm#"\t$dst, $src1, $src2",
2208                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2209class WideMulAccumAlias<string asm, Instruction inst>
2210    : InstAlias<asm#"\t$dst, $src1, $src2",
2211                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2212
2213class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2214              SDPatternOperator OpNode, string asm>
2215  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2216      asm, "\t$Rd, $Rn, $Rm", "",
2217      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2218    Sched<[WriteISReg, ReadI, ReadISReg]> {
2219  bits<5> Rd;
2220  bits<5> Rn;
2221  bits<5> Rm;
2222
2223  let Inst{31} = sf;
2224  let Inst{30-21} = 0b0011010110;
2225  let Inst{20-16} = Rm;
2226  let Inst{15-13} = 0b010;
2227  let Inst{12} = C;
2228  let Inst{11-10} = sz;
2229  let Inst{9-5} = Rn;
2230  let Inst{4-0} = Rd;
2231  let Predicates = [HasCRC];
2232}
2233
2234//---
2235// Address generation.
2236//---
2237
2238class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2239    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2240        pattern>,
2241      Sched<[WriteI]> {
2242  bits<5>  Xd;
2243  bits<21> label;
2244  let Inst{31}    = page;
2245  let Inst{30-29} = label{1-0};
2246  let Inst{28-24} = 0b10000;
2247  let Inst{23-5}  = label{20-2};
2248  let Inst{4-0}   = Xd;
2249
2250  let DecoderMethod = "DecodeAdrInstruction";
2251}
2252
2253//---
2254// Move immediate.
2255//---
2256
2257def movimm32_imm : Operand<i32> {
2258  let ParserMatchClass = AsmImmRange<0, 65535>;
2259  let EncoderMethod = "getMoveWideImmOpValue";
2260  let PrintMethod = "printImm";
2261}
2262def movimm32_shift : Operand<i32> {
2263  let PrintMethod = "printShifter";
2264  let ParserMatchClass = MovImm32ShifterOperand;
2265}
2266def movimm64_shift : Operand<i32> {
2267  let PrintMethod = "printShifter";
2268  let ParserMatchClass = MovImm64ShifterOperand;
2269}
2270
2271let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2272class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2273                        string asm>
2274  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2275       asm, "\t$Rd, $imm$shift", "", []>,
2276    Sched<[WriteImm]> {
2277  bits<5> Rd;
2278  bits<16> imm;
2279  bits<6> shift;
2280  let Inst{30-29} = opc;
2281  let Inst{28-23} = 0b100101;
2282  let Inst{22-21} = shift{5-4};
2283  let Inst{20-5}  = imm;
2284  let Inst{4-0}   = Rd;
2285
2286  let DecoderMethod = "DecodeMoveImmInstruction";
2287}
2288
2289multiclass MoveImmediate<bits<2> opc, string asm> {
2290  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2291    let Inst{31} = 0;
2292  }
2293
2294  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2295    let Inst{31} = 1;
2296  }
2297}
2298
2299let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2300class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2301                          string asm>
2302  : I<(outs regtype:$Rd),
2303      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2304       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2305    Sched<[WriteI, ReadI]> {
2306  bits<5> Rd;
2307  bits<16> imm;
2308  bits<6> shift;
2309  let Inst{30-29} = opc;
2310  let Inst{28-23} = 0b100101;
2311  let Inst{22-21} = shift{5-4};
2312  let Inst{20-5}  = imm;
2313  let Inst{4-0}   = Rd;
2314
2315  let DecoderMethod = "DecodeMoveImmInstruction";
2316}
2317
2318multiclass InsertImmediate<bits<2> opc, string asm> {
2319  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2320    let Inst{31} = 0;
2321  }
2322
2323  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2324    let Inst{31} = 1;
2325  }
2326}
2327
2328//---
2329// Add/Subtract
2330//---
2331
2332class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2333                    string asm_inst, string asm_ops,
2334                    dag inputs, dag pattern>
2335    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2336      Sched<[WriteI, ReadI]> {
2337  bits<5>  Rd;
2338  bits<5>  Rn;
2339  let Inst{30}    = isSub;
2340  let Inst{29}    = setFlags;
2341  let Inst{28-24} = 0b10001;
2342  let Inst{9-5}   = Rn;
2343  let Inst{4-0}   = Rd;
2344}
2345
2346class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2347                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2348                     string asm_inst, SDPatternOperator OpNode>
2349    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2350                    (ins srcRegtype:$Rn, immtype:$imm),
2351                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2352  bits<14> imm;
2353  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2354  let Inst{21-10} = imm{11-0};
2355  let DecoderMethod = "DecodeAddSubImmShift";
2356}
2357
2358class BaseAddSubRegPseudo<RegisterClass regtype,
2359                          SDPatternOperator OpNode>
2360    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2361             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2362      Sched<[WriteI, ReadI, ReadI]>;
2363
2364class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2365                     arith_shifted_reg shifted_regtype, string asm,
2366                     SDPatternOperator OpNode>
2367    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2368        asm, "\t$Rd, $Rn, $Rm", "",
2369        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2370      Sched<[WriteISReg, ReadI, ReadISReg]> {
2371  // The operands are in order to match the 'addr' MI operands, so we
2372  // don't need an encoder method and by-name matching. Just use the default
2373  // in-order handling. Since we're using by-order, make sure the names
2374  // do not match.
2375  bits<5> dst;
2376  bits<5> src1;
2377  bits<5> src2;
2378  bits<8> shift;
2379  let Inst{30}    = isSub;
2380  let Inst{29}    = setFlags;
2381  let Inst{28-24} = 0b01011;
2382  let Inst{23-22} = shift{7-6};
2383  let Inst{21}    = 0;
2384  let Inst{20-16} = src2;
2385  let Inst{15-10} = shift{5-0};
2386  let Inst{9-5}   = src1;
2387  let Inst{4-0}   = dst;
2388
2389  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2390}
2391
2392class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2393                     RegisterClass src1Regtype, Operand src2Regtype,
2394                     string asm, SDPatternOperator OpNode>
2395    : I<(outs dstRegtype:$R1),
2396        (ins src1Regtype:$R2, src2Regtype:$R3),
2397        asm, "\t$R1, $R2, $R3", "",
2398        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2399      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2400  bits<5> Rd;
2401  bits<5> Rn;
2402  bits<5> Rm;
2403  bits<6> ext;
2404  let Inst{30}    = isSub;
2405  let Inst{29}    = setFlags;
2406  let Inst{28-24} = 0b01011;
2407  let Inst{23-21} = 0b001;
2408  let Inst{20-16} = Rm;
2409  let Inst{15-13} = ext{5-3};
2410  let Inst{12-10} = ext{2-0};
2411  let Inst{9-5}   = Rn;
2412  let Inst{4-0}   = Rd;
2413
2414  let DecoderMethod = "DecodeAddSubERegInstruction";
2415}
2416
2417let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2418class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2419                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2420                       Operand ext_op, string asm>
2421    : I<(outs dstRegtype:$Rd),
2422        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2423        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2424      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2425  bits<5> Rd;
2426  bits<5> Rn;
2427  bits<5> Rm;
2428  bits<6> ext;
2429  let Inst{30}    = isSub;
2430  let Inst{29}    = setFlags;
2431  let Inst{28-24} = 0b01011;
2432  let Inst{23-21} = 0b001;
2433  let Inst{20-16} = Rm;
2434  let Inst{15}    = ext{5};
2435  let Inst{12-10} = ext{2-0};
2436  let Inst{9-5}   = Rn;
2437  let Inst{4-0}   = Rd;
2438
2439  let DecoderMethod = "DecodeAddSubERegInstruction";
2440}
2441
2442// Aliases for register+register add/subtract.
2443class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2444                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2445                     int shiftExt>
2446    : InstAlias<asm#"\t$dst, $src1, $src2",
2447                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2448                      shiftExt)>;
2449
2450multiclass AddSub<bit isSub, string mnemonic, string alias,
2451                  SDPatternOperator OpNode = null_frag> {
2452  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2453  // Add/Subtract immediate
2454  // Increase the weight of the immediate variant to try to match it before
2455  // the extended register variant.
2456  // We used to match the register variant before the immediate when the
2457  // register argument could be implicitly zero-extended.
2458  let AddedComplexity = 6 in
2459  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2460                           mnemonic, OpNode> {
2461    let Inst{31} = 0;
2462  }
2463  let AddedComplexity = 6 in
2464  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2465                           mnemonic, OpNode> {
2466    let Inst{31} = 1;
2467  }
2468
2469  // Add/Subtract register - Only used for CodeGen
2470  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2471  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2472
2473  // Add/Subtract shifted register
2474  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2475                           OpNode> {
2476    let Inst{31} = 0;
2477  }
2478  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2479                           OpNode> {
2480    let Inst{31} = 1;
2481  }
2482  }
2483
2484  // Add/Subtract extended register
2485  let AddedComplexity = 1, hasSideEffects = 0 in {
2486  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2487                           arith_extended_reg32_i32, mnemonic, OpNode> {
2488    let Inst{31} = 0;
2489  }
2490  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2491                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2492    let Inst{31} = 1;
2493  }
2494  }
2495
2496  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2497                               arith_extendlsl64, mnemonic> {
2498    // UXTX and SXTX only.
2499    let Inst{14-13} = 0b11;
2500    let Inst{31} = 1;
2501  }
2502
2503  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2504  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2505                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2506                      addsub_shifted_imm32_neg:$imm), 0>;
2507  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2508                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2509                       addsub_shifted_imm64_neg:$imm), 0>;
2510
2511  // Register/register aliases with no shift when SP is not used.
2512  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2513                       GPR32, GPR32, GPR32, 0>;
2514  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2515                       GPR64, GPR64, GPR64, 0>;
2516
2517  // Register/register aliases with no shift when either the destination or
2518  // first source register is SP.
2519  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2520                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2521  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2522                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2523  def : AddSubRegAlias<mnemonic,
2524                       !cast<Instruction>(NAME#"Xrx64"),
2525                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2526  def : AddSubRegAlias<mnemonic,
2527                       !cast<Instruction>(NAME#"Xrx64"),
2528                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2529}
2530
2531multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2532                   string alias, string cmpAlias> {
2533  let isCompare = 1, Defs = [NZCV] in {
2534  // Add/Subtract immediate
2535  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2536                           mnemonic, OpNode> {
2537    let Inst{31} = 0;
2538  }
2539  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2540                           mnemonic, OpNode> {
2541    let Inst{31} = 1;
2542  }
2543
2544  // Add/Subtract register
2545  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2546  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2547
2548  // Add/Subtract shifted register
2549  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2550                           OpNode> {
2551    let Inst{31} = 0;
2552  }
2553  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2554                           OpNode> {
2555    let Inst{31} = 1;
2556  }
2557
2558  // Add/Subtract extended register
2559  let AddedComplexity = 1 in {
2560  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2561                           arith_extended_reg32_i32, mnemonic, OpNode> {
2562    let Inst{31} = 0;
2563  }
2564  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2565                           arith_extended_reg32_i64, mnemonic, OpNode> {
2566    let Inst{31} = 1;
2567  }
2568  }
2569
2570  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2571                               arith_extendlsl64, mnemonic> {
2572    // UXTX and SXTX only.
2573    let Inst{14-13} = 0b11;
2574    let Inst{31} = 1;
2575  }
2576  } // Defs = [NZCV]
2577
2578  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2579  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2580                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2581                      addsub_shifted_imm32_neg:$imm), 0>;
2582  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2583                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2584                       addsub_shifted_imm64_neg:$imm), 0>;
2585
2586  // Compare aliases
2587  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2588                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2589  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2590                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2591  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2592                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2593  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2594                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2595  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2596                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2597  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2598                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2599  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2600                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2601
2602  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2603  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2604                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2605  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2606                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2607
2608  // Compare shorthands
2609  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2610                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2611  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2612                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2613  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2614                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2615  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2616                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2617
2618  // Register/register aliases with no shift when SP is not used.
2619  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2620                       GPR32, GPR32, GPR32, 0>;
2621  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2622                       GPR64, GPR64, GPR64, 0>;
2623
2624  // Register/register aliases with no shift when the first source register
2625  // is SP.
2626  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2627                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2628  def : AddSubRegAlias<mnemonic,
2629                       !cast<Instruction>(NAME#"Xrx64"),
2630                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2631}
2632
2633class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2634      : BaseAddSubImm<
2635          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2636          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2637          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2638  bits<6> imm6;
2639  bits<4> imm4;
2640  let Inst{31} = 1;
2641  let Inst{23-22} = 0b10;
2642  let Inst{21-16} = imm6;
2643  let Inst{15-14} = 0b00;
2644  let Inst{13-10} = imm4;
2645  let Unpredictable{15-14} = 0b11;
2646}
2647
2648class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2649      : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2650  let Inst{31} = 1;
2651  let Inst{29} = setsFlags;
2652}
2653
2654//---
2655// Extract
2656//---
2657def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2658                                      SDTCisPtrTy<3>]>;
2659def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2660
2661class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2662                     list<dag> patterns>
2663    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2664         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2665      Sched<[WriteExtr, ReadExtrHi]> {
2666  bits<5> Rd;
2667  bits<5> Rn;
2668  bits<5> Rm;
2669  bits<6> imm;
2670
2671  let Inst{30-23} = 0b00100111;
2672  let Inst{21}    = 0;
2673  let Inst{20-16} = Rm;
2674  let Inst{15-10} = imm;
2675  let Inst{9-5}   = Rn;
2676  let Inst{4-0}   = Rd;
2677}
2678
2679multiclass ExtractImm<string asm> {
2680  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2681                      [(set GPR32:$Rd,
2682                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2683    let Inst{31} = 0;
2684    let Inst{22} = 0;
2685    // imm<5> must be zero.
2686    let imm{5}   = 0;
2687  }
2688  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2689                      [(set GPR64:$Rd,
2690                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2691
2692    let Inst{31} = 1;
2693    let Inst{22} = 1;
2694  }
2695}
2696
2697//---
2698// Bitfield
2699//---
2700
2701let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2702class BaseBitfieldImm<bits<2> opc,
2703                      RegisterClass regtype, Operand imm_type, string asm>
2704    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2705         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2706      Sched<[WriteIS, ReadI]> {
2707  bits<5> Rd;
2708  bits<5> Rn;
2709  bits<6> immr;
2710  bits<6> imms;
2711
2712  let Inst{30-29} = opc;
2713  let Inst{28-23} = 0b100110;
2714  let Inst{21-16} = immr;
2715  let Inst{15-10} = imms;
2716  let Inst{9-5}   = Rn;
2717  let Inst{4-0}   = Rd;
2718}
2719
2720multiclass BitfieldImm<bits<2> opc, string asm> {
2721  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2722    let Inst{31} = 0;
2723    let Inst{22} = 0;
2724    // imms<5> and immr<5> must be zero, else ReservedValue().
2725    let Inst{21} = 0;
2726    let Inst{15} = 0;
2727  }
2728  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2729    let Inst{31} = 1;
2730    let Inst{22} = 1;
2731  }
2732}
2733
2734let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2735class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2736                      RegisterClass regtype, Operand imm_type, string asm>
2737    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2738                             imm_type:$imms),
2739         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2740      Sched<[WriteIS, ReadI]> {
2741  bits<5> Rd;
2742  bits<5> Rn;
2743  bits<6> immr;
2744  bits<6> imms;
2745
2746  let Inst{30-29} = opc;
2747  let Inst{28-23} = 0b100110;
2748  let Inst{21-16} = immr;
2749  let Inst{15-10} = imms;
2750  let Inst{9-5}   = Rn;
2751  let Inst{4-0}   = Rd;
2752}
2753
2754multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2755  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2756    let Inst{31} = 0;
2757    let Inst{22} = 0;
2758    // imms<5> and immr<5> must be zero, else ReservedValue().
2759    let Inst{21} = 0;
2760    let Inst{15} = 0;
2761  }
2762  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2763    let Inst{31} = 1;
2764    let Inst{22} = 1;
2765  }
2766}
2767
2768//---
2769// Logical
2770//---
2771
2772// Logical (immediate)
2773class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2774                     RegisterClass sregtype, Operand imm_type, string asm,
2775                     list<dag> pattern>
2776    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2777         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2778      Sched<[WriteI, ReadI]> {
2779  bits<5>  Rd;
2780  bits<5>  Rn;
2781  bits<13> imm;
2782  let Inst{30-29} = opc;
2783  let Inst{28-23} = 0b100100;
2784  let Inst{22}    = imm{12};
2785  let Inst{21-16} = imm{11-6};
2786  let Inst{15-10} = imm{5-0};
2787  let Inst{9-5}   = Rn;
2788  let Inst{4-0}   = Rd;
2789
2790  let DecoderMethod = "DecodeLogicalImmInstruction";
2791}
2792
2793// Logical (shifted register)
2794class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2795                      logical_shifted_reg shifted_regtype, string asm,
2796                      list<dag> pattern>
2797    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2798        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2799      Sched<[WriteISReg, ReadI, ReadISReg]> {
2800  // The operands are in order to match the 'addr' MI operands, so we
2801  // don't need an encoder method and by-name matching. Just use the default
2802  // in-order handling. Since we're using by-order, make sure the names
2803  // do not match.
2804  bits<5> dst;
2805  bits<5> src1;
2806  bits<5> src2;
2807  bits<8> shift;
2808  let Inst{30-29} = opc;
2809  let Inst{28-24} = 0b01010;
2810  let Inst{23-22} = shift{7-6};
2811  let Inst{21}    = N;
2812  let Inst{20-16} = src2;
2813  let Inst{15-10} = shift{5-0};
2814  let Inst{9-5}   = src1;
2815  let Inst{4-0}   = dst;
2816
2817  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2818}
2819
2820// Aliases for register+register logical instructions.
2821class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2822    : InstAlias<asm#"\t$dst, $src1, $src2",
2823                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2824
2825multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2826                      string Alias> {
2827  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2828  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2829                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2830                                               logical_imm32:$imm))]> {
2831    let Inst{31} = 0;
2832    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2833  }
2834  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2835  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2836                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2837                                               logical_imm64:$imm))]> {
2838    let Inst{31} = 1;
2839  }
2840
2841  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2842                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2843                      logical_imm32_not:$imm), 0>;
2844  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2845                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2846                       logical_imm64_not:$imm), 0>;
2847}
2848
2849multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2850                       string Alias> {
2851  let isCompare = 1, Defs = [NZCV] in {
2852  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2853      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2854    let Inst{31} = 0;
2855    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2856  }
2857  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2858      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2859    let Inst{31} = 1;
2860  }
2861  } // end Defs = [NZCV]
2862
2863  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2864                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2865                      logical_imm32_not:$imm), 0>;
2866  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2867                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2868                       logical_imm64_not:$imm), 0>;
2869}
2870
2871class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2872    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2873             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2874      Sched<[WriteI, ReadI, ReadI]>;
2875
2876// Split from LogicalImm as not all instructions have both.
2877multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2878                      SDPatternOperator OpNode> {
2879  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2880  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2881  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2882  }
2883
2884  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2885                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2886                                                 logical_shifted_reg32:$Rm))]> {
2887    let Inst{31} = 0;
2888  }
2889  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2890                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2891                                                 logical_shifted_reg64:$Rm))]> {
2892    let Inst{31} = 1;
2893  }
2894
2895  def : LogicalRegAlias<mnemonic,
2896                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2897  def : LogicalRegAlias<mnemonic,
2898                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2899}
2900
2901// Split from LogicalReg to allow setting NZCV Defs
2902multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2903                       SDPatternOperator OpNode = null_frag> {
2904  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2905  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2906  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2907
2908  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2909            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2910    let Inst{31} = 0;
2911  }
2912  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2913            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2914    let Inst{31} = 1;
2915  }
2916  } // Defs = [NZCV]
2917
2918  def : LogicalRegAlias<mnemonic,
2919                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2920  def : LogicalRegAlias<mnemonic,
2921                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2922}
2923
2924//---
2925// Conditionally set flags
2926//---
2927
2928let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2929class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2930                            string mnemonic, SDNode OpNode>
2931    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2932         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2933         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2934                             (i32 imm:$cond), NZCV))]>,
2935      Sched<[WriteI, ReadI]> {
2936  let Uses = [NZCV];
2937  let Defs = [NZCV];
2938
2939  bits<5> Rn;
2940  bits<5> imm;
2941  bits<4> nzcv;
2942  bits<4> cond;
2943
2944  let Inst{30}    = op;
2945  let Inst{29-21} = 0b111010010;
2946  let Inst{20-16} = imm;
2947  let Inst{15-12} = cond;
2948  let Inst{11-10} = 0b10;
2949  let Inst{9-5}   = Rn;
2950  let Inst{4}     = 0b0;
2951  let Inst{3-0}   = nzcv;
2952}
2953
2954let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2955class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2956                            SDNode OpNode>
2957    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2958         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2959         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2960                             (i32 imm:$cond), NZCV))]>,
2961      Sched<[WriteI, ReadI, ReadI]> {
2962  let Uses = [NZCV];
2963  let Defs = [NZCV];
2964
2965  bits<5> Rn;
2966  bits<5> Rm;
2967  bits<4> nzcv;
2968  bits<4> cond;
2969
2970  let Inst{30}    = op;
2971  let Inst{29-21} = 0b111010010;
2972  let Inst{20-16} = Rm;
2973  let Inst{15-12} = cond;
2974  let Inst{11-10} = 0b00;
2975  let Inst{9-5}   = Rn;
2976  let Inst{4}     = 0b0;
2977  let Inst{3-0}   = nzcv;
2978}
2979
2980multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2981  // immediate operand variants
2982  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2983    let Inst{31} = 0;
2984  }
2985  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2986    let Inst{31} = 1;
2987  }
2988  // register operand variants
2989  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2990    let Inst{31} = 0;
2991  }
2992  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2993    let Inst{31} = 1;
2994  }
2995}
2996
2997//---
2998// Conditional select
2999//---
3000
3001class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3002    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3003         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3004         [(set regtype:$Rd,
3005               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3006      Sched<[WriteI, ReadI, ReadI]> {
3007  let Uses = [NZCV];
3008
3009  bits<5> Rd;
3010  bits<5> Rn;
3011  bits<5> Rm;
3012  bits<4> cond;
3013
3014  let Inst{30}    = op;
3015  let Inst{29-21} = 0b011010100;
3016  let Inst{20-16} = Rm;
3017  let Inst{15-12} = cond;
3018  let Inst{11-10} = op2;
3019  let Inst{9-5}   = Rn;
3020  let Inst{4-0}   = Rd;
3021}
3022
3023multiclass CondSelect<bit op, bits<2> op2, string asm> {
3024  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3025    let Inst{31} = 0;
3026  }
3027  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3028    let Inst{31} = 1;
3029  }
3030}
3031
3032class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3033                       PatFrag frag>
3034    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3035         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3036         [(set regtype:$Rd,
3037               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3038               (i32 imm:$cond), NZCV))]>,
3039      Sched<[WriteI, ReadI, ReadI]> {
3040  let Uses = [NZCV];
3041
3042  bits<5> Rd;
3043  bits<5> Rn;
3044  bits<5> Rm;
3045  bits<4> cond;
3046
3047  let Inst{30}    = op;
3048  let Inst{29-21} = 0b011010100;
3049  let Inst{20-16} = Rm;
3050  let Inst{15-12} = cond;
3051  let Inst{11-10} = op2;
3052  let Inst{9-5}   = Rn;
3053  let Inst{4-0}   = Rd;
3054}
3055
3056def inv_cond_XFORM : SDNodeXForm<imm, [{
3057  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3058  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3059                                   MVT::i32);
3060}]>;
3061
3062multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3063  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3064    let Inst{31} = 0;
3065  }
3066  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3067    let Inst{31} = 1;
3068  }
3069
3070  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3071            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3072                                           (inv_cond_XFORM imm:$cond))>;
3073
3074  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3075            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3076                                           (inv_cond_XFORM imm:$cond))>;
3077}
3078
3079//---
3080// Special Mask Value
3081//---
3082def maski8_or_more : Operand<i32>,
3083  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3084}
3085def maski16_or_more : Operand<i32>,
3086  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3087}
3088
3089
3090//---
3091// Load/store
3092//---
3093
3094// (unsigned immediate)
3095// Indexed for 8-bit registers. offset is in range [0,4095].
3096def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
3097def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
3098def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
3099def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
3100def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
3101
3102def gi_am_indexed8 :
3103    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3104    GIComplexPatternEquiv<am_indexed8>;
3105def gi_am_indexed16 :
3106    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3107    GIComplexPatternEquiv<am_indexed16>;
3108def gi_am_indexed32 :
3109    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3110    GIComplexPatternEquiv<am_indexed32>;
3111def gi_am_indexed64 :
3112    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3113    GIComplexPatternEquiv<am_indexed64>;
3114def gi_am_indexed128 :
3115    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3116    GIComplexPatternEquiv<am_indexed128>;
3117
3118class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3119  let Name = "UImm12Offset" # Scale;
3120  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3121  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3122  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3123}
3124
3125def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3126def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3127def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3128def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3129def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3130
3131class uimm12_scaled<int Scale> : Operand<i64> {
3132  let ParserMatchClass
3133   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3134  let EncoderMethod
3135   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3136  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3137}
3138
3139def uimm12s1 : uimm12_scaled<1>;
3140def uimm12s2 : uimm12_scaled<2>;
3141def uimm12s4 : uimm12_scaled<4>;
3142def uimm12s8 : uimm12_scaled<8>;
3143def uimm12s16 : uimm12_scaled<16>;
3144
3145class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3146                      string asm, list<dag> pattern>
3147    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3148  bits<5> Rt;
3149
3150  bits<5> Rn;
3151  bits<12> offset;
3152
3153  let Inst{31-30} = sz;
3154  let Inst{29-27} = 0b111;
3155  let Inst{26}    = V;
3156  let Inst{25-24} = 0b01;
3157  let Inst{23-22} = opc;
3158  let Inst{21-10} = offset;
3159  let Inst{9-5}   = Rn;
3160  let Inst{4-0}   = Rt;
3161
3162  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3163}
3164
3165multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3166                  Operand indextype, string asm, list<dag> pattern> {
3167  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3168  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3169                           (ins GPR64sp:$Rn, indextype:$offset),
3170                           asm, pattern>,
3171           Sched<[WriteLD]>;
3172
3173  def : InstAlias<asm # "\t$Rt, [$Rn]",
3174                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3175}
3176
3177multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3178             Operand indextype, string asm, list<dag> pattern> {
3179  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3180  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3181                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3182                           asm, pattern>,
3183           Sched<[WriteST]>;
3184
3185  def : InstAlias<asm # "\t$Rt, [$Rn]",
3186                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3187}
3188
3189// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3190// substitute zero-registers automatically.
3191//
3192// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3193//       into StoreUI.
3194multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3195             Operand indextype, string asm, list<dag> pattern> {
3196  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3197  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3198                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3199                           asm, pattern>,
3200           Sched<[WriteST]>;
3201
3202  def : InstAlias<asm # "\t$Rt, [$Rn]",
3203                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3204}
3205
3206def PrefetchOperand : AsmOperandClass {
3207  let Name = "Prefetch";
3208  let ParserMethod = "tryParsePrefetch";
3209}
3210def prfop : Operand<i32> {
3211  let PrintMethod = "printPrefetchOp";
3212  let ParserMatchClass = PrefetchOperand;
3213}
3214
3215let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3216class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3217    : BaseLoadStoreUI<sz, V, opc,
3218                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3219                      asm, pat>,
3220      Sched<[WriteLD]>;
3221
3222//---
3223// Load literal
3224//---
3225
3226// Load literal address: 19-bit immediate. The low two bits of the target
3227// offset are implied zero and so are not part of the immediate.
3228def am_ldrlit : Operand<iPTR> {
3229  let EncoderMethod = "getLoadLiteralOpValue";
3230  let DecoderMethod = "DecodePCRelLabel19";
3231  let PrintMethod = "printAlignedLabel";
3232  let ParserMatchClass = PCRelLabel19Operand;
3233  let OperandType = "OPERAND_PCREL";
3234}
3235
3236let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3237class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3238    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3239        asm, "\t$Rt, $label", "", pat>,
3240      Sched<[WriteLD]> {
3241  bits<5> Rt;
3242  bits<19> label;
3243  let Inst{31-30} = opc;
3244  let Inst{29-27} = 0b011;
3245  let Inst{26}    = V;
3246  let Inst{25-24} = 0b00;
3247  let Inst{23-5}  = label;
3248  let Inst{4-0}   = Rt;
3249}
3250
3251let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3252class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3253    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3254        asm, "\t$Rt, $label", "", pat>,
3255      Sched<[WriteLD]> {
3256  bits<5> Rt;
3257  bits<19> label;
3258  let Inst{31-30} = opc;
3259  let Inst{29-27} = 0b011;
3260  let Inst{26}    = V;
3261  let Inst{25-24} = 0b00;
3262  let Inst{23-5}  = label;
3263  let Inst{4-0}   = Rt;
3264}
3265
3266//---
3267// Load/store register offset
3268//---
3269
3270def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
3271def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
3272def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
3273def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
3274def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
3275
3276def gi_ro_Xindexed8 :
3277    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3278    GIComplexPatternEquiv<ro_Xindexed8>;
3279def gi_ro_Xindexed16 :
3280    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3281    GIComplexPatternEquiv<ro_Xindexed16>;
3282def gi_ro_Xindexed32 :
3283    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3284    GIComplexPatternEquiv<ro_Xindexed32>;
3285def gi_ro_Xindexed64 :
3286    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3287    GIComplexPatternEquiv<ro_Xindexed64>;
3288def gi_ro_Xindexed128 :
3289    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3290    GIComplexPatternEquiv<ro_Xindexed128>;
3291
3292def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
3293def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
3294def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
3295def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
3296def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
3297
3298def gi_ro_Windexed8 :
3299    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3300    GIComplexPatternEquiv<ro_Windexed8>;
3301def gi_ro_Windexed16 :
3302    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3303    GIComplexPatternEquiv<ro_Windexed16>;
3304def gi_ro_Windexed32 :
3305    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3306    GIComplexPatternEquiv<ro_Windexed32>;
3307def gi_ro_Windexed64 :
3308    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3309    GIComplexPatternEquiv<ro_Windexed64>;
3310def gi_ro_Windexed128 :
3311    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3312    GIComplexPatternEquiv<ro_Windexed128>;
3313
3314class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3315  let Name = "Mem" # Reg # "Extend" # Width;
3316  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3317  let RenderMethod = "addMemExtendOperands";
3318  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3319}
3320
3321def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3322  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3323  // the trivial shift.
3324  let RenderMethod = "addMemExtend8Operands";
3325}
3326def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3327def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3328def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3329def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3330
3331def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3332  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3333  // the trivial shift.
3334  let RenderMethod = "addMemExtend8Operands";
3335}
3336def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3337def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3338def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3339def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3340
3341class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3342        : Operand<i32> {
3343  let ParserMatchClass = ParserClass;
3344  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3345  let DecoderMethod = "DecodeMemExtend";
3346  let EncoderMethod = "getMemExtendOpValue";
3347  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3348}
3349
3350def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3351def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3352def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3353def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3354def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3355
3356def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3357def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3358def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3359def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3360def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3361
3362class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3363                  Operand wextend, Operand xextend>  {
3364  // CodeGen-level pattern covering the entire addressing mode.
3365  ComplexPattern Wpat = windex;
3366  ComplexPattern Xpat = xindex;
3367
3368  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3369  Operand Wext = wextend;
3370  Operand Xext = xextend;
3371}
3372
3373def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3374def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3375def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3376def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3377def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3378                       ro_Xextend128>;
3379
3380class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3381                      string asm, dag ins, dag outs, list<dag> pat>
3382    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3383  bits<5> Rt;
3384  bits<5> Rn;
3385  bits<5> Rm;
3386  bits<2> extend;
3387  let Inst{31-30} = sz;
3388  let Inst{29-27} = 0b111;
3389  let Inst{26}    = V;
3390  let Inst{25-24} = 0b00;
3391  let Inst{23-22} = opc;
3392  let Inst{21}    = 1;
3393  let Inst{20-16} = Rm;
3394  let Inst{15}    = extend{1}; // sign extend Rm?
3395  let Inst{14}    = 1;
3396  let Inst{12}    = extend{0}; // do shift?
3397  let Inst{11-10} = 0b10;
3398  let Inst{9-5}   = Rn;
3399  let Inst{4-0}   = Rt;
3400}
3401
3402class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
3403  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3404              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3405
3406multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3407                   string asm, ValueType Ty, SDPatternOperator loadop> {
3408  let AddedComplexity = 10 in
3409  def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3410                 (outs regtype:$Rt),
3411                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3412                 [(set (Ty regtype:$Rt),
3413                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3414                                             ro_Wextend8:$extend)))]>,
3415           Sched<[WriteLDIdx, ReadAdrBase]> {
3416    let Inst{13} = 0b0;
3417  }
3418
3419  let AddedComplexity = 10 in
3420  def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3421                 (outs regtype:$Rt),
3422                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3423                 [(set (Ty regtype:$Rt),
3424                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3425                                             ro_Xextend8:$extend)))]>,
3426           Sched<[WriteLDIdx, ReadAdrBase]> {
3427    let Inst{13} = 0b1;
3428  }
3429
3430  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3431}
3432
3433multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3434                    string asm, ValueType Ty, SDPatternOperator storeop> {
3435  let AddedComplexity = 10 in
3436  def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3437                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3438                 [(storeop (Ty regtype:$Rt),
3439                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3440                                         ro_Wextend8:$extend))]>,
3441            Sched<[WriteSTIdx, ReadAdrBase]> {
3442    let Inst{13} = 0b0;
3443  }
3444
3445  let AddedComplexity = 10 in
3446  def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3447                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3448                 [(storeop (Ty regtype:$Rt),
3449                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3450                                         ro_Xextend8:$extend))]>,
3451            Sched<[WriteSTIdx, ReadAdrBase]> {
3452    let Inst{13} = 0b1;
3453  }
3454
3455  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3456}
3457
3458class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3459                      string asm, dag ins, dag outs, list<dag> pat>
3460    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3461  bits<5> Rt;
3462  bits<5> Rn;
3463  bits<5> Rm;
3464  bits<2> extend;
3465  let Inst{31-30} = sz;
3466  let Inst{29-27} = 0b111;
3467  let Inst{26}    = V;
3468  let Inst{25-24} = 0b00;
3469  let Inst{23-22} = opc;
3470  let Inst{21}    = 1;
3471  let Inst{20-16} = Rm;
3472  let Inst{15}    = extend{1}; // sign extend Rm?
3473  let Inst{14}    = 1;
3474  let Inst{12}    = extend{0}; // do shift?
3475  let Inst{11-10} = 0b10;
3476  let Inst{9-5}   = Rn;
3477  let Inst{4-0}   = Rt;
3478}
3479
3480multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3481                    string asm, ValueType Ty, SDPatternOperator loadop> {
3482  let AddedComplexity = 10 in
3483  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3484                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3485                 [(set (Ty regtype:$Rt),
3486                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3487                                              ro_Wextend16:$extend)))]>,
3488            Sched<[WriteLDIdx, ReadAdrBase]> {
3489    let Inst{13} = 0b0;
3490  }
3491
3492  let AddedComplexity = 10 in
3493  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3494                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3495                 [(set (Ty regtype:$Rt),
3496                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3497                                             ro_Xextend16:$extend)))]>,
3498            Sched<[WriteLDIdx, ReadAdrBase]> {
3499    let Inst{13} = 0b1;
3500  }
3501
3502  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3503}
3504
3505multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3506                     string asm, ValueType Ty, SDPatternOperator storeop> {
3507  let AddedComplexity = 10 in
3508  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3509                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3510                [(storeop (Ty regtype:$Rt),
3511                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3512                                         ro_Wextend16:$extend))]>,
3513           Sched<[WriteSTIdx, ReadAdrBase]> {
3514    let Inst{13} = 0b0;
3515  }
3516
3517  let AddedComplexity = 10 in
3518  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3519                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3520                [(storeop (Ty regtype:$Rt),
3521                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3522                                         ro_Xextend16:$extend))]>,
3523           Sched<[WriteSTIdx, ReadAdrBase]> {
3524    let Inst{13} = 0b1;
3525  }
3526
3527  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3528}
3529
3530class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3531                      string asm, dag ins, dag outs, list<dag> pat>
3532    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3533  bits<5> Rt;
3534  bits<5> Rn;
3535  bits<5> Rm;
3536  bits<2> extend;
3537  let Inst{31-30} = sz;
3538  let Inst{29-27} = 0b111;
3539  let Inst{26}    = V;
3540  let Inst{25-24} = 0b00;
3541  let Inst{23-22} = opc;
3542  let Inst{21}    = 1;
3543  let Inst{20-16} = Rm;
3544  let Inst{15}    = extend{1}; // sign extend Rm?
3545  let Inst{14}    = 1;
3546  let Inst{12}    = extend{0}; // do shift?
3547  let Inst{11-10} = 0b10;
3548  let Inst{9-5}   = Rn;
3549  let Inst{4-0}   = Rt;
3550}
3551
3552multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3553                    string asm, ValueType Ty, SDPatternOperator loadop> {
3554  let AddedComplexity = 10 in
3555  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3556                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3557                 [(set (Ty regtype:$Rt),
3558                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3559                                              ro_Wextend32:$extend)))]>,
3560           Sched<[WriteLDIdx, ReadAdrBase]> {
3561    let Inst{13} = 0b0;
3562  }
3563
3564  let AddedComplexity = 10 in
3565  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3566                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3567                 [(set (Ty regtype:$Rt),
3568                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3569                                              ro_Xextend32:$extend)))]>,
3570           Sched<[WriteLDIdx, ReadAdrBase]> {
3571    let Inst{13} = 0b1;
3572  }
3573
3574  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3575}
3576
3577multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3578                     string asm, ValueType Ty, SDPatternOperator storeop> {
3579  let AddedComplexity = 10 in
3580  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3581                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3582                [(storeop (Ty regtype:$Rt),
3583                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3584                                         ro_Wextend32:$extend))]>,
3585            Sched<[WriteSTIdx, ReadAdrBase]> {
3586    let Inst{13} = 0b0;
3587  }
3588
3589  let AddedComplexity = 10 in
3590  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3591                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3592                [(storeop (Ty regtype:$Rt),
3593                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3594                                        ro_Xextend32:$extend))]>,
3595            Sched<[WriteSTIdx, ReadAdrBase]> {
3596    let Inst{13} = 0b1;
3597  }
3598
3599  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3600}
3601
3602class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3603                      string asm, dag ins, dag outs, list<dag> pat>
3604    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3605  bits<5> Rt;
3606  bits<5> Rn;
3607  bits<5> Rm;
3608  bits<2> extend;
3609  let Inst{31-30} = sz;
3610  let Inst{29-27} = 0b111;
3611  let Inst{26}    = V;
3612  let Inst{25-24} = 0b00;
3613  let Inst{23-22} = opc;
3614  let Inst{21}    = 1;
3615  let Inst{20-16} = Rm;
3616  let Inst{15}    = extend{1}; // sign extend Rm?
3617  let Inst{14}    = 1;
3618  let Inst{12}    = extend{0}; // do shift?
3619  let Inst{11-10} = 0b10;
3620  let Inst{9-5}   = Rn;
3621  let Inst{4-0}   = Rt;
3622}
3623
3624multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3625                    string asm, ValueType Ty, SDPatternOperator loadop> {
3626  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3627  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3628                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3629                [(set (Ty regtype:$Rt),
3630                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3631                                             ro_Wextend64:$extend)))]>,
3632           Sched<[WriteLDIdx, ReadAdrBase]> {
3633    let Inst{13} = 0b0;
3634  }
3635
3636  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3637  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3638                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3639                 [(set (Ty regtype:$Rt),
3640                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3641                                              ro_Xextend64:$extend)))]>,
3642           Sched<[WriteLDIdx, ReadAdrBase]> {
3643    let Inst{13} = 0b1;
3644  }
3645
3646  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3647}
3648
3649multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3650                     string asm, ValueType Ty, SDPatternOperator storeop> {
3651  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3652  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3653                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3654                [(storeop (Ty regtype:$Rt),
3655                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3656                                         ro_Wextend64:$extend))]>,
3657            Sched<[WriteSTIdx, ReadAdrBase]> {
3658    let Inst{13} = 0b0;
3659  }
3660
3661  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3662  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3663                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3664                [(storeop (Ty regtype:$Rt),
3665                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3666                                         ro_Xextend64:$extend))]>,
3667            Sched<[WriteSTIdx, ReadAdrBase]> {
3668    let Inst{13} = 0b1;
3669  }
3670
3671  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3672}
3673
3674class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3675                      string asm, dag ins, dag outs, list<dag> pat>
3676    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3677  bits<5> Rt;
3678  bits<5> Rn;
3679  bits<5> Rm;
3680  bits<2> extend;
3681  let Inst{31-30} = sz;
3682  let Inst{29-27} = 0b111;
3683  let Inst{26}    = V;
3684  let Inst{25-24} = 0b00;
3685  let Inst{23-22} = opc;
3686  let Inst{21}    = 1;
3687  let Inst{20-16} = Rm;
3688  let Inst{15}    = extend{1}; // sign extend Rm?
3689  let Inst{14}    = 1;
3690  let Inst{12}    = extend{0}; // do shift?
3691  let Inst{11-10} = 0b10;
3692  let Inst{9-5}   = Rn;
3693  let Inst{4-0}   = Rt;
3694}
3695
3696multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3697                     string asm, ValueType Ty, SDPatternOperator loadop> {
3698  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3699  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3700                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3701                 [(set (Ty regtype:$Rt),
3702                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3703                                               ro_Wextend128:$extend)))]>,
3704            Sched<[WriteLDIdx, ReadAdrBase]> {
3705    let Inst{13} = 0b0;
3706  }
3707
3708  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3709  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3710                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3711                 [(set (Ty regtype:$Rt),
3712                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3713                                               ro_Xextend128:$extend)))]>,
3714            Sched<[WriteLDIdx, ReadAdrBase]> {
3715    let Inst{13} = 0b1;
3716  }
3717
3718  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3719}
3720
3721multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3722                      string asm, ValueType Ty, SDPatternOperator storeop> {
3723  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3724  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3725               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3726                []>,
3727            Sched<[WriteSTIdx, ReadAdrBase]> {
3728    let Inst{13} = 0b0;
3729  }
3730
3731  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3732  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3733               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3734                []>,
3735            Sched<[WriteSTIdx, ReadAdrBase]> {
3736    let Inst{13} = 0b1;
3737  }
3738
3739  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3740}
3741
3742let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3743class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3744                     string asm, list<dag> pat>
3745    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3746      Sched<[WriteLD]> {
3747  bits<5> Rt;
3748  bits<5> Rn;
3749  bits<5> Rm;
3750  bits<2> extend;
3751  let Inst{31-30} = sz;
3752  let Inst{29-27} = 0b111;
3753  let Inst{26}    = V;
3754  let Inst{25-24} = 0b00;
3755  let Inst{23-22} = opc;
3756  let Inst{21}    = 1;
3757  let Inst{20-16} = Rm;
3758  let Inst{15}    = extend{1}; // sign extend Rm?
3759  let Inst{14}    = 1;
3760  let Inst{12}    = extend{0}; // do shift?
3761  let Inst{11-10} = 0b10;
3762  let Inst{9-5}   = Rn;
3763  let Inst{4-0}   = Rt;
3764}
3765
3766multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3767  def roW : BasePrefetchRO<sz, V, opc, (outs),
3768                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3769                asm, [(AArch64Prefetch imm:$Rt,
3770                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3771                                                    ro_Wextend64:$extend))]> {
3772    let Inst{13} = 0b0;
3773  }
3774
3775  def roX : BasePrefetchRO<sz, V, opc, (outs),
3776                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3777                asm,  [(AArch64Prefetch imm:$Rt,
3778                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3779                                                     ro_Xextend64:$extend))]> {
3780    let Inst{13} = 0b1;
3781  }
3782
3783  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3784               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3785                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3786}
3787
3788//---
3789// Load/store unscaled immediate
3790//---
3791
3792def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3793def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3794def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3795def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3796def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3797
3798def gi_am_unscaled8 :
3799    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3800    GIComplexPatternEquiv<am_unscaled8>;
3801def gi_am_unscaled16 :
3802    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3803    GIComplexPatternEquiv<am_unscaled16>;
3804def gi_am_unscaled32 :
3805    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3806    GIComplexPatternEquiv<am_unscaled32>;
3807def gi_am_unscaled64 :
3808    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3809    GIComplexPatternEquiv<am_unscaled64>;
3810def gi_am_unscaled128 :
3811    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3812    GIComplexPatternEquiv<am_unscaled128>;
3813
3814
3815class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3816                           string asm, list<dag> pattern>
3817    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3818  bits<5> Rt;
3819  bits<5> Rn;
3820  bits<9> offset;
3821  let Inst{31-30} = sz;
3822  let Inst{29-27} = 0b111;
3823  let Inst{26}    = V;
3824  let Inst{25-24} = 0b00;
3825  let Inst{23-22} = opc;
3826  let Inst{21}    = 0;
3827  let Inst{20-12} = offset;
3828  let Inst{11-10} = 0b00;
3829  let Inst{9-5}   = Rn;
3830  let Inst{4-0}   = Rt;
3831
3832  let DecoderMethod = "DecodeSignedLdStInstruction";
3833}
3834
3835// Armv8.4 LDAPR & STLR with Immediate Offset instruction
3836multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3837                              RegisterOperand regtype > {
3838  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3839                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3840          Sched<[WriteST]> {
3841    let Inst{29} = 0;
3842    let Inst{24} = 1;
3843  }
3844  def : InstAlias<asm # "\t$Rt, [$Rn]",
3845                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3846}
3847
3848multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3849                               RegisterOperand regtype > {
3850  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3851                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3852                               asm, []>,
3853          Sched<[WriteST]> {
3854    let Inst{29} = 0;
3855    let Inst{24} = 1;
3856  }
3857  def : InstAlias<asm # "\t$Rt, [$Rn]",
3858                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3859}
3860
3861multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3862                   string asm, list<dag> pattern> {
3863  let AddedComplexity = 1 in // try this before LoadUI
3864  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3865                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3866          Sched<[WriteLD]>;
3867
3868  def : InstAlias<asm # "\t$Rt, [$Rn]",
3869                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3870}
3871
3872multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3873                         string asm, list<dag> pattern> {
3874  let AddedComplexity = 1 in // try this before StoreUI
3875  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3876                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3877                               asm, pattern>,
3878          Sched<[WriteST]>;
3879
3880  def : InstAlias<asm # "\t$Rt, [$Rn]",
3881                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3882}
3883
3884multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3885                            list<dag> pat> {
3886  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3887  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3888                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3889                               asm, pat>,
3890          Sched<[WriteLD]>;
3891
3892  def : InstAlias<asm # "\t$Rt, [$Rn]",
3893                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3894}
3895
3896//---
3897// Load/store unscaled immediate, unprivileged
3898//---
3899
3900class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3901                                dag oops, dag iops, string asm>
3902    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3903  bits<5> Rt;
3904  bits<5> Rn;
3905  bits<9> offset;
3906  let Inst{31-30} = sz;
3907  let Inst{29-27} = 0b111;
3908  let Inst{26}    = V;
3909  let Inst{25-24} = 0b00;
3910  let Inst{23-22} = opc;
3911  let Inst{21}    = 0;
3912  let Inst{20-12} = offset;
3913  let Inst{11-10} = 0b10;
3914  let Inst{9-5}   = Rn;
3915  let Inst{4-0}   = Rt;
3916
3917  let DecoderMethod = "DecodeSignedLdStInstruction";
3918}
3919
3920multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3921                            RegisterClass regtype, string asm> {
3922  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3923  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3924                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
3925          Sched<[WriteLD]>;
3926
3927  def : InstAlias<asm # "\t$Rt, [$Rn]",
3928                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3929}
3930
3931multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3932                             RegisterClass regtype, string asm> {
3933  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3934  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3935                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3936                                 asm>,
3937          Sched<[WriteST]>;
3938
3939  def : InstAlias<asm # "\t$Rt, [$Rn]",
3940                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3941}
3942
3943//---
3944// Load/store pre-indexed
3945//---
3946
3947class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3948                          string asm, string cstr, list<dag> pat>
3949    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3950  bits<5> Rt;
3951  bits<5> Rn;
3952  bits<9> offset;
3953  let Inst{31-30} = sz;
3954  let Inst{29-27} = 0b111;
3955  let Inst{26}    = V;
3956  let Inst{25-24} = 0;
3957  let Inst{23-22} = opc;
3958  let Inst{21}    = 0;
3959  let Inst{20-12} = offset;
3960  let Inst{11-10} = 0b11;
3961  let Inst{9-5}   = Rn;
3962  let Inst{4-0}   = Rt;
3963
3964  let DecoderMethod = "DecodeSignedLdStInstruction";
3965}
3966
3967let hasSideEffects = 0 in {
3968let mayStore = 0, mayLoad = 1 in
3969class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3970             string asm>
3971    : BaseLoadStorePreIdx<sz, V, opc,
3972                     (outs GPR64sp:$wback, regtype:$Rt),
3973                     (ins GPR64sp:$Rn, simm9:$offset), asm,
3974                     "$Rn = $wback,@earlyclobber $wback", []>,
3975      Sched<[WriteAdr, WriteLD]>;
3976
3977let mayStore = 1, mayLoad = 0 in
3978class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3979                  string asm, SDPatternOperator storeop, ValueType Ty>
3980    : BaseLoadStorePreIdx<sz, V, opc,
3981                      (outs GPR64sp:$wback),
3982                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3983                      asm, "$Rn = $wback,@earlyclobber $wback",
3984      [(set GPR64sp:$wback,
3985            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3986      Sched<[WriteAdr, WriteST]>;
3987} // hasSideEffects = 0
3988
3989//---
3990// Load/store post-indexed
3991//---
3992
3993class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3994                          string asm, string cstr, list<dag> pat>
3995    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3996  bits<5> Rt;
3997  bits<5> Rn;
3998  bits<9> offset;
3999  let Inst{31-30} = sz;
4000  let Inst{29-27} = 0b111;
4001  let Inst{26}    = V;
4002  let Inst{25-24} = 0b00;
4003  let Inst{23-22} = opc;
4004  let Inst{21}    = 0b0;
4005  let Inst{20-12} = offset;
4006  let Inst{11-10} = 0b01;
4007  let Inst{9-5}   = Rn;
4008  let Inst{4-0}   = Rt;
4009
4010  let DecoderMethod = "DecodeSignedLdStInstruction";
4011}
4012
4013let hasSideEffects = 0 in {
4014let mayStore = 0, mayLoad = 1 in
4015class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4016             string asm>
4017    : BaseLoadStorePostIdx<sz, V, opc,
4018                      (outs GPR64sp:$wback, regtype:$Rt),
4019                      (ins GPR64sp:$Rn, simm9:$offset),
4020                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4021      Sched<[WriteAdr, WriteLD]>;
4022
4023let mayStore = 1, mayLoad = 0 in
4024class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4025                   string asm, SDPatternOperator storeop, ValueType Ty>
4026    : BaseLoadStorePostIdx<sz, V, opc,
4027                      (outs GPR64sp:$wback),
4028                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4029                       asm, "$Rn = $wback,@earlyclobber $wback",
4030      [(set GPR64sp:$wback,
4031            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4032    Sched<[WriteAdr, WriteST]>;
4033} // hasSideEffects = 0
4034
4035
4036//---
4037// Load/store pair
4038//---
4039
4040// (indexed, offset)
4041
4042class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4043                              string asm>
4044    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4045  bits<5> Rt;
4046  bits<5> Rt2;
4047  bits<5> Rn;
4048  bits<7> offset;
4049  let Inst{31-30} = opc;
4050  let Inst{29-27} = 0b101;
4051  let Inst{26}    = V;
4052  let Inst{25-23} = 0b010;
4053  let Inst{22}    = L;
4054  let Inst{21-15} = offset;
4055  let Inst{14-10} = Rt2;
4056  let Inst{9-5}   = Rn;
4057  let Inst{4-0}   = Rt;
4058
4059  let DecoderMethod = "DecodePairLdStInstruction";
4060}
4061
4062multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4063                          Operand indextype, string asm> {
4064  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4065  def i : BaseLoadStorePairOffset<opc, V, 1,
4066                                  (outs regtype:$Rt, regtype:$Rt2),
4067                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4068          Sched<[WriteLD, WriteLDHi]>;
4069
4070  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4071                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4072                                                  GPR64sp:$Rn, 0)>;
4073}
4074
4075
4076multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4077                           Operand indextype, string asm> {
4078  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4079  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4080                                  (ins regtype:$Rt, regtype:$Rt2,
4081                                       GPR64sp:$Rn, indextype:$offset),
4082                                  asm>,
4083          Sched<[WriteSTP]>;
4084
4085  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4086                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4087                                                  GPR64sp:$Rn, 0)>;
4088}
4089
4090// (pre-indexed)
4091class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4092                              string asm>
4093    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4094  bits<5> Rt;
4095  bits<5> Rt2;
4096  bits<5> Rn;
4097  bits<7> offset;
4098  let Inst{31-30} = opc;
4099  let Inst{29-27} = 0b101;
4100  let Inst{26}    = V;
4101  let Inst{25-23} = 0b011;
4102  let Inst{22}    = L;
4103  let Inst{21-15} = offset;
4104  let Inst{14-10} = Rt2;
4105  let Inst{9-5}   = Rn;
4106  let Inst{4-0}   = Rt;
4107
4108  let DecoderMethod = "DecodePairLdStInstruction";
4109}
4110
4111let hasSideEffects = 0 in {
4112let mayStore = 0, mayLoad = 1 in
4113class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4114                     Operand indextype, string asm>
4115    : BaseLoadStorePairPreIdx<opc, V, 1,
4116                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4117                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4118      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4119
4120let mayStore = 1, mayLoad = 0 in
4121class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4122                      Operand indextype, string asm>
4123    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4124                             (ins regtype:$Rt, regtype:$Rt2,
4125                                  GPR64sp:$Rn, indextype:$offset),
4126                             asm>,
4127      Sched<[WriteAdr, WriteSTP]>;
4128} // hasSideEffects = 0
4129
4130// (post-indexed)
4131
4132class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4133                              string asm>
4134    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4135  bits<5> Rt;
4136  bits<5> Rt2;
4137  bits<5> Rn;
4138  bits<7> offset;
4139  let Inst{31-30} = opc;
4140  let Inst{29-27} = 0b101;
4141  let Inst{26}    = V;
4142  let Inst{25-23} = 0b001;
4143  let Inst{22}    = L;
4144  let Inst{21-15} = offset;
4145  let Inst{14-10} = Rt2;
4146  let Inst{9-5}   = Rn;
4147  let Inst{4-0}   = Rt;
4148
4149  let DecoderMethod = "DecodePairLdStInstruction";
4150}
4151
4152let hasSideEffects = 0 in {
4153let mayStore = 0, mayLoad = 1 in
4154class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4155                      Operand idxtype, string asm>
4156    : BaseLoadStorePairPostIdx<opc, V, 1,
4157                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4158                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4159      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4160
4161let mayStore = 1, mayLoad = 0 in
4162class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4163                       Operand idxtype, string asm>
4164    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4165                             (ins regtype:$Rt, regtype:$Rt2,
4166                                  GPR64sp:$Rn, idxtype:$offset),
4167                             asm>,
4168      Sched<[WriteAdr, WriteSTP]>;
4169} // hasSideEffects = 0
4170
4171//  (no-allocate)
4172
4173class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4174                              string asm>
4175    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4176  bits<5> Rt;
4177  bits<5> Rt2;
4178  bits<5> Rn;
4179  bits<7> offset;
4180  let Inst{31-30} = opc;
4181  let Inst{29-27} = 0b101;
4182  let Inst{26}    = V;
4183  let Inst{25-23} = 0b000;
4184  let Inst{22}    = L;
4185  let Inst{21-15} = offset;
4186  let Inst{14-10} = Rt2;
4187  let Inst{9-5}   = Rn;
4188  let Inst{4-0}   = Rt;
4189
4190  let DecoderMethod = "DecodePairLdStInstruction";
4191}
4192
4193multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
4194                           Operand indextype, string asm> {
4195  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4196  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4197                                   (outs regtype:$Rt, regtype:$Rt2),
4198                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4199          Sched<[WriteLD, WriteLDHi]>;
4200
4201
4202  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4203                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4204                                                  GPR64sp:$Rn, 0)>;
4205}
4206
4207multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
4208                      Operand indextype, string asm> {
4209  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4210  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4211                                   (ins regtype:$Rt, regtype:$Rt2,
4212                                        GPR64sp:$Rn, indextype:$offset),
4213                                   asm>,
4214          Sched<[WriteSTP]>;
4215
4216  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4217                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4218                                                  GPR64sp:$Rn, 0)>;
4219}
4220
4221//---
4222// Load/store exclusive
4223//---
4224
4225// True exclusive operations write to and/or read from the system's exclusive
4226// monitors, which as far as a compiler is concerned can be modelled as a
4227// random shared memory address. Hence LoadExclusive mayStore.
4228//
4229// Since these instructions have the undefined register bits set to 1 in
4230// their canonical form, we need a post encoder method to set those bits
4231// to 1 when encoding these instructions. We do this using the
4232// fixLoadStoreExclusive function. This function has template parameters:
4233//
4234// fixLoadStoreExclusive<int hasRs, int hasRt2>
4235//
4236// hasRs indicates that the instruction uses the Rs field, so we won't set
4237// it to 1 (and the same for Rt2). We don't need template parameters for
4238// the other register fields since Rt and Rn are always used.
4239//
4240let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4241class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4242                             dag oops, dag iops, string asm, string operands>
4243    : I<oops, iops, asm, operands, "", []> {
4244  let Inst{31-30} = sz;
4245  let Inst{29-24} = 0b001000;
4246  let Inst{23}    = o2;
4247  let Inst{22}    = L;
4248  let Inst{21}    = o1;
4249  let Inst{15}    = o0;
4250
4251  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4252}
4253
4254// Neither Rs nor Rt2 operands.
4255class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4256                               dag oops, dag iops, string asm, string operands>
4257    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4258  bits<5> Rt;
4259  bits<5> Rn;
4260  let Inst{20-16} = 0b11111;
4261  let Unpredictable{20-16} = 0b11111;
4262  let Inst{14-10} = 0b11111;
4263  let Unpredictable{14-10} = 0b11111;
4264  let Inst{9-5} = Rn;
4265  let Inst{4-0} = Rt;
4266
4267  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4268}
4269
4270// Simple load acquires don't set the exclusive monitor
4271let mayLoad = 1, mayStore = 0 in
4272class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4273                  RegisterClass regtype, string asm>
4274    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4275                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4276      Sched<[WriteLD]>;
4277
4278class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4279                    RegisterClass regtype, string asm>
4280    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4281                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4282      Sched<[WriteLD]>;
4283
4284class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4285                       RegisterClass regtype, string asm>
4286    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4287                             (outs regtype:$Rt, regtype:$Rt2),
4288                             (ins GPR64sp0:$Rn), asm,
4289                             "\t$Rt, $Rt2, [$Rn]">,
4290      Sched<[WriteLD, WriteLDHi]> {
4291  bits<5> Rt;
4292  bits<5> Rt2;
4293  bits<5> Rn;
4294  let Inst{14-10} = Rt2;
4295  let Inst{9-5} = Rn;
4296  let Inst{4-0} = Rt;
4297
4298  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4299}
4300
4301// Simple store release operations do not check the exclusive monitor.
4302let mayLoad = 0, mayStore = 1 in
4303class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4304                   RegisterClass regtype, string asm>
4305    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4306                               (ins regtype:$Rt, GPR64sp0:$Rn),
4307                               asm, "\t$Rt, [$Rn]">,
4308      Sched<[WriteST]>;
4309
4310let mayLoad = 1, mayStore = 1 in
4311class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4312                     RegisterClass regtype, string asm>
4313    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4314                             (ins regtype:$Rt, GPR64sp0:$Rn),
4315                             asm, "\t$Ws, $Rt, [$Rn]">,
4316      Sched<[WriteSTX]> {
4317  bits<5> Ws;
4318  bits<5> Rt;
4319  bits<5> Rn;
4320  let Inst{20-16} = Ws;
4321  let Inst{9-5} = Rn;
4322  let Inst{4-0} = Rt;
4323
4324  let Constraints = "@earlyclobber $Ws";
4325  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4326}
4327
4328class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4329                         RegisterClass regtype, string asm>
4330    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4331                             (outs GPR32:$Ws),
4332                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4333                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4334      Sched<[WriteSTX]> {
4335  bits<5> Ws;
4336  bits<5> Rt;
4337  bits<5> Rt2;
4338  bits<5> Rn;
4339  let Inst{20-16} = Ws;
4340  let Inst{14-10} = Rt2;
4341  let Inst{9-5} = Rn;
4342  let Inst{4-0} = Rt;
4343
4344  let Constraints = "@earlyclobber $Ws";
4345}
4346
4347// Armv8.5-A Memory Tagging Extension
4348class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4349                 string asm_opnds, string cstr, dag oops, dag iops>
4350    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4351      Sched<[]> {
4352  bits<5> Rn;
4353
4354  let Inst{31-24} = 0b11011001;
4355  let Inst{23-22} = opc1;
4356  let Inst{21}    = 1;
4357  // Inst{20-12} defined by subclass
4358  let Inst{11-10} = opc2;
4359  let Inst{9-5}   = Rn;
4360  // Inst{4-0} defined by subclass
4361}
4362
4363class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4364                   dag oops, dag iops>
4365    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4366                  "", oops, iops> {
4367  bits<5> Rt;
4368
4369  let Inst{20-12} = 0b000000000;
4370  let Inst{4-0}   = Rt;
4371
4372  let mayLoad = Load;
4373}
4374
4375class MemTagLoad<string asm_insn, string asm_opnds>
4376    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4377                 (outs GPR64:$wback),
4378                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4379  bits<5> Rt;
4380  bits<9> offset;
4381
4382  let Inst{20-12} = offset;
4383  let Inst{4-0}   = Rt;
4384
4385  let mayLoad = 1;
4386}
4387
4388class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4389                     string asm_opnds, string cstr, dag oops, dag iops>
4390    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4391  bits<5> Rt;
4392  bits<9> offset;
4393
4394  let Inst{20-12} = offset;
4395  let Inst{4-0}   = Rt;
4396
4397  let mayStore = 1;
4398}
4399
4400multiclass MemTagStore<bits<2> opc1, string insn> {
4401  def Offset :
4402    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4403                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4404  def PreIndex :
4405    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4406                    "$Rn = $wback",
4407                    (outs GPR64sp:$wback),
4408                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4409  def PostIndex :
4410    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4411                    "$Rn = $wback",
4412                    (outs GPR64sp:$wback),
4413                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4414
4415  def : InstAlias<insn # "\t$Rt, [$Rn]",
4416                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4417}
4418
4419//---
4420// Exception generation
4421//---
4422
4423let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4424class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4425    : I<(outs), (ins i32_imm0_65535:$imm), asm, "\t$imm", "", []>,
4426      Sched<[WriteSys]> {
4427  bits<16> imm;
4428  let Inst{31-24} = 0b11010100;
4429  let Inst{23-21} = op1;
4430  let Inst{20-5}  = imm;
4431  let Inst{4-2}   = 0b000;
4432  let Inst{1-0}   = ll;
4433}
4434
4435//---
4436// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4437//--
4438let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4439class UDFType<bits<16> opc, string asm>
4440  : I<(outs), (ins uimm16:$imm),
4441       asm, "\t$imm", "", []>,
4442    Sched<[]> {
4443  bits<16> imm;
4444  let Inst{31-16} = opc;
4445  let Inst{15-0} = imm;
4446}
4447}
4448let Predicates = [HasFPARMv8] in {
4449
4450//---
4451// Floating point to integer conversion
4452//---
4453
4454class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4455                      RegisterClass srcType, RegisterClass dstType,
4456                      string asm, list<dag> pattern>
4457    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4458         asm, "\t$Rd, $Rn", "", pattern>,
4459      Sched<[WriteFCvt]> {
4460  bits<5> Rd;
4461  bits<5> Rn;
4462  let Inst{30-29} = 0b00;
4463  let Inst{28-24} = 0b11110;
4464  let Inst{23-22} = type;
4465  let Inst{21}    = 1;
4466  let Inst{20-19} = rmode;
4467  let Inst{18-16} = opcode;
4468  let Inst{15-10} = 0;
4469  let Inst{9-5}   = Rn;
4470  let Inst{4-0}   = Rd;
4471}
4472
4473let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4474class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4475                      RegisterClass srcType, RegisterClass dstType,
4476                      Operand immType, string asm, list<dag> pattern>
4477    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4478         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4479      Sched<[WriteFCvt]> {
4480  bits<5> Rd;
4481  bits<5> Rn;
4482  bits<6> scale;
4483  let Inst{30-29} = 0b00;
4484  let Inst{28-24} = 0b11110;
4485  let Inst{23-22} = type;
4486  let Inst{21}    = 0;
4487  let Inst{20-19} = rmode;
4488  let Inst{18-16} = opcode;
4489  let Inst{15-10} = scale;
4490  let Inst{9-5}   = Rn;
4491  let Inst{4-0}   = Rd;
4492}
4493
4494multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4495           SDPatternOperator OpN> {
4496  // Unscaled half-precision to 32-bit
4497  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4498                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4499    let Inst{31} = 0; // 32-bit GPR flag
4500    let Predicates = [HasFullFP16];
4501  }
4502
4503  // Unscaled half-precision to 64-bit
4504  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4505                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4506    let Inst{31} = 1; // 64-bit GPR flag
4507    let Predicates = [HasFullFP16];
4508  }
4509
4510  // Unscaled single-precision to 32-bit
4511  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4512                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4513    let Inst{31} = 0; // 32-bit GPR flag
4514  }
4515
4516  // Unscaled single-precision to 64-bit
4517  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4518                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4519    let Inst{31} = 1; // 64-bit GPR flag
4520  }
4521
4522  // Unscaled double-precision to 32-bit
4523  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4524                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4525    let Inst{31} = 0; // 32-bit GPR flag
4526  }
4527
4528  // Unscaled double-precision to 64-bit
4529  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4530                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4531    let Inst{31} = 1; // 64-bit GPR flag
4532  }
4533}
4534
4535multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4536                             SDPatternOperator OpN> {
4537  // Scaled half-precision to 32-bit
4538  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4539                              fixedpoint_f16_i32, asm,
4540              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4541                                          fixedpoint_f16_i32:$scale)))]> {
4542    let Inst{31} = 0; // 32-bit GPR flag
4543    let scale{5} = 1;
4544    let Predicates = [HasFullFP16];
4545  }
4546
4547  // Scaled half-precision to 64-bit
4548  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4549                              fixedpoint_f16_i64, asm,
4550              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4551                                          fixedpoint_f16_i64:$scale)))]> {
4552    let Inst{31} = 1; // 64-bit GPR flag
4553    let Predicates = [HasFullFP16];
4554  }
4555
4556  // Scaled single-precision to 32-bit
4557  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4558                              fixedpoint_f32_i32, asm,
4559              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4560                                          fixedpoint_f32_i32:$scale)))]> {
4561    let Inst{31} = 0; // 32-bit GPR flag
4562    let scale{5} = 1;
4563  }
4564
4565  // Scaled single-precision to 64-bit
4566  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4567                              fixedpoint_f32_i64, asm,
4568              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4569                                          fixedpoint_f32_i64:$scale)))]> {
4570    let Inst{31} = 1; // 64-bit GPR flag
4571  }
4572
4573  // Scaled double-precision to 32-bit
4574  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4575                              fixedpoint_f64_i32, asm,
4576              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4577                                          fixedpoint_f64_i32:$scale)))]> {
4578    let Inst{31} = 0; // 32-bit GPR flag
4579    let scale{5} = 1;
4580  }
4581
4582  // Scaled double-precision to 64-bit
4583  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4584                              fixedpoint_f64_i64, asm,
4585              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4586                                          fixedpoint_f64_i64:$scale)))]> {
4587    let Inst{31} = 1; // 64-bit GPR flag
4588  }
4589}
4590
4591//---
4592// Integer to floating point conversion
4593//---
4594
4595let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4596class BaseIntegerToFP<bit isUnsigned,
4597                      RegisterClass srcType, RegisterClass dstType,
4598                      Operand immType, string asm, list<dag> pattern>
4599    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4600         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4601      Sched<[WriteFCvt]> {
4602  bits<5> Rd;
4603  bits<5> Rn;
4604  bits<6> scale;
4605  let Inst{30-24} = 0b0011110;
4606  let Inst{21-17} = 0b00001;
4607  let Inst{16}    = isUnsigned;
4608  let Inst{15-10} = scale;
4609  let Inst{9-5}   = Rn;
4610  let Inst{4-0}   = Rd;
4611}
4612
4613class BaseIntegerToFPUnscaled<bit isUnsigned,
4614                      RegisterClass srcType, RegisterClass dstType,
4615                      ValueType dvt, string asm, SDNode node>
4616    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4617         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4618      Sched<[WriteFCvt]> {
4619  bits<5> Rd;
4620  bits<5> Rn;
4621  bits<6> scale;
4622  let Inst{30-24} = 0b0011110;
4623  let Inst{21-17} = 0b10001;
4624  let Inst{16}    = isUnsigned;
4625  let Inst{15-10} = 0b000000;
4626  let Inst{9-5}   = Rn;
4627  let Inst{4-0}   = Rd;
4628}
4629
4630multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4631  // Unscaled
4632  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4633    let Inst{31} = 0; // 32-bit GPR flag
4634    let Inst{23-22} = 0b11; // 16-bit FPR flag
4635    let Predicates = [HasFullFP16];
4636  }
4637
4638  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4639    let Inst{31} = 0; // 32-bit GPR flag
4640    let Inst{23-22} = 0b00; // 32-bit FPR flag
4641  }
4642
4643  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4644    let Inst{31} = 0; // 32-bit GPR flag
4645    let Inst{23-22} = 0b01; // 64-bit FPR flag
4646  }
4647
4648  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4649    let Inst{31} = 1; // 64-bit GPR flag
4650    let Inst{23-22} = 0b11; // 16-bit FPR flag
4651    let Predicates = [HasFullFP16];
4652  }
4653
4654  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4655    let Inst{31} = 1; // 64-bit GPR flag
4656    let Inst{23-22} = 0b00; // 32-bit FPR flag
4657  }
4658
4659  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4660    let Inst{31} = 1; // 64-bit GPR flag
4661    let Inst{23-22} = 0b01; // 64-bit FPR flag
4662  }
4663
4664  // Scaled
4665  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4666                             [(set (f16 FPR16:$Rd),
4667                                   (fdiv (node GPR32:$Rn),
4668                                         fixedpoint_f16_i32:$scale))]> {
4669    let Inst{31} = 0; // 32-bit GPR flag
4670    let Inst{23-22} = 0b11; // 16-bit FPR flag
4671    let scale{5} = 1;
4672    let Predicates = [HasFullFP16];
4673  }
4674
4675  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4676                             [(set FPR32:$Rd,
4677                                   (fdiv (node GPR32:$Rn),
4678                                         fixedpoint_f32_i32:$scale))]> {
4679    let Inst{31} = 0; // 32-bit GPR flag
4680    let Inst{23-22} = 0b00; // 32-bit FPR flag
4681    let scale{5} = 1;
4682  }
4683
4684  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4685                             [(set FPR64:$Rd,
4686                                   (fdiv (node GPR32:$Rn),
4687                                         fixedpoint_f64_i32:$scale))]> {
4688    let Inst{31} = 0; // 32-bit GPR flag
4689    let Inst{23-22} = 0b01; // 64-bit FPR flag
4690    let scale{5} = 1;
4691  }
4692
4693  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4694                             [(set (f16 FPR16:$Rd),
4695                                   (fdiv (node GPR64:$Rn),
4696                                         fixedpoint_f16_i64:$scale))]> {
4697    let Inst{31} = 1; // 64-bit GPR flag
4698    let Inst{23-22} = 0b11; // 16-bit FPR flag
4699    let Predicates = [HasFullFP16];
4700  }
4701
4702  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4703                             [(set FPR32:$Rd,
4704                                   (fdiv (node GPR64:$Rn),
4705                                         fixedpoint_f32_i64:$scale))]> {
4706    let Inst{31} = 1; // 64-bit GPR flag
4707    let Inst{23-22} = 0b00; // 32-bit FPR flag
4708  }
4709
4710  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4711                             [(set FPR64:$Rd,
4712                                   (fdiv (node GPR64:$Rn),
4713                                         fixedpoint_f64_i64:$scale))]> {
4714    let Inst{31} = 1; // 64-bit GPR flag
4715    let Inst{23-22} = 0b01; // 64-bit FPR flag
4716  }
4717}
4718
4719//---
4720// Unscaled integer <-> floating point conversion (i.e. FMOV)
4721//---
4722
4723let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4724class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4725                      RegisterClass srcType, RegisterClass dstType,
4726                      string asm>
4727    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4728        // We use COPY_TO_REGCLASS for these bitconvert operations.
4729        // copyPhysReg() expands the resultant COPY instructions after
4730        // regalloc is done. This gives greater freedom for the allocator
4731        // and related passes (coalescing, copy propagation, et. al.) to
4732        // be more effective.
4733        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4734      Sched<[WriteFCopy]> {
4735  bits<5> Rd;
4736  bits<5> Rn;
4737  let Inst{30-24} = 0b0011110;
4738  let Inst{21}    = 1;
4739  let Inst{20-19} = rmode;
4740  let Inst{18-16} = opcode;
4741  let Inst{15-10} = 0b000000;
4742  let Inst{9-5}   = Rn;
4743  let Inst{4-0}   = Rd;
4744}
4745
4746let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4747class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4748                     RegisterClass srcType, RegisterOperand dstType, string asm,
4749                     string kind>
4750    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4751        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4752      Sched<[WriteFCopy]> {
4753  bits<5> Rd;
4754  bits<5> Rn;
4755  let Inst{30-23} = 0b00111101;
4756  let Inst{21}    = 1;
4757  let Inst{20-19} = rmode;
4758  let Inst{18-16} = opcode;
4759  let Inst{15-10} = 0b000000;
4760  let Inst{9-5}   = Rn;
4761  let Inst{4-0}   = Rd;
4762
4763  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4764}
4765
4766let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4767class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4768                     RegisterOperand srcType, RegisterClass dstType, string asm,
4769                     string kind>
4770    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4771        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4772      Sched<[WriteFCopy]> {
4773  bits<5> Rd;
4774  bits<5> Rn;
4775  let Inst{30-23} = 0b00111101;
4776  let Inst{21}    = 1;
4777  let Inst{20-19} = rmode;
4778  let Inst{18-16} = opcode;
4779  let Inst{15-10} = 0b000000;
4780  let Inst{9-5}   = Rn;
4781  let Inst{4-0}   = Rd;
4782
4783  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4784}
4785
4786
4787multiclass UnscaledConversion<string asm> {
4788  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4789    let Inst{31} = 0; // 32-bit GPR flag
4790    let Inst{23-22} = 0b11; // 16-bit FPR flag
4791    let Predicates = [HasFullFP16];
4792  }
4793
4794  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4795    let Inst{31} = 1; // 64-bit GPR flag
4796    let Inst{23-22} = 0b11; // 16-bit FPR flag
4797    let Predicates = [HasFullFP16];
4798  }
4799
4800  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4801    let Inst{31} = 0; // 32-bit GPR flag
4802    let Inst{23-22} = 0b00; // 32-bit FPR flag
4803  }
4804
4805  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4806    let Inst{31} = 1; // 64-bit GPR flag
4807    let Inst{23-22} = 0b01; // 64-bit FPR flag
4808  }
4809
4810  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4811    let Inst{31} = 0; // 32-bit GPR flag
4812    let Inst{23-22} = 0b11; // 16-bit FPR flag
4813    let Predicates = [HasFullFP16];
4814  }
4815
4816  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4817    let Inst{31} = 1; // 64-bit GPR flag
4818    let Inst{23-22} = 0b11; // 16-bit FPR flag
4819    let Predicates = [HasFullFP16];
4820  }
4821
4822  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4823    let Inst{31} = 0; // 32-bit GPR flag
4824    let Inst{23-22} = 0b00; // 32-bit FPR flag
4825  }
4826
4827  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4828    let Inst{31} = 1; // 64-bit GPR flag
4829    let Inst{23-22} = 0b01; // 64-bit FPR flag
4830  }
4831
4832  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4833                                             asm, ".d"> {
4834    let Inst{31} = 1;
4835    let Inst{22} = 0;
4836  }
4837
4838  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4839                                               asm, ".d"> {
4840    let Inst{31} = 1;
4841    let Inst{22} = 0;
4842  }
4843}
4844
4845//---
4846// Floating point conversion
4847//---
4848
4849class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4850                       RegisterClass srcType, string asm, list<dag> pattern>
4851    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4852      Sched<[WriteFCvt]> {
4853  bits<5> Rd;
4854  bits<5> Rn;
4855  let Inst{31-24} = 0b00011110;
4856  let Inst{23-22} = type;
4857  let Inst{21-17} = 0b10001;
4858  let Inst{16-15} = opcode;
4859  let Inst{14-10} = 0b10000;
4860  let Inst{9-5}   = Rn;
4861  let Inst{4-0}   = Rd;
4862}
4863
4864multiclass FPConversion<string asm> {
4865  // Double-precision to Half-precision
4866  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4867                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
4868
4869  // Double-precision to Single-precision
4870  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4871                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
4872
4873  // Half-precision to Double-precision
4874  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4875                             [(set FPR64:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4876
4877  // Half-precision to Single-precision
4878  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4879                             [(set FPR32:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4880
4881  // Single-precision to Double-precision
4882  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4883                             [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4884
4885  // Single-precision to Half-precision
4886  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4887                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
4888}
4889
4890//---
4891// Single operand floating point data processing
4892//---
4893
4894let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4895class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4896                              ValueType vt, string asm, SDPatternOperator node>
4897    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4898         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4899      Sched<[WriteF]> {
4900  bits<5> Rd;
4901  bits<5> Rn;
4902  let Inst{31-24} = 0b00011110;
4903  let Inst{21}    = 0b1;
4904  let Inst{20-15} = opcode;
4905  let Inst{14-10} = 0b10000;
4906  let Inst{9-5}   = Rn;
4907  let Inst{4-0}   = Rd;
4908}
4909
4910multiclass SingleOperandFPData<bits<4> opcode, string asm,
4911                               SDPatternOperator node = null_frag> {
4912
4913  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4914    let Inst{23-22} = 0b11; // 16-bit size flag
4915    let Predicates = [HasFullFP16];
4916  }
4917
4918  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4919    let Inst{23-22} = 0b00; // 32-bit size flag
4920  }
4921
4922  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4923    let Inst{23-22} = 0b01; // 64-bit size flag
4924  }
4925}
4926
4927multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4928                  SDPatternOperator node = null_frag>{
4929
4930  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4931    let Inst{23-22} = 0b00; // 32-bit registers
4932  }
4933
4934  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4935    let Inst{23-22} = 0b01; // 64-bit registers
4936  }
4937}
4938
4939// FRInt[32|64][Z|N] instructions
4940multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4941      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4942
4943//---
4944// Two operand floating point data processing
4945//---
4946
4947let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4948class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4949                           string asm, list<dag> pat>
4950    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4951         asm, "\t$Rd, $Rn, $Rm", "", pat>,
4952      Sched<[WriteF]> {
4953  bits<5> Rd;
4954  bits<5> Rn;
4955  bits<5> Rm;
4956  let Inst{31-24} = 0b00011110;
4957  let Inst{21}    = 1;
4958  let Inst{20-16} = Rm;
4959  let Inst{15-12} = opcode;
4960  let Inst{11-10} = 0b10;
4961  let Inst{9-5}   = Rn;
4962  let Inst{4-0}   = Rd;
4963}
4964
4965multiclass TwoOperandFPData<bits<4> opcode, string asm,
4966                            SDPatternOperator node = null_frag> {
4967  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4968                         [(set (f16 FPR16:$Rd),
4969                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4970    let Inst{23-22} = 0b11; // 16-bit size flag
4971    let Predicates = [HasFullFP16];
4972  }
4973
4974  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4975                         [(set (f32 FPR32:$Rd),
4976                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4977    let Inst{23-22} = 0b00; // 32-bit size flag
4978  }
4979
4980  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4981                         [(set (f64 FPR64:$Rd),
4982                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4983    let Inst{23-22} = 0b01; // 64-bit size flag
4984  }
4985}
4986
4987multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4988  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4989                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
4990    let Inst{23-22} = 0b11; // 16-bit size flag
4991    let Predicates = [HasFullFP16];
4992  }
4993
4994  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4995                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4996    let Inst{23-22} = 0b00; // 32-bit size flag
4997  }
4998
4999  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5000                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5001    let Inst{23-22} = 0b01; // 64-bit size flag
5002  }
5003}
5004
5005
5006//---
5007// Three operand floating point data processing
5008//---
5009
5010class BaseThreeOperandFPData<bit isNegated, bit isSub,
5011                             RegisterClass regtype, string asm, list<dag> pat>
5012    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5013         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5014      Sched<[WriteFMul]> {
5015  bits<5> Rd;
5016  bits<5> Rn;
5017  bits<5> Rm;
5018  bits<5> Ra;
5019  let Inst{31-24} = 0b00011111;
5020  let Inst{21}    = isNegated;
5021  let Inst{20-16} = Rm;
5022  let Inst{15}    = isSub;
5023  let Inst{14-10} = Ra;
5024  let Inst{9-5}   = Rn;
5025  let Inst{4-0}   = Rd;
5026}
5027
5028multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5029                              SDPatternOperator node> {
5030  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5031            [(set (f16 FPR16:$Rd),
5032                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5033    let Inst{23-22} = 0b11; // 16-bit size flag
5034    let Predicates = [HasFullFP16];
5035  }
5036
5037  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5038            [(set FPR32:$Rd,
5039                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5040    let Inst{23-22} = 0b00; // 32-bit size flag
5041  }
5042
5043  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5044            [(set FPR64:$Rd,
5045                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5046    let Inst{23-22} = 0b01; // 64-bit size flag
5047  }
5048}
5049
5050//---
5051// Floating point data comparisons
5052//---
5053
5054let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5055class BaseOneOperandFPComparison<bit signalAllNans,
5056                                 RegisterClass regtype, string asm,
5057                                 list<dag> pat>
5058    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5059      Sched<[WriteFCmp]> {
5060  bits<5> Rn;
5061  let Inst{31-24} = 0b00011110;
5062  let Inst{21}    = 1;
5063
5064  let Inst{15-10} = 0b001000;
5065  let Inst{9-5}   = Rn;
5066  let Inst{4}     = signalAllNans;
5067  let Inst{3-0}   = 0b1000;
5068
5069  // Rm should be 0b00000 canonically, but we need to accept any value.
5070  let PostEncoderMethod = "fixOneOperandFPComparison";
5071}
5072
5073let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5074class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5075                                string asm, list<dag> pat>
5076    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5077      Sched<[WriteFCmp]> {
5078  bits<5> Rm;
5079  bits<5> Rn;
5080  let Inst{31-24} = 0b00011110;
5081  let Inst{21}    = 1;
5082  let Inst{20-16} = Rm;
5083  let Inst{15-10} = 0b001000;
5084  let Inst{9-5}   = Rn;
5085  let Inst{4}     = signalAllNans;
5086  let Inst{3-0}   = 0b0000;
5087}
5088
5089multiclass FPComparison<bit signalAllNans, string asm,
5090                        SDPatternOperator OpNode = null_frag> {
5091  let Defs = [NZCV] in {
5092  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5093      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5094    let Inst{23-22} = 0b11;
5095    let Predicates = [HasFullFP16];
5096  }
5097
5098  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5099      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5100    let Inst{23-22} = 0b11;
5101    let Predicates = [HasFullFP16];
5102  }
5103
5104  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5105      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5106    let Inst{23-22} = 0b00;
5107  }
5108
5109  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5110      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5111    let Inst{23-22} = 0b00;
5112  }
5113
5114  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5115      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5116    let Inst{23-22} = 0b01;
5117  }
5118
5119  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5120      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5121    let Inst{23-22} = 0b01;
5122  }
5123  } // Defs = [NZCV]
5124}
5125
5126//---
5127// Floating point conditional comparisons
5128//---
5129
5130let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5131class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5132                           string mnemonic, list<dag> pat>
5133    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5134         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5135      Sched<[WriteFCmp]> {
5136  let Uses = [NZCV];
5137  let Defs = [NZCV];
5138
5139  bits<5> Rn;
5140  bits<5> Rm;
5141  bits<4> nzcv;
5142  bits<4> cond;
5143
5144  let Inst{31-24} = 0b00011110;
5145  let Inst{21}    = 1;
5146  let Inst{20-16} = Rm;
5147  let Inst{15-12} = cond;
5148  let Inst{11-10} = 0b01;
5149  let Inst{9-5}   = Rn;
5150  let Inst{4}     = signalAllNans;
5151  let Inst{3-0}   = nzcv;
5152}
5153
5154multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5155                            SDPatternOperator OpNode = null_frag> {
5156  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5157      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5158                          (i32 imm:$cond), NZCV))]> {
5159    let Inst{23-22} = 0b11;
5160    let Predicates = [HasFullFP16];
5161  }
5162
5163  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5164      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5165                          (i32 imm:$cond), NZCV))]> {
5166    let Inst{23-22} = 0b00;
5167  }
5168
5169  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5170      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5171                          (i32 imm:$cond), NZCV))]> {
5172    let Inst{23-22} = 0b01;
5173  }
5174}
5175
5176//---
5177// Floating point conditional select
5178//---
5179
5180class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5181    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5182         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5183         [(set regtype:$Rd,
5184               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5185                          (i32 imm:$cond), NZCV))]>,
5186      Sched<[WriteF]> {
5187  bits<5> Rd;
5188  bits<5> Rn;
5189  bits<5> Rm;
5190  bits<4> cond;
5191
5192  let Inst{31-24} = 0b00011110;
5193  let Inst{21}    = 1;
5194  let Inst{20-16} = Rm;
5195  let Inst{15-12} = cond;
5196  let Inst{11-10} = 0b11;
5197  let Inst{9-5}   = Rn;
5198  let Inst{4-0}   = Rd;
5199}
5200
5201multiclass FPCondSelect<string asm> {
5202  let Uses = [NZCV] in {
5203  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5204    let Inst{23-22} = 0b11;
5205    let Predicates = [HasFullFP16];
5206  }
5207
5208  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5209    let Inst{23-22} = 0b00;
5210  }
5211
5212  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5213    let Inst{23-22} = 0b01;
5214  }
5215  } // Uses = [NZCV]
5216}
5217
5218//---
5219// Floating move immediate
5220//---
5221
5222class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5223  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5224      [(set regtype:$Rd, fpimmtype:$imm)]>,
5225    Sched<[WriteFImm]> {
5226  bits<5> Rd;
5227  bits<8> imm;
5228  let Inst{31-24} = 0b00011110;
5229  let Inst{21}    = 1;
5230  let Inst{20-13} = imm;
5231  let Inst{12-5}  = 0b10000000;
5232  let Inst{4-0}   = Rd;
5233}
5234
5235multiclass FPMoveImmediate<string asm> {
5236  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5237    let Inst{23-22} = 0b11;
5238    let Predicates = [HasFullFP16];
5239  }
5240
5241  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5242    let Inst{23-22} = 0b00;
5243  }
5244
5245  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5246    let Inst{23-22} = 0b01;
5247  }
5248}
5249} // end of 'let Predicates = [HasFPARMv8]'
5250
5251//----------------------------------------------------------------------------
5252// AdvSIMD
5253//----------------------------------------------------------------------------
5254
5255let Predicates = [HasNEON] in {
5256
5257//----------------------------------------------------------------------------
5258// AdvSIMD three register vector instructions
5259//----------------------------------------------------------------------------
5260
5261let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5262class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5263                        RegisterOperand regtype, string asm, string kind,
5264                        list<dag> pattern>
5265  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5266      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5267      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5268    Sched<[WriteV]> {
5269  bits<5> Rd;
5270  bits<5> Rn;
5271  bits<5> Rm;
5272  let Inst{31}    = 0;
5273  let Inst{30}    = Q;
5274  let Inst{29}    = U;
5275  let Inst{28-24} = 0b01110;
5276  let Inst{23-21} = size;
5277  let Inst{20-16} = Rm;
5278  let Inst{15-11} = opcode;
5279  let Inst{10}    = 1;
5280  let Inst{9-5}   = Rn;
5281  let Inst{4-0}   = Rd;
5282}
5283
5284let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5285class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5286                        RegisterOperand regtype, string asm, string kind,
5287                        list<dag> pattern>
5288  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5289      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5290      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5291    Sched<[WriteV]> {
5292  bits<5> Rd;
5293  bits<5> Rn;
5294  bits<5> Rm;
5295  let Inst{31}    = 0;
5296  let Inst{30}    = Q;
5297  let Inst{29}    = U;
5298  let Inst{28-24} = 0b01110;
5299  let Inst{23-21} = size;
5300  let Inst{20-16} = Rm;
5301  let Inst{15-11} = opcode;
5302  let Inst{10}    = 1;
5303  let Inst{9-5}   = Rn;
5304  let Inst{4-0}   = Rd;
5305}
5306
5307let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5308class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5309  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5310    Sched<[WriteV]>;
5311
5312multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5313  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5314             [(set (v8i8 V64:$dst),
5315                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5316  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5317             [(set (v16i8 V128:$dst),
5318                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5319                           (v16i8 V128:$Rm)))]>;
5320
5321  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5322                           (v4i16 V64:$RHS))),
5323          (!cast<Instruction>(NAME#"v8i8")
5324            V64:$LHS, V64:$MHS, V64:$RHS)>;
5325  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5326                           (v2i32 V64:$RHS))),
5327          (!cast<Instruction>(NAME#"v8i8")
5328            V64:$LHS, V64:$MHS, V64:$RHS)>;
5329  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5330                           (v1i64 V64:$RHS))),
5331          (!cast<Instruction>(NAME#"v8i8")
5332            V64:$LHS, V64:$MHS, V64:$RHS)>;
5333
5334  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5335                           (v8i16 V128:$RHS))),
5336      (!cast<Instruction>(NAME#"v16i8")
5337        V128:$LHS, V128:$MHS, V128:$RHS)>;
5338  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5339                           (v4i32 V128:$RHS))),
5340      (!cast<Instruction>(NAME#"v16i8")
5341        V128:$LHS, V128:$MHS, V128:$RHS)>;
5342  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5343                           (v2i64 V128:$RHS))),
5344      (!cast<Instruction>(NAME#"v16i8")
5345        V128:$LHS, V128:$MHS, V128:$RHS)>;
5346}
5347
5348// All operand sizes distinguished in the encoding.
5349multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5350                               SDPatternOperator OpNode> {
5351  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5352                                      asm, ".8b",
5353         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5354  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5355                                      asm, ".16b",
5356         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5357  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5358                                      asm, ".4h",
5359         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5360  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5361                                      asm, ".8h",
5362         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5363  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5364                                      asm, ".2s",
5365         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5366  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5367                                      asm, ".4s",
5368         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5369  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5370                                      asm, ".2d",
5371         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5372}
5373
5374multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5375  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5376          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5377  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5378          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5379  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5380          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5381
5382  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5383          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5384  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5385          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5386  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5387          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5388  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5389          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5390}
5391
5392// As above, but D sized elements unsupported.
5393multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5394                                  SDPatternOperator OpNode> {
5395  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5396                                      asm, ".8b",
5397        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5398  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5399                                      asm, ".16b",
5400        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5401  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5402                                      asm, ".4h",
5403        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5404  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5405                                      asm, ".8h",
5406        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5407  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5408                                      asm, ".2s",
5409        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5410  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5411                                      asm, ".4s",
5412        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5413}
5414
5415multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5416                                  SDPatternOperator OpNode> {
5417  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5418                                      asm, ".8b",
5419      [(set (v8i8 V64:$dst),
5420            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5421  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5422                                      asm, ".16b",
5423      [(set (v16i8 V128:$dst),
5424            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5425  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5426                                      asm, ".4h",
5427      [(set (v4i16 V64:$dst),
5428            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5429  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5430                                      asm, ".8h",
5431      [(set (v8i16 V128:$dst),
5432            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5433  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5434                                      asm, ".2s",
5435      [(set (v2i32 V64:$dst),
5436            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5437  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5438                                      asm, ".4s",
5439      [(set (v4i32 V128:$dst),
5440            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5441}
5442
5443// As above, but only B sized elements supported.
5444multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5445                                SDPatternOperator OpNode> {
5446  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5447                                      asm, ".8b",
5448    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5449  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5450                                      asm, ".16b",
5451    [(set (v16i8 V128:$Rd),
5452          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5453}
5454
5455// As above, but only floating point elements supported.
5456multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5457                                 string asm, SDPatternOperator OpNode> {
5458  let Predicates = [HasNEON, HasFullFP16] in {
5459  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5460                                      asm, ".4h",
5461        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5462  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5463                                      asm, ".8h",
5464        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5465  } // Predicates = [HasNEON, HasFullFP16]
5466  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5467                                      asm, ".2s",
5468        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5469  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5470                                      asm, ".4s",
5471        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5472  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5473                                      asm, ".2d",
5474        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5475}
5476
5477multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5478                                    string asm,
5479                                    SDPatternOperator OpNode> {
5480  let Predicates = [HasNEON, HasFullFP16] in {
5481  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5482                                      asm, ".4h",
5483        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5484  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5485                                      asm, ".8h",
5486        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5487  } // Predicates = [HasNEON, HasFullFP16]
5488  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5489                                      asm, ".2s",
5490        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5491  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5492                                      asm, ".4s",
5493        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5494  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5495                                      asm, ".2d",
5496        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5497}
5498
5499multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5500                                 string asm, SDPatternOperator OpNode> {
5501  let Predicates = [HasNEON, HasFullFP16] in {
5502  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5503                                      asm, ".4h",
5504     [(set (v4f16 V64:$dst),
5505           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5506  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5507                                      asm, ".8h",
5508     [(set (v8f16 V128:$dst),
5509           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5510  } // Predicates = [HasNEON, HasFullFP16]
5511  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5512                                      asm, ".2s",
5513     [(set (v2f32 V64:$dst),
5514           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5515  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5516                                      asm, ".4s",
5517     [(set (v4f32 V128:$dst),
5518           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5519  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5520                                      asm, ".2d",
5521     [(set (v2f64 V128:$dst),
5522           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5523}
5524
5525// As above, but D and B sized elements unsupported.
5526multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5527                                SDPatternOperator OpNode> {
5528  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5529                                      asm, ".4h",
5530        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5531  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5532                                      asm, ".8h",
5533        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5534  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5535                                      asm, ".2s",
5536        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5537  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5538                                      asm, ".4s",
5539        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5540}
5541
5542// Logical three vector ops share opcode bits, and only use B sized elements.
5543multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5544                                  SDPatternOperator OpNode = null_frag> {
5545  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5546                                     asm, ".8b",
5547                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5548  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5549                                     asm, ".16b",
5550                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5551
5552  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5553          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5554  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5555          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5556  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5557          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5558
5559  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5560      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5561  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5562      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5563  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5564      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5565}
5566
5567multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5568                                  string asm, SDPatternOperator OpNode = null_frag> {
5569  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5570                                     asm, ".8b",
5571             [(set (v8i8 V64:$dst),
5572                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5573  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5574                                     asm, ".16b",
5575             [(set (v16i8 V128:$dst),
5576                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5577                           (v16i8 V128:$Rm)))]>;
5578
5579  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5580                           (v4i16 V64:$RHS))),
5581          (!cast<Instruction>(NAME#"v8i8")
5582            V64:$LHS, V64:$MHS, V64:$RHS)>;
5583  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5584                           (v2i32 V64:$RHS))),
5585          (!cast<Instruction>(NAME#"v8i8")
5586            V64:$LHS, V64:$MHS, V64:$RHS)>;
5587  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5588                           (v1i64 V64:$RHS))),
5589          (!cast<Instruction>(NAME#"v8i8")
5590            V64:$LHS, V64:$MHS, V64:$RHS)>;
5591
5592  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5593                           (v8i16 V128:$RHS))),
5594      (!cast<Instruction>(NAME#"v16i8")
5595        V128:$LHS, V128:$MHS, V128:$RHS)>;
5596  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5597                           (v4i32 V128:$RHS))),
5598      (!cast<Instruction>(NAME#"v16i8")
5599        V128:$LHS, V128:$MHS, V128:$RHS)>;
5600  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5601                           (v2i64 V128:$RHS))),
5602      (!cast<Instruction>(NAME#"v16i8")
5603        V128:$LHS, V128:$MHS, V128:$RHS)>;
5604}
5605
5606// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5607// bytes from S-sized elements.
5608class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5609                                 string kind2, RegisterOperand RegType,
5610                                 ValueType AccumType, ValueType InputType,
5611                                 SDPatternOperator OpNode> :
5612        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5613        [(set (AccumType RegType:$dst),
5614              (OpNode (AccumType RegType:$Rd),
5615                      (InputType RegType:$Rn),
5616                      (InputType RegType:$Rm)))]> {
5617  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5618}
5619
5620multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5621  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5622                                         v2i32, v8i8, OpNode>;
5623  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5624                                         v4i32, v16i8, OpNode>;
5625}
5626
5627// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5628// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5629// 8H to 4S, when Q=1).
5630class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5631                                 string kind2, RegisterOperand RegType,
5632                                 ValueType AccumType, ValueType InputType,
5633                                 SDPatternOperator OpNode> :
5634        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5635		[(set (AccumType RegType:$dst),
5636              (OpNode (AccumType RegType:$Rd),
5637                      (InputType RegType:$Rn),
5638                      (InputType RegType:$Rm)))]> {
5639  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5640  let Inst{13} = b13;
5641}
5642
5643multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5644                                  SDPatternOperator OpNode> {
5645  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5646                                         v2f32, v4f16, OpNode>;
5647  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5648                                         v4f32, v8f16, OpNode>;
5649}
5650
5651
5652//----------------------------------------------------------------------------
5653// AdvSIMD two register vector instructions.
5654//----------------------------------------------------------------------------
5655
5656let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5657class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5658                            bits<2> size2, RegisterOperand regtype, string asm,
5659                            string dstkind, string srckind, list<dag> pattern>
5660  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5661      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5662      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5663    Sched<[WriteV]> {
5664  bits<5> Rd;
5665  bits<5> Rn;
5666  let Inst{31}    = 0;
5667  let Inst{30}    = Q;
5668  let Inst{29}    = U;
5669  let Inst{28-24} = 0b01110;
5670  let Inst{23-22} = size;
5671  let Inst{21} = 0b1;
5672  let Inst{20-19} = size2;
5673  let Inst{18-17} = 0b00;
5674  let Inst{16-12} = opcode;
5675  let Inst{11-10} = 0b10;
5676  let Inst{9-5}   = Rn;
5677  let Inst{4-0}   = Rd;
5678}
5679
5680let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5681class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5682                                bits<2> size2, RegisterOperand regtype,
5683                                string asm, string dstkind, string srckind,
5684                                list<dag> pattern>
5685  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5686      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5687      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5688    Sched<[WriteV]> {
5689  bits<5> Rd;
5690  bits<5> Rn;
5691  let Inst{31}    = 0;
5692  let Inst{30}    = Q;
5693  let Inst{29}    = U;
5694  let Inst{28-24} = 0b01110;
5695  let Inst{23-22} = size;
5696  let Inst{21} = 0b1;
5697  let Inst{20-19} = size2;
5698  let Inst{18-17} = 0b00;
5699  let Inst{16-12} = opcode;
5700  let Inst{11-10} = 0b10;
5701  let Inst{9-5}   = Rn;
5702  let Inst{4-0}   = Rd;
5703}
5704
5705// Supports B, H, and S element sizes.
5706multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5707                            SDPatternOperator OpNode> {
5708  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5709                                      asm, ".8b", ".8b",
5710                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5711  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5712                                      asm, ".16b", ".16b",
5713                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5714  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5715                                      asm, ".4h", ".4h",
5716                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5717  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5718                                      asm, ".8h", ".8h",
5719                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5720  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5721                                      asm, ".2s", ".2s",
5722                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5723  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5724                                      asm, ".4s", ".4s",
5725                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5726}
5727
5728class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5729                            RegisterOperand regtype, string asm, string dstkind,
5730                            string srckind, string amount>
5731  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5732      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5733      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5734    Sched<[WriteV]> {
5735  bits<5> Rd;
5736  bits<5> Rn;
5737  let Inst{31}    = 0;
5738  let Inst{30}    = Q;
5739  let Inst{29-24} = 0b101110;
5740  let Inst{23-22} = size;
5741  let Inst{21-10} = 0b100001001110;
5742  let Inst{9-5}   = Rn;
5743  let Inst{4-0}   = Rd;
5744}
5745
5746multiclass SIMDVectorLShiftLongBySizeBHS {
5747  let hasSideEffects = 0 in {
5748  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5749                                             "shll", ".8h",  ".8b", "8">;
5750  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5751                                             "shll2", ".8h", ".16b", "8">;
5752  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5753                                             "shll", ".4s",  ".4h", "16">;
5754  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5755                                             "shll2", ".4s", ".8h", "16">;
5756  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5757                                             "shll", ".2d",  ".2s", "32">;
5758  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5759                                             "shll2", ".2d", ".4s", "32">;
5760  }
5761}
5762
5763// Supports all element sizes.
5764multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5765                             SDPatternOperator OpNode> {
5766  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5767                                      asm, ".4h", ".8b",
5768               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5769  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5770                                      asm, ".8h", ".16b",
5771               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5772  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5773                                      asm, ".2s", ".4h",
5774               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5775  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5776                                      asm, ".4s", ".8h",
5777               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5778  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5779                                      asm, ".1d", ".2s",
5780               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5781  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5782                                      asm, ".2d", ".4s",
5783               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5784}
5785
5786multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5787                                 SDPatternOperator OpNode> {
5788  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5789                                          asm, ".4h", ".8b",
5790      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5791                                      (v8i8 V64:$Rn)))]>;
5792  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5793                                          asm, ".8h", ".16b",
5794      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5795                                      (v16i8 V128:$Rn)))]>;
5796  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5797                                          asm, ".2s", ".4h",
5798      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5799                                      (v4i16 V64:$Rn)))]>;
5800  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5801                                          asm, ".4s", ".8h",
5802      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5803                                      (v8i16 V128:$Rn)))]>;
5804  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5805                                          asm, ".1d", ".2s",
5806      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5807                                      (v2i32 V64:$Rn)))]>;
5808  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5809                                          asm, ".2d", ".4s",
5810      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5811                                      (v4i32 V128:$Rn)))]>;
5812}
5813
5814// Supports all element sizes, except 1xD.
5815multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5816                                  SDPatternOperator OpNode> {
5817  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5818                                    asm, ".8b", ".8b",
5819    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5820  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5821                                    asm, ".16b", ".16b",
5822    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5823  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5824                                    asm, ".4h", ".4h",
5825    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5826  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5827                                    asm, ".8h", ".8h",
5828    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5829  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5830                                    asm, ".2s", ".2s",
5831    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5832  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5833                                    asm, ".4s", ".4s",
5834    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5835  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5836                                    asm, ".2d", ".2d",
5837    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5838}
5839
5840multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5841                             SDPatternOperator OpNode = null_frag> {
5842  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5843                                asm, ".8b", ".8b",
5844    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5845  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5846                                asm, ".16b", ".16b",
5847    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5848  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5849                                asm, ".4h", ".4h",
5850    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5851  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5852                                asm, ".8h", ".8h",
5853    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5854  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5855                                asm, ".2s", ".2s",
5856    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5857  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5858                                asm, ".4s", ".4s",
5859    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5860  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5861                                asm, ".2d", ".2d",
5862    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5863}
5864
5865
5866// Supports only B element sizes.
5867multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5868                          SDPatternOperator OpNode> {
5869  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5870                                asm, ".8b", ".8b",
5871                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5872  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5873                                asm, ".16b", ".16b",
5874                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5875
5876}
5877
5878// Supports only B and H element sizes.
5879multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5880                                SDPatternOperator OpNode> {
5881  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5882                                asm, ".8b", ".8b",
5883                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5884  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5885                                asm, ".16b", ".16b",
5886                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5887  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5888                                asm, ".4h", ".4h",
5889                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5890  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5891                                asm, ".8h", ".8h",
5892                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5893}
5894
5895// Supports H, S and D element sizes, uses high bit of the size field
5896// as an extra opcode bit.
5897multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5898                           SDPatternOperator OpNode> {
5899  let Predicates = [HasNEON, HasFullFP16] in {
5900  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5901                                asm, ".4h", ".4h",
5902                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5903  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5904                                asm, ".8h", ".8h",
5905                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5906  } // Predicates = [HasNEON, HasFullFP16]
5907  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5908                                asm, ".2s", ".2s",
5909                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5910  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5911                                asm, ".4s", ".4s",
5912                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5913  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5914                                asm, ".2d", ".2d",
5915                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5916}
5917
5918// Supports only S and D element sizes
5919multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5920                           SDPatternOperator OpNode = null_frag> {
5921
5922  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5923                                asm, ".2s", ".2s",
5924                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5925  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5926                                asm, ".4s", ".4s",
5927                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5928  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5929                                asm, ".2d", ".2d",
5930                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5931}
5932
5933multiclass FRIntNNTVector<bit U, bit op, string asm,
5934                          SDPatternOperator OpNode = null_frag> :
5935           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5936
5937// Supports only S element size.
5938multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5939                           SDPatternOperator OpNode> {
5940  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5941                                asm, ".2s", ".2s",
5942                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5943  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5944                                asm, ".4s", ".4s",
5945                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5946}
5947
5948
5949multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5950                           SDPatternOperator OpNode> {
5951  let Predicates = [HasNEON, HasFullFP16] in {
5952  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5953                                asm, ".4h", ".4h",
5954                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5955  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5956                                asm, ".8h", ".8h",
5957                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5958  } // Predicates = [HasNEON, HasFullFP16]
5959  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5960                                asm, ".2s", ".2s",
5961                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5962  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5963                                asm, ".4s", ".4s",
5964                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5965  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5966                                asm, ".2d", ".2d",
5967                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5968}
5969
5970multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5971                           SDPatternOperator OpNode> {
5972  let Predicates = [HasNEON, HasFullFP16] in {
5973  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5974                                asm, ".4h", ".4h",
5975                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5976  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5977                                asm, ".8h", ".8h",
5978                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5979  } // Predicates = [HasNEON, HasFullFP16]
5980  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5981                                asm, ".2s", ".2s",
5982                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5983  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5984                                asm, ".4s", ".4s",
5985                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5986  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5987                                asm, ".2d", ".2d",
5988                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5989}
5990
5991
5992class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5993                           RegisterOperand inreg, RegisterOperand outreg,
5994                           string asm, string outkind, string inkind,
5995                           list<dag> pattern>
5996  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5997      "{\t$Rd" # outkind # ", $Rn" # inkind #
5998      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5999    Sched<[WriteV]> {
6000  bits<5> Rd;
6001  bits<5> Rn;
6002  let Inst{31}    = 0;
6003  let Inst{30}    = Q;
6004  let Inst{29}    = U;
6005  let Inst{28-24} = 0b01110;
6006  let Inst{23-22} = size;
6007  let Inst{21-17} = 0b10000;
6008  let Inst{16-12} = opcode;
6009  let Inst{11-10} = 0b10;
6010  let Inst{9-5}   = Rn;
6011  let Inst{4-0}   = Rd;
6012}
6013
6014class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6015                           RegisterOperand inreg, RegisterOperand outreg,
6016                           string asm, string outkind, string inkind,
6017                           list<dag> pattern>
6018  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6019      "{\t$Rd" # outkind # ", $Rn" # inkind #
6020      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6021    Sched<[WriteV]> {
6022  bits<5> Rd;
6023  bits<5> Rn;
6024  let Inst{31}    = 0;
6025  let Inst{30}    = Q;
6026  let Inst{29}    = U;
6027  let Inst{28-24} = 0b01110;
6028  let Inst{23-22} = size;
6029  let Inst{21-17} = 0b10000;
6030  let Inst{16-12} = opcode;
6031  let Inst{11-10} = 0b10;
6032  let Inst{9-5}   = Rn;
6033  let Inst{4-0}   = Rd;
6034}
6035
6036multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6037                              SDPatternOperator OpNode> {
6038  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6039                                      asm, ".8b", ".8h",
6040        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6041  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6042                                      asm#"2", ".16b", ".8h", []>;
6043  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6044                                      asm, ".4h", ".4s",
6045        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6046  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6047                                      asm#"2", ".8h", ".4s", []>;
6048  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6049                                      asm, ".2s", ".2d",
6050        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6051  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6052                                      asm#"2", ".4s", ".2d", []>;
6053
6054  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6055            (!cast<Instruction>(NAME # "v16i8")
6056                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6057  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6058            (!cast<Instruction>(NAME # "v8i16")
6059                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6060  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6061            (!cast<Instruction>(NAME # "v4i32")
6062                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6063}
6064
6065class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6066                           bits<5> opcode, RegisterOperand regtype, string asm,
6067                           string kind, string zero, ValueType dty,
6068                           ValueType sty, SDNode OpNode>
6069  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6070      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6071      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6072      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6073    Sched<[WriteV]> {
6074  bits<5> Rd;
6075  bits<5> Rn;
6076  let Inst{31}    = 0;
6077  let Inst{30}    = Q;
6078  let Inst{29}    = U;
6079  let Inst{28-24} = 0b01110;
6080  let Inst{23-22} = size;
6081  let Inst{21} = 0b1;
6082  let Inst{20-19} = size2;
6083  let Inst{18-17} = 0b00;
6084  let Inst{16-12} = opcode;
6085  let Inst{11-10} = 0b10;
6086  let Inst{9-5}   = Rn;
6087  let Inst{4-0}   = Rd;
6088}
6089
6090// Comparisons support all element sizes, except 1xD.
6091multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6092                            SDNode OpNode> {
6093  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6094                                     asm, ".8b", "0",
6095                                     v8i8, v8i8, OpNode>;
6096  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6097                                     asm, ".16b", "0",
6098                                     v16i8, v16i8, OpNode>;
6099  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6100                                     asm, ".4h", "0",
6101                                     v4i16, v4i16, OpNode>;
6102  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6103                                     asm, ".8h", "0",
6104                                     v8i16, v8i16, OpNode>;
6105  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6106                                     asm, ".2s", "0",
6107                                     v2i32, v2i32, OpNode>;
6108  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6109                                     asm, ".4s", "0",
6110                                     v4i32, v4i32, OpNode>;
6111  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6112                                     asm, ".2d", "0",
6113                                     v2i64, v2i64, OpNode>;
6114}
6115
6116// FP Comparisons support only S and D element sizes (and H for v8.2a).
6117multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6118                              string asm, SDNode OpNode> {
6119
6120  let Predicates = [HasNEON, HasFullFP16] in {
6121  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6122                                     asm, ".4h", "0.0",
6123                                     v4i16, v4f16, OpNode>;
6124  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6125                                     asm, ".8h", "0.0",
6126                                     v8i16, v8f16, OpNode>;
6127  } // Predicates = [HasNEON, HasFullFP16]
6128  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6129                                     asm, ".2s", "0.0",
6130                                     v2i32, v2f32, OpNode>;
6131  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6132                                     asm, ".4s", "0.0",
6133                                     v4i32, v4f32, OpNode>;
6134  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6135                                     asm, ".2d", "0.0",
6136                                     v2i64, v2f64, OpNode>;
6137
6138  let Predicates = [HasNEON, HasFullFP16] in {
6139  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6140                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6141  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6142                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6143  }
6144  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6145                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6146  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6147                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6148  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6149                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6150  let Predicates = [HasNEON, HasFullFP16] in {
6151  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6152                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6153  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6154                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6155  }
6156  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6157                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6158  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6159                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6160  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6161                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6162}
6163
6164let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6165class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6166                             RegisterOperand outtype, RegisterOperand intype,
6167                             string asm, string VdTy, string VnTy,
6168                             list<dag> pattern>
6169  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6170      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6171    Sched<[WriteV]> {
6172  bits<5> Rd;
6173  bits<5> Rn;
6174  let Inst{31}    = 0;
6175  let Inst{30}    = Q;
6176  let Inst{29}    = U;
6177  let Inst{28-24} = 0b01110;
6178  let Inst{23-22} = size;
6179  let Inst{21-17} = 0b10000;
6180  let Inst{16-12} = opcode;
6181  let Inst{11-10} = 0b10;
6182  let Inst{9-5}   = Rn;
6183  let Inst{4-0}   = Rd;
6184}
6185
6186class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6187                             RegisterOperand outtype, RegisterOperand intype,
6188                             string asm, string VdTy, string VnTy,
6189                             list<dag> pattern>
6190  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6191      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6192    Sched<[WriteV]> {
6193  bits<5> Rd;
6194  bits<5> Rn;
6195  let Inst{31}    = 0;
6196  let Inst{30}    = Q;
6197  let Inst{29}    = U;
6198  let Inst{28-24} = 0b01110;
6199  let Inst{23-22} = size;
6200  let Inst{21-17} = 0b10000;
6201  let Inst{16-12} = opcode;
6202  let Inst{11-10} = 0b10;
6203  let Inst{9-5}   = Rn;
6204  let Inst{4-0}   = Rd;
6205}
6206
6207multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6208  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6209                                    asm, ".4s", ".4h", []>;
6210  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6211                                    asm#"2", ".4s", ".8h", []>;
6212  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6213                                    asm, ".2d", ".2s", []>;
6214  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6215                                    asm#"2", ".2d", ".4s", []>;
6216}
6217
6218multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6219  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6220                                    asm, ".4h", ".4s", []>;
6221  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6222                                    asm#"2", ".8h", ".4s", []>;
6223  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6224                                    asm, ".2s", ".2d", []>;
6225  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6226                                    asm#"2", ".4s", ".2d", []>;
6227}
6228
6229multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6230                                     Intrinsic OpNode> {
6231  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6232                                     asm, ".2s", ".2d",
6233                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6234  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6235                                    asm#"2", ".4s", ".2d", []>;
6236
6237  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6238            (!cast<Instruction>(NAME # "v4f32")
6239                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6240}
6241
6242//----------------------------------------------------------------------------
6243// AdvSIMD three register different-size vector instructions.
6244//----------------------------------------------------------------------------
6245
6246let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6247class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6248                      RegisterOperand outtype, RegisterOperand intype1,
6249                      RegisterOperand intype2, string asm,
6250                      string outkind, string inkind1, string inkind2,
6251                      list<dag> pattern>
6252  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6253      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6254      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6255    Sched<[WriteV]> {
6256  bits<5> Rd;
6257  bits<5> Rn;
6258  bits<5> Rm;
6259  let Inst{31}    = 0;
6260  let Inst{30}    = size{0};
6261  let Inst{29}    = U;
6262  let Inst{28-24} = 0b01110;
6263  let Inst{23-22} = size{2-1};
6264  let Inst{21}    = 1;
6265  let Inst{20-16} = Rm;
6266  let Inst{15-12} = opcode;
6267  let Inst{11-10} = 0b00;
6268  let Inst{9-5}   = Rn;
6269  let Inst{4-0}   = Rd;
6270}
6271
6272let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6273class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6274                      RegisterOperand outtype, RegisterOperand intype1,
6275                      RegisterOperand intype2, string asm,
6276                      string outkind, string inkind1, string inkind2,
6277                      list<dag> pattern>
6278  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6279      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6280      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6281    Sched<[WriteV]> {
6282  bits<5> Rd;
6283  bits<5> Rn;
6284  bits<5> Rm;
6285  let Inst{31}    = 0;
6286  let Inst{30}    = size{0};
6287  let Inst{29}    = U;
6288  let Inst{28-24} = 0b01110;
6289  let Inst{23-22} = size{2-1};
6290  let Inst{21}    = 1;
6291  let Inst{20-16} = Rm;
6292  let Inst{15-12} = opcode;
6293  let Inst{11-10} = 0b00;
6294  let Inst{9-5}   = Rn;
6295  let Inst{4-0}   = Rd;
6296}
6297
6298// FIXME: TableGen doesn't know how to deal with expanded types that also
6299//        change the element count (in this case, placing the results in
6300//        the high elements of the result register rather than the low
6301//        elements). Until that's fixed, we can't code-gen those.
6302multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6303                                    Intrinsic IntOp> {
6304  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6305                                                  V64, V128, V128,
6306                                                  asm, ".8b", ".8h", ".8h",
6307     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6308  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6309                                                  V128, V128, V128,
6310                                                  asm#"2", ".16b", ".8h", ".8h",
6311     []>;
6312  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6313                                                  V64, V128, V128,
6314                                                  asm, ".4h", ".4s", ".4s",
6315     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6316  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6317                                                  V128, V128, V128,
6318                                                  asm#"2", ".8h", ".4s", ".4s",
6319     []>;
6320  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6321                                                  V64, V128, V128,
6322                                                  asm, ".2s", ".2d", ".2d",
6323     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6324  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6325                                                  V128, V128, V128,
6326                                                  asm#"2", ".4s", ".2d", ".2d",
6327     []>;
6328
6329
6330  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6331  // a version attached to an instruction.
6332  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6333                                                   (v8i16 V128:$Rm))),
6334            (!cast<Instruction>(NAME # "v8i16_v16i8")
6335                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6336                V128:$Rn, V128:$Rm)>;
6337  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6338                                                    (v4i32 V128:$Rm))),
6339            (!cast<Instruction>(NAME # "v4i32_v8i16")
6340                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6341                V128:$Rn, V128:$Rm)>;
6342  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6343                                                    (v2i64 V128:$Rm))),
6344            (!cast<Instruction>(NAME # "v2i64_v4i32")
6345                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6346                V128:$Rn, V128:$Rm)>;
6347}
6348
6349multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6350                                      Intrinsic IntOp> {
6351  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6352                                            V128, V64, V64,
6353                                            asm, ".8h", ".8b", ".8b",
6354      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6355  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6356                                            V128, V128, V128,
6357                                            asm#"2", ".8h", ".16b", ".16b", []>;
6358  let Predicates = [HasAES] in {
6359    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6360                                              V128, V64, V64,
6361                                              asm, ".1q", ".1d", ".1d", []>;
6362    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6363                                              V128, V128, V128,
6364                                              asm#"2", ".1q", ".2d", ".2d", []>;
6365  }
6366
6367  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
6368                          (v8i8 (extract_high_v16i8 V128:$Rm)))),
6369      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6370}
6371
6372multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6373                                 SDPatternOperator OpNode> {
6374  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6375                                                  V128, V64, V64,
6376                                                  asm, ".4s", ".4h", ".4h",
6377      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6378  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6379                                                  V128, V128, V128,
6380                                                  asm#"2", ".4s", ".8h", ".8h",
6381      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6382                                      (extract_high_v8i16 V128:$Rm)))]>;
6383  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6384                                                  V128, V64, V64,
6385                                                  asm, ".2d", ".2s", ".2s",
6386      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6387  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6388                                                  V128, V128, V128,
6389                                                  asm#"2", ".2d", ".4s", ".4s",
6390      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6391                                      (extract_high_v4i32 V128:$Rm)))]>;
6392}
6393
6394multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6395                                  SDPatternOperator OpNode = null_frag> {
6396  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6397                                                  V128, V64, V64,
6398                                                  asm, ".8h", ".8b", ".8b",
6399      [(set (v8i16 V128:$Rd),
6400            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6401  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6402                                                 V128, V128, V128,
6403                                                 asm#"2", ".8h", ".16b", ".16b",
6404      [(set (v8i16 V128:$Rd),
6405            (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6406                                (extract_high_v16i8 V128:$Rm)))))]>;
6407  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6408                                                  V128, V64, V64,
6409                                                  asm, ".4s", ".4h", ".4h",
6410      [(set (v4i32 V128:$Rd),
6411            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6412  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6413                                                  V128, V128, V128,
6414                                                  asm#"2", ".4s", ".8h", ".8h",
6415      [(set (v4i32 V128:$Rd),
6416            (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6417                                  (extract_high_v8i16 V128:$Rm)))))]>;
6418  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6419                                                  V128, V64, V64,
6420                                                  asm, ".2d", ".2s", ".2s",
6421      [(set (v2i64 V128:$Rd),
6422            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6423  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6424                                                  V128, V128, V128,
6425                                                  asm#"2", ".2d", ".4s", ".4s",
6426      [(set (v2i64 V128:$Rd),
6427            (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6428                                 (extract_high_v4i32 V128:$Rm)))))]>;
6429}
6430
6431multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6432                                          string asm,
6433                                          SDPatternOperator OpNode> {
6434  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6435                                                  V128, V64, V64,
6436                                                  asm, ".8h", ".8b", ".8b",
6437    [(set (v8i16 V128:$dst),
6438          (add (v8i16 V128:$Rd),
6439               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6440  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6441                                                 V128, V128, V128,
6442                                                 asm#"2", ".8h", ".16b", ".16b",
6443    [(set (v8i16 V128:$dst),
6444          (add (v8i16 V128:$Rd),
6445               (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6446                                   (extract_high_v16i8 V128:$Rm))))))]>;
6447  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6448                                                  V128, V64, V64,
6449                                                  asm, ".4s", ".4h", ".4h",
6450    [(set (v4i32 V128:$dst),
6451          (add (v4i32 V128:$Rd),
6452               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6453  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6454                                                  V128, V128, V128,
6455                                                  asm#"2", ".4s", ".8h", ".8h",
6456    [(set (v4i32 V128:$dst),
6457          (add (v4i32 V128:$Rd),
6458               (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6459                                    (extract_high_v8i16 V128:$Rm))))))]>;
6460  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6461                                                  V128, V64, V64,
6462                                                  asm, ".2d", ".2s", ".2s",
6463    [(set (v2i64 V128:$dst),
6464          (add (v2i64 V128:$Rd),
6465               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6466  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6467                                                  V128, V128, V128,
6468                                                  asm#"2", ".2d", ".4s", ".4s",
6469    [(set (v2i64 V128:$dst),
6470          (add (v2i64 V128:$Rd),
6471               (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6472                                    (extract_high_v4i32 V128:$Rm))))))]>;
6473}
6474
6475multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6476                                  SDPatternOperator OpNode = null_frag> {
6477  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6478                                                  V128, V64, V64,
6479                                                  asm, ".8h", ".8b", ".8b",
6480      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6481  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6482                                                 V128, V128, V128,
6483                                                 asm#"2", ".8h", ".16b", ".16b",
6484      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6485                                      (extract_high_v16i8 V128:$Rm)))]>;
6486  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6487                                                  V128, V64, V64,
6488                                                  asm, ".4s", ".4h", ".4h",
6489      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6490  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6491                                                  V128, V128, V128,
6492                                                  asm#"2", ".4s", ".8h", ".8h",
6493      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6494                                      (extract_high_v8i16 V128:$Rm)))]>;
6495  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6496                                                  V128, V64, V64,
6497                                                  asm, ".2d", ".2s", ".2s",
6498      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6499  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6500                                                  V128, V128, V128,
6501                                                  asm#"2", ".2d", ".4s", ".4s",
6502      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6503                                      (extract_high_v4i32 V128:$Rm)))]>;
6504}
6505
6506multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6507                                      string asm,
6508                                      SDPatternOperator OpNode> {
6509  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6510                                                  V128, V64, V64,
6511                                                  asm, ".8h", ".8b", ".8b",
6512    [(set (v8i16 V128:$dst),
6513          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6514  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6515                                                 V128, V128, V128,
6516                                                 asm#"2", ".8h", ".16b", ".16b",
6517    [(set (v8i16 V128:$dst),
6518          (OpNode (v8i16 V128:$Rd),
6519                  (extract_high_v16i8 V128:$Rn),
6520                  (extract_high_v16i8 V128:$Rm)))]>;
6521  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6522                                                  V128, V64, V64,
6523                                                  asm, ".4s", ".4h", ".4h",
6524    [(set (v4i32 V128:$dst),
6525          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6526  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6527                                                  V128, V128, V128,
6528                                                  asm#"2", ".4s", ".8h", ".8h",
6529    [(set (v4i32 V128:$dst),
6530          (OpNode (v4i32 V128:$Rd),
6531                  (extract_high_v8i16 V128:$Rn),
6532                  (extract_high_v8i16 V128:$Rm)))]>;
6533  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6534                                                  V128, V64, V64,
6535                                                  asm, ".2d", ".2s", ".2s",
6536    [(set (v2i64 V128:$dst),
6537          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6538  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6539                                                  V128, V128, V128,
6540                                                  asm#"2", ".2d", ".4s", ".4s",
6541    [(set (v2i64 V128:$dst),
6542          (OpNode (v2i64 V128:$Rd),
6543                  (extract_high_v4i32 V128:$Rn),
6544                  (extract_high_v4i32 V128:$Rm)))]>;
6545}
6546
6547multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6548                                           SDPatternOperator Accum> {
6549  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6550                                                  V128, V64, V64,
6551                                                  asm, ".4s", ".4h", ".4h",
6552    [(set (v4i32 V128:$dst),
6553          (Accum (v4i32 V128:$Rd),
6554                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6555                                                (v4i16 V64:$Rm)))))]>;
6556  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6557                                                  V128, V128, V128,
6558                                                  asm#"2", ".4s", ".8h", ".8h",
6559    [(set (v4i32 V128:$dst),
6560          (Accum (v4i32 V128:$Rd),
6561                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6562                                            (extract_high_v8i16 V128:$Rm)))))]>;
6563  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6564                                                  V128, V64, V64,
6565                                                  asm, ".2d", ".2s", ".2s",
6566    [(set (v2i64 V128:$dst),
6567          (Accum (v2i64 V128:$Rd),
6568                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6569                                                (v2i32 V64:$Rm)))))]>;
6570  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6571                                                  V128, V128, V128,
6572                                                  asm#"2", ".2d", ".4s", ".4s",
6573    [(set (v2i64 V128:$dst),
6574          (Accum (v2i64 V128:$Rd),
6575                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6576                                            (extract_high_v4i32 V128:$Rm)))))]>;
6577}
6578
6579multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6580                                  SDPatternOperator OpNode> {
6581  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6582                                                  V128, V128, V64,
6583                                                  asm, ".8h", ".8h", ".8b",
6584       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6585  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6586                                                  V128, V128, V128,
6587                                                  asm#"2", ".8h", ".8h", ".16b",
6588       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6589                                       (extract_high_v16i8 V128:$Rm)))]>;
6590  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6591                                                  V128, V128, V64,
6592                                                  asm, ".4s", ".4s", ".4h",
6593       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6594  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6595                                                  V128, V128, V128,
6596                                                  asm#"2", ".4s", ".4s", ".8h",
6597       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6598                                       (extract_high_v8i16 V128:$Rm)))]>;
6599  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6600                                                  V128, V128, V64,
6601                                                  asm, ".2d", ".2d", ".2s",
6602       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6603  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6604                                                  V128, V128, V128,
6605                                                  asm#"2", ".2d", ".2d", ".4s",
6606       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6607                                       (extract_high_v4i32 V128:$Rm)))]>;
6608}
6609
6610//----------------------------------------------------------------------------
6611// AdvSIMD bitwise extract from vector
6612//----------------------------------------------------------------------------
6613
6614class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6615                             string asm, string kind>
6616  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6617      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6618      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6619      [(set (vty regtype:$Rd),
6620            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6621    Sched<[WriteV]> {
6622  bits<5> Rd;
6623  bits<5> Rn;
6624  bits<5> Rm;
6625  bits<4> imm;
6626  let Inst{31}    = 0;
6627  let Inst{30}    = size;
6628  let Inst{29-21} = 0b101110000;
6629  let Inst{20-16} = Rm;
6630  let Inst{15}    = 0;
6631  let Inst{14-11} = imm;
6632  let Inst{10}    = 0;
6633  let Inst{9-5}   = Rn;
6634  let Inst{4-0}   = Rd;
6635}
6636
6637
6638multiclass SIMDBitwiseExtract<string asm> {
6639  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6640    let imm{3} = 0;
6641  }
6642  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6643}
6644
6645//----------------------------------------------------------------------------
6646// AdvSIMD zip vector
6647//----------------------------------------------------------------------------
6648
6649class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6650                        string asm, string kind, SDNode OpNode, ValueType valty>
6651  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6652      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6653      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6654      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6655    Sched<[WriteV]> {
6656  bits<5> Rd;
6657  bits<5> Rn;
6658  bits<5> Rm;
6659  let Inst{31}    = 0;
6660  let Inst{30}    = size{0};
6661  let Inst{29-24} = 0b001110;
6662  let Inst{23-22} = size{2-1};
6663  let Inst{21}    = 0;
6664  let Inst{20-16} = Rm;
6665  let Inst{15}    = 0;
6666  let Inst{14-12} = opc;
6667  let Inst{11-10} = 0b10;
6668  let Inst{9-5}   = Rn;
6669  let Inst{4-0}   = Rd;
6670}
6671
6672multiclass SIMDZipVector<bits<3>opc, string asm,
6673                         SDNode OpNode> {
6674  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6675      asm, ".8b", OpNode, v8i8>;
6676  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6677      asm, ".16b", OpNode, v16i8>;
6678  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6679      asm, ".4h", OpNode, v4i16>;
6680  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6681      asm, ".8h", OpNode, v8i16>;
6682  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6683      asm, ".2s", OpNode, v2i32>;
6684  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6685      asm, ".4s", OpNode, v4i32>;
6686  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6687      asm, ".2d", OpNode, v2i64>;
6688
6689  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6690        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6691  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6692        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6693  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6694        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6695  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6696        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6697  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6698        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6699}
6700
6701//----------------------------------------------------------------------------
6702// AdvSIMD three register scalar instructions
6703//----------------------------------------------------------------------------
6704
6705let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6706class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6707                        RegisterClass regtype, string asm,
6708                        list<dag> pattern>
6709  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6710      "\t$Rd, $Rn, $Rm", "", pattern>,
6711    Sched<[WriteV]> {
6712  bits<5> Rd;
6713  bits<5> Rn;
6714  bits<5> Rm;
6715  let Inst{31-30} = 0b01;
6716  let Inst{29}    = U;
6717  let Inst{28-24} = 0b11110;
6718  let Inst{23-21} = size;
6719  let Inst{20-16} = Rm;
6720  let Inst{15-11} = opcode;
6721  let Inst{10}    = 1;
6722  let Inst{9-5}   = Rn;
6723  let Inst{4-0}   = Rd;
6724}
6725
6726let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6727class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6728                        dag oops, dag iops, string asm,
6729            list<dag> pattern>
6730  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6731    Sched<[WriteV]> {
6732  bits<5> Rd;
6733  bits<5> Rn;
6734  bits<5> Rm;
6735  let Inst{31-30} = 0b01;
6736  let Inst{29}    = U;
6737  let Inst{28-24} = 0b11110;
6738  let Inst{23-22} = size;
6739  let Inst{21}    = R;
6740  let Inst{20-16} = Rm;
6741  let Inst{15-11} = opcode;
6742  let Inst{10}    = 1;
6743  let Inst{9-5}   = Rn;
6744  let Inst{4-0}   = Rd;
6745}
6746
6747multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6748                            SDPatternOperator OpNode> {
6749  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6750    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6751}
6752
6753multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6754                               SDPatternOperator OpNode> {
6755  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6756    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6757  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6758  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6759  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6760
6761  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6762            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6763  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6764            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6765}
6766
6767multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6768                             SDPatternOperator OpNode> {
6769  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6770                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6771  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6772}
6773
6774multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6775                                 SDPatternOperator OpNode = null_frag> {
6776  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6777                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6778                                     asm, []>;
6779  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6780                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6781                                     asm, []>;
6782}
6783
6784multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6785                             SDPatternOperator OpNode = null_frag> {
6786  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6787    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6788      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6789    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6790      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6791    let Predicates = [HasNEON, HasFullFP16] in {
6792    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6793      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
6794    } // Predicates = [HasNEON, HasFullFP16]
6795  }
6796
6797  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6798            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6799}
6800
6801multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6802                                SDPatternOperator OpNode = null_frag> {
6803  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6804    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6805      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6806    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6807      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6808    let Predicates = [HasNEON, HasFullFP16] in {
6809    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6810      []>;
6811    } // Predicates = [HasNEON, HasFullFP16]
6812  }
6813
6814  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6815            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6816}
6817
6818class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6819              dag oops, dag iops, string asm, string cstr, list<dag> pat>
6820  : I<oops, iops, asm,
6821      "\t$Rd, $Rn, $Rm", cstr, pat>,
6822    Sched<[WriteV]> {
6823  bits<5> Rd;
6824  bits<5> Rn;
6825  bits<5> Rm;
6826  let Inst{31-30} = 0b01;
6827  let Inst{29}    = U;
6828  let Inst{28-24} = 0b11110;
6829  let Inst{23-22} = size;
6830  let Inst{21}    = 1;
6831  let Inst{20-16} = Rm;
6832  let Inst{15-11} = opcode;
6833  let Inst{10}    = 0;
6834  let Inst{9-5}   = Rn;
6835  let Inst{4-0}   = Rd;
6836}
6837
6838let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6839multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6840                                  SDPatternOperator OpNode = null_frag> {
6841  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6842                                      (outs FPR32:$Rd),
6843                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6844  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6845                                      (outs FPR64:$Rd),
6846                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6847            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6848}
6849
6850let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6851multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6852                                  SDPatternOperator OpNode = null_frag> {
6853  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6854                                      (outs FPR32:$dst),
6855                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6856                                      asm, "$Rd = $dst", []>;
6857  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6858                                      (outs FPR64:$dst),
6859                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6860                                      asm, "$Rd = $dst",
6861            [(set (i64 FPR64:$dst),
6862                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6863}
6864
6865//----------------------------------------------------------------------------
6866// AdvSIMD two register scalar instructions
6867//----------------------------------------------------------------------------
6868
6869let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6870class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6871                        RegisterClass regtype, RegisterClass regtype2,
6872                        string asm, list<dag> pat>
6873  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6874      "\t$Rd, $Rn", "", pat>,
6875    Sched<[WriteV]> {
6876  bits<5> Rd;
6877  bits<5> Rn;
6878  let Inst{31-30} = 0b01;
6879  let Inst{29}    = U;
6880  let Inst{28-24} = 0b11110;
6881  let Inst{23-22} = size;
6882  let Inst{21} = 0b1;
6883  let Inst{20-19} = size2;
6884  let Inst{18-17} = 0b00;
6885  let Inst{16-12} = opcode;
6886  let Inst{11-10} = 0b10;
6887  let Inst{9-5}   = Rn;
6888  let Inst{4-0}   = Rd;
6889}
6890
6891let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6892class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6893                        RegisterClass regtype, RegisterClass regtype2,
6894                        string asm, list<dag> pat>
6895  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6896      "\t$Rd, $Rn", "$Rd = $dst", pat>,
6897    Sched<[WriteV]> {
6898  bits<5> Rd;
6899  bits<5> Rn;
6900  let Inst{31-30} = 0b01;
6901  let Inst{29}    = U;
6902  let Inst{28-24} = 0b11110;
6903  let Inst{23-22} = size;
6904  let Inst{21-17} = 0b10000;
6905  let Inst{16-12} = opcode;
6906  let Inst{11-10} = 0b10;
6907  let Inst{9-5}   = Rn;
6908  let Inst{4-0}   = Rd;
6909}
6910
6911
6912let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6913class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6914                        RegisterClass regtype, string asm, string zero>
6915  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6916      "\t$Rd, $Rn, #" # zero, "", []>,
6917    Sched<[WriteV]> {
6918  bits<5> Rd;
6919  bits<5> Rn;
6920  let Inst{31-30} = 0b01;
6921  let Inst{29}    = U;
6922  let Inst{28-24} = 0b11110;
6923  let Inst{23-22} = size;
6924  let Inst{21} = 0b1;
6925  let Inst{20-19} = size2;
6926  let Inst{18-17} = 0b00;
6927  let Inst{16-12} = opcode;
6928  let Inst{11-10} = 0b10;
6929  let Inst{9-5}   = Rn;
6930  let Inst{4-0}   = Rd;
6931}
6932
6933class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6934  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6935     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6936    Sched<[WriteV]> {
6937  bits<5> Rd;
6938  bits<5> Rn;
6939  let Inst{31-17} = 0b011111100110000;
6940  let Inst{16-12} = opcode;
6941  let Inst{11-10} = 0b10;
6942  let Inst{9-5}   = Rn;
6943  let Inst{4-0}   = Rd;
6944}
6945
6946multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6947                             SDPatternOperator OpNode> {
6948  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6949
6950  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6951            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6952}
6953
6954multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6955                              SDPatternOperator OpNode> {
6956  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6957  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6958  let Predicates = [HasNEON, HasFullFP16] in {
6959  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6960  }
6961
6962  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6963                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6964  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6965                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6966  let Predicates = [HasNEON, HasFullFP16] in {
6967  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6968                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6969  }
6970
6971  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6972            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6973}
6974
6975multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6976                          SDPatternOperator OpNode = null_frag> {
6977  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6978    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6979
6980  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6981            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6982}
6983
6984multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6985  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6986  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6987  let Predicates = [HasNEON, HasFullFP16] in {
6988  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6989  }
6990}
6991
6992multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6993                              SDPatternOperator OpNode> {
6994  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6995                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6996  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6997                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6998  let Predicates = [HasNEON, HasFullFP16] in {
6999  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7000                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7001  }
7002}
7003
7004multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7005                             SDPatternOperator OpNode = null_frag> {
7006  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7007    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7008           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7009    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7010           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7011    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7012    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7013  }
7014
7015  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7016            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7017}
7018
7019multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7020                                 Intrinsic OpNode> {
7021  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7022    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7023        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7024    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7025        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7026    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7027    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7028  }
7029
7030  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7031            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7032}
7033
7034
7035
7036let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7037multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7038                                 SDPatternOperator OpNode = null_frag> {
7039  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7040        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7041  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7042  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7043}
7044
7045//----------------------------------------------------------------------------
7046// AdvSIMD scalar pairwise instructions
7047//----------------------------------------------------------------------------
7048
7049let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7050class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7051                        RegisterOperand regtype, RegisterOperand vectype,
7052                        string asm, string kind>
7053  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7054      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7055    Sched<[WriteV]> {
7056  bits<5> Rd;
7057  bits<5> Rn;
7058  let Inst{31-30} = 0b01;
7059  let Inst{29}    = U;
7060  let Inst{28-24} = 0b11110;
7061  let Inst{23-22} = size;
7062  let Inst{21-17} = 0b11000;
7063  let Inst{16-12} = opcode;
7064  let Inst{11-10} = 0b10;
7065  let Inst{9-5}   = Rn;
7066  let Inst{4-0}   = Rd;
7067}
7068
7069multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7070  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7071                                      asm, ".2d">;
7072}
7073
7074multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7075  let Predicates = [HasNEON, HasFullFP16] in {
7076  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7077                                      asm, ".2h">;
7078  }
7079  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7080                                      asm, ".2s">;
7081  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7082                                      asm, ".2d">;
7083}
7084
7085//----------------------------------------------------------------------------
7086// AdvSIMD across lanes instructions
7087//----------------------------------------------------------------------------
7088
7089let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7090class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7091                          RegisterClass regtype, RegisterOperand vectype,
7092                          string asm, string kind, list<dag> pattern>
7093  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7094      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7095    Sched<[WriteV]> {
7096  bits<5> Rd;
7097  bits<5> Rn;
7098  let Inst{31}    = 0;
7099  let Inst{30}    = Q;
7100  let Inst{29}    = U;
7101  let Inst{28-24} = 0b01110;
7102  let Inst{23-22} = size;
7103  let Inst{21-17} = 0b11000;
7104  let Inst{16-12} = opcode;
7105  let Inst{11-10} = 0b10;
7106  let Inst{9-5}   = Rn;
7107  let Inst{4-0}   = Rd;
7108}
7109
7110multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7111                              string asm> {
7112  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7113                                   asm, ".8b", []>;
7114  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7115                                   asm, ".16b", []>;
7116  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7117                                   asm, ".4h", []>;
7118  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7119                                   asm, ".8h", []>;
7120  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7121                                   asm, ".4s", []>;
7122}
7123
7124multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7125  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7126                                   asm, ".8b", []>;
7127  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7128                                   asm, ".16b", []>;
7129  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7130                                   asm, ".4h", []>;
7131  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7132                                   asm, ".8h", []>;
7133  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7134                                   asm, ".4s", []>;
7135}
7136
7137multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7138                            Intrinsic intOp> {
7139  let Predicates = [HasNEON, HasFullFP16] in {
7140  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7141                                   asm, ".4h",
7142        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7143  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7144                                   asm, ".8h",
7145        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7146  } // Predicates = [HasNEON, HasFullFP16]
7147  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7148                                   asm, ".4s",
7149        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7150}
7151
7152//----------------------------------------------------------------------------
7153// AdvSIMD INS/DUP instructions
7154//----------------------------------------------------------------------------
7155
7156// FIXME: There has got to be a better way to factor these. ugh.
7157
7158class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7159                     string operands, string constraints, list<dag> pattern>
7160  : I<outs, ins, asm, operands, constraints, pattern>,
7161    Sched<[WriteV]> {
7162  bits<5> Rd;
7163  bits<5> Rn;
7164  let Inst{31} = 0;
7165  let Inst{30} = Q;
7166  let Inst{29} = op;
7167  let Inst{28-21} = 0b01110000;
7168  let Inst{15} = 0;
7169  let Inst{10} = 1;
7170  let Inst{9-5} = Rn;
7171  let Inst{4-0} = Rd;
7172}
7173
7174class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7175                      RegisterOperand vecreg, RegisterClass regtype>
7176  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7177                   "{\t$Rd" # size # ", $Rn" #
7178                   "|" # size # "\t$Rd, $Rn}", "",
7179                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7180  let Inst{20-16} = imm5;
7181  let Inst{14-11} = 0b0001;
7182}
7183
7184class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7185                         ValueType vectype, ValueType insreg,
7186                         RegisterOperand vecreg, Operand idxtype,
7187                         ValueType elttype, SDNode OpNode>
7188  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7189                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7190                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7191                 [(set (vectype vecreg:$Rd),
7192                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7193  let Inst{14-11} = 0b0000;
7194}
7195
7196class SIMDDup64FromElement
7197  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7198                       VectorIndexD, i64, AArch64duplane64> {
7199  bits<1> idx;
7200  let Inst{20} = idx;
7201  let Inst{19-16} = 0b1000;
7202}
7203
7204class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7205                           RegisterOperand vecreg>
7206  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7207                       VectorIndexS, i64, AArch64duplane32> {
7208  bits<2> idx;
7209  let Inst{20-19} = idx;
7210  let Inst{18-16} = 0b100;
7211}
7212
7213class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7214                           RegisterOperand vecreg>
7215  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7216                       VectorIndexH, i64, AArch64duplane16> {
7217  bits<3> idx;
7218  let Inst{20-18} = idx;
7219  let Inst{17-16} = 0b10;
7220}
7221
7222class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7223                          RegisterOperand vecreg>
7224  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7225                       VectorIndexB, i64, AArch64duplane8> {
7226  bits<4> idx;
7227  let Inst{20-17} = idx;
7228  let Inst{16} = 1;
7229}
7230
7231class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7232                  Operand idxtype, string asm, list<dag> pattern>
7233  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7234                   "{\t$Rd, $Rn" # size # "$idx" #
7235                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7236  let Inst{14-11} = imm4;
7237}
7238
7239class SIMDSMov<bit Q, string size, RegisterClass regtype,
7240               Operand idxtype>
7241  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7242class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7243               Operand idxtype>
7244  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7245      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7246
7247class SIMDMovAlias<string asm, string size, Instruction inst,
7248                   RegisterClass regtype, Operand idxtype>
7249    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7250                    "|" # size # "\t$dst, $src$idx}",
7251                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7252
7253multiclass SMov {
7254  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7255    bits<4> idx;
7256    let Inst{20-17} = idx;
7257    let Inst{16} = 1;
7258  }
7259  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7260    bits<4> idx;
7261    let Inst{20-17} = idx;
7262    let Inst{16} = 1;
7263  }
7264  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7265    bits<3> idx;
7266    let Inst{20-18} = idx;
7267    let Inst{17-16} = 0b10;
7268  }
7269  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7270    bits<3> idx;
7271    let Inst{20-18} = idx;
7272    let Inst{17-16} = 0b10;
7273  }
7274  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7275    bits<2> idx;
7276    let Inst{20-19} = idx;
7277    let Inst{18-16} = 0b100;
7278  }
7279}
7280
7281multiclass UMov {
7282  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7283    bits<4> idx;
7284    let Inst{20-17} = idx;
7285    let Inst{16} = 1;
7286  }
7287  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7288    bits<3> idx;
7289    let Inst{20-18} = idx;
7290    let Inst{17-16} = 0b10;
7291  }
7292  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7293    bits<2> idx;
7294    let Inst{20-19} = idx;
7295    let Inst{18-16} = 0b100;
7296  }
7297  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7298    bits<1> idx;
7299    let Inst{20} = idx;
7300    let Inst{19-16} = 0b1000;
7301  }
7302  def : SIMDMovAlias<"mov", ".s",
7303                     !cast<Instruction>(NAME#"vi32"),
7304                     GPR32, VectorIndexS>;
7305  def : SIMDMovAlias<"mov", ".d",
7306                     !cast<Instruction>(NAME#"vi64"),
7307                     GPR64, VectorIndexD>;
7308}
7309
7310class SIMDInsFromMain<string size, ValueType vectype,
7311                      RegisterClass regtype, Operand idxtype>
7312  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7313                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7314                   "{\t$Rd" # size # "$idx, $Rn" #
7315                   "|" # size # "\t$Rd$idx, $Rn}",
7316                   "$Rd = $dst",
7317            [(set V128:$dst,
7318              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7319  let Inst{14-11} = 0b0011;
7320}
7321
7322class SIMDInsFromElement<string size, ValueType vectype,
7323                         ValueType elttype, Operand idxtype>
7324  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7325                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7326                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7327                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7328                   "$Rd = $dst",
7329         [(set V128:$dst,
7330               (vector_insert
7331                 (vectype V128:$Rd),
7332                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7333                 idxtype:$idx))]>;
7334
7335class SIMDInsMainMovAlias<string size, Instruction inst,
7336                          RegisterClass regtype, Operand idxtype>
7337    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7338                        "|" # size #"\t$dst$idx, $src}",
7339                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7340class SIMDInsElementMovAlias<string size, Instruction inst,
7341                             Operand idxtype>
7342    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7343                      # "|" # size #"\t$dst$idx, $src$idx2}",
7344                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7345
7346
7347multiclass SIMDIns {
7348  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7349    bits<4> idx;
7350    let Inst{20-17} = idx;
7351    let Inst{16} = 1;
7352  }
7353  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7354    bits<3> idx;
7355    let Inst{20-18} = idx;
7356    let Inst{17-16} = 0b10;
7357  }
7358  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7359    bits<2> idx;
7360    let Inst{20-19} = idx;
7361    let Inst{18-16} = 0b100;
7362  }
7363  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7364    bits<1> idx;
7365    let Inst{20} = idx;
7366    let Inst{19-16} = 0b1000;
7367  }
7368
7369  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7370    bits<4> idx;
7371    bits<4> idx2;
7372    let Inst{20-17} = idx;
7373    let Inst{16} = 1;
7374    let Inst{14-11} = idx2;
7375  }
7376  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7377    bits<3> idx;
7378    bits<3> idx2;
7379    let Inst{20-18} = idx;
7380    let Inst{17-16} = 0b10;
7381    let Inst{14-12} = idx2;
7382    let Inst{11} = {?};
7383  }
7384  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7385    bits<2> idx;
7386    bits<2> idx2;
7387    let Inst{20-19} = idx;
7388    let Inst{18-16} = 0b100;
7389    let Inst{14-13} = idx2;
7390    let Inst{12-11} = {?,?};
7391  }
7392  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7393    bits<1> idx;
7394    bits<1> idx2;
7395    let Inst{20} = idx;
7396    let Inst{19-16} = 0b1000;
7397    let Inst{14} = idx2;
7398    let Inst{13-11} = {?,?,?};
7399  }
7400
7401  // For all forms of the INS instruction, the "mov" mnemonic is the
7402  // preferred alias. Why they didn't just call the instruction "mov" in
7403  // the first place is a very good question indeed...
7404  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7405                         GPR32, VectorIndexB>;
7406  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7407                         GPR32, VectorIndexH>;
7408  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7409                         GPR32, VectorIndexS>;
7410  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7411                         GPR64, VectorIndexD>;
7412
7413  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7414                         VectorIndexB>;
7415  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7416                         VectorIndexH>;
7417  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7418                         VectorIndexS>;
7419  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7420                         VectorIndexD>;
7421}
7422
7423//----------------------------------------------------------------------------
7424// AdvSIMD TBL/TBX
7425//----------------------------------------------------------------------------
7426
7427let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7428class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7429                          RegisterOperand listtype, string asm, string kind>
7430  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7431       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7432    Sched<[WriteV]> {
7433  bits<5> Vd;
7434  bits<5> Vn;
7435  bits<5> Vm;
7436  let Inst{31}    = 0;
7437  let Inst{30}    = Q;
7438  let Inst{29-21} = 0b001110000;
7439  let Inst{20-16} = Vm;
7440  let Inst{15}    = 0;
7441  let Inst{14-13} = len;
7442  let Inst{12}    = op;
7443  let Inst{11-10} = 0b00;
7444  let Inst{9-5}   = Vn;
7445  let Inst{4-0}   = Vd;
7446}
7447
7448let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7449class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7450                          RegisterOperand listtype, string asm, string kind>
7451  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7452       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7453    Sched<[WriteV]> {
7454  bits<5> Vd;
7455  bits<5> Vn;
7456  bits<5> Vm;
7457  let Inst{31}    = 0;
7458  let Inst{30}    = Q;
7459  let Inst{29-21} = 0b001110000;
7460  let Inst{20-16} = Vm;
7461  let Inst{15}    = 0;
7462  let Inst{14-13} = len;
7463  let Inst{12}    = op;
7464  let Inst{11-10} = 0b00;
7465  let Inst{9-5}   = Vn;
7466  let Inst{4-0}   = Vd;
7467}
7468
7469class SIMDTableLookupAlias<string asm, Instruction inst,
7470                          RegisterOperand vectype, RegisterOperand listtype>
7471    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7472                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7473
7474multiclass SIMDTableLookup<bit op, string asm> {
7475  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7476                                      asm, ".8b">;
7477  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7478                                      asm, ".8b">;
7479  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7480                                      asm, ".8b">;
7481  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7482                                      asm, ".8b">;
7483  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7484                                      asm, ".16b">;
7485  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7486                                      asm, ".16b">;
7487  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7488                                      asm, ".16b">;
7489  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7490                                      asm, ".16b">;
7491
7492  def : SIMDTableLookupAlias<asm # ".8b",
7493                         !cast<Instruction>(NAME#"v8i8One"),
7494                         V64, VecListOne128>;
7495  def : SIMDTableLookupAlias<asm # ".8b",
7496                         !cast<Instruction>(NAME#"v8i8Two"),
7497                         V64, VecListTwo128>;
7498  def : SIMDTableLookupAlias<asm # ".8b",
7499                         !cast<Instruction>(NAME#"v8i8Three"),
7500                         V64, VecListThree128>;
7501  def : SIMDTableLookupAlias<asm # ".8b",
7502                         !cast<Instruction>(NAME#"v8i8Four"),
7503                         V64, VecListFour128>;
7504  def : SIMDTableLookupAlias<asm # ".16b",
7505                         !cast<Instruction>(NAME#"v16i8One"),
7506                         V128, VecListOne128>;
7507  def : SIMDTableLookupAlias<asm # ".16b",
7508                         !cast<Instruction>(NAME#"v16i8Two"),
7509                         V128, VecListTwo128>;
7510  def : SIMDTableLookupAlias<asm # ".16b",
7511                         !cast<Instruction>(NAME#"v16i8Three"),
7512                         V128, VecListThree128>;
7513  def : SIMDTableLookupAlias<asm # ".16b",
7514                         !cast<Instruction>(NAME#"v16i8Four"),
7515                         V128, VecListFour128>;
7516}
7517
7518multiclass SIMDTableLookupTied<bit op, string asm> {
7519  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7520                                      asm, ".8b">;
7521  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7522                                      asm, ".8b">;
7523  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7524                                      asm, ".8b">;
7525  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7526                                      asm, ".8b">;
7527  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7528                                      asm, ".16b">;
7529  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7530                                      asm, ".16b">;
7531  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7532                                      asm, ".16b">;
7533  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7534                                      asm, ".16b">;
7535
7536  def : SIMDTableLookupAlias<asm # ".8b",
7537                         !cast<Instruction>(NAME#"v8i8One"),
7538                         V64, VecListOne128>;
7539  def : SIMDTableLookupAlias<asm # ".8b",
7540                         !cast<Instruction>(NAME#"v8i8Two"),
7541                         V64, VecListTwo128>;
7542  def : SIMDTableLookupAlias<asm # ".8b",
7543                         !cast<Instruction>(NAME#"v8i8Three"),
7544                         V64, VecListThree128>;
7545  def : SIMDTableLookupAlias<asm # ".8b",
7546                         !cast<Instruction>(NAME#"v8i8Four"),
7547                         V64, VecListFour128>;
7548  def : SIMDTableLookupAlias<asm # ".16b",
7549                         !cast<Instruction>(NAME#"v16i8One"),
7550                         V128, VecListOne128>;
7551  def : SIMDTableLookupAlias<asm # ".16b",
7552                         !cast<Instruction>(NAME#"v16i8Two"),
7553                         V128, VecListTwo128>;
7554  def : SIMDTableLookupAlias<asm # ".16b",
7555                         !cast<Instruction>(NAME#"v16i8Three"),
7556                         V128, VecListThree128>;
7557  def : SIMDTableLookupAlias<asm # ".16b",
7558                         !cast<Instruction>(NAME#"v16i8Four"),
7559                         V128, VecListFour128>;
7560}
7561
7562
7563//----------------------------------------------------------------------------
7564// AdvSIMD scalar CPY
7565//----------------------------------------------------------------------------
7566let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7567class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7568                        string kind, Operand idxtype>
7569  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7570       "{\t$dst, $src" # kind # "$idx" #
7571       "|\t$dst, $src$idx}", "", []>,
7572    Sched<[WriteV]> {
7573  bits<5> dst;
7574  bits<5> src;
7575  let Inst{31-21} = 0b01011110000;
7576  let Inst{15-10} = 0b000001;
7577  let Inst{9-5}   = src;
7578  let Inst{4-0}   = dst;
7579}
7580
7581class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7582      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7583    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7584                    # "|\t$dst, $src$index}",
7585                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7586
7587
7588multiclass SIMDScalarCPY<string asm> {
7589  def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
7590    bits<4> idx;
7591    let Inst{20-17} = idx;
7592    let Inst{16} = 1;
7593  }
7594  def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7595    bits<3> idx;
7596    let Inst{20-18} = idx;
7597    let Inst{17-16} = 0b10;
7598  }
7599  def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7600    bits<2> idx;
7601    let Inst{20-19} = idx;
7602    let Inst{18-16} = 0b100;
7603  }
7604  def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7605    bits<1> idx;
7606    let Inst{20} = idx;
7607    let Inst{19-16} = 0b1000;
7608  }
7609
7610  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7611                                                          VectorIndexD:$idx)))),
7612            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7613
7614  // 'DUP' mnemonic aliases.
7615  def : SIMDScalarCPYAlias<"dup", ".b",
7616                           !cast<Instruction>(NAME#"i8"),
7617                           FPR8, V128, VectorIndexB>;
7618  def : SIMDScalarCPYAlias<"dup", ".h",
7619                           !cast<Instruction>(NAME#"i16"),
7620                           FPR16, V128, VectorIndexH>;
7621  def : SIMDScalarCPYAlias<"dup", ".s",
7622                           !cast<Instruction>(NAME#"i32"),
7623                           FPR32, V128, VectorIndexS>;
7624  def : SIMDScalarCPYAlias<"dup", ".d",
7625                           !cast<Instruction>(NAME#"i64"),
7626                           FPR64, V128, VectorIndexD>;
7627}
7628
7629//----------------------------------------------------------------------------
7630// AdvSIMD modified immediate instructions
7631//----------------------------------------------------------------------------
7632
7633class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7634                          string asm, string op_string,
7635                          string cstr, list<dag> pattern>
7636  : I<oops, iops, asm, op_string, cstr, pattern>,
7637    Sched<[WriteV]> {
7638  bits<5> Rd;
7639  bits<8> imm8;
7640  let Inst{31}    = 0;
7641  let Inst{30}    = Q;
7642  let Inst{29}    = op;
7643  let Inst{28-19} = 0b0111100000;
7644  let Inst{18-16} = imm8{7-5};
7645  let Inst{11} = op2;
7646  let Inst{10} = 1;
7647  let Inst{9-5}   = imm8{4-0};
7648  let Inst{4-0}   = Rd;
7649}
7650
7651class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7652                                Operand immtype, dag opt_shift_iop,
7653                                string opt_shift, string asm, string kind,
7654                                list<dag> pattern>
7655  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7656                        !con((ins immtype:$imm8), opt_shift_iop), asm,
7657                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
7658                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7659                        "", pattern> {
7660  let DecoderMethod = "DecodeModImmInstruction";
7661}
7662
7663class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7664                                Operand immtype, dag opt_shift_iop,
7665                                string opt_shift, string asm, string kind,
7666                                list<dag> pattern>
7667  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7668                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7669                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7670                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7671                        "$Rd = $dst", pattern> {
7672  let DecoderMethod = "DecodeModImmTiedInstruction";
7673}
7674
7675class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7676                                     RegisterOperand vectype, string asm,
7677                                     string kind, list<dag> pattern>
7678  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7679                              (ins logical_vec_shift:$shift),
7680                              "$shift", asm, kind, pattern> {
7681  bits<2> shift;
7682  let Inst{15}    = b15_b12{1};
7683  let Inst{14-13} = shift;
7684  let Inst{12}    = b15_b12{0};
7685}
7686
7687class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7688                                     RegisterOperand vectype, string asm,
7689                                     string kind, list<dag> pattern>
7690  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7691                              (ins logical_vec_shift:$shift),
7692                              "$shift", asm, kind, pattern> {
7693  bits<2> shift;
7694  let Inst{15}    = b15_b12{1};
7695  let Inst{14-13} = shift;
7696  let Inst{12}    = b15_b12{0};
7697}
7698
7699
7700class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7701                                         RegisterOperand vectype, string asm,
7702                                         string kind, list<dag> pattern>
7703  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7704                              (ins logical_vec_hw_shift:$shift),
7705                              "$shift", asm, kind, pattern> {
7706  bits<2> shift;
7707  let Inst{15} = b15_b12{1};
7708  let Inst{14} = 0;
7709  let Inst{13} = shift{0};
7710  let Inst{12} = b15_b12{0};
7711}
7712
7713class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7714                                         RegisterOperand vectype, string asm,
7715                                         string kind, list<dag> pattern>
7716  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7717                              (ins logical_vec_hw_shift:$shift),
7718                              "$shift", asm, kind, pattern> {
7719  bits<2> shift;
7720  let Inst{15} = b15_b12{1};
7721  let Inst{14} = 0;
7722  let Inst{13} = shift{0};
7723  let Inst{12} = b15_b12{0};
7724}
7725
7726multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7727                                      string asm> {
7728  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7729                                                 asm, ".4h", []>;
7730  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7731                                                 asm, ".8h", []>;
7732
7733  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7734                                             asm, ".2s", []>;
7735  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7736                                             asm, ".4s", []>;
7737}
7738
7739multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7740                                      bits<2> w_cmode, string asm,
7741                                      SDNode OpNode> {
7742  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7743                                                 asm, ".4h",
7744             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7745                                             imm0_255:$imm8,
7746                                             (i32 imm:$shift)))]>;
7747  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7748                                                 asm, ".8h",
7749             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7750                                              imm0_255:$imm8,
7751                                              (i32 imm:$shift)))]>;
7752
7753  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7754                                             asm, ".2s",
7755             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7756                                             imm0_255:$imm8,
7757                                             (i32 imm:$shift)))]>;
7758  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7759                                             asm, ".4s",
7760             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7761                                              imm0_255:$imm8,
7762                                              (i32 imm:$shift)))]>;
7763}
7764
7765class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7766                             RegisterOperand vectype, string asm,
7767                             string kind, list<dag> pattern>
7768  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7769                              (ins move_vec_shift:$shift),
7770                              "$shift", asm, kind, pattern> {
7771  bits<1> shift;
7772  let Inst{15-13} = cmode{3-1};
7773  let Inst{12}    = shift;
7774}
7775
7776class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7777                                   RegisterOperand vectype,
7778                                   Operand imm_type, string asm,
7779                                   string kind, list<dag> pattern>
7780  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7781                              asm, kind, pattern> {
7782  let Inst{15-12} = cmode;
7783}
7784
7785class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7786                                   list<dag> pattern>
7787  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7788                        "\t$Rd, $imm8", "", pattern> {
7789  let Inst{15-12} = cmode;
7790  let DecoderMethod = "DecodeModImmInstruction";
7791}
7792
7793//----------------------------------------------------------------------------
7794// AdvSIMD indexed element
7795//----------------------------------------------------------------------------
7796
7797let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7798class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7799                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7800                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7801                      string apple_kind, string dst_kind, string lhs_kind,
7802                      string rhs_kind, list<dag> pattern>
7803  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7804      asm,
7805      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7806      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7807    Sched<[WriteV]> {
7808  bits<5> Rd;
7809  bits<5> Rn;
7810  bits<5> Rm;
7811
7812  let Inst{31}    = 0;
7813  let Inst{30}    = Q;
7814  let Inst{29}    = U;
7815  let Inst{28}    = Scalar;
7816  let Inst{27-24} = 0b1111;
7817  let Inst{23-22} = size;
7818  // Bit 21 must be set by the derived class.
7819  let Inst{20-16} = Rm;
7820  let Inst{15-12} = opc;
7821  // Bit 11 must be set by the derived class.
7822  let Inst{10}    = 0;
7823  let Inst{9-5}   = Rn;
7824  let Inst{4-0}   = Rd;
7825}
7826
7827let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7828class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7829                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7830                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7831                      string apple_kind, string dst_kind, string lhs_kind,
7832                      string rhs_kind, list<dag> pattern>
7833  : I<(outs dst_reg:$dst),
7834      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7835      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7836      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7837    Sched<[WriteV]> {
7838  bits<5> Rd;
7839  bits<5> Rn;
7840  bits<5> Rm;
7841
7842  let Inst{31}    = 0;
7843  let Inst{30}    = Q;
7844  let Inst{29}    = U;
7845  let Inst{28}    = Scalar;
7846  let Inst{27-24} = 0b1111;
7847  let Inst{23-22} = size;
7848  // Bit 21 must be set by the derived class.
7849  let Inst{20-16} = Rm;
7850  let Inst{15-12} = opc;
7851  // Bit 11 must be set by the derived class.
7852  let Inst{10}    = 0;
7853  let Inst{9-5}   = Rn;
7854  let Inst{4-0}   = Rd;
7855}
7856
7857
7858//----------------------------------------------------------------------------
7859// Armv8.6 BFloat16 Extension
7860//----------------------------------------------------------------------------
7861let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
7862
7863class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
7864                                   string kind2, RegisterOperand RegType,
7865                                   ValueType AccumType, ValueType InputType>
7866  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
7867                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
7868                                            (InputType RegType:$Rn),
7869                                            (InputType RegType:$Rm)))]> {
7870  let AsmString = !strconcat(asm,
7871                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
7872                               ", $Rm" # kind2 # "}");
7873}
7874
7875multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
7876  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
7877                                           v2f32, v4bf16>;
7878  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
7879                                           v4f32, v8bf16>;
7880}
7881
7882class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
7883                                      string dst_kind, string lhs_kind,
7884                                      string rhs_kind,
7885                                      RegisterOperand RegType,
7886                                      ValueType AccumType,
7887                                      ValueType InputType>
7888  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
7889                        RegType, RegType, V128, VectorIndexS,
7890                        asm, "", dst_kind, lhs_kind, rhs_kind,
7891        [(set (AccumType RegType:$dst),
7892              (AccumType (int_aarch64_neon_bfdot
7893                                 (AccumType RegType:$Rd),
7894                                 (InputType RegType:$Rn),
7895                                 (InputType (bitconvert (AccumType
7896                                    (AArch64duplane32 (v4f32 V128:$Rm),
7897                                        VectorIndexS:$idx)))))))]> {
7898
7899  bits<2> idx;
7900  let Inst{21}    = idx{0};  // L
7901  let Inst{11}    = idx{1};  // H
7902}
7903
7904multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
7905
7906  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
7907                                               ".2h", V64, v2f32, v4bf16>;
7908  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
7909                                              ".2h", V128, v4f32, v8bf16>;
7910}
7911
7912class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
7913  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
7914              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
7915                                               (v8bf16 V128:$Rn),
7916                                               (v8bf16 V128:$Rm)))]> {
7917  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
7918}
7919
7920class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
7921  : I<(outs V128:$dst),
7922      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
7923      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
7924          [(set (v4f32 V128:$dst),
7925                (v4f32 (OpNode (v4f32 V128:$Rd),
7926                               (v8bf16 V128:$Rn),
7927                               (v8bf16
7928                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
7929                                      VectorIndexH:$idx)))))]>,
7930    Sched<[WriteV]> {
7931  bits<5> Rd;
7932  bits<5> Rn;
7933  bits<4> Rm;
7934  bits<3> idx;
7935
7936  let Inst{31}    = 0;
7937  let Inst{30}    = Q;
7938  let Inst{29-22} = 0b00111111;
7939  let Inst{21-20} = idx{1-0};
7940  let Inst{19-16} = Rm;
7941  let Inst{15-12} = 0b1111;
7942  let Inst{11}    = idx{2};   // H
7943  let Inst{10}    = 0;
7944  let Inst{9-5}   = Rn;
7945  let Inst{4-0}   = Rd;
7946}
7947
7948class SIMDThreeSameVectorBF16MatrixMul<string asm>
7949  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
7950                                V128, asm, ".4s",
7951                          [(set (v4f32 V128:$dst),
7952                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
7953                                                         (v8bf16 V128:$Rn),
7954                                                         (v8bf16 V128:$Rm)))]> {
7955  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
7956                                    ", $Rm", ".8h", "}");
7957}
7958
7959class SIMD_BFCVTN
7960  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
7961                           "bfcvtn", ".4h", ".4s",
7962    [(set (v8bf16 V128:$Rd),
7963          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
7964
7965class SIMD_BFCVTN2
7966  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
7967                           "bfcvtn2", ".8h", ".4s",
7968    [(set (v8bf16 V128:$dst),
7969          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
7970
7971class BF16ToSinglePrecision<string asm>
7972  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
7973    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
7974    Sched<[WriteFCvt]> {
7975  bits<5> Rd;
7976  bits<5> Rn;
7977  let Inst{31-10} = 0b0001111001100011010000;
7978  let Inst{9-5}   = Rn;
7979  let Inst{4-0}   = Rd;
7980}
7981} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
7982
7983//----------------------------------------------------------------------------
7984// Armv8.6 Matrix Multiply Extension
7985//----------------------------------------------------------------------------
7986
7987class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
7988  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
7989              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
7990                                               (v16i8 V128:$Rn),
7991                                               (v16i8 V128:$Rm)))]> {
7992  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
7993}
7994
7995//----------------------------------------------------------------------------
7996// ARMv8.2-A Dot Product Instructions (Indexed)
7997class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
7998                                      string dst_kind, string lhs_kind, string rhs_kind,
7999                                      RegisterOperand RegType,
8000                                      ValueType AccumType, ValueType InputType,
8001                                      SDPatternOperator OpNode> :
8002        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
8003                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8004        [(set (AccumType RegType:$dst),
8005              (AccumType (OpNode (AccumType RegType:$Rd),
8006                                 (InputType RegType:$Rn),
8007                                 (InputType (bitconvert (AccumType
8008                                    (AArch64duplane32 (v4i32 V128:$Rm),
8009                                        VectorIndexS:$idx)))))))]> {
8010  bits<2> idx;
8011  let Inst{21}    = idx{0};  // L
8012  let Inst{11}    = idx{1};  // H
8013}
8014
8015multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8016                                       SDPatternOperator OpNode> {
8017  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
8018                                              V64, v2i32, v8i8, OpNode>;
8019  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
8020                                              V128, v4i32, v16i8, OpNode>;
8021}
8022
8023// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8024class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
8025                                      string dst_kind, string lhs_kind,
8026                                      string rhs_kind, RegisterOperand RegType,
8027                                      ValueType AccumType, ValueType InputType,
8028                                      SDPatternOperator OpNode> :
8029        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
8030                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8031          [(set (AccumType RegType:$dst),
8032                (AccumType (OpNode (AccumType RegType:$Rd),
8033                                   (InputType RegType:$Rn),
8034                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
8035                                                VectorIndexH:$idx)))))]> {
8036  // idx = H:L:M
8037  bits<3> idx;
8038  let Inst{11} = idx{2}; // H
8039  let Inst{21} = idx{1}; // L
8040  let Inst{20} = idx{0}; // M
8041}
8042
8043multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8044                                       SDPatternOperator OpNode> {
8045  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8046                                              V64, v2f32, v4f16, OpNode>;
8047  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8048                                              V128, v4f32, v8f16, OpNode>;
8049}
8050
8051multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8052                         SDPatternOperator OpNode> {
8053  let Predicates = [HasNEON, HasFullFP16] in {
8054  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8055                                      V64, V64,
8056                                      V128_lo, VectorIndexH,
8057                                      asm, ".4h", ".4h", ".4h", ".h",
8058    [(set (v4f16 V64:$Rd),
8059        (OpNode (v4f16 V64:$Rn),
8060         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8061    bits<3> idx;
8062    let Inst{11} = idx{2};
8063    let Inst{21} = idx{1};
8064    let Inst{20} = idx{0};
8065  }
8066
8067  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8068                                      V128, V128,
8069                                      V128_lo, VectorIndexH,
8070                                      asm, ".8h", ".8h", ".8h", ".h",
8071    [(set (v8f16 V128:$Rd),
8072        (OpNode (v8f16 V128:$Rn),
8073         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8074    bits<3> idx;
8075    let Inst{11} = idx{2};
8076    let Inst{21} = idx{1};
8077    let Inst{20} = idx{0};
8078  }
8079  } // Predicates = [HasNEON, HasFullFP16]
8080
8081  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8082                                      V64, V64,
8083                                      V128, VectorIndexS,
8084                                      asm, ".2s", ".2s", ".2s", ".s",
8085    [(set (v2f32 V64:$Rd),
8086        (OpNode (v2f32 V64:$Rn),
8087         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8088    bits<2> idx;
8089    let Inst{11} = idx{1};
8090    let Inst{21} = idx{0};
8091  }
8092
8093  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8094                                      V128, V128,
8095                                      V128, VectorIndexS,
8096                                      asm, ".4s", ".4s", ".4s", ".s",
8097    [(set (v4f32 V128:$Rd),
8098        (OpNode (v4f32 V128:$Rn),
8099         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8100    bits<2> idx;
8101    let Inst{11} = idx{1};
8102    let Inst{21} = idx{0};
8103  }
8104
8105  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8106                                      V128, V128,
8107                                      V128, VectorIndexD,
8108                                      asm, ".2d", ".2d", ".2d", ".d",
8109    [(set (v2f64 V128:$Rd),
8110        (OpNode (v2f64 V128:$Rn),
8111         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8112    bits<1> idx;
8113    let Inst{11} = idx{0};
8114    let Inst{21} = 0;
8115  }
8116
8117  let Predicates = [HasNEON, HasFullFP16] in {
8118  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8119                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8120                                      asm, ".h", "", "", ".h",
8121    [(set (f16 FPR16Op:$Rd),
8122          (OpNode (f16 FPR16Op:$Rn),
8123                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8124                                       VectorIndexH:$idx))))]> {
8125    bits<3> idx;
8126    let Inst{11} = idx{2};
8127    let Inst{21} = idx{1};
8128    let Inst{20} = idx{0};
8129  }
8130  } // Predicates = [HasNEON, HasFullFP16]
8131
8132  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8133                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8134                                      asm, ".s", "", "", ".s",
8135    [(set (f32 FPR32Op:$Rd),
8136          (OpNode (f32 FPR32Op:$Rn),
8137                  (f32 (vector_extract (v4f32 V128:$Rm),
8138                                       VectorIndexS:$idx))))]> {
8139    bits<2> idx;
8140    let Inst{11} = idx{1};
8141    let Inst{21} = idx{0};
8142  }
8143
8144  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8145                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8146                                      asm, ".d", "", "", ".d",
8147    [(set (f64 FPR64Op:$Rd),
8148          (OpNode (f64 FPR64Op:$Rn),
8149                  (f64 (vector_extract (v2f64 V128:$Rm),
8150                                       VectorIndexD:$idx))))]> {
8151    bits<1> idx;
8152    let Inst{11} = idx{0};
8153    let Inst{21} = 0;
8154  }
8155}
8156
8157multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8158  let Predicates = [HasNEON, HasFullFP16] in {
8159  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8160  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8161                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8162                                           VectorIndexH:$idx))),
8163            (!cast<Instruction>(INST # "v8i16_indexed")
8164                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8165  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8166                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8167            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8168                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8169
8170  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8171                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8172                                           VectorIndexH:$idx))),
8173            (!cast<Instruction>(INST # "v4i16_indexed")
8174                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8175  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8176                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8177            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8178                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8179
8180  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8181                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8182            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8183                V128_lo:$Rm, VectorIndexH:$idx)>;
8184  } // Predicates = [HasNEON, HasFullFP16]
8185
8186  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8187  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8188                           (AArch64duplane32 (v4f32 V128:$Rm),
8189                                           VectorIndexS:$idx))),
8190            (!cast<Instruction>(INST # v2i32_indexed)
8191                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8192  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8193                           (AArch64dup (f32 FPR32Op:$Rm)))),
8194            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8195                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8196
8197
8198  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8199  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8200                           (AArch64duplane32 (v4f32 V128:$Rm),
8201                                           VectorIndexS:$idx))),
8202            (!cast<Instruction>(INST # "v4i32_indexed")
8203                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8204  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8205                           (AArch64dup (f32 FPR32Op:$Rm)))),
8206            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8207                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8208
8209  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8210  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8211                           (AArch64duplane64 (v2f64 V128:$Rm),
8212                                           VectorIndexD:$idx))),
8213            (!cast<Instruction>(INST # "v2i64_indexed")
8214                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8215  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8216                           (AArch64dup (f64 FPR64Op:$Rm)))),
8217            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8218                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8219
8220  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8221  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8222                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8223            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8224                V128:$Rm, VectorIndexS:$idx)>;
8225
8226  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8227  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8228                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8229            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8230                V128:$Rm, VectorIndexD:$idx)>;
8231}
8232
8233multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8234  let Predicates = [HasNEON, HasFullFP16] in {
8235  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8236                                          V128_lo, VectorIndexH,
8237                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8238    bits<3> idx;
8239    let Inst{11} = idx{2};
8240    let Inst{21} = idx{1};
8241    let Inst{20} = idx{0};
8242  }
8243
8244  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8245                                          V128, V128,
8246                                          V128_lo, VectorIndexH,
8247                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8248    bits<3> idx;
8249    let Inst{11} = idx{2};
8250    let Inst{21} = idx{1};
8251    let Inst{20} = idx{0};
8252  }
8253  } // Predicates = [HasNEON, HasFullFP16]
8254
8255  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8256                                          V128, VectorIndexS,
8257                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8258    bits<2> idx;
8259    let Inst{11} = idx{1};
8260    let Inst{21} = idx{0};
8261  }
8262
8263  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8264                                      V128, V128,
8265                                      V128, VectorIndexS,
8266                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8267    bits<2> idx;
8268    let Inst{11} = idx{1};
8269    let Inst{21} = idx{0};
8270  }
8271
8272  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8273                                      V128, V128,
8274                                      V128, VectorIndexD,
8275                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8276    bits<1> idx;
8277    let Inst{11} = idx{0};
8278    let Inst{21} = 0;
8279  }
8280
8281  let Predicates = [HasNEON, HasFullFP16] in {
8282  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8283                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8284                                      asm, ".h", "", "", ".h", []> {
8285    bits<3> idx;
8286    let Inst{11} = idx{2};
8287    let Inst{21} = idx{1};
8288    let Inst{20} = idx{0};
8289  }
8290  } // Predicates = [HasNEON, HasFullFP16]
8291
8292  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8293                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8294                                      asm, ".s", "", "", ".s", []> {
8295    bits<2> idx;
8296    let Inst{11} = idx{1};
8297    let Inst{21} = idx{0};
8298  }
8299
8300  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8301                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8302                                      asm, ".d", "", "", ".d", []> {
8303    bits<1> idx;
8304    let Inst{11} = idx{0};
8305    let Inst{21} = 0;
8306  }
8307}
8308
8309multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8310                                 SDPatternOperator OpNodeLaneQ> {
8311
8312  def : Pat<(v4i16 (OpNodeLane
8313                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8314                     VectorIndexS32b:$idx)),
8315            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8316              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8317              (UImmS1XForm $idx))>;
8318
8319  def : Pat<(v4i16 (OpNodeLaneQ
8320                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8321                     VectorIndexH32b:$idx)),
8322            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8323              (UImmS1XForm $idx))>;
8324
8325  def : Pat<(v8i16 (OpNodeLane
8326                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8327                     VectorIndexS32b:$idx)),
8328            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8329              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8330              (UImmS1XForm $idx))>;
8331
8332  def : Pat<(v8i16 (OpNodeLaneQ
8333                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8334                     VectorIndexH32b:$idx)),
8335            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8336              (UImmS1XForm $idx))>;
8337
8338  def : Pat<(v2i32 (OpNodeLane
8339                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8340                     VectorIndexD32b:$idx)),
8341            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8342              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8343              (UImmS1XForm $idx))>;
8344
8345  def : Pat<(v2i32 (OpNodeLaneQ
8346                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8347                     VectorIndexS32b:$idx)),
8348            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8349              (UImmS1XForm $idx))>;
8350
8351  def : Pat<(v4i32 (OpNodeLane
8352                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8353                     VectorIndexD32b:$idx)),
8354            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8355              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8356              (UImmS1XForm $idx))>;
8357
8358  def : Pat<(v4i32 (OpNodeLaneQ
8359                     (v4i32 V128:$Rn),
8360                     (v4i32 V128:$Rm),
8361                     VectorIndexS32b:$idx)),
8362            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8363              (UImmS1XForm $idx))>;
8364
8365}
8366
8367multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8368                         SDPatternOperator OpNode> {
8369  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8370                                      V128_lo, VectorIndexH,
8371                                      asm, ".4h", ".4h", ".4h", ".h",
8372    [(set (v4i16 V64:$Rd),
8373        (OpNode (v4i16 V64:$Rn),
8374         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8375    bits<3> idx;
8376    let Inst{11} = idx{2};
8377    let Inst{21} = idx{1};
8378    let Inst{20} = idx{0};
8379  }
8380
8381  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8382                                      V128, V128,
8383                                      V128_lo, VectorIndexH,
8384                                      asm, ".8h", ".8h", ".8h", ".h",
8385    [(set (v8i16 V128:$Rd),
8386       (OpNode (v8i16 V128:$Rn),
8387         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8388    bits<3> idx;
8389    let Inst{11} = idx{2};
8390    let Inst{21} = idx{1};
8391    let Inst{20} = idx{0};
8392  }
8393
8394  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8395                                      V64, V64,
8396                                      V128, VectorIndexS,
8397                                      asm, ".2s", ".2s", ".2s",  ".s",
8398    [(set (v2i32 V64:$Rd),
8399       (OpNode (v2i32 V64:$Rn),
8400          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8401    bits<2> idx;
8402    let Inst{11} = idx{1};
8403    let Inst{21} = idx{0};
8404  }
8405
8406  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8407                                      V128, V128,
8408                                      V128, VectorIndexS,
8409                                      asm, ".4s", ".4s", ".4s", ".s",
8410    [(set (v4i32 V128:$Rd),
8411       (OpNode (v4i32 V128:$Rn),
8412          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8413    bits<2> idx;
8414    let Inst{11} = idx{1};
8415    let Inst{21} = idx{0};
8416  }
8417
8418  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8419                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8420                                      asm, ".h", "", "", ".h", []> {
8421    bits<3> idx;
8422    let Inst{11} = idx{2};
8423    let Inst{21} = idx{1};
8424    let Inst{20} = idx{0};
8425  }
8426
8427  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8428                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8429                                      asm, ".s", "", "", ".s",
8430      [(set (i32 FPR32Op:$Rd),
8431            (OpNode FPR32Op:$Rn,
8432                    (i32 (vector_extract (v4i32 V128:$Rm),
8433                                         VectorIndexS:$idx))))]> {
8434    bits<2> idx;
8435    let Inst{11} = idx{1};
8436    let Inst{21} = idx{0};
8437  }
8438}
8439
8440multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8441                               SDPatternOperator OpNode> {
8442  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8443                                      V64, V64,
8444                                      V128_lo, VectorIndexH,
8445                                      asm, ".4h", ".4h", ".4h", ".h",
8446    [(set (v4i16 V64:$Rd),
8447        (OpNode (v4i16 V64:$Rn),
8448         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8449    bits<3> idx;
8450    let Inst{11} = idx{2};
8451    let Inst{21} = idx{1};
8452    let Inst{20} = idx{0};
8453  }
8454
8455  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8456                                      V128, V128,
8457                                      V128_lo, VectorIndexH,
8458                                      asm, ".8h", ".8h", ".8h", ".h",
8459    [(set (v8i16 V128:$Rd),
8460       (OpNode (v8i16 V128:$Rn),
8461         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8462    bits<3> idx;
8463    let Inst{11} = idx{2};
8464    let Inst{21} = idx{1};
8465    let Inst{20} = idx{0};
8466  }
8467
8468  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8469                                      V64, V64,
8470                                      V128, VectorIndexS,
8471                                      asm, ".2s", ".2s", ".2s", ".s",
8472    [(set (v2i32 V64:$Rd),
8473       (OpNode (v2i32 V64:$Rn),
8474          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8475    bits<2> idx;
8476    let Inst{11} = idx{1};
8477    let Inst{21} = idx{0};
8478  }
8479
8480  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8481                                      V128, V128,
8482                                      V128, VectorIndexS,
8483                                      asm, ".4s", ".4s", ".4s", ".s",
8484    [(set (v4i32 V128:$Rd),
8485       (OpNode (v4i32 V128:$Rn),
8486          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8487    bits<2> idx;
8488    let Inst{11} = idx{1};
8489    let Inst{21} = idx{0};
8490  }
8491}
8492
8493multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8494                                   SDPatternOperator OpNode> {
8495  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8496                                          V128_lo, VectorIndexH,
8497                                          asm, ".4h", ".4h", ".4h", ".h",
8498    [(set (v4i16 V64:$dst),
8499        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8500         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8501    bits<3> idx;
8502    let Inst{11} = idx{2};
8503    let Inst{21} = idx{1};
8504    let Inst{20} = idx{0};
8505  }
8506
8507  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8508                                      V128, V128,
8509                                      V128_lo, VectorIndexH,
8510                                      asm, ".8h", ".8h", ".8h", ".h",
8511    [(set (v8i16 V128:$dst),
8512       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8513         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8514    bits<3> idx;
8515    let Inst{11} = idx{2};
8516    let Inst{21} = idx{1};
8517    let Inst{20} = idx{0};
8518  }
8519
8520  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8521                                      V64, V64,
8522                                      V128, VectorIndexS,
8523                                      asm, ".2s", ".2s", ".2s", ".s",
8524    [(set (v2i32 V64:$dst),
8525       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8526          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8527    bits<2> idx;
8528    let Inst{11} = idx{1};
8529    let Inst{21} = idx{0};
8530  }
8531
8532  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8533                                      V128, V128,
8534                                      V128, VectorIndexS,
8535                                      asm, ".4s", ".4s", ".4s", ".s",
8536    [(set (v4i32 V128:$dst),
8537       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8538          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8539    bits<2> idx;
8540    let Inst{11} = idx{1};
8541    let Inst{21} = idx{0};
8542  }
8543}
8544
8545multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8546                             SDPatternOperator OpNode> {
8547  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8548                                      V128, V64,
8549                                      V128_lo, VectorIndexH,
8550                                      asm, ".4s", ".4s", ".4h", ".h",
8551    [(set (v4i32 V128:$Rd),
8552        (OpNode (v4i16 V64:$Rn),
8553         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8554    bits<3> idx;
8555    let Inst{11} = idx{2};
8556    let Inst{21} = idx{1};
8557    let Inst{20} = idx{0};
8558  }
8559
8560  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8561                                      V128, V128,
8562                                      V128_lo, VectorIndexH,
8563                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8564    [(set (v4i32 V128:$Rd),
8565          (OpNode (extract_high_v8i16 V128:$Rn),
8566                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8567                                                      VectorIndexH:$idx))))]> {
8568
8569    bits<3> idx;
8570    let Inst{11} = idx{2};
8571    let Inst{21} = idx{1};
8572    let Inst{20} = idx{0};
8573  }
8574
8575  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8576                                      V128, V64,
8577                                      V128, VectorIndexS,
8578                                      asm, ".2d", ".2d", ".2s", ".s",
8579    [(set (v2i64 V128:$Rd),
8580        (OpNode (v2i32 V64:$Rn),
8581         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8582    bits<2> idx;
8583    let Inst{11} = idx{1};
8584    let Inst{21} = idx{0};
8585  }
8586
8587  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8588                                      V128, V128,
8589                                      V128, VectorIndexS,
8590                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8591    [(set (v2i64 V128:$Rd),
8592          (OpNode (extract_high_v4i32 V128:$Rn),
8593                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8594                                                      VectorIndexS:$idx))))]> {
8595    bits<2> idx;
8596    let Inst{11} = idx{1};
8597    let Inst{21} = idx{0};
8598  }
8599
8600  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8601                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8602                                      asm, ".h", "", "", ".h", []> {
8603    bits<3> idx;
8604    let Inst{11} = idx{2};
8605    let Inst{21} = idx{1};
8606    let Inst{20} = idx{0};
8607  }
8608
8609  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8610                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8611                                      asm, ".s", "", "", ".s", []> {
8612    bits<2> idx;
8613    let Inst{11} = idx{1};
8614    let Inst{21} = idx{0};
8615  }
8616}
8617
8618multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8619                                       SDPatternOperator Accum> {
8620  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8621                                      V128, V64,
8622                                      V128_lo, VectorIndexH,
8623                                      asm, ".4s", ".4s", ".4h", ".h",
8624    [(set (v4i32 V128:$dst),
8625          (Accum (v4i32 V128:$Rd),
8626                 (v4i32 (int_aarch64_neon_sqdmull
8627                             (v4i16 V64:$Rn),
8628                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8629                                                    VectorIndexH:$idx))))))]> {
8630    bits<3> idx;
8631    let Inst{11} = idx{2};
8632    let Inst{21} = idx{1};
8633    let Inst{20} = idx{0};
8634  }
8635
8636  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8637  // intermediate EXTRACT_SUBREG would be untyped.
8638  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8639                (i32 (vector_extract (v4i32
8640                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8641                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8642                                                    VectorIndexH:$idx)))),
8643                         (i64 0))))),
8644            (EXTRACT_SUBREG
8645                (!cast<Instruction>(NAME # v4i16_indexed)
8646                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8647                    V128_lo:$Rm, VectorIndexH:$idx),
8648                ssub)>;
8649
8650  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8651                                      V128, V128,
8652                                      V128_lo, VectorIndexH,
8653                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8654    [(set (v4i32 V128:$dst),
8655          (Accum (v4i32 V128:$Rd),
8656                 (v4i32 (int_aarch64_neon_sqdmull
8657                            (extract_high_v8i16 V128:$Rn),
8658                            (extract_high_v8i16
8659                                (AArch64duplane16 (v8i16 V128_lo:$Rm),
8660                                                VectorIndexH:$idx))))))]> {
8661    bits<3> idx;
8662    let Inst{11} = idx{2};
8663    let Inst{21} = idx{1};
8664    let Inst{20} = idx{0};
8665  }
8666
8667  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8668                                      V128, V64,
8669                                      V128, VectorIndexS,
8670                                      asm, ".2d", ".2d", ".2s", ".s",
8671    [(set (v2i64 V128:$dst),
8672        (Accum (v2i64 V128:$Rd),
8673               (v2i64 (int_aarch64_neon_sqdmull
8674                          (v2i32 V64:$Rn),
8675                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8676                                                 VectorIndexS:$idx))))))]> {
8677    bits<2> idx;
8678    let Inst{11} = idx{1};
8679    let Inst{21} = idx{0};
8680  }
8681
8682  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8683                                      V128, V128,
8684                                      V128, VectorIndexS,
8685                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8686    [(set (v2i64 V128:$dst),
8687          (Accum (v2i64 V128:$Rd),
8688                 (v2i64 (int_aarch64_neon_sqdmull
8689                            (extract_high_v4i32 V128:$Rn),
8690                            (extract_high_v4i32
8691                                (AArch64duplane32 (v4i32 V128:$Rm),
8692                                                VectorIndexS:$idx))))))]> {
8693    bits<2> idx;
8694    let Inst{11} = idx{1};
8695    let Inst{21} = idx{0};
8696  }
8697
8698  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8699                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8700                                      asm, ".h", "", "", ".h", []> {
8701    bits<3> idx;
8702    let Inst{11} = idx{2};
8703    let Inst{21} = idx{1};
8704    let Inst{20} = idx{0};
8705  }
8706
8707
8708  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8709                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8710                                      asm, ".s", "", "", ".s",
8711    [(set (i64 FPR64Op:$dst),
8712          (Accum (i64 FPR64Op:$Rd),
8713                 (i64 (int_aarch64_neon_sqdmulls_scalar
8714                            (i32 FPR32Op:$Rn),
8715                            (i32 (vector_extract (v4i32 V128:$Rm),
8716                                                 VectorIndexS:$idx))))))]> {
8717
8718    bits<2> idx;
8719    let Inst{11} = idx{1};
8720    let Inst{21} = idx{0};
8721  }
8722}
8723
8724multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8725                                   SDPatternOperator OpNode> {
8726  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8727  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8728                                      V128, V64,
8729                                      V128_lo, VectorIndexH,
8730                                      asm, ".4s", ".4s", ".4h", ".h",
8731    [(set (v4i32 V128:$Rd),
8732        (OpNode (v4i16 V64:$Rn),
8733         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8734    bits<3> idx;
8735    let Inst{11} = idx{2};
8736    let Inst{21} = idx{1};
8737    let Inst{20} = idx{0};
8738  }
8739
8740  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8741                                      V128, V128,
8742                                      V128_lo, VectorIndexH,
8743                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8744    [(set (v4i32 V128:$Rd),
8745          (OpNode (extract_high_v8i16 V128:$Rn),
8746                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8747                                                      VectorIndexH:$idx))))]> {
8748
8749    bits<3> idx;
8750    let Inst{11} = idx{2};
8751    let Inst{21} = idx{1};
8752    let Inst{20} = idx{0};
8753  }
8754
8755  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8756                                      V128, V64,
8757                                      V128, VectorIndexS,
8758                                      asm, ".2d", ".2d", ".2s", ".s",
8759    [(set (v2i64 V128:$Rd),
8760        (OpNode (v2i32 V64:$Rn),
8761         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8762    bits<2> idx;
8763    let Inst{11} = idx{1};
8764    let Inst{21} = idx{0};
8765  }
8766
8767  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8768                                      V128, V128,
8769                                      V128, VectorIndexS,
8770                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8771    [(set (v2i64 V128:$Rd),
8772          (OpNode (extract_high_v4i32 V128:$Rn),
8773                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8774                                                      VectorIndexS:$idx))))]> {
8775    bits<2> idx;
8776    let Inst{11} = idx{1};
8777    let Inst{21} = idx{0};
8778  }
8779  }
8780}
8781
8782multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8783                                       SDPatternOperator OpNode> {
8784  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8785  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8786                                      V128, V64,
8787                                      V128_lo, VectorIndexH,
8788                                      asm, ".4s", ".4s", ".4h", ".h",
8789    [(set (v4i32 V128:$dst),
8790        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8791         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8792    bits<3> idx;
8793    let Inst{11} = idx{2};
8794    let Inst{21} = idx{1};
8795    let Inst{20} = idx{0};
8796  }
8797
8798  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8799                                      V128, V128,
8800                                      V128_lo, VectorIndexH,
8801                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8802    [(set (v4i32 V128:$dst),
8803          (OpNode (v4i32 V128:$Rd),
8804                  (extract_high_v8i16 V128:$Rn),
8805                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8806                                                      VectorIndexH:$idx))))]> {
8807    bits<3> idx;
8808    let Inst{11} = idx{2};
8809    let Inst{21} = idx{1};
8810    let Inst{20} = idx{0};
8811  }
8812
8813  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8814                                      V128, V64,
8815                                      V128, VectorIndexS,
8816                                      asm, ".2d", ".2d", ".2s", ".s",
8817    [(set (v2i64 V128:$dst),
8818        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8819         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8820    bits<2> idx;
8821    let Inst{11} = idx{1};
8822    let Inst{21} = idx{0};
8823  }
8824
8825  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8826                                      V128, V128,
8827                                      V128, VectorIndexS,
8828                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8829    [(set (v2i64 V128:$dst),
8830          (OpNode (v2i64 V128:$Rd),
8831                  (extract_high_v4i32 V128:$Rn),
8832                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8833                                                      VectorIndexS:$idx))))]> {
8834    bits<2> idx;
8835    let Inst{11} = idx{1};
8836    let Inst{21} = idx{0};
8837  }
8838  }
8839}
8840
8841//----------------------------------------------------------------------------
8842// AdvSIMD scalar shift by immediate
8843//----------------------------------------------------------------------------
8844
8845let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8846class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8847                     RegisterClass regtype1, RegisterClass regtype2,
8848                     Operand immtype, string asm, list<dag> pattern>
8849  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8850      asm, "\t$Rd, $Rn, $imm", "", pattern>,
8851    Sched<[WriteV]> {
8852  bits<5> Rd;
8853  bits<5> Rn;
8854  bits<7> imm;
8855  let Inst{31-30} = 0b01;
8856  let Inst{29}    = U;
8857  let Inst{28-23} = 0b111110;
8858  let Inst{22-16} = fixed_imm;
8859  let Inst{15-11} = opc;
8860  let Inst{10}    = 1;
8861  let Inst{9-5} = Rn;
8862  let Inst{4-0} = Rd;
8863}
8864
8865let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8866class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8867                     RegisterClass regtype1, RegisterClass regtype2,
8868                     Operand immtype, string asm, list<dag> pattern>
8869  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8870      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8871    Sched<[WriteV]> {
8872  bits<5> Rd;
8873  bits<5> Rn;
8874  bits<7> imm;
8875  let Inst{31-30} = 0b01;
8876  let Inst{29}    = U;
8877  let Inst{28-23} = 0b111110;
8878  let Inst{22-16} = fixed_imm;
8879  let Inst{15-11} = opc;
8880  let Inst{10}    = 1;
8881  let Inst{9-5} = Rn;
8882  let Inst{4-0} = Rd;
8883}
8884
8885
8886multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8887  let Predicates = [HasNEON, HasFullFP16] in {
8888  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8889                              FPR16, FPR16, vecshiftR16, asm, []> {
8890    let Inst{19-16} = imm{3-0};
8891  }
8892  } // Predicates = [HasNEON, HasFullFP16]
8893  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8894                              FPR32, FPR32, vecshiftR32, asm, []> {
8895    let Inst{20-16} = imm{4-0};
8896  }
8897  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8898                              FPR64, FPR64, vecshiftR64, asm, []> {
8899    let Inst{21-16} = imm{5-0};
8900  }
8901}
8902
8903multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8904                             SDPatternOperator OpNode> {
8905  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8906                              FPR64, FPR64, vecshiftR64, asm,
8907  [(set (i64 FPR64:$Rd),
8908     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8909    let Inst{21-16} = imm{5-0};
8910  }
8911
8912  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8913            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8914}
8915
8916multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8917                                 SDPatternOperator OpNode = null_frag> {
8918  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8919                              FPR64, FPR64, vecshiftR64, asm,
8920  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8921                                                   (i32 vecshiftR64:$imm)))]> {
8922    let Inst{21-16} = imm{5-0};
8923  }
8924
8925  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8926                           (i32 vecshiftR64:$imm))),
8927            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8928                                            vecshiftR64:$imm)>;
8929}
8930
8931multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8932                             SDPatternOperator OpNode> {
8933  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8934                              FPR64, FPR64, vecshiftL64, asm,
8935    [(set (v1i64 FPR64:$Rd),
8936       (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8937    let Inst{21-16} = imm{5-0};
8938  }
8939}
8940
8941let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8942multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8943  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8944                              FPR64, FPR64, vecshiftL64, asm, []> {
8945    let Inst{21-16} = imm{5-0};
8946  }
8947}
8948
8949let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8950multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8951                               SDPatternOperator OpNode = null_frag> {
8952  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8953                              FPR8, FPR16, vecshiftR8, asm, []> {
8954    let Inst{18-16} = imm{2-0};
8955  }
8956
8957  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8958                              FPR16, FPR32, vecshiftR16, asm, []> {
8959    let Inst{19-16} = imm{3-0};
8960  }
8961
8962  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8963                              FPR32, FPR64, vecshiftR32, asm,
8964    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8965    let Inst{20-16} = imm{4-0};
8966  }
8967}
8968
8969multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8970                                SDPatternOperator OpNode> {
8971  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8972                              FPR8, FPR8, vecshiftL8, asm, []> {
8973    let Inst{18-16} = imm{2-0};
8974  }
8975
8976  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8977                              FPR16, FPR16, vecshiftL16, asm, []> {
8978    let Inst{19-16} = imm{3-0};
8979  }
8980
8981  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8982                              FPR32, FPR32, vecshiftL32, asm,
8983    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8984    let Inst{20-16} = imm{4-0};
8985  }
8986
8987  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8988                              FPR64, FPR64, vecshiftL64, asm,
8989    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8990    let Inst{21-16} = imm{5-0};
8991  }
8992
8993  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8994            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8995}
8996
8997multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8998  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8999                              FPR8, FPR8, vecshiftR8, asm, []> {
9000    let Inst{18-16} = imm{2-0};
9001  }
9002
9003  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9004                              FPR16, FPR16, vecshiftR16, asm, []> {
9005    let Inst{19-16} = imm{3-0};
9006  }
9007
9008  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9009                              FPR32, FPR32, vecshiftR32, asm, []> {
9010    let Inst{20-16} = imm{4-0};
9011  }
9012
9013  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9014                              FPR64, FPR64, vecshiftR64, asm, []> {
9015    let Inst{21-16} = imm{5-0};
9016  }
9017}
9018
9019//----------------------------------------------------------------------------
9020// AdvSIMD vector x indexed element
9021//----------------------------------------------------------------------------
9022
9023let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9024class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9025                     RegisterOperand dst_reg, RegisterOperand src_reg,
9026                     Operand immtype,
9027                     string asm, string dst_kind, string src_kind,
9028                     list<dag> pattern>
9029  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9030      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9031           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9032    Sched<[WriteV]> {
9033  bits<5> Rd;
9034  bits<5> Rn;
9035  let Inst{31}    = 0;
9036  let Inst{30}    = Q;
9037  let Inst{29}    = U;
9038  let Inst{28-23} = 0b011110;
9039  let Inst{22-16} = fixed_imm;
9040  let Inst{15-11} = opc;
9041  let Inst{10}    = 1;
9042  let Inst{9-5}   = Rn;
9043  let Inst{4-0}   = Rd;
9044}
9045
9046let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9047class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9048                     RegisterOperand vectype1, RegisterOperand vectype2,
9049                     Operand immtype,
9050                     string asm, string dst_kind, string src_kind,
9051                     list<dag> pattern>
9052  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9053      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9054           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9055    Sched<[WriteV]> {
9056  bits<5> Rd;
9057  bits<5> Rn;
9058  let Inst{31}    = 0;
9059  let Inst{30}    = Q;
9060  let Inst{29}    = U;
9061  let Inst{28-23} = 0b011110;
9062  let Inst{22-16} = fixed_imm;
9063  let Inst{15-11} = opc;
9064  let Inst{10}    = 1;
9065  let Inst{9-5}   = Rn;
9066  let Inst{4-0}   = Rd;
9067}
9068
9069multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9070                              Intrinsic OpNode> {
9071  let Predicates = [HasNEON, HasFullFP16] in {
9072  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9073                                  V64, V64, vecshiftR16,
9074                                  asm, ".4h", ".4h",
9075      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9076    bits<4> imm;
9077    let Inst{19-16} = imm;
9078  }
9079
9080  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9081                                  V128, V128, vecshiftR16,
9082                                  asm, ".8h", ".8h",
9083      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9084    bits<4> imm;
9085    let Inst{19-16} = imm;
9086  }
9087  } // Predicates = [HasNEON, HasFullFP16]
9088  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9089                                  V64, V64, vecshiftR32,
9090                                  asm, ".2s", ".2s",
9091      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9092    bits<5> imm;
9093    let Inst{20-16} = imm;
9094  }
9095
9096  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9097                                  V128, V128, vecshiftR32,
9098                                  asm, ".4s", ".4s",
9099      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9100    bits<5> imm;
9101    let Inst{20-16} = imm;
9102  }
9103
9104  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9105                                  V128, V128, vecshiftR64,
9106                                  asm, ".2d", ".2d",
9107      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9108    bits<6> imm;
9109    let Inst{21-16} = imm;
9110  }
9111}
9112
9113multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9114                                  Intrinsic OpNode> {
9115  let Predicates = [HasNEON, HasFullFP16] in {
9116  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9117                                  V64, V64, vecshiftR16,
9118                                  asm, ".4h", ".4h",
9119      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9120    bits<4> imm;
9121    let Inst{19-16} = imm;
9122  }
9123
9124  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9125                                  V128, V128, vecshiftR16,
9126                                  asm, ".8h", ".8h",
9127      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9128    bits<4> imm;
9129    let Inst{19-16} = imm;
9130  }
9131  } // Predicates = [HasNEON, HasFullFP16]
9132
9133  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9134                                  V64, V64, vecshiftR32,
9135                                  asm, ".2s", ".2s",
9136      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9137    bits<5> imm;
9138    let Inst{20-16} = imm;
9139  }
9140
9141  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9142                                  V128, V128, vecshiftR32,
9143                                  asm, ".4s", ".4s",
9144      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9145    bits<5> imm;
9146    let Inst{20-16} = imm;
9147  }
9148
9149  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9150                                  V128, V128, vecshiftR64,
9151                                  asm, ".2d", ".2d",
9152      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9153    bits<6> imm;
9154    let Inst{21-16} = imm;
9155  }
9156}
9157
9158multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9159                                     SDPatternOperator OpNode> {
9160  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9161                                  V64, V128, vecshiftR16Narrow,
9162                                  asm, ".8b", ".8h",
9163      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9164    bits<3> imm;
9165    let Inst{18-16} = imm;
9166  }
9167
9168  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9169                                  V128, V128, vecshiftR16Narrow,
9170                                  asm#"2", ".16b", ".8h", []> {
9171    bits<3> imm;
9172    let Inst{18-16} = imm;
9173    let hasSideEffects = 0;
9174  }
9175
9176  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9177                                  V64, V128, vecshiftR32Narrow,
9178                                  asm, ".4h", ".4s",
9179      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9180    bits<4> imm;
9181    let Inst{19-16} = imm;
9182  }
9183
9184  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9185                                  V128, V128, vecshiftR32Narrow,
9186                                  asm#"2", ".8h", ".4s", []> {
9187    bits<4> imm;
9188    let Inst{19-16} = imm;
9189    let hasSideEffects = 0;
9190  }
9191
9192  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9193                                  V64, V128, vecshiftR64Narrow,
9194                                  asm, ".2s", ".2d",
9195      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9196    bits<5> imm;
9197    let Inst{20-16} = imm;
9198  }
9199
9200  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9201                                  V128, V128, vecshiftR64Narrow,
9202                                  asm#"2", ".4s", ".2d", []> {
9203    bits<5> imm;
9204    let Inst{20-16} = imm;
9205    let hasSideEffects = 0;
9206  }
9207
9208  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9209  // themselves, so put them here instead.
9210
9211  // Patterns involving what's effectively an insert high and a normal
9212  // intrinsic, represented by CONCAT_VECTORS.
9213  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9214                                                   vecshiftR16Narrow:$imm)),
9215            (!cast<Instruction>(NAME # "v16i8_shift")
9216                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9217                V128:$Rn, vecshiftR16Narrow:$imm)>;
9218  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9219                                                     vecshiftR32Narrow:$imm)),
9220            (!cast<Instruction>(NAME # "v8i16_shift")
9221                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9222                V128:$Rn, vecshiftR32Narrow:$imm)>;
9223  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9224                                                     vecshiftR64Narrow:$imm)),
9225            (!cast<Instruction>(NAME # "v4i32_shift")
9226                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9227                V128:$Rn, vecshiftR64Narrow:$imm)>;
9228}
9229
9230multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9231                                SDPatternOperator OpNode> {
9232  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9233                                  V64, V64, vecshiftL8,
9234                                  asm, ".8b", ".8b",
9235                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9236                       (i32 vecshiftL8:$imm)))]> {
9237    bits<3> imm;
9238    let Inst{18-16} = imm;
9239  }
9240
9241  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9242                                  V128, V128, vecshiftL8,
9243                                  asm, ".16b", ".16b",
9244             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9245                   (i32 vecshiftL8:$imm)))]> {
9246    bits<3> imm;
9247    let Inst{18-16} = imm;
9248  }
9249
9250  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9251                                  V64, V64, vecshiftL16,
9252                                  asm, ".4h", ".4h",
9253              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9254                    (i32 vecshiftL16:$imm)))]> {
9255    bits<4> imm;
9256    let Inst{19-16} = imm;
9257  }
9258
9259  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9260                                  V128, V128, vecshiftL16,
9261                                  asm, ".8h", ".8h",
9262            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9263                  (i32 vecshiftL16:$imm)))]> {
9264    bits<4> imm;
9265    let Inst{19-16} = imm;
9266  }
9267
9268  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9269                                  V64, V64, vecshiftL32,
9270                                  asm, ".2s", ".2s",
9271              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9272                    (i32 vecshiftL32:$imm)))]> {
9273    bits<5> imm;
9274    let Inst{20-16} = imm;
9275  }
9276
9277  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9278                                  V128, V128, vecshiftL32,
9279                                  asm, ".4s", ".4s",
9280            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9281                  (i32 vecshiftL32:$imm)))]> {
9282    bits<5> imm;
9283    let Inst{20-16} = imm;
9284  }
9285
9286  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9287                                  V128, V128, vecshiftL64,
9288                                  asm, ".2d", ".2d",
9289            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9290                  (i32 vecshiftL64:$imm)))]> {
9291    bits<6> imm;
9292    let Inst{21-16} = imm;
9293  }
9294}
9295
9296multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9297                                SDPatternOperator OpNode> {
9298  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9299                                  V64, V64, vecshiftR8,
9300                                  asm, ".8b", ".8b",
9301                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9302                       (i32 vecshiftR8:$imm)))]> {
9303    bits<3> imm;
9304    let Inst{18-16} = imm;
9305  }
9306
9307  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9308                                  V128, V128, vecshiftR8,
9309                                  asm, ".16b", ".16b",
9310             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9311                   (i32 vecshiftR8:$imm)))]> {
9312    bits<3> imm;
9313    let Inst{18-16} = imm;
9314  }
9315
9316  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9317                                  V64, V64, vecshiftR16,
9318                                  asm, ".4h", ".4h",
9319              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9320                    (i32 vecshiftR16:$imm)))]> {
9321    bits<4> imm;
9322    let Inst{19-16} = imm;
9323  }
9324
9325  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9326                                  V128, V128, vecshiftR16,
9327                                  asm, ".8h", ".8h",
9328            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9329                  (i32 vecshiftR16:$imm)))]> {
9330    bits<4> imm;
9331    let Inst{19-16} = imm;
9332  }
9333
9334  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9335                                  V64, V64, vecshiftR32,
9336                                  asm, ".2s", ".2s",
9337              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9338                    (i32 vecshiftR32:$imm)))]> {
9339    bits<5> imm;
9340    let Inst{20-16} = imm;
9341  }
9342
9343  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9344                                  V128, V128, vecshiftR32,
9345                                  asm, ".4s", ".4s",
9346            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9347                  (i32 vecshiftR32:$imm)))]> {
9348    bits<5> imm;
9349    let Inst{20-16} = imm;
9350  }
9351
9352  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9353                                  V128, V128, vecshiftR64,
9354                                  asm, ".2d", ".2d",
9355            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9356                  (i32 vecshiftR64:$imm)))]> {
9357    bits<6> imm;
9358    let Inst{21-16} = imm;
9359  }
9360}
9361
9362let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9363multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9364                                    SDPatternOperator OpNode = null_frag> {
9365  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9366                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9367                 [(set (v8i8 V64:$dst),
9368                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9369                           (i32 vecshiftR8:$imm)))]> {
9370    bits<3> imm;
9371    let Inst{18-16} = imm;
9372  }
9373
9374  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9375                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9376             [(set (v16i8 V128:$dst),
9377               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9378                       (i32 vecshiftR8:$imm)))]> {
9379    bits<3> imm;
9380    let Inst{18-16} = imm;
9381  }
9382
9383  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9384                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9385              [(set (v4i16 V64:$dst),
9386                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9387                        (i32 vecshiftR16:$imm)))]> {
9388    bits<4> imm;
9389    let Inst{19-16} = imm;
9390  }
9391
9392  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9393                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9394            [(set (v8i16 V128:$dst),
9395              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9396                      (i32 vecshiftR16:$imm)))]> {
9397    bits<4> imm;
9398    let Inst{19-16} = imm;
9399  }
9400
9401  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9402                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9403              [(set (v2i32 V64:$dst),
9404                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9405                        (i32 vecshiftR32:$imm)))]> {
9406    bits<5> imm;
9407    let Inst{20-16} = imm;
9408  }
9409
9410  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9411                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9412            [(set (v4i32 V128:$dst),
9413              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9414                      (i32 vecshiftR32:$imm)))]> {
9415    bits<5> imm;
9416    let Inst{20-16} = imm;
9417  }
9418
9419  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9420                                  V128, V128, vecshiftR64,
9421                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9422              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9423                      (i32 vecshiftR64:$imm)))]> {
9424    bits<6> imm;
9425    let Inst{21-16} = imm;
9426  }
9427}
9428
9429multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9430                                    SDPatternOperator OpNode = null_frag> {
9431  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9432                                  V64, V64, vecshiftL8,
9433                                  asm, ".8b", ".8b",
9434                    [(set (v8i8 V64:$dst),
9435                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9436                                  (i32 vecshiftL8:$imm)))]> {
9437    bits<3> imm;
9438    let Inst{18-16} = imm;
9439  }
9440
9441  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9442                                  V128, V128, vecshiftL8,
9443                                  asm, ".16b", ".16b",
9444                    [(set (v16i8 V128:$dst),
9445                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9446                                  (i32 vecshiftL8:$imm)))]> {
9447    bits<3> imm;
9448    let Inst{18-16} = imm;
9449  }
9450
9451  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9452                                  V64, V64, vecshiftL16,
9453                                  asm, ".4h", ".4h",
9454                    [(set (v4i16 V64:$dst),
9455                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9456                                   (i32 vecshiftL16:$imm)))]> {
9457    bits<4> imm;
9458    let Inst{19-16} = imm;
9459  }
9460
9461  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9462                                  V128, V128, vecshiftL16,
9463                                  asm, ".8h", ".8h",
9464                    [(set (v8i16 V128:$dst),
9465                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9466                                  (i32 vecshiftL16:$imm)))]> {
9467    bits<4> imm;
9468    let Inst{19-16} = imm;
9469  }
9470
9471  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9472                                  V64, V64, vecshiftL32,
9473                                  asm, ".2s", ".2s",
9474                    [(set (v2i32 V64:$dst),
9475                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9476                                  (i32 vecshiftL32:$imm)))]> {
9477    bits<5> imm;
9478    let Inst{20-16} = imm;
9479  }
9480
9481  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9482                                  V128, V128, vecshiftL32,
9483                                  asm, ".4s", ".4s",
9484                    [(set (v4i32 V128:$dst),
9485                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9486                                  (i32 vecshiftL32:$imm)))]> {
9487    bits<5> imm;
9488    let Inst{20-16} = imm;
9489  }
9490
9491  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9492                                  V128, V128, vecshiftL64,
9493                                  asm, ".2d", ".2d",
9494                    [(set (v2i64 V128:$dst),
9495                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9496                                  (i32 vecshiftL64:$imm)))]> {
9497    bits<6> imm;
9498    let Inst{21-16} = imm;
9499  }
9500}
9501
9502multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9503                                   SDPatternOperator OpNode> {
9504  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9505                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9506      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9507    bits<3> imm;
9508    let Inst{18-16} = imm;
9509  }
9510
9511  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9512                                  V128, V128, vecshiftL8,
9513                                  asm#"2", ".8h", ".16b",
9514      [(set (v8i16 V128:$Rd),
9515            (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
9516    bits<3> imm;
9517    let Inst{18-16} = imm;
9518  }
9519
9520  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9521                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9522      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9523    bits<4> imm;
9524    let Inst{19-16} = imm;
9525  }
9526
9527  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9528                                  V128, V128, vecshiftL16,
9529                                  asm#"2", ".4s", ".8h",
9530      [(set (v4i32 V128:$Rd),
9531            (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
9532
9533    bits<4> imm;
9534    let Inst{19-16} = imm;
9535  }
9536
9537  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9538                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9539      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9540    bits<5> imm;
9541    let Inst{20-16} = imm;
9542  }
9543
9544  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9545                                  V128, V128, vecshiftL32,
9546                                  asm#"2", ".2d", ".4s",
9547      [(set (v2i64 V128:$Rd),
9548            (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
9549    bits<5> imm;
9550    let Inst{20-16} = imm;
9551  }
9552}
9553
9554
9555//---
9556// Vector load/store
9557//---
9558// SIMD ldX/stX no-index memory references don't allow the optional
9559// ", #0" constant and handle post-indexing explicitly, so we use
9560// a more specialized parse method for them. Otherwise, it's the same as
9561// the general GPR64sp handling.
9562
9563class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9564                   string asm, dag oops, dag iops, list<dag> pattern>
9565  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9566  bits<5> Vt;
9567  bits<5> Rn;
9568  let Inst{31} = 0;
9569  let Inst{30} = Q;
9570  let Inst{29-23} = 0b0011000;
9571  let Inst{22} = L;
9572  let Inst{21-16} = 0b000000;
9573  let Inst{15-12} = opcode;
9574  let Inst{11-10} = size;
9575  let Inst{9-5} = Rn;
9576  let Inst{4-0} = Vt;
9577}
9578
9579class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9580                       string asm, dag oops, dag iops>
9581  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9582  bits<5> Vt;
9583  bits<5> Rn;
9584  bits<5> Xm;
9585  let Inst{31} = 0;
9586  let Inst{30} = Q;
9587  let Inst{29-23} = 0b0011001;
9588  let Inst{22} = L;
9589  let Inst{21} = 0;
9590  let Inst{20-16} = Xm;
9591  let Inst{15-12} = opcode;
9592  let Inst{11-10} = size;
9593  let Inst{9-5} = Rn;
9594  let Inst{4-0} = Vt;
9595}
9596
9597// The immediate form of AdvSIMD post-indexed addressing is encoded with
9598// register post-index addressing from the zero register.
9599multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9600                           int Offset, int Size> {
9601  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9602  //      "ld1\t$Vt, [$Rn], #16"
9603  // may get mapped to
9604  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9605  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9606                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9607                      GPR64sp:$Rn,
9608                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9609                      XZR), 1>;
9610
9611  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9612  //      "ld1.8b\t$Vt, [$Rn], #16"
9613  // may get mapped to
9614  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9615  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9616                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9617                      GPR64sp:$Rn,
9618                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9619                      XZR), 0>;
9620
9621  // E.g. "ld1.8b { v0, v1 }, [x1]"
9622  //      "ld1\t$Vt, [$Rn]"
9623  // may get mapped to
9624  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9625  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9626                  (!cast<Instruction>(BaseName # Count # "v" # layout)
9627                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9628                      GPR64sp:$Rn), 0>;
9629
9630  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9631  //      "ld1\t$Vt, [$Rn], $Xm"
9632  // may get mapped to
9633  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9634  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9635                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9636                      GPR64sp:$Rn,
9637                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9638                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9639}
9640
9641multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9642                       int Offset128, int Offset64, bits<4> opcode> {
9643  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9644    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9645                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9646                           (ins GPR64sp:$Rn), []>;
9647    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9648                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9649                           (ins GPR64sp:$Rn), []>;
9650    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9651                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9652                           (ins GPR64sp:$Rn), []>;
9653    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9654                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9655                           (ins GPR64sp:$Rn), []>;
9656    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9657                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9658                           (ins GPR64sp:$Rn), []>;
9659    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9660                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9661                           (ins GPR64sp:$Rn), []>;
9662    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9663                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9664                           (ins GPR64sp:$Rn), []>;
9665
9666
9667    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9668                       (outs GPR64sp:$wback,
9669                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
9670                       (ins GPR64sp:$Rn,
9671                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9672    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9673                       (outs GPR64sp:$wback,
9674                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
9675                       (ins GPR64sp:$Rn,
9676                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9677    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9678                       (outs GPR64sp:$wback,
9679                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
9680                       (ins GPR64sp:$Rn,
9681                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9682    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9683                       (outs GPR64sp:$wback,
9684                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
9685                       (ins GPR64sp:$Rn,
9686                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9687    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9688                       (outs GPR64sp:$wback,
9689                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
9690                       (ins GPR64sp:$Rn,
9691                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9692    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9693                       (outs GPR64sp:$wback,
9694                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
9695                       (ins GPR64sp:$Rn,
9696                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9697    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9698                       (outs GPR64sp:$wback,
9699                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
9700                       (ins GPR64sp:$Rn,
9701                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9702  }
9703
9704  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9705  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9706  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9707  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9708  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9709  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9710  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9711}
9712
9713// Only ld1/st1 has a v1d version.
9714multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9715                       int Offset128, int Offset64, bits<4> opcode> {
9716  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9717    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9718                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9719                                 GPR64sp:$Rn), []>;
9720    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9721                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9722                                GPR64sp:$Rn), []>;
9723    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9724                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9725                                GPR64sp:$Rn), []>;
9726    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9727                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9728                                GPR64sp:$Rn), []>;
9729    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9730                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9731                                GPR64sp:$Rn), []>;
9732    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9733                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9734                                GPR64sp:$Rn), []>;
9735    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9736                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9737                                GPR64sp:$Rn), []>;
9738
9739    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9740                       (outs GPR64sp:$wback),
9741                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9742                            GPR64sp:$Rn,
9743                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9744    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9745                       (outs GPR64sp:$wback),
9746                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9747                            GPR64sp:$Rn,
9748                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9749    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9750                       (outs GPR64sp:$wback),
9751                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9752                            GPR64sp:$Rn,
9753                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9754    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9755                       (outs GPR64sp:$wback),
9756                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9757                            GPR64sp:$Rn,
9758                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9759    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9760                       (outs GPR64sp:$wback),
9761                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9762                            GPR64sp:$Rn,
9763                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9764    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9765                       (outs GPR64sp:$wback),
9766                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9767                            GPR64sp:$Rn,
9768                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9769    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9770                       (outs GPR64sp:$wback),
9771                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9772                            GPR64sp:$Rn,
9773                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9774  }
9775
9776  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9777  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9778  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9779  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9780  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9781  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9782  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9783}
9784
9785multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9786                       int Offset128, int Offset64, bits<4> opcode>
9787  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9788
9789  // LD1 instructions have extra "1d" variants.
9790  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9791    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9792                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9793                           (ins GPR64sp:$Rn), []>;
9794
9795    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9796                       (outs GPR64sp:$wback,
9797                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
9798                       (ins GPR64sp:$Rn,
9799                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9800  }
9801
9802  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9803}
9804
9805multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9806                       int Offset128, int Offset64, bits<4> opcode>
9807  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9808
9809  // ST1 instructions have extra "1d" variants.
9810  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9811    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9812                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9813                                GPR64sp:$Rn), []>;
9814
9815    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9816                       (outs GPR64sp:$wback),
9817                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9818                            GPR64sp:$Rn,
9819                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9820  }
9821
9822  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9823}
9824
9825multiclass SIMDLd1Multiple<string asm> {
9826  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9827  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9828  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9829  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9830}
9831
9832multiclass SIMDSt1Multiple<string asm> {
9833  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9834  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9835  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9836  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9837}
9838
9839multiclass SIMDLd2Multiple<string asm> {
9840  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9841}
9842
9843multiclass SIMDSt2Multiple<string asm> {
9844  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9845}
9846
9847multiclass SIMDLd3Multiple<string asm> {
9848  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9849}
9850
9851multiclass SIMDSt3Multiple<string asm> {
9852  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9853}
9854
9855multiclass SIMDLd4Multiple<string asm> {
9856  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9857}
9858
9859multiclass SIMDSt4Multiple<string asm> {
9860  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9861}
9862
9863//---
9864// AdvSIMD Load/store single-element
9865//---
9866
9867class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9868                         string asm, string operands, string cst,
9869                         dag oops, dag iops, list<dag> pattern>
9870  : I<oops, iops, asm, operands, cst, pattern> {
9871  bits<5> Vt;
9872  bits<5> Rn;
9873  let Inst{31} = 0;
9874  let Inst{29-24} = 0b001101;
9875  let Inst{22} = L;
9876  let Inst{21} = R;
9877  let Inst{15-13} = opcode;
9878  let Inst{9-5} = Rn;
9879  let Inst{4-0} = Vt;
9880}
9881
9882class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9883                         string asm, string operands, string cst,
9884                         dag oops, dag iops, list<dag> pattern>
9885  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9886  bits<5> Vt;
9887  bits<5> Rn;
9888  let Inst{31} = 0;
9889  let Inst{29-24} = 0b001101;
9890  let Inst{22} = L;
9891  let Inst{21} = R;
9892  let Inst{15-13} = opcode;
9893  let Inst{9-5} = Rn;
9894  let Inst{4-0} = Vt;
9895}
9896
9897
9898let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9899class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9900                  DAGOperand listtype>
9901  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9902                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
9903                       []> {
9904  let Inst{30} = Q;
9905  let Inst{23} = 0;
9906  let Inst{20-16} = 0b00000;
9907  let Inst{12} = S;
9908  let Inst{11-10} = size;
9909}
9910let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9911class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9912                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
9913  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9914                       "$Rn = $wback",
9915                       (outs GPR64sp:$wback, listtype:$Vt),
9916                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9917  bits<5> Xm;
9918  let Inst{30} = Q;
9919  let Inst{23} = 1;
9920  let Inst{20-16} = Xm;
9921  let Inst{12} = S;
9922  let Inst{11-10} = size;
9923}
9924
9925multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9926                          int Offset, int Size> {
9927  // E.g. "ld1r { v0.8b }, [x1], #1"
9928  //      "ld1r.8b\t$Vt, [$Rn], #1"
9929  // may get mapped to
9930  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9931  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9932                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9933                      GPR64sp:$Rn,
9934                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9935                      XZR), 1>;
9936
9937  // E.g. "ld1r.8b { v0 }, [x1], #1"
9938  //      "ld1r.8b\t$Vt, [$Rn], #1"
9939  // may get mapped to
9940  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9941  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9942                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9943                      GPR64sp:$Rn,
9944                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9945                      XZR), 0>;
9946
9947  // E.g. "ld1r.8b { v0 }, [x1]"
9948  //      "ld1r.8b\t$Vt, [$Rn]"
9949  // may get mapped to
9950  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9951  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9952                  (!cast<Instruction>(BaseName # "v" # layout)
9953                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9954                      GPR64sp:$Rn), 0>;
9955
9956  // E.g. "ld1r.8b { v0 }, [x1], x2"
9957  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9958  // may get mapped to
9959  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9960  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9961                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9962                      GPR64sp:$Rn,
9963                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9964                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9965}
9966
9967multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9968  int Offset1, int Offset2, int Offset4, int Offset8> {
9969  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9970                        !cast<DAGOperand>("VecList" # Count # "8b")>;
9971  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9972                        !cast<DAGOperand>("VecList" # Count #"16b")>;
9973  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9974                        !cast<DAGOperand>("VecList" # Count #"4h")>;
9975  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9976                        !cast<DAGOperand>("VecList" # Count #"8h")>;
9977  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9978                        !cast<DAGOperand>("VecList" # Count #"2s")>;
9979  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9980                        !cast<DAGOperand>("VecList" # Count #"4s")>;
9981  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9982                        !cast<DAGOperand>("VecList" # Count #"1d")>;
9983  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9984                        !cast<DAGOperand>("VecList" # Count #"2d")>;
9985
9986  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9987                                 !cast<DAGOperand>("VecList" # Count # "8b"),
9988                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9989  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9990                                 !cast<DAGOperand>("VecList" # Count # "16b"),
9991                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9992  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9993                                 !cast<DAGOperand>("VecList" # Count # "4h"),
9994                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9995  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9996                                 !cast<DAGOperand>("VecList" # Count # "8h"),
9997                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9998  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9999                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10000                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10001  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10002                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10003                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10004  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10005                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10006                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10007  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10008                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10009                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10010
10011  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10012  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10013  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10014  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10015  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10016  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10017  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10018  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10019}
10020
10021class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10022                      dag oops, dag iops, list<dag> pattern>
10023  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10024                       pattern> {
10025  // idx encoded in Q:S:size fields.
10026  bits<4> idx;
10027  let Inst{30} = idx{3};
10028  let Inst{23} = 0;
10029  let Inst{20-16} = 0b00000;
10030  let Inst{12} = idx{2};
10031  let Inst{11-10} = idx{1-0};
10032}
10033class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10034                      dag oops, dag iops, list<dag> pattern>
10035  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10036                           oops, iops, pattern> {
10037  // idx encoded in Q:S:size fields.
10038  bits<4> idx;
10039  let Inst{30} = idx{3};
10040  let Inst{23} = 0;
10041  let Inst{20-16} = 0b00000;
10042  let Inst{12} = idx{2};
10043  let Inst{11-10} = idx{1-0};
10044}
10045class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10046                          dag oops, dag iops>
10047  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10048                       "$Rn = $wback", oops, iops, []> {
10049  // idx encoded in Q:S:size fields.
10050  bits<4> idx;
10051  bits<5> Xm;
10052  let Inst{30} = idx{3};
10053  let Inst{23} = 1;
10054  let Inst{20-16} = Xm;
10055  let Inst{12} = idx{2};
10056  let Inst{11-10} = idx{1-0};
10057}
10058class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10059                          dag oops, dag iops>
10060  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10061                           "$Rn = $wback", oops, iops, []> {
10062  // idx encoded in Q:S:size fields.
10063  bits<4> idx;
10064  bits<5> Xm;
10065  let Inst{30} = idx{3};
10066  let Inst{23} = 1;
10067  let Inst{20-16} = Xm;
10068  let Inst{12} = idx{2};
10069  let Inst{11-10} = idx{1-0};
10070}
10071
10072class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10073                      dag oops, dag iops, list<dag> pattern>
10074  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10075                       pattern> {
10076  // idx encoded in Q:S:size<1> fields.
10077  bits<3> idx;
10078  let Inst{30} = idx{2};
10079  let Inst{23} = 0;
10080  let Inst{20-16} = 0b00000;
10081  let Inst{12} = idx{1};
10082  let Inst{11} = idx{0};
10083  let Inst{10} = size;
10084}
10085class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10086                      dag oops, dag iops, list<dag> pattern>
10087  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10088                           oops, iops, pattern> {
10089  // idx encoded in Q:S:size<1> fields.
10090  bits<3> idx;
10091  let Inst{30} = idx{2};
10092  let Inst{23} = 0;
10093  let Inst{20-16} = 0b00000;
10094  let Inst{12} = idx{1};
10095  let Inst{11} = idx{0};
10096  let Inst{10} = size;
10097}
10098
10099class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10100                          dag oops, dag iops>
10101  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10102                       "$Rn = $wback", oops, iops, []> {
10103  // idx encoded in Q:S:size<1> fields.
10104  bits<3> idx;
10105  bits<5> Xm;
10106  let Inst{30} = idx{2};
10107  let Inst{23} = 1;
10108  let Inst{20-16} = Xm;
10109  let Inst{12} = idx{1};
10110  let Inst{11} = idx{0};
10111  let Inst{10} = size;
10112}
10113class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10114                          dag oops, dag iops>
10115  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10116                           "$Rn = $wback", oops, iops, []> {
10117  // idx encoded in Q:S:size<1> fields.
10118  bits<3> idx;
10119  bits<5> Xm;
10120  let Inst{30} = idx{2};
10121  let Inst{23} = 1;
10122  let Inst{20-16} = Xm;
10123  let Inst{12} = idx{1};
10124  let Inst{11} = idx{0};
10125  let Inst{10} = size;
10126}
10127class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10128                      dag oops, dag iops, list<dag> pattern>
10129  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10130                       pattern> {
10131  // idx encoded in Q:S fields.
10132  bits<2> idx;
10133  let Inst{30} = idx{1};
10134  let Inst{23} = 0;
10135  let Inst{20-16} = 0b00000;
10136  let Inst{12} = idx{0};
10137  let Inst{11-10} = size;
10138}
10139class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10140                      dag oops, dag iops, list<dag> pattern>
10141  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10142                           oops, iops, pattern> {
10143  // idx encoded in Q:S fields.
10144  bits<2> idx;
10145  let Inst{30} = idx{1};
10146  let Inst{23} = 0;
10147  let Inst{20-16} = 0b00000;
10148  let Inst{12} = idx{0};
10149  let Inst{11-10} = size;
10150}
10151class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10152                          string asm, dag oops, dag iops>
10153  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10154                       "$Rn = $wback", oops, iops, []> {
10155  // idx encoded in Q:S fields.
10156  bits<2> idx;
10157  bits<5> Xm;
10158  let Inst{30} = idx{1};
10159  let Inst{23} = 1;
10160  let Inst{20-16} = Xm;
10161  let Inst{12} = idx{0};
10162  let Inst{11-10} = size;
10163}
10164class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10165                          string asm, dag oops, dag iops>
10166  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10167                           "$Rn = $wback", oops, iops, []> {
10168  // idx encoded in Q:S fields.
10169  bits<2> idx;
10170  bits<5> Xm;
10171  let Inst{30} = idx{1};
10172  let Inst{23} = 1;
10173  let Inst{20-16} = Xm;
10174  let Inst{12} = idx{0};
10175  let Inst{11-10} = size;
10176}
10177class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10178                      dag oops, dag iops, list<dag> pattern>
10179  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10180                       pattern> {
10181  // idx encoded in Q field.
10182  bits<1> idx;
10183  let Inst{30} = idx;
10184  let Inst{23} = 0;
10185  let Inst{20-16} = 0b00000;
10186  let Inst{12} = 0;
10187  let Inst{11-10} = size;
10188}
10189class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10190                      dag oops, dag iops, list<dag> pattern>
10191  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10192                           oops, iops, pattern> {
10193  // idx encoded in Q field.
10194  bits<1> idx;
10195  let Inst{30} = idx;
10196  let Inst{23} = 0;
10197  let Inst{20-16} = 0b00000;
10198  let Inst{12} = 0;
10199  let Inst{11-10} = size;
10200}
10201class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10202                          string asm, dag oops, dag iops>
10203  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10204                       "$Rn = $wback", oops, iops, []> {
10205  // idx encoded in Q field.
10206  bits<1> idx;
10207  bits<5> Xm;
10208  let Inst{30} = idx;
10209  let Inst{23} = 1;
10210  let Inst{20-16} = Xm;
10211  let Inst{12} = 0;
10212  let Inst{11-10} = size;
10213}
10214class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10215                          string asm, dag oops, dag iops>
10216  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10217                           "$Rn = $wback", oops, iops, []> {
10218  // idx encoded in Q field.
10219  bits<1> idx;
10220  bits<5> Xm;
10221  let Inst{30} = idx;
10222  let Inst{23} = 1;
10223  let Inst{20-16} = Xm;
10224  let Inst{12} = 0;
10225  let Inst{11-10} = size;
10226}
10227
10228let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10229multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10230                         RegisterOperand listtype,
10231                         RegisterOperand GPR64pi> {
10232  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10233                           (outs listtype:$dst),
10234                           (ins listtype:$Vt, VectorIndexB:$idx,
10235                                GPR64sp:$Rn), []>;
10236
10237  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10238                            (outs GPR64sp:$wback, listtype:$dst),
10239                            (ins listtype:$Vt, VectorIndexB:$idx,
10240                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10241}
10242let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10243multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10244                         RegisterOperand listtype,
10245                         RegisterOperand GPR64pi> {
10246  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10247                            (outs listtype:$dst),
10248                            (ins listtype:$Vt, VectorIndexH:$idx,
10249                                 GPR64sp:$Rn), []>;
10250
10251  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10252                            (outs GPR64sp:$wback, listtype:$dst),
10253                            (ins listtype:$Vt, VectorIndexH:$idx,
10254                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10255}
10256let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10257multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10258                         RegisterOperand listtype,
10259                         RegisterOperand GPR64pi> {
10260  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10261                            (outs listtype:$dst),
10262                            (ins listtype:$Vt, VectorIndexS:$idx,
10263                                 GPR64sp:$Rn), []>;
10264
10265  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10266                            (outs GPR64sp:$wback, listtype:$dst),
10267                            (ins listtype:$Vt, VectorIndexS:$idx,
10268                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10269}
10270let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10271multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10272                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10273  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10274                            (outs listtype:$dst),
10275                            (ins listtype:$Vt, VectorIndexD:$idx,
10276                                 GPR64sp:$Rn), []>;
10277
10278  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10279                            (outs GPR64sp:$wback, listtype:$dst),
10280                            (ins listtype:$Vt, VectorIndexD:$idx,
10281                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10282}
10283let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10284multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10285                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10286  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10287                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10288                                        GPR64sp:$Rn), []>;
10289
10290  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10291                                    (outs GPR64sp:$wback),
10292                                    (ins listtype:$Vt, VectorIndexB:$idx,
10293                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10294}
10295let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10296multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10297                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10298  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10299                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10300                                         GPR64sp:$Rn), []>;
10301
10302  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10303                            (outs GPR64sp:$wback),
10304                            (ins listtype:$Vt, VectorIndexH:$idx,
10305                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10306}
10307let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10308multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10309                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10310  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10311                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10312                                         GPR64sp:$Rn), []>;
10313
10314  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10315                            (outs GPR64sp:$wback),
10316                            (ins listtype:$Vt, VectorIndexS:$idx,
10317                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10318}
10319let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10320multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10321                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10322  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10323                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10324                                         GPR64sp:$Rn), []>;
10325
10326  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10327                            (outs GPR64sp:$wback),
10328                            (ins listtype:$Vt, VectorIndexD:$idx,
10329                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10330}
10331
10332multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10333                                 string Count, int Offset, Operand idxtype> {
10334  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10335  //      "ld1\t$Vt, [$Rn], #1"
10336  // may get mapped to
10337  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10338  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10339                  (!cast<Instruction>(NAME # Type  # "_POST")
10340                      GPR64sp:$Rn,
10341                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10342                      idxtype:$idx, XZR), 1>;
10343
10344  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10345  //      "ld1.8b\t$Vt, [$Rn], #1"
10346  // may get mapped to
10347  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10348  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10349                  (!cast<Instruction>(NAME # Type # "_POST")
10350                      GPR64sp:$Rn,
10351                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10352                      idxtype:$idx, XZR), 0>;
10353
10354  // E.g. "ld1.8b { v0 }[0], [x1]"
10355  //      "ld1.8b\t$Vt, [$Rn]"
10356  // may get mapped to
10357  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10358  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10359                      (!cast<Instruction>(NAME # Type)
10360                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10361                         idxtype:$idx, GPR64sp:$Rn), 0>;
10362
10363  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10364  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10365  // may get mapped to
10366  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10367  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10368                      (!cast<Instruction>(NAME # Type # "_POST")
10369                         GPR64sp:$Rn,
10370                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10371                         idxtype:$idx,
10372                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10373}
10374
10375multiclass SIMDLdSt1SingleAliases<string asm> {
10376  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10377  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10378  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10379  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10380}
10381
10382multiclass SIMDLdSt2SingleAliases<string asm> {
10383  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10384  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10385  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10386  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10387}
10388
10389multiclass SIMDLdSt3SingleAliases<string asm> {
10390  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10391  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10392  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10393  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10394}
10395
10396multiclass SIMDLdSt4SingleAliases<string asm> {
10397  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10398  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10399  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10400  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10401}
10402} // end of 'let Predicates = [HasNEON]'
10403
10404//----------------------------------------------------------------------------
10405// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10406//----------------------------------------------------------------------------
10407
10408let Predicates = [HasNEON, HasRDM] in {
10409
10410class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10411                                    RegisterOperand regtype, string asm,
10412                                    string kind, list<dag> pattern>
10413  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10414                                pattern> {
10415}
10416multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10417                                             SDPatternOperator Accum> {
10418  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10419    [(set (v4i16 V64:$dst),
10420          (Accum (v4i16 V64:$Rd),
10421                 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
10422                                                   (v4i16 V64:$Rm)))))]>;
10423  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10424    [(set (v8i16 V128:$dst),
10425          (Accum (v8i16 V128:$Rd),
10426                 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
10427                                                   (v8i16 V128:$Rm)))))]>;
10428  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10429    [(set (v2i32 V64:$dst),
10430          (Accum (v2i32 V64:$Rd),
10431                 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
10432                                                   (v2i32 V64:$Rm)))))]>;
10433  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10434    [(set (v4i32 V128:$dst),
10435          (Accum (v4i32 V128:$Rd),
10436                 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
10437                                                   (v4i32 V128:$Rm)))))]>;
10438}
10439
10440multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10441                                     SDPatternOperator Accum> {
10442  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10443                                          V64, V64, V128_lo, VectorIndexH,
10444                                          asm, ".4h", ".4h", ".4h", ".h",
10445    [(set (v4i16 V64:$dst),
10446          (Accum (v4i16 V64:$Rd),
10447                 (v4i16 (int_aarch64_neon_sqrdmulh
10448                          (v4i16 V64:$Rn),
10449                          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10450                                                    VectorIndexH:$idx))))))]> {
10451    bits<3> idx;
10452    let Inst{11} = idx{2};
10453    let Inst{21} = idx{1};
10454    let Inst{20} = idx{0};
10455  }
10456
10457  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10458                                          V128, V128, V128_lo, VectorIndexH,
10459                                          asm, ".8h", ".8h", ".8h", ".h",
10460    [(set (v8i16 V128:$dst),
10461          (Accum (v8i16 V128:$Rd),
10462                 (v8i16 (int_aarch64_neon_sqrdmulh
10463                          (v8i16 V128:$Rn),
10464                          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10465                                                   VectorIndexH:$idx))))))]> {
10466    bits<3> idx;
10467    let Inst{11} = idx{2};
10468    let Inst{21} = idx{1};
10469    let Inst{20} = idx{0};
10470  }
10471
10472  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10473                                          V64, V64, V128, VectorIndexS,
10474                                          asm, ".2s", ".2s", ".2s", ".s",
10475    [(set (v2i32 V64:$dst),
10476        (Accum (v2i32 V64:$Rd),
10477               (v2i32 (int_aarch64_neon_sqrdmulh
10478                        (v2i32 V64:$Rn),
10479                        (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10480                                                 VectorIndexS:$idx))))))]> {
10481    bits<2> idx;
10482    let Inst{11} = idx{1};
10483    let Inst{21} = idx{0};
10484  }
10485
10486  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10487  // an intermediate EXTRACT_SUBREG would be untyped.
10488  // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
10489  // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
10490  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10491                       (i32 (vector_extract
10492                               (v4i32 (insert_subvector
10493                                       (undef),
10494                                        (v2i32 (int_aarch64_neon_sqrdmulh
10495                                                 (v2i32 V64:$Rn),
10496                                                 (v2i32 (AArch64duplane32
10497                                                          (v4i32 V128:$Rm),
10498                                                          VectorIndexS:$idx)))),
10499                                      (i32 0))),
10500                               (i64 0))))),
10501            (EXTRACT_SUBREG
10502                (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
10503                          (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
10504                                                FPR32Op:$Rd,
10505                                                ssub)),
10506                          V64:$Rn,
10507                          V128:$Rm,
10508                          VectorIndexS:$idx)),
10509                ssub)>;
10510
10511  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10512                                          V128, V128, V128, VectorIndexS,
10513                                          asm, ".4s", ".4s", ".4s", ".s",
10514    [(set (v4i32 V128:$dst),
10515          (Accum (v4i32 V128:$Rd),
10516                 (v4i32 (int_aarch64_neon_sqrdmulh
10517                          (v4i32 V128:$Rn),
10518                          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10519                                                   VectorIndexS:$idx))))))]> {
10520    bits<2> idx;
10521    let Inst{11} = idx{1};
10522    let Inst{21} = idx{0};
10523  }
10524
10525  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10526  // an intermediate EXTRACT_SUBREG would be untyped.
10527  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10528                        (i32 (vector_extract
10529                               (v4i32 (int_aarch64_neon_sqrdmulh
10530                                        (v4i32 V128:$Rn),
10531                                        (v4i32 (AArch64duplane32
10532                                                 (v4i32 V128:$Rm),
10533                                                 VectorIndexS:$idx)))),
10534                               (i64 0))))),
10535            (EXTRACT_SUBREG
10536                (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
10537                         (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
10538                                               FPR32Op:$Rd,
10539                                               ssub)),
10540                         V128:$Rn,
10541                         V128:$Rm,
10542                         VectorIndexS:$idx)),
10543                ssub)>;
10544
10545  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10546                                        FPR16Op, FPR16Op, V128_lo,
10547                                        VectorIndexH, asm, ".h", "", "", ".h",
10548                                        []> {
10549    bits<3> idx;
10550    let Inst{11} = idx{2};
10551    let Inst{21} = idx{1};
10552    let Inst{20} = idx{0};
10553  }
10554
10555  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10556                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10557                                        asm, ".s", "", "", ".s",
10558    [(set (i32 FPR32Op:$dst),
10559          (Accum (i32 FPR32Op:$Rd),
10560                 (i32 (int_aarch64_neon_sqrdmulh
10561                        (i32 FPR32Op:$Rn),
10562                        (i32 (vector_extract (v4i32 V128:$Rm),
10563                                             VectorIndexS:$idx))))))]> {
10564    bits<2> idx;
10565    let Inst{11} = idx{1};
10566    let Inst{21} = idx{0};
10567  }
10568}
10569} // let Predicates = [HasNeon, HasRDM]
10570
10571//----------------------------------------------------------------------------
10572// ARMv8.3 Complex ADD/MLA instructions
10573//----------------------------------------------------------------------------
10574
10575class ComplexRotationOperand<int Angle, int Remainder, string Type>
10576  : AsmOperandClass {
10577  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10578  let DiagnosticType = "InvalidComplexRotation" # Type;
10579  let Name = "ComplexRotation" # Type;
10580}
10581def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10582                                                  SDNodeXForm<imm, [{
10583  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10584}]>> {
10585  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10586  let PrintMethod = "printComplexRotationOp<90, 0>";
10587}
10588def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10589                                                  SDNodeXForm<imm, [{
10590  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10591}]>> {
10592  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10593  let PrintMethod = "printComplexRotationOp<180, 90>";
10594}
10595let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10596class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10597                                     RegisterOperand regtype, Operand rottype,
10598                                     string asm, string kind, list<dag> pattern>
10599  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10600      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10601      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10602    Sched<[WriteV]> {
10603  bits<5> Rd;
10604  bits<5> Rn;
10605  bits<5> Rm;
10606  bits<1> rot;
10607  let Inst{31}    = 0;
10608  let Inst{30}    = Q;
10609  let Inst{29}    = U;
10610  let Inst{28-24} = 0b01110;
10611  let Inst{23-22} = size;
10612  let Inst{21}    = 0;
10613  let Inst{20-16} = Rm;
10614  let Inst{15-13} = opcode;
10615  // Non-tied version (FCADD) only has one rotation bit
10616  let Inst{12}    = rot;
10617  let Inst{11}    = 0;
10618  let Inst{10}    = 1;
10619  let Inst{9-5}   = Rn;
10620  let Inst{4-0}   = Rd;
10621}
10622
10623//8.3 CompNum - Floating-point complex number support
10624multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10625                                          string asm, SDPatternOperator OpNode>{
10626  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10627  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10628              asm, ".4h",
10629              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10630                                              (v4f16 V64:$Rn),
10631                                              (v4f16 V64:$Rm),
10632                                              (i32 rottype:$rot)))]>;
10633
10634  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10635              asm, ".8h",
10636              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10637                                               (v8f16 V128:$Rn),
10638                                               (v8f16 V128:$Rm),
10639                                               (i32 rottype:$rot)))]>;
10640  }
10641
10642  let Predicates = [HasComplxNum, HasNEON] in {
10643  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10644              asm, ".2s",
10645              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10646                                              (v2f32 V64:$Rn),
10647                                              (v2f32 V64:$Rm),
10648                                              (i32 rottype:$rot)))]>;
10649
10650  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10651              asm, ".4s",
10652              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10653                                               (v4f32 V128:$Rn),
10654                                               (v4f32 V128:$Rm),
10655                                               (i32 rottype:$rot)))]>;
10656
10657  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10658              asm, ".2d",
10659              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10660                                               (v2f64 V128:$Rn),
10661                                               (v2f64 V128:$Rm),
10662                                               (i32 rottype:$rot)))]>;
10663  }
10664}
10665
10666let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10667class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10668                                         bits<3> opcode,
10669                                         RegisterOperand regtype,
10670                                         Operand rottype, string asm,
10671                                         string kind, list<dag> pattern>
10672  : I<(outs regtype:$dst),
10673      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10674      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10675      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10676    Sched<[WriteV]> {
10677  bits<5> Rd;
10678  bits<5> Rn;
10679  bits<5> Rm;
10680  bits<2> rot;
10681  let Inst{31}    = 0;
10682  let Inst{30}    = Q;
10683  let Inst{29}    = U;
10684  let Inst{28-24} = 0b01110;
10685  let Inst{23-22} = size;
10686  let Inst{21}    = 0;
10687  let Inst{20-16} = Rm;
10688  let Inst{15-13} = opcode;
10689  let Inst{12-11} = rot;
10690  let Inst{10}    = 1;
10691  let Inst{9-5}   = Rn;
10692  let Inst{4-0}   = Rd;
10693}
10694
10695multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10696                                             Operand rottype, string asm,
10697                                             SDPatternOperator OpNode> {
10698  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10699  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10700              rottype, asm, ".4h",
10701              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10702                                              (v4f16 V64:$Rn),
10703                                              (v4f16 V64:$Rm),
10704                                              (i32 rottype:$rot)))]>;
10705
10706  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10707              rottype, asm, ".8h",
10708              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10709                                               (v8f16 V128:$Rn),
10710                                               (v8f16 V128:$Rm),
10711                                               (i32 rottype:$rot)))]>;
10712  }
10713
10714  let Predicates = [HasComplxNum, HasNEON] in {
10715  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10716              rottype, asm, ".2s",
10717              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10718                                              (v2f32 V64:$Rn),
10719                                              (v2f32 V64:$Rm),
10720                                              (i32 rottype:$rot)))]>;
10721
10722  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10723              rottype, asm, ".4s",
10724              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10725                                               (v4f32 V128:$Rn),
10726                                               (v4f32 V128:$Rm),
10727                                               (i32 rottype:$rot)))]>;
10728
10729  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10730              rottype, asm, ".2d",
10731              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10732                                               (v2f64 V128:$Rn),
10733                                               (v2f64 V128:$Rm),
10734                                               (i32 rottype:$rot)))]>;
10735  }
10736}
10737
10738let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10739class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10740                                 bit opc1, bit opc2, RegisterOperand dst_reg,
10741                                 RegisterOperand lhs_reg,
10742                                 RegisterOperand rhs_reg, Operand vec_idx,
10743                                 Operand rottype, string asm, string apple_kind,
10744                                 string dst_kind, string lhs_kind,
10745                                 string rhs_kind, list<dag> pattern>
10746  : I<(outs dst_reg:$dst),
10747      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10748      asm,
10749      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10750      "$idx, $rot" # "|" # apple_kind #
10751      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10752    Sched<[WriteV]> {
10753  bits<5> Rd;
10754  bits<5> Rn;
10755  bits<5> Rm;
10756  bits<2> rot;
10757
10758  let Inst{31}    = 0;
10759  let Inst{30}    = Q;
10760  let Inst{29}    = U;
10761  let Inst{28}    = Scalar;
10762  let Inst{27-24} = 0b1111;
10763  let Inst{23-22} = size;
10764  // Bit 21 must be set by the derived class.
10765  let Inst{20-16} = Rm;
10766  let Inst{15}    = opc1;
10767  let Inst{14-13} = rot;
10768  let Inst{12}    = opc2;
10769  // Bit 11 must be set by the derived class.
10770  let Inst{10}    = 0;
10771  let Inst{9-5}   = Rn;
10772  let Inst{4-0}   = Rd;
10773}
10774
10775// The complex instructions index by pairs of elements, so the VectorIndexes
10776// don't match the lane types, and the index bits are different to the other
10777// classes.
10778multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10779                                     string asm, SDPatternOperator OpNode> {
10780  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10781  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10782                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10783                      ".4h", ".h", []> {
10784    bits<1> idx;
10785    let Inst{11} = 0;
10786    let Inst{21} = idx{0};
10787  }
10788
10789  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10790                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10791                      ".8h", ".8h", ".h", []> {
10792    bits<2> idx;
10793    let Inst{11} = idx{1};
10794    let Inst{21} = idx{0};
10795  }
10796  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10797
10798  let Predicates = [HasComplxNum, HasNEON] in {
10799  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10800                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10801                      ".4s", ".4s", ".s", []> {
10802    bits<1> idx;
10803    let Inst{11} = idx{0};
10804    let Inst{21} = 0;
10805  }
10806  } // Predicates = [HasComplxNum, HasNEON]
10807}
10808
10809//----------------------------------------------------------------------------
10810// Crypto extensions
10811//----------------------------------------------------------------------------
10812
10813let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10814class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10815              list<dag> pat>
10816  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10817    Sched<[WriteV]>{
10818  bits<5> Rd;
10819  bits<5> Rn;
10820  let Inst{31-16} = 0b0100111000101000;
10821  let Inst{15-12} = opc;
10822  let Inst{11-10} = 0b10;
10823  let Inst{9-5}   = Rn;
10824  let Inst{4-0}   = Rd;
10825}
10826
10827class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10828  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10829            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10830
10831class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10832  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10833            "$Rd = $dst",
10834            [(set (v16i8 V128:$dst),
10835                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10836
10837let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10838class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10839                     dag oops, dag iops, list<dag> pat>
10840  : I<oops, iops, asm,
10841      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10842      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10843    Sched<[WriteV]>{
10844  bits<5> Rd;
10845  bits<5> Rn;
10846  bits<5> Rm;
10847  let Inst{31-21} = 0b01011110000;
10848  let Inst{20-16} = Rm;
10849  let Inst{15}    = 0;
10850  let Inst{14-12} = opc;
10851  let Inst{11-10} = 0b00;
10852  let Inst{9-5}   = Rn;
10853  let Inst{4-0}   = Rd;
10854}
10855
10856class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10857  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10858                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10859                   [(set (v4i32 FPR128:$dst),
10860                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10861                                 (v4i32 V128:$Rm)))]>;
10862
10863class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10864  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10865                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
10866                   [(set (v4i32 V128:$dst),
10867                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10868                                 (v4i32 V128:$Rm)))]>;
10869
10870class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10871  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10872                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10873                   [(set (v4i32 FPR128:$dst),
10874                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10875                                 (v4i32 V128:$Rm)))]>;
10876
10877let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10878class SHA2OpInst<bits<4> opc, string asm, string kind,
10879                 string cstr, dag oops, dag iops,
10880                 list<dag> pat>
10881  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10882                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10883    Sched<[WriteV]>{
10884  bits<5> Rd;
10885  bits<5> Rn;
10886  let Inst{31-16} = 0b0101111000101000;
10887  let Inst{15-12} = opc;
10888  let Inst{11-10} = 0b10;
10889  let Inst{9-5}   = Rn;
10890  let Inst{4-0}   = Rd;
10891}
10892
10893class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10894  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10895               (ins V128:$Rd, V128:$Rn),
10896               [(set (v4i32 V128:$dst),
10897                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10898
10899class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10900  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10901               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10902
10903// Armv8.2-A Crypto extensions
10904class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10905                    list<dag> pattern>
10906  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10907  bits<5> Vd;
10908  bits<5> Vn;
10909  let Inst{31-25} = 0b1100111;
10910  let Inst{9-5}   = Vn;
10911  let Inst{4-0}   = Vd;
10912}
10913
10914class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10915  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10916                  "$Vm = $Vd", []> {
10917  let Inst{31-25} = 0b1100111;
10918  let Inst{24-21} = 0b0110;
10919  let Inst{20-15} = 0b000001;
10920  let Inst{14}    = op0;
10921  let Inst{13-12} = 0b00;
10922  let Inst{11-10} = op1;
10923}
10924class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10925  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
10926class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10927  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
10928
10929class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10930                string asmops, string cst>
10931  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10932  bits<5> Vm;
10933  let Inst{24-21} = 0b0011;
10934  let Inst{20-16} = Vm;
10935  let Inst{15}    = 0b1;
10936  let Inst{14}    = op0;
10937  let Inst{13-12} = 0b00;
10938  let Inst{11-10} = op1;
10939}
10940class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10941  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10942              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
10943class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10944  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10945              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10946class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10947  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10948              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
10949class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10950  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10951              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10952class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10953  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10954              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10955
10956class CryptoRRRR<bits<2>op0, string asm, string asmops>
10957  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10958                  asmops, "", []> {
10959  bits<5> Vm;
10960  bits<5> Va;
10961  let Inst{24-23} = 0b00;
10962  let Inst{22-21} = op0;
10963  let Inst{20-16} = Vm;
10964  let Inst{15}    = 0b0;
10965  let Inst{14-10} = Va;
10966}
10967class CryptoRRRR_16B<bits<2>op0, string asm>
10968 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
10969                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
10970}
10971class CryptoRRRR_4S<bits<2>op0, string asm>
10972 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
10973                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
10974}
10975
10976class CryptoRRRi6<string asm>
10977  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10978                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
10979                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
10980  bits<6> imm;
10981  bits<5> Vm;
10982  let Inst{24-21} = 0b0100;
10983  let Inst{20-16} = Vm;
10984  let Inst{15-10} = imm;
10985  let Inst{9-5}   = Vn;
10986  let Inst{4-0}   = Vd;
10987}
10988
10989class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10990  : BaseCryptoV82<(outs V128:$Vdst),
10991                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10992                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
10993                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
10994  bits<2> imm;
10995  bits<5> Vm;
10996  let Inst{24-21} = 0b0010;
10997  let Inst{20-16} = Vm;
10998  let Inst{15}    = 0b1;
10999  let Inst{14}    = op0;
11000  let Inst{13-12} = imm;
11001  let Inst{11-10} = op1;
11002}
11003
11004//----------------------------------------------------------------------------
11005// v8.1 atomic instructions extension:
11006// * CAS
11007// * CASP
11008// * SWP
11009// * LDOPregister<OP>, and aliases STOPregister<OP>
11010
11011// Instruction encodings:
11012//
11013//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11014// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11015// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11016// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11017// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11018// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11019
11020// Instruction syntax:
11021//
11022// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11023// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11024// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11025// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11026// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11027// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11028// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11029// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11030// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11031// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11032
11033let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11034class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11035                      string cstr, list<dag> pattern>
11036      : I<oops, iops, asm, operands, cstr, pattern> {
11037  bits<2> Sz;
11038  bit NP;
11039  bit Acq;
11040  bit Rel;
11041  bits<5> Rs;
11042  bits<5> Rn;
11043  bits<5> Rt;
11044  let Inst{31-30} = Sz;
11045  let Inst{29-24} = 0b001000;
11046  let Inst{23} = NP;
11047  let Inst{22} = Acq;
11048  let Inst{21} = 0b1;
11049  let Inst{20-16} = Rs;
11050  let Inst{15} = Rel;
11051  let Inst{14-10} = 0b11111;
11052  let Inst{9-5} = Rn;
11053  let Inst{4-0} = Rt;
11054  let Predicates = [HasLSE];
11055}
11056
11057class BaseCAS<string order, string size, RegisterClass RC>
11058      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11059                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11060                        "$out = $Rs",[]>,
11061        Sched<[WriteAtomic]> {
11062  let NP = 1;
11063}
11064
11065multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11066  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11067  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11068  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11069  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11070}
11071
11072class BaseCASP<string order, string size, RegisterOperand RC>
11073      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11074                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11075                        "$out = $Rs",[]>,
11076        Sched<[WriteAtomic]> {
11077  let NP = 0;
11078}
11079
11080multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11081  let Sz = 0b00, Acq = Acq, Rel = Rel in
11082    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11083  let Sz = 0b01, Acq = Acq, Rel = Rel in
11084    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11085}
11086
11087let Predicates = [HasLSE] in
11088class BaseSWP<string order, string size, RegisterClass RC>
11089      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11090          "\t$Rs, $Rt, [$Rn]","",[]>,
11091        Sched<[WriteAtomic]> {
11092  bits<2> Sz;
11093  bit Acq;
11094  bit Rel;
11095  bits<5> Rs;
11096  bits<3> opc = 0b000;
11097  bits<5> Rn;
11098  bits<5> Rt;
11099  let Inst{31-30} = Sz;
11100  let Inst{29-24} = 0b111000;
11101  let Inst{23} = Acq;
11102  let Inst{22} = Rel;
11103  let Inst{21} = 0b1;
11104  let Inst{20-16} = Rs;
11105  let Inst{15} = 0b1;
11106  let Inst{14-12} = opc;
11107  let Inst{11-10} = 0b00;
11108  let Inst{9-5} = Rn;
11109  let Inst{4-0} = Rt;
11110  let Predicates = [HasLSE];
11111}
11112
11113multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11114  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11115  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11116  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11117  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11118}
11119
11120let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11121class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11122      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11123          "\t$Rs, $Rt, [$Rn]","",[]>,
11124        Sched<[WriteAtomic]> {
11125  bits<2> Sz;
11126  bit Acq;
11127  bit Rel;
11128  bits<5> Rs;
11129  bits<3> opc;
11130  bits<5> Rn;
11131  bits<5> Rt;
11132  let Inst{31-30} = Sz;
11133  let Inst{29-24} = 0b111000;
11134  let Inst{23} = Acq;
11135  let Inst{22} = Rel;
11136  let Inst{21} = 0b1;
11137  let Inst{20-16} = Rs;
11138  let Inst{15} = 0b0;
11139  let Inst{14-12} = opc;
11140  let Inst{11-10} = 0b00;
11141  let Inst{9-5} = Rn;
11142  let Inst{4-0} = Rt;
11143  let Predicates = [HasLSE];
11144}
11145
11146multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11147                        string order> {
11148  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11149    def B : BaseLDOPregister<op, order, "b", GPR32>;
11150  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11151    def H : BaseLDOPregister<op, order, "h", GPR32>;
11152  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11153    def W : BaseLDOPregister<op, order, "", GPR32>;
11154  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11155    def X : BaseLDOPregister<op, order, "", GPR64>;
11156}
11157
11158// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11159// complex DAG for DstRHS.
11160let Predicates = [HasLSE] in
11161multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11162                                         string size, dag SrcRHS, dag DstRHS> {
11163  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11164            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11165  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11166            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11167  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11168            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11169  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11170            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11171  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11172            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11173}
11174
11175multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11176                                     string size, dag RHS> {
11177  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11178}
11179
11180multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11181                                         string size, dag LHS, dag RHS> {
11182  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11183}
11184
11185multiclass LDOPregister_patterns<string inst, string op> {
11186  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11187  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11188  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11189  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11190}
11191
11192multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11193  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11194                        (i64 GPR64:$Rm),
11195                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11196  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11197                        (i32 GPR32:$Rm),
11198                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11199  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11200                        (i32 GPR32:$Rm),
11201                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11202  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11203                        (i32 GPR32:$Rm),
11204                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11205}
11206
11207let Predicates = [HasLSE] in
11208multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11209                                        string size, dag OLD, dag NEW> {
11210  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11211            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11212  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11213            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11214  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11215            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11216  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11217            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11218  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11219            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11220}
11221
11222multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11223                                    string size, dag OLD, dag NEW> {
11224  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11225}
11226
11227multiclass CASregister_patterns<string inst, string op> {
11228  defm : CASregister_patterns_ord<inst, "X", op, "64",
11229                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11230  defm : CASregister_patterns_ord<inst, "W", op, "32",
11231                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11232  defm : CASregister_patterns_ord<inst, "H", op, "16",
11233                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11234  defm : CASregister_patterns_ord<inst, "B", op, "8",
11235                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11236}
11237
11238let Predicates = [HasLSE] in
11239class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11240                        Instruction inst> :
11241      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11242
11243multiclass STOPregister<string asm, string instr> {
11244  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11245                    !cast<Instruction>(instr # "LB")>;
11246  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11247                    !cast<Instruction>(instr # "LH")>;
11248  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11249                    !cast<Instruction>(instr # "LW")>;
11250  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11251                    !cast<Instruction>(instr # "LX")>;
11252  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11253                    !cast<Instruction>(instr # "B")>;
11254  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11255                    !cast<Instruction>(instr # "H")>;
11256  def : BaseSTOPregister<asm,        GPR32, WZR,
11257                    !cast<Instruction>(instr # "W")>;
11258  def : BaseSTOPregister<asm,        GPR64, XZR,
11259                    !cast<Instruction>(instr # "X")>;
11260}
11261
11262class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11263                        dag iops, dag oops, list<dag> pat>
11264    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11265      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11266  bits<5> Rt;
11267  bits<5> Rn;
11268  let Inst{31-21} = 0b11111000001;
11269  let Inst{15}    = 1;
11270  let Inst{14-12} = opc;
11271  let Inst{11-10} = 0b00;
11272  let Inst{9-5}   = Rn;
11273  let Inst{4-0}   = Rt;
11274
11275  let Predicates = [HasV8_7a];
11276}
11277
11278class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11279                      list<dag> pat = []>
11280    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11281  let Inst{20-16} = 0b11111;
11282}
11283
11284class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11285    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11286                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11287  bits<5> Rs;
11288  let Inst{20-16} = Rs;
11289}
11290
11291//----------------------------------------------------------------------------
11292// Allow the size specifier tokens to be upper case, not just lower.
11293def : TokenAlias<".4B", ".4b">;  // Add dot product
11294def : TokenAlias<".8B", ".8b">;
11295def : TokenAlias<".4H", ".4h">;
11296def : TokenAlias<".2S", ".2s">;
11297def : TokenAlias<".1D", ".1d">;
11298def : TokenAlias<".16B", ".16b">;
11299def : TokenAlias<".8H", ".8h">;
11300def : TokenAlias<".4S", ".4s">;
11301def : TokenAlias<".2D", ".2d">;
11302def : TokenAlias<".1Q", ".1q">;
11303def : TokenAlias<".2H", ".2h">;
11304def : TokenAlias<".B", ".b">;
11305def : TokenAlias<".H", ".h">;
11306def : TokenAlias<".S", ".s">;
11307def : TokenAlias<".D", ".d">;
11308def : TokenAlias<".Q", ".q">;
11309