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>;
39def DestructiveUnaryPassthru      : DestructiveInstTypeEnum<9>;
40
41class FalseLanesEnum<bits<2> val> {
42  bits<2> Value = val;
43}
44def FalseLanesNone  : FalseLanesEnum<0>;
45def FalseLanesZero  : FalseLanesEnum<1>;
46def FalseLanesUndef : FalseLanesEnum<2>;
47
48// AArch64 Instruction Format
49class AArch64Inst<Format f, string cstr> : Instruction {
50  field bits<32> Inst; // Instruction encoding.
51  // Mask of bits that cause an encoding to be UNPREDICTABLE.
52  // If a bit is set, then if the corresponding bit in the
53  // target encoding differs from its value in the "Inst" field,
54  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
55  field bits<32> Unpredictable = 0;
56  // SoftFail is the generic name for this field, but we alias it so
57  // as to make it more obvious what it means in ARM-land.
58  field bits<32> SoftFail = Unpredictable;
59  let Namespace   = "AArch64";
60  Format F        = f;
61  bits<2> Form    = F.Value;
62
63  // Defaults
64  bit isWhile = 0;
65  bit isPTestLike = 0;
66  FalseLanesEnum FalseLanes = FalseLanesNone;
67  DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
68  ElementSizeEnum ElementSize = ElementSizeNone;
69
70  let TSFlags{10}  = isPTestLike;
71  let TSFlags{9}   = isWhile;
72  let TSFlags{8-7} = FalseLanes.Value;
73  let TSFlags{6-3} = DestructiveInstType.Value;
74  let TSFlags{2-0} = ElementSize.Value;
75
76  let Pattern     = [];
77  let Constraints = cstr;
78}
79
80class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
81  : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
82
83// Pseudo instructions (don't have encoding information)
84class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
85    : AArch64Inst<PseudoFrm, cstr> {
86  dag OutOperandList = oops;
87  dag InOperandList  = iops;
88  let Pattern        = pattern;
89  let isCodeGenOnly  = 1;
90  let isPseudo       = 1;
91}
92
93// Real instructions (have encoding information)
94class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
95  let Pattern = pattern;
96  let Size = 4;
97}
98
99// Normal instructions
100class I<dag oops, dag iops, string asm, string operands, string cstr,
101        list<dag> pattern>
102    : EncodedI<cstr, pattern> {
103  dag OutOperandList = oops;
104  dag InOperandList  = iops;
105  let AsmString      = !strconcat(asm, operands);
106}
107
108class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
109class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
110class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
111
112// Helper fragment for an extract of the high portion of a 128-bit vector. The
113// ComplexPattern match both extract_subvector and bitcast(extract_subvector(..)).
114def extract_high_v16i8 :
115    ComplexPattern<v8i8, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
116def extract_high_v8i16 :
117    ComplexPattern<v4i16, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
118def extract_high_v4i32 :
119    ComplexPattern<v2i32, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
120
121def extract_high_dup_v8i16 :
122   BinOpFrag<(extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 4))>;
123def extract_high_dup_v4i32 :
124   BinOpFrag<(extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 2))>;
125
126//===----------------------------------------------------------------------===//
127// Asm Operand Classes.
128//
129
130// Shifter operand for arithmetic shifted encodings.
131def ShifterOperand : AsmOperandClass {
132  let Name = "Shifter";
133}
134
135// Shifter operand for mov immediate encodings.
136def MovImm32ShifterOperand : AsmOperandClass {
137  let SuperClasses = [ShifterOperand];
138  let Name = "MovImm32Shifter";
139  let RenderMethod = "addShifterOperands";
140  let DiagnosticType = "InvalidMovImm32Shift";
141}
142def MovImm64ShifterOperand : AsmOperandClass {
143  let SuperClasses = [ShifterOperand];
144  let Name = "MovImm64Shifter";
145  let RenderMethod = "addShifterOperands";
146  let DiagnosticType = "InvalidMovImm64Shift";
147}
148
149// Shifter operand for arithmetic register shifted encodings.
150class ArithmeticShifterOperand<int width> : AsmOperandClass {
151  let SuperClasses = [ShifterOperand];
152  let Name = "ArithmeticShifter" # width;
153  let PredicateMethod = "isArithmeticShifter<" # width # ">";
154  let RenderMethod = "addShifterOperands";
155  let DiagnosticType = "AddSubRegShift" # width;
156}
157
158def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
159def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
160
161// Shifter operand for logical register shifted encodings.
162class LogicalShifterOperand<int width> : AsmOperandClass {
163  let SuperClasses = [ShifterOperand];
164  let Name = "LogicalShifter" # width;
165  let PredicateMethod = "isLogicalShifter<" # width # ">";
166  let RenderMethod = "addShifterOperands";
167  let DiagnosticType = "AddSubRegShift" # width;
168}
169
170def LogicalShifterOperand32 : LogicalShifterOperand<32>;
171def LogicalShifterOperand64 : LogicalShifterOperand<64>;
172
173// Shifter operand for logical vector 128/64-bit shifted encodings.
174def LogicalVecShifterOperand : AsmOperandClass {
175  let SuperClasses = [ShifterOperand];
176  let Name = "LogicalVecShifter";
177  let RenderMethod = "addShifterOperands";
178}
179def LogicalVecHalfWordShifterOperand : AsmOperandClass {
180  let SuperClasses = [LogicalVecShifterOperand];
181  let Name = "LogicalVecHalfWordShifter";
182  let RenderMethod = "addShifterOperands";
183}
184
185// The "MSL" shifter on the vector MOVI instruction.
186def MoveVecShifterOperand : AsmOperandClass {
187  let SuperClasses = [ShifterOperand];
188  let Name = "MoveVecShifter";
189  let RenderMethod = "addShifterOperands";
190}
191
192// Extend operand for arithmetic encodings.
193def ExtendOperand : AsmOperandClass {
194  let Name = "Extend";
195  let DiagnosticType = "AddSubRegExtendLarge";
196}
197def ExtendOperand64 : AsmOperandClass {
198  let SuperClasses = [ExtendOperand];
199  let Name = "Extend64";
200  let DiagnosticType = "AddSubRegExtendSmall";
201}
202// 'extend' that's a lsl of a 64-bit register.
203def ExtendOperandLSL64 : AsmOperandClass {
204  let SuperClasses = [ExtendOperand];
205  let Name = "ExtendLSL64";
206  let RenderMethod = "addExtend64Operands";
207  let DiagnosticType = "AddSubRegExtendLarge";
208}
209
210// 8-bit floating-point immediate encodings.
211def FPImmOperand : AsmOperandClass {
212  let Name = "FPImm";
213  let ParserMethod = "tryParseFPImm<true>";
214  let DiagnosticType = "InvalidFPImm";
215}
216
217def CondCode : AsmOperandClass {
218  let Name = "CondCode";
219  let DiagnosticType = "InvalidCondCode";
220}
221
222// A 32-bit register pasrsed as 64-bit
223def GPR32as64Operand : AsmOperandClass {
224  let Name = "GPR32as64";
225  let ParserMethod =
226      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
227}
228def GPR32as64 : RegisterOperand<GPR32> {
229  let ParserMatchClass = GPR32as64Operand;
230}
231
232// A 64-bit register pasrsed as 32-bit
233def GPR64as32Operand : AsmOperandClass {
234  let Name = "GPR64as32";
235  let ParserMethod =
236      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
237}
238def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
239  let ParserMatchClass = GPR64as32Operand;
240}
241
242// 8-bit immediate for AdvSIMD where 64-bit values of the form:
243// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
244// are encoded as the eight bit value 'abcdefgh'.
245def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
246
247class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
248  let Name = "UImm" # Width # "s" # Scale;
249  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
250  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
251  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
252}
253
254class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
255  let Name = "SImm" # Width # "s" # Scale;
256  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
257  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
258  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
259}
260
261//===----------------------------------------------------------------------===//
262// Operand Definitions.
263//
264
265// ADR[P] instruction labels.
266def AdrpOperand : AsmOperandClass {
267  let Name = "AdrpLabel";
268  let ParserMethod = "tryParseAdrpLabel";
269  let DiagnosticType = "InvalidLabel";
270}
271def adrplabel : Operand<i64> {
272  let EncoderMethod = "getAdrLabelOpValue";
273  let PrintMethod = "printAdrpLabel";
274  let ParserMatchClass = AdrpOperand;
275  let OperandType = "OPERAND_PCREL";
276}
277
278def AdrOperand : AsmOperandClass {
279  let Name = "AdrLabel";
280  let ParserMethod = "tryParseAdrLabel";
281  let DiagnosticType = "InvalidLabel";
282}
283def adrlabel : Operand<i64> {
284  let EncoderMethod = "getAdrLabelOpValue";
285  let ParserMatchClass = AdrOperand;
286}
287
288class SImmOperand<int width> : AsmOperandClass {
289  let Name = "SImm" # width;
290  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
291  let RenderMethod = "addImmOperands";
292  let PredicateMethod = "isSImm<" # width # ">";
293}
294
295
296class AsmImmRange<int Low, int High> : AsmOperandClass {
297  let Name = "Imm" # Low # "_" # High;
298  let DiagnosticType = "InvalidImm" # Low # "_" # High;
299  let RenderMethod = "addImmOperands";
300  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
301}
302
303// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
304def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
305def simm10Scaled : Operand<i64> {
306  let ParserMatchClass = SImm10s8Operand;
307  let DecoderMethod = "DecodeSImm<10>";
308  let PrintMethod = "printImmScale<8>";
309}
310
311def simm9s16 : Operand<i64> {
312  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
313  let DecoderMethod = "DecodeSImm<9>";
314  let PrintMethod = "printImmScale<16>";
315}
316
317// uimm6 predicate - True if the immediate is in the range [0, 63].
318def UImm6Operand : AsmOperandClass {
319  let Name = "UImm6";
320  let DiagnosticType = "InvalidImm0_63";
321}
322
323def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
324  let ParserMatchClass = UImm6Operand;
325}
326
327def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
328  let ParserMatchClass = AsmImmRange<0, 65535>;
329}
330
331def SImm9Operand : SImmOperand<9>;
332def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
333  let ParserMatchClass = SImm9Operand;
334  let DecoderMethod = "DecodeSImm<9>";
335}
336
337def SImm8Operand : SImmOperand<8>;
338def simm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
339  let ParserMatchClass = SImm8Operand;
340  let DecoderMethod = "DecodeSImm<8>";
341}
342
343def SImm6Operand : SImmOperand<6>;
344def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
345  let ParserMatchClass = SImm6Operand;
346  let DecoderMethod = "DecodeSImm<6>";
347}
348
349def SImm5Operand : SImmOperand<5>;
350def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
351  let ParserMatchClass = SImm5Operand;
352  let DecoderMethod = "DecodeSImm<5>";
353}
354
355def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
356  let ParserMatchClass = SImm5Operand;
357  let DecoderMethod = "DecodeSImm<5>";
358}
359
360def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
361  let ParserMatchClass = SImm5Operand;
362  let DecoderMethod = "DecodeSImm<5>";
363  let PrintMethod = "printSImm<8>";
364}
365
366def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
367  let ParserMatchClass = SImm5Operand;
368  let DecoderMethod = "DecodeSImm<5>";
369  let PrintMethod = "printSImm<16>";
370}
371
372// simm7sN predicate - True if the immediate is a multiple of N in the range
373// [-64 * N, 63 * N].
374
375def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
376def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
377def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
378
379def simm7s4 : Operand<i32> {
380  let ParserMatchClass = SImm7s4Operand;
381  let PrintMethod = "printImmScale<4>";
382}
383
384def simm7s8 : Operand<i32> {
385  let ParserMatchClass = SImm7s8Operand;
386  let PrintMethod = "printImmScale<8>";
387}
388
389def simm7s16 : Operand<i32> {
390  let ParserMatchClass = SImm7s16Operand;
391  let PrintMethod = "printImmScale<16>";
392}
393
394def am_sve_fi : ComplexPattern<iPTR, 2, "SelectAddrModeFrameIndexSVE", []>;
395
396def am_indexed7s8   : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S8", []>;
397def am_indexed7s16  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S16", []>;
398def am_indexed7s32  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S32", []>;
399def am_indexed7s64  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S64", []>;
400def am_indexed7s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S128", []>;
401
402def am_indexedu6s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedU6S128", []>;
403def am_indexeds9s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedS9S128", []>;
404
405def UImmS1XForm : SDNodeXForm<imm, [{
406  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
407}]>;
408def UImmS2XForm : SDNodeXForm<imm, [{
409  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
410}]>;
411def UImmS4XForm : SDNodeXForm<imm, [{
412  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
413}]>;
414def UImmS8XForm : SDNodeXForm<imm, [{
415  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
416}]>;
417
418// uimm5sN predicate - True if the immediate is a multiple of N in the range
419// [0 * N, 32 * N].
420def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
421def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
422def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
423
424def uimm5s2 : Operand<i64>, ImmLeaf<i64,
425                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
426                UImmS2XForm> {
427  let ParserMatchClass = UImm5s2Operand;
428  let PrintMethod = "printImmScale<2>";
429}
430def uimm5s4 : Operand<i64>, ImmLeaf<i64,
431                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
432                UImmS4XForm> {
433  let ParserMatchClass = UImm5s4Operand;
434  let PrintMethod = "printImmScale<4>";
435}
436def uimm5s8 : Operand<i64>, ImmLeaf<i64,
437                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
438                UImmS8XForm> {
439  let ParserMatchClass = UImm5s8Operand;
440  let PrintMethod = "printImmScale<8>";
441}
442
443// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
444// instead of ImmLeaf (Constant)
445def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
446                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
447                UImmS2XForm> {
448  let ParserMatchClass = UImm5s2Operand;
449  let PrintMethod = "printImmScale<2>";
450}
451def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
452                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
453                UImmS4XForm> {
454  let ParserMatchClass = UImm5s4Operand;
455  let PrintMethod = "printImmScale<4>";
456}
457def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
458                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
459                UImmS8XForm> {
460  let ParserMatchClass = UImm5s8Operand;
461  let PrintMethod = "printImmScale<8>";
462}
463
464// uimm6sN predicate - True if the immediate is a multiple of N in the range
465// [0 * N, 64 * N].
466def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
467def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
468def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
469def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
470def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
471
472def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
473  let ParserMatchClass = UImm6s1Operand;
474}
475def uimm6s2 : Operand<i64>, ImmLeaf<i64,
476[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
477  let PrintMethod = "printImmScale<2>";
478  let ParserMatchClass = UImm6s2Operand;
479}
480def uimm6s4 : Operand<i64>, ImmLeaf<i64,
481[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
482  let PrintMethod = "printImmScale<4>";
483  let ParserMatchClass = UImm6s4Operand;
484}
485def uimm6s8 : Operand<i64>, ImmLeaf<i64,
486[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
487  let PrintMethod = "printImmScale<8>";
488  let ParserMatchClass = UImm6s8Operand;
489}
490def uimm6s16 : Operand<i64>, ImmLeaf<i64,
491[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
492  let PrintMethod = "printImmScale<16>";
493  let ParserMatchClass = UImm6s16Operand;
494}
495
496def SImmS2XForm : SDNodeXForm<imm, [{
497  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
498}]>;
499def SImmS3XForm : SDNodeXForm<imm, [{
500  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
501}]>;
502def SImmS4XForm : SDNodeXForm<imm, [{
503  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
504}]>;
505def SImmS16XForm : SDNodeXForm<imm, [{
506  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
507}]>;
508def SImmS32XForm : SDNodeXForm<imm, [{
509  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
510}]>;
511
512// simm6sN predicate - True if the immediate is a multiple of N in the range
513// [-32 * N, 31 * N].
514def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
515def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
516  let ParserMatchClass = SImm6s1Operand;
517  let DecoderMethod = "DecodeSImm<6>";
518}
519
520// simm4sN predicate - True if the immediate is a multiple of N in the range
521// [ -8* N, 7 * N].
522def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
523def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
524def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
525def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
526def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
527def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
528
529def simm4s1 : Operand<i64>, ImmLeaf<i64,
530[{ return Imm >=-8  && Imm <= 7; }]> {
531  let ParserMatchClass = SImm4s1Operand;
532  let DecoderMethod = "DecodeSImm<4>";
533}
534
535def simm4s2 : Operand<i64>, ImmLeaf<i64,
536[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
537  let PrintMethod = "printImmScale<2>";
538  let ParserMatchClass = SImm4s2Operand;
539  let DecoderMethod = "DecodeSImm<4>";
540}
541
542def simm4s3 : Operand<i64>, ImmLeaf<i64,
543[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
544  let PrintMethod = "printImmScale<3>";
545  let ParserMatchClass = SImm4s3Operand;
546  let DecoderMethod = "DecodeSImm<4>";
547}
548
549def simm4s4 : Operand<i64>, ImmLeaf<i64,
550[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
551  let PrintMethod = "printImmScale<4>";
552  let ParserMatchClass = SImm4s4Operand;
553  let DecoderMethod = "DecodeSImm<4>";
554}
555def simm4s16 : Operand<i64>, ImmLeaf<i64,
556[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
557  let PrintMethod = "printImmScale<16>";
558  let ParserMatchClass = SImm4s16Operand;
559  let DecoderMethod = "DecodeSImm<4>";
560}
561def simm4s32 : Operand<i64>, ImmLeaf<i64,
562[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
563  let PrintMethod = "printImmScale<32>";
564  let ParserMatchClass = SImm4s32Operand;
565  let DecoderMethod = "DecodeSImm<4>";
566}
567
568def Imm1_8Operand : AsmImmRange<1, 8>;
569def Imm1_16Operand : AsmImmRange<1, 16>;
570def Imm1_32Operand : AsmImmRange<1, 32>;
571def Imm1_64Operand : AsmImmRange<1, 64>;
572
573class BranchTarget<int N> : AsmOperandClass {
574  let Name = "BranchTarget" # N;
575  let DiagnosticType = "InvalidLabel";
576  let PredicateMethod = "isBranchTarget<" # N # ">";
577}
578
579class PCRelLabel<int N> : BranchTarget<N> {
580  let Name = "PCRelLabel" # N;
581}
582
583def BranchTarget14Operand : BranchTarget<14>;
584def BranchTarget26Operand : BranchTarget<26>;
585def PCRelLabel19Operand   : PCRelLabel<19>;
586
587def MovWSymbolG3AsmOperand : AsmOperandClass {
588  let Name = "MovWSymbolG3";
589  let RenderMethod = "addImmOperands";
590}
591
592def movw_symbol_g3 : Operand<i32> {
593  let ParserMatchClass = MovWSymbolG3AsmOperand;
594}
595
596def MovWSymbolG2AsmOperand : AsmOperandClass {
597  let Name = "MovWSymbolG2";
598  let RenderMethod = "addImmOperands";
599}
600
601def movw_symbol_g2 : Operand<i32> {
602  let ParserMatchClass = MovWSymbolG2AsmOperand;
603}
604
605def MovWSymbolG1AsmOperand : AsmOperandClass {
606  let Name = "MovWSymbolG1";
607  let RenderMethod = "addImmOperands";
608}
609
610def movw_symbol_g1 : Operand<i32> {
611  let ParserMatchClass = MovWSymbolG1AsmOperand;
612}
613
614def MovWSymbolG0AsmOperand : AsmOperandClass {
615  let Name = "MovWSymbolG0";
616  let RenderMethod = "addImmOperands";
617}
618
619def movw_symbol_g0 : Operand<i32> {
620  let ParserMatchClass = MovWSymbolG0AsmOperand;
621}
622
623class fixedpoint_i32<ValueType FloatVT>
624  : Operand<FloatVT>,
625    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
626  let EncoderMethod = "getFixedPointScaleOpValue";
627  let DecoderMethod = "DecodeFixedPointScaleImm32";
628  let ParserMatchClass = Imm1_32Operand;
629}
630
631class fixedpoint_i64<ValueType FloatVT>
632  : Operand<FloatVT>,
633    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
634  let EncoderMethod = "getFixedPointScaleOpValue";
635  let DecoderMethod = "DecodeFixedPointScaleImm64";
636  let ParserMatchClass = Imm1_64Operand;
637}
638
639def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
640def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
641def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
642
643def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
644def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
645def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
646
647def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
648  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
649}]> {
650  let EncoderMethod = "getVecShiftR8OpValue";
651  let DecoderMethod = "DecodeVecShiftR8Imm";
652  let ParserMatchClass = Imm1_8Operand;
653}
654def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
655  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
656}]> {
657  let EncoderMethod = "getVecShiftR16OpValue";
658  let DecoderMethod = "DecodeVecShiftR16Imm";
659  let ParserMatchClass = Imm1_16Operand;
660}
661def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
662  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
663}]> {
664  let EncoderMethod = "getVecShiftR16OpValue";
665  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
666  let ParserMatchClass = Imm1_8Operand;
667}
668def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
669  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
670}]> {
671  let EncoderMethod = "getVecShiftR32OpValue";
672  let DecoderMethod = "DecodeVecShiftR32Imm";
673  let ParserMatchClass = Imm1_32Operand;
674}
675def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
676  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
677}]> {
678  let EncoderMethod = "getVecShiftR32OpValue";
679  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
680  let ParserMatchClass = Imm1_16Operand;
681}
682def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
683  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
684}]> {
685  let EncoderMethod = "getVecShiftR64OpValue";
686  let DecoderMethod = "DecodeVecShiftR64Imm";
687  let ParserMatchClass = Imm1_64Operand;
688}
689def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
690  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
691}]> {
692  let EncoderMethod = "getVecShiftR64OpValue";
693  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
694  let ParserMatchClass = Imm1_32Operand;
695}
696
697// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
698// (ImmLeaf)
699def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
700  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
701}]> {
702  let EncoderMethod = "getVecShiftR8OpValue";
703  let DecoderMethod = "DecodeVecShiftR8Imm";
704  let ParserMatchClass = Imm1_8Operand;
705}
706def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
707  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
708}]> {
709  let EncoderMethod = "getVecShiftR16OpValue";
710  let DecoderMethod = "DecodeVecShiftR16Imm";
711  let ParserMatchClass = Imm1_16Operand;
712}
713def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
714  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
715}]> {
716  let EncoderMethod = "getVecShiftR32OpValue";
717  let DecoderMethod = "DecodeVecShiftR32Imm";
718  let ParserMatchClass = Imm1_32Operand;
719}
720def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
721  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
722}]> {
723  let EncoderMethod = "getVecShiftR64OpValue";
724  let DecoderMethod = "DecodeVecShiftR64Imm";
725  let ParserMatchClass = Imm1_64Operand;
726}
727
728def Imm0_0Operand : AsmImmRange<0, 0>;
729def Imm0_1Operand : AsmImmRange<0, 1>;
730def Imm0_3Operand : AsmImmRange<0, 3>;
731def Imm0_7Operand : AsmImmRange<0, 7>;
732def Imm0_15Operand : AsmImmRange<0, 15>;
733def Imm0_31Operand : AsmImmRange<0, 31>;
734def Imm0_63Operand : AsmImmRange<0, 63>;
735
736def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
737  return (((uint32_t)Imm) < 8);
738}]> {
739  let EncoderMethod = "getVecShiftL8OpValue";
740  let DecoderMethod = "DecodeVecShiftL8Imm";
741  let ParserMatchClass = Imm0_7Operand;
742}
743def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
744  return (((uint32_t)Imm) < 16);
745}]> {
746  let EncoderMethod = "getVecShiftL16OpValue";
747  let DecoderMethod = "DecodeVecShiftL16Imm";
748  let ParserMatchClass = Imm0_15Operand;
749}
750def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
751  return (((uint32_t)Imm) < 32);
752}]> {
753  let EncoderMethod = "getVecShiftL32OpValue";
754  let DecoderMethod = "DecodeVecShiftL32Imm";
755  let ParserMatchClass = Imm0_31Operand;
756}
757def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
758  return (((uint32_t)Imm) < 64);
759}]> {
760  let EncoderMethod = "getVecShiftL64OpValue";
761  let DecoderMethod = "DecodeVecShiftL64Imm";
762  let ParserMatchClass = Imm0_63Operand;
763}
764
765// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
766// (ImmLeaf)
767def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
768  return (((uint32_t)Imm) < 8);
769}]> {
770  let EncoderMethod = "getVecShiftL8OpValue";
771  let DecoderMethod = "DecodeVecShiftL8Imm";
772  let ParserMatchClass = Imm0_7Operand;
773}
774def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
775  return (((uint32_t)Imm) < 16);
776}]> {
777  let EncoderMethod = "getVecShiftL16OpValue";
778  let DecoderMethod = "DecodeVecShiftL16Imm";
779  let ParserMatchClass = Imm0_15Operand;
780}
781def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
782  return (((uint32_t)Imm) < 32);
783}]> {
784  let EncoderMethod = "getVecShiftL32OpValue";
785  let DecoderMethod = "DecodeVecShiftL32Imm";
786  let ParserMatchClass = Imm0_31Operand;
787}
788def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
789  return (((uint32_t)Imm) < 64);
790}]> {
791  let EncoderMethod = "getVecShiftL64OpValue";
792  let DecoderMethod = "DecodeVecShiftL64Imm";
793  let ParserMatchClass = Imm0_63Operand;
794}
795
796// Crazy immediate formats used by 32-bit and 64-bit logical immediate
797// instructions for splatting repeating bit patterns across the immediate.
798def logical_imm32_XFORM : SDNodeXForm<imm, [{
799  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
800  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
801}]>;
802def logical_imm64_XFORM : SDNodeXForm<imm, [{
803  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
804  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
805}]>;
806
807def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
808  GISDNodeXFormEquiv<logical_imm32_XFORM>;
809def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
810  GISDNodeXFormEquiv<logical_imm64_XFORM>;
811
812let DiagnosticType = "LogicalSecondSource" in {
813  def LogicalImm32Operand : AsmOperandClass {
814    let Name = "LogicalImm32";
815    let PredicateMethod = "isLogicalImm<int32_t>";
816    let RenderMethod = "addLogicalImmOperands<int32_t>";
817  }
818  def LogicalImm64Operand : AsmOperandClass {
819    let Name = "LogicalImm64";
820    let PredicateMethod = "isLogicalImm<int64_t>";
821    let RenderMethod = "addLogicalImmOperands<int64_t>";
822  }
823  def LogicalImm32NotOperand : AsmOperandClass {
824    let Name = "LogicalImm32Not";
825    let PredicateMethod = "isLogicalImm<int32_t>";
826    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
827  }
828  def LogicalImm64NotOperand : AsmOperandClass {
829    let Name = "LogicalImm64Not";
830    let PredicateMethod = "isLogicalImm<int64_t>";
831    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
832  }
833}
834def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
835  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
836}], logical_imm32_XFORM> {
837  let PrintMethod = "printLogicalImm<int32_t>";
838  let ParserMatchClass = LogicalImm32Operand;
839}
840def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
841  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
842}], logical_imm64_XFORM> {
843  let PrintMethod = "printLogicalImm<int64_t>";
844  let ParserMatchClass = LogicalImm64Operand;
845}
846def logical_imm32_not : Operand<i32> {
847  let ParserMatchClass = LogicalImm32NotOperand;
848}
849def logical_imm64_not : Operand<i64> {
850  let ParserMatchClass = LogicalImm64NotOperand;
851}
852
853// immXX_0_65535 predicates - True if the immediate is in the range [0,65535].
854let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
855def timm32_0_65535 : Operand<i32>, TImmLeaf<i32, [{
856  return ((uint32_t)Imm) < 65536;
857}]>;
858
859def timm64_0_65535 : Operand<i64>, TImmLeaf<i64, [{
860  return ((uint64_t)Imm) < 65536;
861}]>;
862}
863
864// imm0_255 predicate - True if the immediate is in the range [0,255].
865def Imm0_255Operand : AsmImmRange<0,255>;
866
867def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
868  return ((uint32_t)Imm) < 256;
869}]> {
870  let ParserMatchClass = Imm0_255Operand;
871  let PrintMethod = "printImm";
872}
873
874// imm0_127 predicate - True if the immediate is in the range [0,127]
875def Imm0_127Operand : AsmImmRange<0, 127>;
876def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
877  return ((uint32_t)Imm) < 128;
878}]> {
879  let ParserMatchClass = Imm0_127Operand;
880  let PrintMethod = "printImm";
881}
882
883def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
884  return ((uint64_t)Imm) < 128;
885}]> {
886  let ParserMatchClass = Imm0_127Operand;
887  let PrintMethod = "printImm";
888}
889
890// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
891// for all shift-amounts.
892
893// imm0_63 predicate - True if the immediate is in the range [0,63]
894def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
895  return ((uint64_t)Imm) < 64;
896}]> {
897  let ParserMatchClass = Imm0_63Operand;
898}
899
900def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
901  return ((uint64_t)Imm) < 64;
902}]> {
903  let ParserMatchClass = Imm0_63Operand;
904}
905
906// imm0_31 predicate - True if the immediate is in the range [0,31]
907def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
908  return ((uint64_t)Imm) < 32;
909}]> {
910  let ParserMatchClass = Imm0_31Operand;
911}
912
913// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
914// instead of Constant (ImmLeaf)
915def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
916  return ((uint64_t)Imm) < 32;
917}]> {
918  let ParserMatchClass = Imm0_31Operand;
919}
920
921// True if the 32-bit immediate is in the range [0,31]
922def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
923  return ((uint64_t)Imm) < 32;
924}]> {
925  let ParserMatchClass = Imm0_31Operand;
926}
927
928// imm0_1 predicate - True if the immediate is in the range [0,1]
929def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
930  return ((uint64_t)Imm) < 2;
931}]> {
932  let ParserMatchClass = Imm0_1Operand;
933}
934
935// timm0_1 - as above, but use TargetConstant (TImmLeaf)
936def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
937  return ((uint64_t)Imm) < 2;
938}]> {
939  let ParserMatchClass = Imm0_1Operand;
940}
941
942// imm0_15 predicate - True if the immediate is in the range [0,15]
943def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
944  return ((uint64_t)Imm) < 16;
945}]> {
946  let ParserMatchClass = Imm0_15Operand;
947}
948
949// imm0_7 predicate - True if the immediate is in the range [0,7]
950def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
951  return ((uint64_t)Imm) < 8;
952}]> {
953  let ParserMatchClass = Imm0_7Operand;
954}
955
956// imm0_3 predicate - True if the immediate is in the range [0,3]
957def imm0_3 : Operand<i64>, ImmLeaf<i64, [{
958  return ((uint64_t)Imm) < 4;
959}]> {
960  let ParserMatchClass = Imm0_3Operand;
961}
962
963// timm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
964def timm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
965  return ((uint32_t)Imm) < 8;
966}]> {
967  let ParserMatchClass = Imm0_7Operand;
968}
969
970// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
971def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
972  return ((uint32_t)Imm) < 16;
973}]> {
974  let ParserMatchClass = Imm0_15Operand;
975}
976
977// An arithmetic shifter operand:
978//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
979//  {5-0} - imm6
980class arith_shift<ValueType Ty, int width> : Operand<Ty> {
981  let PrintMethod = "printShifter";
982  let ParserMatchClass = !cast<AsmOperandClass>(
983                         "ArithmeticShifterOperand" # width);
984}
985
986def arith_shift32 : arith_shift<i32, 32>;
987def arith_shift64 : arith_shift<i64, 64>;
988
989class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
990    : Operand<Ty>,
991      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
992  let PrintMethod = "printShiftedRegister";
993  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
994}
995
996def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
997def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
998
999def gi_arith_shifted_reg32 :
1000  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
1001  GIComplexPatternEquiv<arith_shifted_reg32>;
1002
1003def gi_arith_shifted_reg64 :
1004  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
1005  GIComplexPatternEquiv<arith_shifted_reg64>;
1006
1007// An arithmetic shifter operand:
1008//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
1009//  {5-0} - imm6
1010class logical_shift<int width> : Operand<i32> {
1011  let PrintMethod = "printShifter";
1012  let ParserMatchClass = !cast<AsmOperandClass>(
1013                         "LogicalShifterOperand" # width);
1014}
1015
1016def logical_shift32 : logical_shift<32>;
1017def logical_shift64 : logical_shift<64>;
1018
1019class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1020    : Operand<Ty>,
1021      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1022  let PrintMethod = "printShiftedRegister";
1023  let MIOperandInfo = (ops regclass, shiftop);
1024}
1025
1026def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1027def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1028
1029def gi_logical_shifted_reg32 :
1030  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1031  GIComplexPatternEquiv<logical_shifted_reg32>;
1032
1033def gi_logical_shifted_reg64 :
1034  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1035  GIComplexPatternEquiv<logical_shifted_reg64>;
1036
1037// A logical vector shifter operand:
1038//  {7-6} - shift type: 00 = lsl
1039//  {5-0} - imm6: #0, #8, #16, or #24
1040def logical_vec_shift : Operand<i32> {
1041  let PrintMethod = "printShifter";
1042  let EncoderMethod = "getVecShifterOpValue";
1043  let ParserMatchClass = LogicalVecShifterOperand;
1044}
1045
1046// A logical vector half-word shifter operand:
1047//  {7-6} - shift type: 00 = lsl
1048//  {5-0} - imm6: #0 or #8
1049def logical_vec_hw_shift : Operand<i32> {
1050  let PrintMethod = "printShifter";
1051  let EncoderMethod = "getVecShifterOpValue";
1052  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1053}
1054
1055// A vector move shifter operand:
1056//  {0} - imm1: #8 or #16
1057def move_vec_shift : Operand<i32> {
1058  let PrintMethod = "printShifter";
1059  let EncoderMethod = "getMoveVecShifterOpValue";
1060  let ParserMatchClass = MoveVecShifterOperand;
1061}
1062
1063let DiagnosticType = "AddSubSecondSource" in {
1064  def AddSubImmOperand : AsmOperandClass {
1065    let Name = "AddSubImm";
1066    let ParserMethod = "tryParseImmWithOptionalShift";
1067    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1068  }
1069  def AddSubImmNegOperand : AsmOperandClass {
1070    let Name = "AddSubImmNeg";
1071    let ParserMethod = "tryParseImmWithOptionalShift";
1072    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1073  }
1074}
1075// An ADD/SUB immediate shifter operand:
1076//  second operand:
1077//  {7-6} - shift type: 00 = lsl
1078//  {5-0} - imm6: #0 or #12
1079class addsub_shifted_imm<ValueType Ty>
1080    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1081  let PrintMethod = "printAddSubImm";
1082  let EncoderMethod = "getAddSubImmOpValue";
1083  let ParserMatchClass = AddSubImmOperand;
1084  let MIOperandInfo = (ops i32imm, i32imm);
1085}
1086
1087class addsub_shifted_imm_neg<ValueType Ty>
1088    : Operand<Ty> {
1089  let EncoderMethod = "getAddSubImmOpValue";
1090  let ParserMatchClass = AddSubImmNegOperand;
1091  let MIOperandInfo = (ops i32imm, i32imm);
1092}
1093
1094def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1095def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1096def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1097def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1098
1099def gi_addsub_shifted_imm32 :
1100    GIComplexOperandMatcher<s32, "selectArithImmed">,
1101    GIComplexPatternEquiv<addsub_shifted_imm32>;
1102
1103def gi_addsub_shifted_imm64 :
1104    GIComplexOperandMatcher<s64, "selectArithImmed">,
1105    GIComplexPatternEquiv<addsub_shifted_imm64>;
1106
1107class neg_addsub_shifted_imm<ValueType Ty>
1108    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1109  let PrintMethod = "printAddSubImm";
1110  let EncoderMethod = "getAddSubImmOpValue";
1111  let ParserMatchClass = AddSubImmOperand;
1112  let MIOperandInfo = (ops i32imm, i32imm);
1113}
1114
1115def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1116def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1117
1118def gi_neg_addsub_shifted_imm32 :
1119    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1120    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1121
1122def gi_neg_addsub_shifted_imm64 :
1123    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1124    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1125
1126// An extend operand:
1127//  {5-3} - extend type
1128//  {2-0} - imm3
1129def arith_extend : Operand<i32> {
1130  let PrintMethod = "printArithExtend";
1131  let ParserMatchClass = ExtendOperand;
1132}
1133def arith_extend64 : Operand<i32> {
1134  let PrintMethod = "printArithExtend";
1135  let ParserMatchClass = ExtendOperand64;
1136}
1137
1138// 'extend' that's a lsl of a 64-bit register.
1139def arith_extendlsl64 : Operand<i32> {
1140  let PrintMethod = "printArithExtend";
1141  let ParserMatchClass = ExtendOperandLSL64;
1142}
1143
1144class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1145                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1146  let PrintMethod = "printExtendedRegister";
1147  let MIOperandInfo = (ops GPR32, arith_extend);
1148}
1149
1150class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1151                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1152  let PrintMethod = "printExtendedRegister";
1153  let MIOperandInfo = (ops GPR32, arith_extend64);
1154}
1155
1156def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1157def gi_arith_extended_reg32_i32 :
1158    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1159    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1160
1161def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1162def gi_arith_extended_reg32_i64 :
1163    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1164    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1165
1166def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1167def gi_arith_extended_reg32to64_i64 :
1168    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1169    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1170
1171// Floating-point immediate.
1172
1173def fpimm16XForm : SDNodeXForm<fpimm, [{
1174      APFloat InVal = N->getValueAPF();
1175      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1176      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1177    }]>;
1178
1179def fpimm32XForm : SDNodeXForm<fpimm, [{
1180      APFloat InVal = N->getValueAPF();
1181      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1182      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1183    }]>;
1184
1185def fpimm32SIMDModImmType4XForm : SDNodeXForm<fpimm, [{
1186      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType4(N->getValueAPF()
1187                                                          .bitcastToAPInt()
1188                                                          .getZExtValue());
1189      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1190    }]>;
1191
1192def fpimm64XForm : SDNodeXForm<fpimm, [{
1193      APFloat InVal = N->getValueAPF();
1194      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1195      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1196    }]>;
1197
1198def fpimm16 : Operand<f16>,
1199              FPImmLeaf<f16, [{
1200      return AArch64_AM::getFP16Imm(Imm) != -1;
1201    }], fpimm16XForm> {
1202  let ParserMatchClass = FPImmOperand;
1203  let PrintMethod = "printFPImmOperand";
1204}
1205
1206def fpimm32 : Operand<f32>,
1207              FPImmLeaf<f32, [{
1208      return AArch64_AM::getFP32Imm(Imm) != -1;
1209    }], fpimm32XForm> {
1210  let ParserMatchClass = FPImmOperand;
1211  let PrintMethod = "printFPImmOperand";
1212}
1213
1214def fpimm32SIMDModImmType4 : FPImmLeaf<f32, [{
1215      uint64_t Enc = Imm.bitcastToAPInt().getZExtValue();
1216      return Enc != 0 && AArch64_AM::isAdvSIMDModImmType4(Enc << 32 | Enc);
1217    }], fpimm32SIMDModImmType4XForm> {
1218}
1219
1220def fpimm64 : Operand<f64>,
1221              FPImmLeaf<f64, [{
1222      return AArch64_AM::getFP64Imm(Imm) != -1;
1223    }], fpimm64XForm> {
1224  let ParserMatchClass = FPImmOperand;
1225  let PrintMethod = "printFPImmOperand";
1226}
1227
1228def fpimm8 : Operand<i32> {
1229  let ParserMatchClass = FPImmOperand;
1230  let PrintMethod = "printFPImmOperand";
1231}
1232
1233def fpimm0 : FPImmLeaf<fAny, [{
1234  return Imm.isExactlyValue(+0.0);
1235}]>;
1236
1237def fpimm_minus0 : FPImmLeaf<fAny, [{
1238  return Imm.isExactlyValue(-0.0);
1239}]>;
1240
1241def fpimm_half : FPImmLeaf<fAny, [{
1242  return Imm.isExactlyValue(+0.5);
1243}]>;
1244
1245def fpimm_one : FPImmLeaf<fAny, [{
1246  return Imm.isExactlyValue(+1.0);
1247}]>;
1248
1249def fpimm_two : FPImmLeaf<fAny, [{
1250  return Imm.isExactlyValue(+2.0);
1251}]>;
1252
1253def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1254  GISDNodeXFormEquiv<fpimm16XForm>;
1255def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1256  GISDNodeXFormEquiv<fpimm32XForm>;
1257def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1258  GISDNodeXFormEquiv<fpimm64XForm>;
1259def gi_fpimm32SIMDModImmType4 :
1260    GICustomOperandRenderer<"renderFPImm32SIMDModImmType4">,
1261  GISDNodeXFormEquiv<fpimm32SIMDModImmType4XForm>;
1262
1263// Vector lane operands
1264class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1265  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1266  let DiagnosticType = "Invalid" # Name;
1267  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1268  let RenderMethod = "addVectorIndexOperands";
1269}
1270
1271class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1272    : Operand<ty> {
1273  let ParserMatchClass = mc;
1274  let PrintMethod = "printVectorIndex";
1275}
1276
1277multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1278  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1279  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1280}
1281
1282def VectorIndex0Operand : AsmVectorIndex<0, 0>;
1283def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1284def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1285def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1286def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1287def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1288
1289let OperandNamespace = "AArch64" in {
1290  let OperandType = "OPERAND_IMPLICIT_IMM_0" in {
1291    defm VectorIndex0 : VectorIndex<i64, VectorIndex0Operand,
1292                                [{ return ((uint64_t)Imm) == 0; }]>;
1293  }
1294}
1295defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1296                                [{ return ((uint64_t)Imm) == 1; }]>;
1297defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1298                                [{ return ((uint64_t)Imm) < 16; }]>;
1299defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1300                                [{ return ((uint64_t)Imm) < 8; }]>;
1301defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1302                                [{ return ((uint64_t)Imm) < 4; }]>;
1303defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1304                                [{ return ((uint64_t)Imm) < 2; }]>;
1305
1306defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1307                                   [{ return ((uint64_t)Imm) == 1; }]>;
1308defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1309                                   [{ return ((uint64_t)Imm) < 16; }]>;
1310defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1311                                   [{ return ((uint64_t)Imm) < 8; }]>;
1312defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1313                                   [{ return ((uint64_t)Imm) < 4; }]>;
1314defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1315                                   [{ return ((uint64_t)Imm) < 2; }]>;
1316
1317def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1318def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1319def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1320def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1321def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1322
1323defm sve_elm_idx_extdup_b
1324  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1325                [{ return ((uint64_t)Imm) < 64; }]>;
1326defm sve_elm_idx_extdup_h
1327  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1328                [{ return ((uint64_t)Imm) < 32; }]>;
1329defm sve_elm_idx_extdup_s
1330  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1331                [{ return ((uint64_t)Imm) < 16; }]>;
1332defm sve_elm_idx_extdup_d
1333  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1334                [{ return ((uint64_t)Imm) < 8; }]>;
1335defm sve_elm_idx_extdup_q
1336  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1337                [{ return ((uint64_t)Imm) < 4; }]>;
1338
1339def sme_elm_idx0_0 : Operand<i64>, ImmLeaf<i64, [{
1340  return ((uint64_t)Imm) == 0;
1341}]> {
1342  let ParserMatchClass = Imm0_0Operand;
1343  let PrintMethod = "printMatrixIndex";
1344  let OperandNamespace = "AArch64";
1345  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1346}
1347def sme_elm_idx0_1 : Operand<i64>, ImmLeaf<i64, [{
1348  return ((uint64_t)Imm) <= 1;
1349}]> {
1350  let ParserMatchClass = Imm0_1Operand;
1351  let PrintMethod = "printMatrixIndex";
1352}
1353def sme_elm_idx0_3 : Operand<i64>, ImmLeaf<i64, [{
1354  return ((uint64_t)Imm) <= 3;
1355}]> {
1356  let ParserMatchClass = Imm0_3Operand;
1357  let PrintMethod = "printMatrixIndex";
1358}
1359def sme_elm_idx0_7 : Operand<i64>, ImmLeaf<i64, [{
1360  return ((uint64_t)Imm) <= 7;
1361}]> {
1362  let ParserMatchClass = Imm0_7Operand;
1363  let PrintMethod = "printMatrixIndex";
1364}
1365def sme_elm_idx0_15 : Operand<i64>, ImmLeaf<i64, [{
1366  return ((uint64_t)Imm) <= 15;
1367}]> {
1368  let ParserMatchClass = Imm0_15Operand;
1369  let PrintMethod = "printMatrixIndex";
1370}
1371
1372// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1373// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1374// are encoded as the eight bit value 'abcdefgh'.
1375def simdimmtype10 : Operand<i32>,
1376                    FPImmLeaf<f64, [{
1377      return AArch64_AM::isAdvSIMDModImmType10(
1378                 Imm.bitcastToAPInt().getZExtValue());
1379    }], SDNodeXForm<fpimm, [{
1380      APFloat InVal = N->getValueAPF();
1381      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1382                                                           .bitcastToAPInt()
1383                                                           .getZExtValue());
1384      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1385    }]>> {
1386  let ParserMatchClass = SIMDImmType10Operand;
1387  let PrintMethod = "printSIMDType10Operand";
1388}
1389
1390
1391//---
1392// System management
1393//---
1394
1395// Base encoding for system instruction operands.
1396let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1397class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1398                  list<dag> pattern = []>
1399    : I<oops, iops, asm, operands, "", pattern> {
1400  let Inst{31-22} = 0b1101010100;
1401  let Inst{21}    = L;
1402}
1403
1404// System instructions which do not have an Rt register.
1405class SimpleSystemI<bit L, dag iops, string asm, string operands,
1406                    list<dag> pattern = []>
1407    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1408  let Inst{4-0} = 0b11111;
1409}
1410
1411// System instructions which have an Rt register.
1412class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1413                list<dag> pattern = []>
1414    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1415      Sched<[WriteSys]> {
1416  bits<5> Rt;
1417  let Inst{4-0} = Rt;
1418}
1419
1420// System instructions for transactional memory extension
1421class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1422                    string asm, string operands, list<dag> pattern>
1423    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1424      Sched<[WriteSys]> {
1425  let Inst{20-12} = 0b000110011;
1426  let Inst{11-8} = CRm;
1427  let Inst{7-5} = op2;
1428  let DecoderMethod = "";
1429
1430  let mayLoad = 1;
1431  let mayStore = 1;
1432}
1433
1434// System instructions for transactional memory - single input operand
1435class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1436    : TMBaseSystemI<0b1, CRm, 0b011,
1437                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1438  bits<5> Rt;
1439  let Inst{4-0} = Rt;
1440}
1441
1442// System instructions that pass a register argument
1443// This class assumes the register is for input rather than output.
1444class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1445                      list<dag> pattern = []>
1446    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1447  let Inst{20-12} = 0b000110001;
1448  let Inst{11-8} = CRm;
1449  let Inst{7-5} = Op2;
1450}
1451
1452// System instructions for transactional memory - no operand
1453class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1454    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1455  let Inst{4-0} = 0b11111;
1456}
1457
1458// System instructions for exit from transactions
1459class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1460    : I<(outs), (ins timm64_0_65535:$imm), asm, "\t$imm", "", pattern>,
1461      Sched<[WriteSys]> {
1462  bits<16> imm;
1463  let Inst{31-24} = 0b11010100;
1464  let Inst{23-21} = op1;
1465  let Inst{20-5}  = imm;
1466  let Inst{4-0}   = 0b00000;
1467}
1468
1469// Hint instructions that take both a CRm and a 3-bit immediate.
1470// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1471// model patterns with sufficiently fine granularity
1472let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1473  class HintI<string mnemonic>
1474      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1475                      [(int_aarch64_hint imm0_127:$imm)]>,
1476        Sched<[WriteHint]> {
1477    bits <7> imm;
1478    let Inst{20-12} = 0b000110010;
1479    let Inst{11-5} = imm;
1480  }
1481
1482// System instructions taking a single literal operand which encodes into
1483// CRm. op2 differentiates the opcodes.
1484def BarrierAsmOperand : AsmOperandClass {
1485  let Name = "Barrier";
1486  let ParserMethod = "tryParseBarrierOperand";
1487}
1488def barrier_op : Operand<i32> {
1489  let PrintMethod = "printBarrierOption";
1490  let ParserMatchClass = BarrierAsmOperand;
1491}
1492def BarriernXSAsmOperand : AsmOperandClass {
1493  let Name = "BarriernXS";
1494  let ParserMethod = "tryParseBarriernXSOperand";
1495}
1496def barrier_nxs_op : Operand<i32> {
1497  let PrintMethod = "printBarriernXSOption";
1498  let ParserMatchClass = BarriernXSAsmOperand;
1499}
1500class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1501                 list<dag> pattern = []>
1502    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1503      Sched<[WriteBarrier]> {
1504  bits<4> CRm;
1505  let Inst{20-12} = 0b000110011;
1506  let Inst{11-8} = CRm;
1507  let Inst{7-5} = opc;
1508}
1509
1510class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1511    : SimpleSystemI<0, (ins), asm, "", pattern>,
1512      Sched<[WriteHint]> {
1513  bits<4> CRm;
1514  let CRm = 0b0011;
1515  let Inst{31-12} = 0b11010101000000110010;
1516  let Inst{11-8} = CRm;
1517  let Inst{7-5} = op2;
1518  let Inst{4-0} = 0b11111;
1519}
1520
1521// MRS/MSR system instructions. These have different operand classes because
1522// a different subset of registers can be accessed through each instruction.
1523def MRSSystemRegisterOperand : AsmOperandClass {
1524  let Name = "MRSSystemRegister";
1525  let ParserMethod = "tryParseSysReg";
1526  let DiagnosticType = "MRS";
1527}
1528// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1529def mrs_sysreg_op : Operand<i32> {
1530  let ParserMatchClass = MRSSystemRegisterOperand;
1531  let DecoderMethod = "DecodeMRSSystemRegister";
1532  let PrintMethod = "printMRSSystemRegister";
1533}
1534
1535def MSRSystemRegisterOperand : AsmOperandClass {
1536  let Name = "MSRSystemRegister";
1537  let ParserMethod = "tryParseSysReg";
1538  let DiagnosticType = "MSR";
1539}
1540def msr_sysreg_op : Operand<i32> {
1541  let ParserMatchClass = MSRSystemRegisterOperand;
1542  let DecoderMethod = "DecodeMSRSystemRegister";
1543  let PrintMethod = "printMSRSystemRegister";
1544}
1545
1546def PSBHintOperand : AsmOperandClass {
1547  let Name = "PSBHint";
1548  let ParserMethod = "tryParsePSBHint";
1549}
1550def psbhint_op : Operand<i32> {
1551  let ParserMatchClass = PSBHintOperand;
1552  let PrintMethod = "printPSBHintOp";
1553  let MCOperandPredicate = [{
1554    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1555    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1556    if (!MCOp.isImm())
1557      return false;
1558    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1559  }];
1560}
1561
1562def BTIHintOperand : AsmOperandClass {
1563  let Name = "BTIHint";
1564  let ParserMethod = "tryParseBTIHint";
1565}
1566def btihint_op : Operand<i32> {
1567  let ParserMatchClass = BTIHintOperand;
1568  let PrintMethod = "printBTIHintOp";
1569  let MCOperandPredicate = [{
1570    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1571    if (!MCOp.isImm())
1572      return false;
1573    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1574  }];
1575}
1576
1577class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1578                       "mrs", "\t$Rt, $systemreg"> {
1579  bits<16> systemreg;
1580  let Inst{20-5} = systemreg;
1581  let DecoderNamespace = "Fallback";
1582  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1583  // require doing this. The alternative was to explicitly model each one, but
1584  // it feels like it is unnecessary because it seems there are no negative
1585  // consequences setting these flags for all.
1586  let Defs = [NZCV];
1587}
1588
1589// FIXME: Some of these def NZCV, others don't. Best way to model that?
1590// Explicitly modeling each of the system register as a register class
1591// would do it, but feels like overkill at this point.
1592class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1593                       "msr", "\t$systemreg, $Rt"> {
1594  bits<16> systemreg;
1595  let Inst{20-5} = systemreg;
1596  let DecoderNamespace = "Fallback";
1597}
1598
1599def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1600  let Name = "SystemPStateFieldWithImm0_15";
1601  let ParserMethod = "tryParseSysReg";
1602}
1603def pstatefield4_op : Operand<i32> {
1604  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1605  let PrintMethod = "printSystemPStateField";
1606}
1607
1608// Instructions to modify PSTATE, no input reg
1609let Defs = [NZCV] in
1610class PstateWriteSimple<dag iops, string asm, string operands>
1611  : SimpleSystemI<0, iops, asm, operands> {
1612
1613  let Inst{20-19} = 0b00;
1614  let Inst{15-12} = 0b0100;
1615}
1616
1617class MSRpstateImm0_15
1618  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1619                  "\t$pstatefield, $imm">,
1620    Sched<[WriteSys]> {
1621
1622  bits<6> pstatefield;
1623  bits<4> imm;
1624  let Inst{18-16} = pstatefield{5-3};
1625  let Inst{11-8} = imm;
1626  let Inst{7-5} = pstatefield{2-0};
1627
1628  let DecoderMethod = "DecodeSystemPStateInstruction";
1629  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1630  // Fail the decoder should attempt to decode the instruction as MSRI.
1631  let hasCompleteDecoder = 0;
1632}
1633
1634def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1635  let Name = "SystemPStateFieldWithImm0_1";
1636  let ParserMethod = "tryParseSysReg";
1637}
1638def pstatefield1_op : Operand<i32> {
1639  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1640  let PrintMethod = "printSystemPStateField";
1641}
1642
1643class MSRpstateImm0_1
1644  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1645                 "\t$pstatefield, $imm">,
1646    Sched<[WriteSys]> {
1647
1648  bits<6> pstatefield;
1649  bit imm;
1650  let Inst{18-16} = pstatefield{5-3};
1651  let Inst{11-9} = 0b000;
1652  let Inst{8} = imm;
1653  let Inst{7-5} = pstatefield{2-0};
1654
1655  let DecoderMethod = "DecodeSystemPStateInstruction";
1656  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1657  // Fail the decoder should attempt to decode the instruction as MSRI.
1658  let hasCompleteDecoder = 0;
1659}
1660
1661// SYS and SYSL generic system instructions.
1662def SysCRAsmOperand : AsmOperandClass {
1663  let Name = "SysCR";
1664  let ParserMethod = "tryParseSysCROperand";
1665}
1666
1667def sys_cr_op : Operand<i32> {
1668  let PrintMethod = "printSysCROperand";
1669  let ParserMatchClass = SysCRAsmOperand;
1670}
1671
1672class SystemXtI<bit L, string asm>
1673  : RtSystemI<L, (outs),
1674       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1675       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1676  bits<3> op1;
1677  bits<4> Cn;
1678  bits<4> Cm;
1679  bits<3> op2;
1680  let Inst{20-19} = 0b01;
1681  let Inst{18-16} = op1;
1682  let Inst{15-12} = Cn;
1683  let Inst{11-8}  = Cm;
1684  let Inst{7-5}   = op2;
1685}
1686
1687class SystemLXtI<bit L, string asm>
1688  : RtSystemI<L, (outs),
1689       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1690       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1691  bits<3> op1;
1692  bits<4> Cn;
1693  bits<4> Cm;
1694  bits<3> op2;
1695  let Inst{20-19} = 0b01;
1696  let Inst{18-16} = op1;
1697  let Inst{15-12} = Cn;
1698  let Inst{11-8}  = Cm;
1699  let Inst{7-5}   = op2;
1700}
1701
1702
1703// Branch (register) instructions:
1704//
1705//  case opc of
1706//    0001 blr
1707//    0000 br
1708//    0101 dret
1709//    0100 eret
1710//    0010 ret
1711//    otherwise UNDEFINED
1712class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1713                    string operands, list<dag> pattern>
1714    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1715  let Inst{31-25} = 0b1101011;
1716  let Inst{24-21} = opc;
1717  let Inst{20-16} = 0b11111;
1718  let Inst{15-10} = 0b000000;
1719  let Inst{4-0}   = 0b00000;
1720}
1721
1722class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1723    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1724  bits<5> Rn;
1725  let Inst{9-5} = Rn;
1726}
1727
1728let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1729class SpecialReturn<bits<4> opc, string asm>
1730    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1731  let Inst{9-5} = 0b11111;
1732}
1733
1734let mayLoad = 1 in
1735class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1736  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1737  Sched<[]> {
1738  bits<5> Rn;
1739  bits<5> Rt;
1740  let Inst{31-30} = sz;
1741  let Inst{29-10} = 0b11100010111111110000;
1742  let Inst{9-5} = Rn;
1743  let Inst{4-0} = Rt;
1744}
1745
1746class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1747               list<dag> pattern>
1748  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1749  let isAuthenticated = 1;
1750  let Inst{31-25} = 0b1101011;
1751  let Inst{20-11} = 0b1111100001;
1752  let Inst{10} = M;
1753  let Inst{4-0} = 0b11111;
1754}
1755
1756class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1757  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1758  bits<5> Rn;
1759  bits<5> Rm;
1760  let Inst{24-22} = 0b100;
1761  let Inst{21} = op;
1762  let Inst{9-5} = Rn;
1763  let Inst{4-0} = Rm;
1764}
1765
1766class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1767  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1768  bits<5> Rn;
1769  let Inst{24} = 0;
1770  let Inst{23-21} = opc;
1771  let Inst{9-5} = Rn;
1772}
1773
1774let Uses = [LR,SP] in
1775class AuthReturn<bits<3> op, bits<1> M, string asm>
1776  : AuthBase<M, (outs), (ins), asm, "", []> {
1777  let Inst{24} = 0;
1778  let Inst{23-21} = op;
1779  let Inst{9-0} = 0b1111111111;
1780}
1781
1782let mayLoad = 1 in
1783class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1784                   string operands, string cstr>
1785  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1786  bits<10> offset;
1787  bits<5> Rn;
1788  bits<5> Rt;
1789  let isAuthenticated = 1;
1790  let Inst{31-24} = 0b11111000;
1791  let Inst{23} = M;
1792  let Inst{22} = offset{9};
1793  let Inst{21} = 1;
1794  let Inst{20-12} = offset{8-0};
1795  let Inst{11} = W;
1796  let Inst{10} = 1;
1797  let Inst{9-5} = Rn;
1798  let Inst{4-0} = Rt;
1799
1800  let DecoderMethod = "DecodeAuthLoadInstruction";
1801}
1802
1803multiclass AuthLoad<bit M, string asm, Operand opr> {
1804  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1805                               (ins GPR64sp:$Rn, opr:$offset),
1806                               asm, "\t$Rt, [$Rn, $offset]", "">;
1807  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1808                               (ins GPR64sp:$Rn, opr:$offset),
1809                               asm, "\t$Rt, [$Rn, $offset]!",
1810                               "$Rn = $wback,@earlyclobber $wback">;
1811
1812  def : InstAlias<asm # "\t$Rt, [$Rn]",
1813                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1814
1815  def : InstAlias<asm # "\t$Rt, [$wback]!",
1816                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1817}
1818
1819//---
1820// Conditional branch instruction.
1821//---
1822
1823// Condition code.
1824// 4-bit immediate. Pretty-printed as <cc>
1825def ccode : Operand<i32> {
1826  let PrintMethod = "printCondCode";
1827  let ParserMatchClass = CondCode;
1828}
1829def inv_ccode : Operand<i32> {
1830  // AL and NV are invalid in the aliases which use inv_ccode
1831  let PrintMethod = "printInverseCondCode";
1832  let ParserMatchClass = CondCode;
1833  let MCOperandPredicate = [{
1834    return MCOp.isImm() &&
1835           MCOp.getImm() != AArch64CC::AL &&
1836           MCOp.getImm() != AArch64CC::NV;
1837  }];
1838}
1839
1840// Conditional branch target. 19-bit immediate. The low two bits of the target
1841// offset are implied zero and so are not part of the immediate.
1842def am_brcond : Operand<OtherVT> {
1843  let EncoderMethod = "getCondBranchTargetOpValue";
1844  let DecoderMethod = "DecodePCRelLabel19";
1845  let PrintMethod = "printAlignedLabel";
1846  let ParserMatchClass = PCRelLabel19Operand;
1847  let OperandType = "OPERAND_PCREL";
1848}
1849
1850class BranchCond<bit bit4, string mnemonic>
1851   : I<(outs), (ins ccode:$cond, am_brcond:$target),
1852       mnemonic, ".$cond\t$target", "",
1853       [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> {
1854  let isBranch = 1;
1855  let isTerminator = 1;
1856  let Uses = [NZCV];
1857
1858  bits<4> cond;
1859  bits<19> target;
1860  let Inst{31-24} = 0b01010100;
1861  let Inst{23-5} = target;
1862  let Inst{4} = bit4;
1863  let Inst{3-0} = cond;
1864}
1865
1866//---
1867// Compare-and-branch instructions.
1868//---
1869class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1870    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1871         asm, "\t$Rt, $target", "",
1872         [(node regtype:$Rt, bb:$target)]>,
1873      Sched<[WriteBr]> {
1874  let isBranch = 1;
1875  let isTerminator = 1;
1876
1877  bits<5> Rt;
1878  bits<19> target;
1879  let Inst{30-25} = 0b011010;
1880  let Inst{24}    = op;
1881  let Inst{23-5}  = target;
1882  let Inst{4-0}   = Rt;
1883}
1884
1885multiclass CmpBranch<bit op, string asm, SDNode node> {
1886  def W : BaseCmpBranch<GPR32, op, asm, node> {
1887    let Inst{31} = 0;
1888  }
1889  def X : BaseCmpBranch<GPR64, op, asm, node> {
1890    let Inst{31} = 1;
1891  }
1892}
1893
1894//---
1895// Test-bit-and-branch instructions.
1896//---
1897// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1898// the target offset are implied zero and so are not part of the immediate.
1899def am_tbrcond : Operand<OtherVT> {
1900  let EncoderMethod = "getTestBranchTargetOpValue";
1901  let PrintMethod = "printAlignedLabel";
1902  let ParserMatchClass = BranchTarget14Operand;
1903  let OperandType = "OPERAND_PCREL";
1904}
1905
1906// AsmOperand classes to emit (or not) special diagnostics
1907def TBZImm0_31Operand : AsmOperandClass {
1908  let Name = "TBZImm0_31";
1909  let PredicateMethod = "isImmInRange<0,31>";
1910  let RenderMethod = "addImmOperands";
1911}
1912def TBZImm32_63Operand : AsmOperandClass {
1913  let Name = "Imm32_63";
1914  let PredicateMethod = "isImmInRange<32,63>";
1915  let DiagnosticType = "InvalidImm0_63";
1916  let RenderMethod = "addImmOperands";
1917}
1918
1919class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1920  return (((uint32_t)Imm) < 32);
1921}]> {
1922  let ParserMatchClass = matcher;
1923}
1924
1925def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1926def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1927
1928def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1929  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1930}]> {
1931  let ParserMatchClass = TBZImm32_63Operand;
1932}
1933
1934class BaseTestBranch<RegisterClass regtype, Operand immtype,
1935                     bit op, string asm, SDNode node>
1936    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1937       asm, "\t$Rt, $bit_off, $target", "",
1938       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1939      Sched<[WriteBr]> {
1940  let isBranch = 1;
1941  let isTerminator = 1;
1942
1943  bits<5> Rt;
1944  bits<6> bit_off;
1945  bits<14> target;
1946
1947  let Inst{30-25} = 0b011011;
1948  let Inst{24}    = op;
1949  let Inst{23-19} = bit_off{4-0};
1950  let Inst{18-5}  = target;
1951  let Inst{4-0}   = Rt;
1952
1953  let DecoderMethod = "DecodeTestAndBranch";
1954}
1955
1956multiclass TestBranch<bit op, string asm, SDNode node> {
1957  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1958    let Inst{31} = 0;
1959  }
1960
1961  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1962    let Inst{31} = 1;
1963  }
1964
1965  // Alias X-reg with 0-31 imm to W-Reg.
1966  def : InstAlias<asm # "\t$Rd, $imm, $target",
1967                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1968                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1969  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1970            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1971            tbz_imm0_31_diag:$imm, bb:$target)>;
1972}
1973
1974//---
1975// Unconditional branch (immediate) instructions.
1976//---
1977def am_b_target : Operand<OtherVT> {
1978  let EncoderMethod = "getBranchTargetOpValue";
1979  let PrintMethod = "printAlignedLabel";
1980  let ParserMatchClass = BranchTarget26Operand;
1981  let OperandType = "OPERAND_PCREL";
1982}
1983def am_bl_target : Operand<i64> {
1984  let EncoderMethod = "getBranchTargetOpValue";
1985  let PrintMethod = "printAlignedLabel";
1986  let ParserMatchClass = BranchTarget26Operand;
1987  let OperandType = "OPERAND_PCREL";
1988}
1989
1990class BImm<bit op, dag iops, string asm, list<dag> pattern>
1991    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1992  bits<26> addr;
1993  let Inst{31}    = op;
1994  let Inst{30-26} = 0b00101;
1995  let Inst{25-0}  = addr;
1996
1997  let DecoderMethod = "DecodeUnconditionalBranch";
1998}
1999
2000class BranchImm<bit op, string asm, list<dag> pattern>
2001    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
2002class CallImm<bit op, string asm, list<dag> pattern>
2003    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
2004
2005//---
2006// Basic one-operand data processing instructions.
2007//---
2008
2009let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2010class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
2011                         SDPatternOperator node>
2012  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
2013      [(set regtype:$Rd, (node regtype:$Rn))]>,
2014    Sched<[WriteI, ReadI]> {
2015  bits<5> Rd;
2016  bits<5> Rn;
2017
2018  let Inst{30-13} = 0b101101011000000000;
2019  let Inst{12-10} = opc;
2020  let Inst{9-5}   = Rn;
2021  let Inst{4-0}   = Rd;
2022}
2023
2024let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2025multiclass OneOperandData<bits<3> opc, string asm,
2026                          SDPatternOperator node = null_frag> {
2027  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
2028    let Inst{31} = 0;
2029  }
2030
2031  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
2032    let Inst{31} = 1;
2033  }
2034}
2035
2036class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
2037    : BaseOneOperandData<opc, GPR32, asm, node> {
2038  let Inst{31} = 0;
2039}
2040
2041class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
2042    : BaseOneOperandData<opc, GPR64, asm, node> {
2043  let Inst{31} = 1;
2044}
2045
2046class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm,
2047                      SDPatternOperator op>
2048  : I<(outs GPR64:$dst), (ins GPR64:$Rd, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
2049      "$dst = $Rd", [(set GPR64:$dst, (op GPR64:$Rd, opcode, GPR64sp:$Rn))]>,
2050    Sched<[WriteI, ReadI]> {
2051  bits<5> Rd;
2052  bits<5> Rn;
2053  let Inst{31-15} = 0b11011010110000010;
2054  let Inst{14-12} = opcode_prefix;
2055  let Inst{11-10} = opcode;
2056  let Inst{9-5} = Rn;
2057  let Inst{4-0} = Rd;
2058}
2059
2060class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm,
2061                   SDPatternOperator op>
2062  : I<(outs GPR64:$dst), (ins GPR64:$Rd), asm, "\t$Rd", "$dst = $Rd",
2063      [(set GPR64:$dst, (op GPR64:$Rd, opcode, (i64 0)))]>,
2064    Sched<[]> {
2065  bits<5> Rd;
2066  let Inst{31-15} = 0b11011010110000010;
2067  let Inst{14-12} = opcode_prefix;
2068  let Inst{11-10} = opcode;
2069  let Inst{9-5} = 0b11111;
2070  let Inst{4-0} = Rd;
2071}
2072
2073class SignAuthTwoOperand<bits<4> opc, string asm,
2074                         SDPatternOperator OpNode>
2075  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
2076      asm, "\t$Rd, $Rn, $Rm", "",
2077      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
2078    Sched<[WriteI, ReadI, ReadI]> {
2079  bits<5> Rd;
2080  bits<5> Rn;
2081  bits<5> Rm;
2082  let Inst{31-21} = 0b10011010110;
2083  let Inst{20-16} = Rm;
2084  let Inst{15-14} = 0b00;
2085  let Inst{13-10} = opc;
2086  let Inst{9-5}   = Rn;
2087  let Inst{4-0}   = Rd;
2088}
2089
2090class ClearAuth<bits<1> data, string asm>
2091  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2092  bits<5> Rd;
2093  let Inst{31-11} = 0b110110101100000101000;
2094  let Inst{10} = data;
2095  let Inst{9-5} = 0b11111;
2096  let Inst{4-0} = Rd;
2097}
2098
2099// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2100class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2101    : I<(outs), iops, asm, ops, "", []>,
2102      Sched<[WriteI, ReadI, ReadI]> {
2103  let Uses = [NZCV];
2104  let Defs = [NZCV];
2105  bits<5> Rn;
2106  let Inst{31}    = sf;
2107  let Inst{30-15} = 0b0111010000000000;
2108  let Inst{14}    = sz;
2109  let Inst{13-10} = 0b0010;
2110  let Inst{9-5}   = Rn;
2111  let Inst{4-0}   = 0b01101;
2112}
2113
2114class FlagRotate<dag iops, string asm, string ops>
2115    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2116  bits<6> imm;
2117  bits<4> mask;
2118  let Inst{20-15} = imm;
2119  let Inst{13-10} = 0b0001;
2120  let Inst{4}     = 0b0;
2121  let Inst{3-0}   = mask;
2122}
2123
2124//---
2125// Basic two-operand data processing instructions.
2126//---
2127class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2128                          list<dag> pattern>
2129    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2130        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2131      Sched<[WriteI, ReadI, ReadI]> {
2132  let Uses = [NZCV];
2133  bits<5> Rd;
2134  bits<5> Rn;
2135  bits<5> Rm;
2136  let Inst{30}    = isSub;
2137  let Inst{28-21} = 0b11010000;
2138  let Inst{20-16} = Rm;
2139  let Inst{15-10} = 0;
2140  let Inst{9-5}   = Rn;
2141  let Inst{4-0}   = Rd;
2142}
2143
2144class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2145                      SDNode OpNode>
2146    : BaseBaseAddSubCarry<isSub, regtype, asm,
2147        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2148
2149class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2150                              SDNode OpNode>
2151    : BaseBaseAddSubCarry<isSub, regtype, asm,
2152        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2153         (implicit NZCV)]> {
2154  let Defs = [NZCV];
2155}
2156
2157multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2158                       SDNode OpNode, SDNode OpNode_setflags> {
2159  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2160    let Inst{31} = 0;
2161    let Inst{29} = 0;
2162  }
2163  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2164    let Inst{31} = 1;
2165    let Inst{29} = 0;
2166  }
2167
2168  // Sets flags.
2169  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2170                                    OpNode_setflags> {
2171    let Inst{31} = 0;
2172    let Inst{29} = 1;
2173  }
2174  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2175                                    OpNode_setflags> {
2176    let Inst{31} = 1;
2177    let Inst{29} = 1;
2178  }
2179}
2180
2181class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
2182                     SDPatternOperator OpNode,
2183                     RegisterClass in1regtype = regtype,
2184                     RegisterClass in2regtype = regtype>
2185  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2186      asm, "\t$Rd, $Rn, $Rm", "",
2187      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2188  bits<5> Rd;
2189  bits<5> Rn;
2190  bits<5> Rm;
2191  let Inst{30-21} = 0b0011010110;
2192  let Inst{20-16} = Rm;
2193  let Inst{15-14} = 0b00;
2194  let Inst{13-10} = opc;
2195  let Inst{9-5}   = Rn;
2196  let Inst{4-0}   = Rd;
2197}
2198
2199class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
2200              SDPatternOperator OpNode>
2201    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
2202  let Inst{10}    = isSigned;
2203}
2204
2205multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2206  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
2207           Sched<[WriteID32, ReadID, ReadID]> {
2208    let Inst{31} = 0;
2209  }
2210  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
2211           Sched<[WriteID64, ReadID, ReadID]> {
2212    let Inst{31} = 1;
2213  }
2214}
2215
2216class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
2217                SDPatternOperator OpNode = null_frag>
2218  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
2219    Sched<[WriteIS, ReadI]> {
2220  let Inst{11-10} = shift_type;
2221}
2222
2223multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2224  def Wr : BaseShift<shift_type, GPR32, asm> {
2225    let Inst{31} = 0;
2226  }
2227
2228  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
2229    let Inst{31} = 1;
2230  }
2231
2232  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2233            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2234                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2235
2236  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2237            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2238
2239  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2240            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2241
2242  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2243            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2244
2245  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2246            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2247                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2248
2249  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2250            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2251                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2252}
2253
2254class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2255    : InstAlias<asm#"\t$dst, $src1, $src2",
2256                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2257
2258class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2259                       RegisterClass addtype, string asm,
2260                       list<dag> pattern>
2261  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2262      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2263  bits<5> Rd;
2264  bits<5> Rn;
2265  bits<5> Rm;
2266  bits<5> Ra;
2267  let Inst{30-24} = 0b0011011;
2268  let Inst{23-21} = opc;
2269  let Inst{20-16} = Rm;
2270  let Inst{15}    = isSub;
2271  let Inst{14-10} = Ra;
2272  let Inst{9-5}   = Rn;
2273  let Inst{4-0}   = Rd;
2274}
2275
2276multiclass MulAccum<bit isSub, string asm> {
2277  // MADD/MSUB generation is decided by MachineCombiner.cpp
2278  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, []>,
2279      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2280    let Inst{31} = 0;
2281  }
2282
2283  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, []>,
2284      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2285    let Inst{31} = 1;
2286  }
2287}
2288
2289class WideMulAccum<bit isSub, bits<3> opc, string asm,
2290                   SDNode AccNode, SDNode ExtNode>
2291  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2292    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2293                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2294    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2295  let Inst{31} = 1;
2296}
2297
2298class MulHi<bits<3> opc, string asm, SDNode OpNode>
2299  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2300      asm, "\t$Rd, $Rn, $Rm", "",
2301      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2302    Sched<[WriteIM64, ReadIM, ReadIM]> {
2303  bits<5> Rd;
2304  bits<5> Rn;
2305  bits<5> Rm;
2306  let Inst{31-24} = 0b10011011;
2307  let Inst{23-21} = opc;
2308  let Inst{20-16} = Rm;
2309  let Inst{15}    = 0;
2310  let Inst{9-5}   = Rn;
2311  let Inst{4-0}   = Rd;
2312
2313  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2314  // (i.e. all bits 1) but is ignored by the processor.
2315  let PostEncoderMethod = "fixMulHigh";
2316}
2317
2318class MulAccumWAlias<string asm, Instruction inst>
2319    : InstAlias<asm#"\t$dst, $src1, $src2",
2320                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2321class MulAccumXAlias<string asm, Instruction inst>
2322    : InstAlias<asm#"\t$dst, $src1, $src2",
2323                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2324class WideMulAccumAlias<string asm, Instruction inst>
2325    : InstAlias<asm#"\t$dst, $src1, $src2",
2326                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2327
2328class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2329              SDPatternOperator OpNode, string asm>
2330  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2331      asm, "\t$Rd, $Rn, $Rm", "",
2332      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2333    Sched<[WriteISReg, ReadI, ReadISReg]> {
2334  bits<5> Rd;
2335  bits<5> Rn;
2336  bits<5> Rm;
2337
2338  let Inst{31} = sf;
2339  let Inst{30-21} = 0b0011010110;
2340  let Inst{20-16} = Rm;
2341  let Inst{15-13} = 0b010;
2342  let Inst{12} = C;
2343  let Inst{11-10} = sz;
2344  let Inst{9-5} = Rn;
2345  let Inst{4-0} = Rd;
2346  let Predicates = [HasCRC];
2347}
2348
2349//---
2350// Address generation.
2351//---
2352
2353class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2354    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2355        pattern>,
2356      Sched<[WriteI]> {
2357  bits<5>  Xd;
2358  bits<21> label;
2359  let Inst{31}    = page;
2360  let Inst{30-29} = label{1-0};
2361  let Inst{28-24} = 0b10000;
2362  let Inst{23-5}  = label{20-2};
2363  let Inst{4-0}   = Xd;
2364
2365  let DecoderMethod = "DecodeAdrInstruction";
2366}
2367
2368//---
2369// Move immediate.
2370//---
2371
2372def movimm32_imm : Operand<i32> {
2373  let ParserMatchClass = AsmImmRange<0, 65535>;
2374  let EncoderMethod = "getMoveWideImmOpValue";
2375  let PrintMethod = "printImm";
2376}
2377def movimm32_shift : Operand<i32> {
2378  let PrintMethod = "printShifter";
2379  let ParserMatchClass = MovImm32ShifterOperand;
2380}
2381def movimm64_shift : Operand<i32> {
2382  let PrintMethod = "printShifter";
2383  let ParserMatchClass = MovImm64ShifterOperand;
2384}
2385
2386let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2387class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2388                        string asm>
2389  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2390       asm, "\t$Rd, $imm$shift", "", []>,
2391    Sched<[WriteImm]> {
2392  bits<5> Rd;
2393  bits<16> imm;
2394  bits<6> shift;
2395  let Inst{30-29} = opc;
2396  let Inst{28-23} = 0b100101;
2397  let Inst{22-21} = shift{5-4};
2398  let Inst{20-5}  = imm;
2399  let Inst{4-0}   = Rd;
2400
2401  let DecoderMethod = "DecodeMoveImmInstruction";
2402}
2403
2404multiclass MoveImmediate<bits<2> opc, string asm> {
2405  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2406    let Inst{31} = 0;
2407  }
2408
2409  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2410    let Inst{31} = 1;
2411  }
2412}
2413
2414let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2415class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2416                          string asm>
2417  : I<(outs regtype:$Rd),
2418      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2419       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2420    Sched<[WriteI, ReadI]> {
2421  bits<5> Rd;
2422  bits<16> imm;
2423  bits<6> shift;
2424  let Inst{30-29} = opc;
2425  let Inst{28-23} = 0b100101;
2426  let Inst{22-21} = shift{5-4};
2427  let Inst{20-5}  = imm;
2428  let Inst{4-0}   = Rd;
2429
2430  let DecoderMethod = "DecodeMoveImmInstruction";
2431}
2432
2433multiclass InsertImmediate<bits<2> opc, string asm> {
2434  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2435    let Inst{31} = 0;
2436  }
2437
2438  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2439    let Inst{31} = 1;
2440  }
2441}
2442
2443//---
2444// Add/Subtract
2445//---
2446
2447class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2448                    string asm_inst, string asm_ops,
2449                    dag inputs, dag pattern>
2450    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2451      Sched<[WriteI, ReadI]> {
2452  bits<5>  Rd;
2453  bits<5>  Rn;
2454  let Inst{30}    = isSub;
2455  let Inst{29}    = setFlags;
2456  let Inst{28-24} = 0b10001;
2457  let Inst{9-5}   = Rn;
2458  let Inst{4-0}   = Rd;
2459}
2460
2461class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2462                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2463                     string asm_inst, SDPatternOperator OpNode>
2464    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2465                    (ins srcRegtype:$Rn, immtype:$imm),
2466                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2467  bits<14> imm;
2468  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2469  let Inst{21-10} = imm{11-0};
2470  let DecoderMethod = "DecodeAddSubImmShift";
2471}
2472
2473class BaseAddSubRegPseudo<RegisterClass regtype,
2474                          SDPatternOperator OpNode>
2475    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2476             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2477      Sched<[WriteI, ReadI, ReadI]>;
2478
2479class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2480                     arith_shifted_reg shifted_regtype, string asm,
2481                     SDPatternOperator OpNode>
2482    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2483        asm, "\t$Rd, $Rn, $Rm", "",
2484        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2485      Sched<[WriteISReg, ReadI, ReadISReg]> {
2486  // The operands are in order to match the 'addr' MI operands, so we
2487  // don't need an encoder method and by-name matching. Just use the default
2488  // in-order handling. Since we're using by-order, make sure the names
2489  // do not match.
2490  bits<5> dst;
2491  bits<5> src1;
2492  bits<5> src2;
2493  bits<8> shift;
2494  let Inst{30}    = isSub;
2495  let Inst{29}    = setFlags;
2496  let Inst{28-24} = 0b01011;
2497  let Inst{23-22} = shift{7-6};
2498  let Inst{21}    = 0;
2499  let Inst{20-16} = src2;
2500  let Inst{15-10} = shift{5-0};
2501  let Inst{9-5}   = src1;
2502  let Inst{4-0}   = dst;
2503
2504  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2505}
2506
2507class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2508                     RegisterClass src1Regtype, Operand src2Regtype,
2509                     string asm, SDPatternOperator OpNode>
2510    : I<(outs dstRegtype:$R1),
2511        (ins src1Regtype:$R2, src2Regtype:$R3),
2512        asm, "\t$R1, $R2, $R3", "",
2513        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2514      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2515  bits<5> Rd;
2516  bits<5> Rn;
2517  bits<5> Rm;
2518  bits<6> ext;
2519  let Inst{30}    = isSub;
2520  let Inst{29}    = setFlags;
2521  let Inst{28-24} = 0b01011;
2522  let Inst{23-21} = 0b001;
2523  let Inst{20-16} = Rm;
2524  let Inst{15-13} = ext{5-3};
2525  let Inst{12-10} = ext{2-0};
2526  let Inst{9-5}   = Rn;
2527  let Inst{4-0}   = Rd;
2528
2529  let DecoderMethod = "DecodeAddSubERegInstruction";
2530}
2531
2532let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2533class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2534                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2535                       Operand ext_op, string asm>
2536    : I<(outs dstRegtype:$Rd),
2537        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2538        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2539      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2540  bits<5> Rd;
2541  bits<5> Rn;
2542  bits<5> Rm;
2543  bits<6> ext;
2544  let Inst{30}    = isSub;
2545  let Inst{29}    = setFlags;
2546  let Inst{28-24} = 0b01011;
2547  let Inst{23-21} = 0b001;
2548  let Inst{20-16} = Rm;
2549  let Inst{15}    = ext{5};
2550  let Inst{12-10} = ext{2-0};
2551  let Inst{9-5}   = Rn;
2552  let Inst{4-0}   = Rd;
2553
2554  let DecoderMethod = "DecodeAddSubERegInstruction";
2555}
2556
2557// Aliases for register+register add/subtract.
2558class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2559                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2560                     int shiftExt>
2561    : InstAlias<asm#"\t$dst, $src1, $src2",
2562                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2563                      shiftExt)>;
2564
2565multiclass AddSub<bit isSub, string mnemonic, string alias,
2566                  SDPatternOperator OpNode = null_frag> {
2567  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2568  // Add/Subtract immediate
2569  // Increase the weight of the immediate variant to try to match it before
2570  // the extended register variant.
2571  // We used to match the register variant before the immediate when the
2572  // register argument could be implicitly zero-extended.
2573  let AddedComplexity = 6 in
2574  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2575                           mnemonic, OpNode> {
2576    let Inst{31} = 0;
2577  }
2578  let AddedComplexity = 6 in
2579  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2580                           mnemonic, OpNode> {
2581    let Inst{31} = 1;
2582  }
2583
2584  // Add/Subtract register - Only used for CodeGen
2585  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2586  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2587
2588  // Add/Subtract shifted register
2589  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2590                           OpNode> {
2591    let Inst{31} = 0;
2592  }
2593  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2594                           OpNode> {
2595    let Inst{31} = 1;
2596  }
2597  }
2598
2599  // Add/Subtract extended register
2600  let AddedComplexity = 1, hasSideEffects = 0 in {
2601  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2602                           arith_extended_reg32_i32, mnemonic, OpNode> {
2603    let Inst{31} = 0;
2604  }
2605  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2606                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2607    let Inst{31} = 1;
2608  }
2609  }
2610
2611  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2612                               arith_extendlsl64, mnemonic> {
2613    // UXTX and SXTX only.
2614    let Inst{14-13} = 0b11;
2615    let Inst{31} = 1;
2616  }
2617
2618  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2619  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2620                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2621                      addsub_shifted_imm32_neg:$imm), 0>;
2622  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2623                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2624                       addsub_shifted_imm64_neg:$imm), 0>;
2625
2626  // Register/register aliases with no shift when SP is not used.
2627  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2628                       GPR32, GPR32, GPR32, 0>;
2629  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2630                       GPR64, GPR64, GPR64, 0>;
2631
2632  // Register/register aliases with no shift when either the destination or
2633  // first source register is SP.
2634  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2635                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2636  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2637                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2638  def : AddSubRegAlias<mnemonic,
2639                       !cast<Instruction>(NAME#"Xrx64"),
2640                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2641  def : AddSubRegAlias<mnemonic,
2642                       !cast<Instruction>(NAME#"Xrx64"),
2643                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2644}
2645
2646multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2647                   string alias, string cmpAlias> {
2648  let isCompare = 1, Defs = [NZCV] in {
2649  // Add/Subtract immediate
2650  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2651                           mnemonic, OpNode> {
2652    let Inst{31} = 0;
2653  }
2654  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2655                           mnemonic, OpNode> {
2656    let Inst{31} = 1;
2657  }
2658
2659  // Add/Subtract register
2660  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2661  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2662
2663  // Add/Subtract shifted register
2664  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2665                           OpNode> {
2666    let Inst{31} = 0;
2667  }
2668  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2669                           OpNode> {
2670    let Inst{31} = 1;
2671  }
2672
2673  // Add/Subtract extended register
2674  let AddedComplexity = 1 in {
2675  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2676                           arith_extended_reg32_i32, mnemonic, OpNode> {
2677    let Inst{31} = 0;
2678  }
2679  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2680                           arith_extended_reg32_i64, mnemonic, OpNode> {
2681    let Inst{31} = 1;
2682  }
2683  }
2684
2685  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2686                               arith_extendlsl64, mnemonic> {
2687    // UXTX and SXTX only.
2688    let Inst{14-13} = 0b11;
2689    let Inst{31} = 1;
2690  }
2691  } // Defs = [NZCV]
2692
2693  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2694  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2695                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2696                      addsub_shifted_imm32_neg:$imm), 0>;
2697  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2698                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2699                       addsub_shifted_imm64_neg:$imm), 0>;
2700
2701  // Compare aliases
2702  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2703                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2704  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2705                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2706  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2707                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2708  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2709                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2710  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2711                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2712  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2713                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2714  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2715                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2716
2717  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2718  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2719                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2720  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2721                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2722
2723  // Compare shorthands
2724  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2725                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2726  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2727                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2728  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2729                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2730  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2731                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2732
2733  // Register/register aliases with no shift when SP is not used.
2734  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2735                       GPR32, GPR32, GPR32, 0>;
2736  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2737                       GPR64, GPR64, GPR64, 0>;
2738
2739  // Register/register aliases with no shift when the first source register
2740  // is SP.
2741  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2742                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2743  def : AddSubRegAlias<mnemonic,
2744                       !cast<Instruction>(NAME#"Xrx64"),
2745                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2746}
2747
2748class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2749      : BaseAddSubImm<
2750          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2751          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2752          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2753  bits<6> imm6;
2754  bits<4> imm4;
2755  let Inst{31} = 1;
2756  let Inst{23-22} = 0b10;
2757  let Inst{21-16} = imm6;
2758  let Inst{15-14} = 0b00;
2759  let Inst{13-10} = imm4;
2760  let Unpredictable{15-14} = 0b11;
2761}
2762
2763class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2764      : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2765  let Inst{31} = 1;
2766  let Inst{29} = setsFlags;
2767}
2768
2769//---
2770// Extract
2771//---
2772def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2773                                      SDTCisPtrTy<3>]>;
2774def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2775
2776class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2777                     list<dag> patterns>
2778    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2779         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2780      Sched<[WriteExtr, ReadExtrHi]> {
2781  bits<5> Rd;
2782  bits<5> Rn;
2783  bits<5> Rm;
2784  bits<6> imm;
2785
2786  let Inst{30-23} = 0b00100111;
2787  let Inst{21}    = 0;
2788  let Inst{20-16} = Rm;
2789  let Inst{15-10} = imm;
2790  let Inst{9-5}   = Rn;
2791  let Inst{4-0}   = Rd;
2792}
2793
2794multiclass ExtractImm<string asm> {
2795  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2796                      [(set GPR32:$Rd,
2797                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2798    let Inst{31} = 0;
2799    let Inst{22} = 0;
2800    // imm<5> must be zero.
2801    let imm{5}   = 0;
2802  }
2803  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2804                      [(set GPR64:$Rd,
2805                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2806
2807    let Inst{31} = 1;
2808    let Inst{22} = 1;
2809  }
2810}
2811
2812//---
2813// Bitfield
2814//---
2815
2816let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2817class BaseBitfieldImm<bits<2> opc,
2818                      RegisterClass regtype, Operand imm_type, string asm>
2819    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2820         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2821      Sched<[WriteIS, ReadI]> {
2822  bits<5> Rd;
2823  bits<5> Rn;
2824  bits<6> immr;
2825  bits<6> imms;
2826
2827  let Inst{30-29} = opc;
2828  let Inst{28-23} = 0b100110;
2829  let Inst{21-16} = immr;
2830  let Inst{15-10} = imms;
2831  let Inst{9-5}   = Rn;
2832  let Inst{4-0}   = Rd;
2833}
2834
2835multiclass BitfieldImm<bits<2> opc, string asm> {
2836  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2837    let Inst{31} = 0;
2838    let Inst{22} = 0;
2839    // imms<5> and immr<5> must be zero, else ReservedValue().
2840    let Inst{21} = 0;
2841    let Inst{15} = 0;
2842  }
2843  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2844    let Inst{31} = 1;
2845    let Inst{22} = 1;
2846  }
2847}
2848
2849let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2850class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2851                      RegisterClass regtype, Operand imm_type, string asm>
2852    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2853                             imm_type:$imms),
2854         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2855      Sched<[WriteIS, ReadI]> {
2856  bits<5> Rd;
2857  bits<5> Rn;
2858  bits<6> immr;
2859  bits<6> imms;
2860
2861  let Inst{30-29} = opc;
2862  let Inst{28-23} = 0b100110;
2863  let Inst{21-16} = immr;
2864  let Inst{15-10} = imms;
2865  let Inst{9-5}   = Rn;
2866  let Inst{4-0}   = Rd;
2867}
2868
2869multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2870  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2871    let Inst{31} = 0;
2872    let Inst{22} = 0;
2873    // imms<5> and immr<5> must be zero, else ReservedValue().
2874    let Inst{21} = 0;
2875    let Inst{15} = 0;
2876  }
2877  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2878    let Inst{31} = 1;
2879    let Inst{22} = 1;
2880  }
2881}
2882
2883//---
2884// Logical
2885//---
2886
2887// Logical (immediate)
2888class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2889                     RegisterClass sregtype, Operand imm_type, string asm,
2890                     list<dag> pattern>
2891    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2892         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2893      Sched<[WriteI, ReadI]> {
2894  bits<5>  Rd;
2895  bits<5>  Rn;
2896  bits<13> imm;
2897  let Inst{30-29} = opc;
2898  let Inst{28-23} = 0b100100;
2899  let Inst{22}    = imm{12};
2900  let Inst{21-16} = imm{11-6};
2901  let Inst{15-10} = imm{5-0};
2902  let Inst{9-5}   = Rn;
2903  let Inst{4-0}   = Rd;
2904
2905  let DecoderMethod = "DecodeLogicalImmInstruction";
2906}
2907
2908// Logical (shifted register)
2909class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2910                      logical_shifted_reg shifted_regtype, string asm,
2911                      list<dag> pattern>
2912    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2913        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2914      Sched<[WriteISReg, ReadI, ReadISReg]> {
2915  // The operands are in order to match the 'addr' MI operands, so we
2916  // don't need an encoder method and by-name matching. Just use the default
2917  // in-order handling. Since we're using by-order, make sure the names
2918  // do not match.
2919  bits<5> dst;
2920  bits<5> src1;
2921  bits<5> src2;
2922  bits<8> shift;
2923  let Inst{30-29} = opc;
2924  let Inst{28-24} = 0b01010;
2925  let Inst{23-22} = shift{7-6};
2926  let Inst{21}    = N;
2927  let Inst{20-16} = src2;
2928  let Inst{15-10} = shift{5-0};
2929  let Inst{9-5}   = src1;
2930  let Inst{4-0}   = dst;
2931
2932  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2933}
2934
2935// Aliases for register+register logical instructions.
2936class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2937    : InstAlias<asm#"\t$dst, $src1, $src2",
2938                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2939
2940multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2941                      string Alias> {
2942  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2943  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2944                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2945                                               logical_imm32:$imm))]> {
2946    let Inst{31} = 0;
2947    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2948  }
2949  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2950  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2951                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2952                                               logical_imm64:$imm))]> {
2953    let Inst{31} = 1;
2954  }
2955
2956  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2957                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2958                      logical_imm32_not:$imm), 0>;
2959  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2960                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2961                       logical_imm64_not:$imm), 0>;
2962}
2963
2964multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2965                       string Alias> {
2966  let isCompare = 1, Defs = [NZCV] in {
2967  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2968      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2969    let Inst{31} = 0;
2970    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2971  }
2972  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2973      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2974    let Inst{31} = 1;
2975  }
2976  } // end Defs = [NZCV]
2977
2978  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2979                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2980                      logical_imm32_not:$imm), 0>;
2981  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2982                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2983                       logical_imm64_not:$imm), 0>;
2984}
2985
2986class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2987    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2988             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2989      Sched<[WriteI, ReadI, ReadI]>;
2990
2991// Split from LogicalImm as not all instructions have both.
2992multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2993                      SDPatternOperator OpNode> {
2994  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2995  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2996  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2997  }
2998
2999  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3000                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
3001                                                 logical_shifted_reg32:$Rm))]> {
3002    let Inst{31} = 0;
3003  }
3004  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3005                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
3006                                                 logical_shifted_reg64:$Rm))]> {
3007    let Inst{31} = 1;
3008  }
3009
3010  def : LogicalRegAlias<mnemonic,
3011                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3012  def : LogicalRegAlias<mnemonic,
3013                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3014}
3015
3016// Split from LogicalReg to allow setting NZCV Defs
3017multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
3018                       SDPatternOperator OpNode = null_frag> {
3019  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
3020  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3021  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3022
3023  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3024            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
3025    let Inst{31} = 0;
3026  }
3027  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3028            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
3029    let Inst{31} = 1;
3030  }
3031  } // Defs = [NZCV]
3032
3033  def : LogicalRegAlias<mnemonic,
3034                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3035  def : LogicalRegAlias<mnemonic,
3036                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3037}
3038
3039//---
3040// Conditionally set flags
3041//---
3042
3043let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3044class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3045                            string mnemonic, SDNode OpNode>
3046    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3047         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3048         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3049                             (i32 imm:$cond), NZCV))]>,
3050      Sched<[WriteI, ReadI]> {
3051  let Uses = [NZCV];
3052  let Defs = [NZCV];
3053
3054  bits<5> Rn;
3055  bits<5> imm;
3056  bits<4> nzcv;
3057  bits<4> cond;
3058
3059  let Inst{30}    = op;
3060  let Inst{29-21} = 0b111010010;
3061  let Inst{20-16} = imm;
3062  let Inst{15-12} = cond;
3063  let Inst{11-10} = 0b10;
3064  let Inst{9-5}   = Rn;
3065  let Inst{4}     = 0b0;
3066  let Inst{3-0}   = nzcv;
3067}
3068
3069let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3070class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3071                            SDNode OpNode>
3072    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3073         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3074         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3075                             (i32 imm:$cond), NZCV))]>,
3076      Sched<[WriteI, ReadI, ReadI]> {
3077  let Uses = [NZCV];
3078  let Defs = [NZCV];
3079
3080  bits<5> Rn;
3081  bits<5> Rm;
3082  bits<4> nzcv;
3083  bits<4> cond;
3084
3085  let Inst{30}    = op;
3086  let Inst{29-21} = 0b111010010;
3087  let Inst{20-16} = Rm;
3088  let Inst{15-12} = cond;
3089  let Inst{11-10} = 0b00;
3090  let Inst{9-5}   = Rn;
3091  let Inst{4}     = 0b0;
3092  let Inst{3-0}   = nzcv;
3093}
3094
3095multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3096  // immediate operand variants
3097  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3098    let Inst{31} = 0;
3099  }
3100  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3101    let Inst{31} = 1;
3102  }
3103  // register operand variants
3104  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3105    let Inst{31} = 0;
3106  }
3107  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3108    let Inst{31} = 1;
3109  }
3110}
3111
3112//---
3113// Conditional select
3114//---
3115
3116class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3117    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3118         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3119         [(set regtype:$Rd,
3120               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3121      Sched<[WriteI, ReadI, ReadI]> {
3122  let Uses = [NZCV];
3123
3124  bits<5> Rd;
3125  bits<5> Rn;
3126  bits<5> Rm;
3127  bits<4> cond;
3128
3129  let Inst{30}    = op;
3130  let Inst{29-21} = 0b011010100;
3131  let Inst{20-16} = Rm;
3132  let Inst{15-12} = cond;
3133  let Inst{11-10} = op2;
3134  let Inst{9-5}   = Rn;
3135  let Inst{4-0}   = Rd;
3136}
3137
3138multiclass CondSelect<bit op, bits<2> op2, string asm> {
3139  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3140    let Inst{31} = 0;
3141  }
3142  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3143    let Inst{31} = 1;
3144  }
3145}
3146
3147class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3148                       PatFrag frag>
3149    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3150         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3151         [(set regtype:$Rd,
3152               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3153               (i32 imm:$cond), NZCV))]>,
3154      Sched<[WriteI, ReadI, ReadI]> {
3155  let Uses = [NZCV];
3156
3157  bits<5> Rd;
3158  bits<5> Rn;
3159  bits<5> Rm;
3160  bits<4> cond;
3161
3162  let Inst{30}    = op;
3163  let Inst{29-21} = 0b011010100;
3164  let Inst{20-16} = Rm;
3165  let Inst{15-12} = cond;
3166  let Inst{11-10} = op2;
3167  let Inst{9-5}   = Rn;
3168  let Inst{4-0}   = Rd;
3169}
3170
3171def inv_cond_XFORM : SDNodeXForm<imm, [{
3172  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3173  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3174                                   MVT::i32);
3175}]>;
3176
3177multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3178  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3179    let Inst{31} = 0;
3180  }
3181  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3182    let Inst{31} = 1;
3183  }
3184
3185  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3186            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3187                                           (inv_cond_XFORM imm:$cond))>;
3188
3189  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3190            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3191                                           (inv_cond_XFORM imm:$cond))>;
3192}
3193
3194//---
3195// Special Mask Value
3196//---
3197def maski8_or_more : Operand<i32>,
3198  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3199}
3200def maski16_or_more : Operand<i32>,
3201  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3202}
3203
3204
3205//---
3206// Load/store
3207//---
3208
3209// (unsigned immediate)
3210// Indexed for 8-bit registers. offset is in range [0,4095].
3211def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3212def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3213def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3214def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3215def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3216
3217// (unsigned immediate)
3218// Indexed for 8-bit registers. offset is in range [0,63].
3219def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3220def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3221def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3222def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3223
3224def gi_am_indexed8 :
3225    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3226    GIComplexPatternEquiv<am_indexed8>;
3227def gi_am_indexed16 :
3228    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3229    GIComplexPatternEquiv<am_indexed16>;
3230def gi_am_indexed32 :
3231    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3232    GIComplexPatternEquiv<am_indexed32>;
3233def gi_am_indexed64 :
3234    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3235    GIComplexPatternEquiv<am_indexed64>;
3236def gi_am_indexed128 :
3237    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3238    GIComplexPatternEquiv<am_indexed128>;
3239
3240class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3241  let Name = "UImm12Offset" # Scale;
3242  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3243  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3244  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3245}
3246
3247def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3248def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3249def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3250def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3251def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3252
3253class uimm12_scaled<int Scale> : Operand<i64> {
3254  let ParserMatchClass
3255   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3256  let EncoderMethod
3257   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3258  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3259}
3260
3261def uimm12s1 : uimm12_scaled<1>;
3262def uimm12s2 : uimm12_scaled<2>;
3263def uimm12s4 : uimm12_scaled<4>;
3264def uimm12s8 : uimm12_scaled<8>;
3265def uimm12s16 : uimm12_scaled<16>;
3266
3267class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3268                      string asm, list<dag> pattern>
3269    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3270  bits<5> Rt;
3271
3272  bits<5> Rn;
3273  bits<12> offset;
3274
3275  let Inst{31-30} = sz;
3276  let Inst{29-27} = 0b111;
3277  let Inst{26}    = V;
3278  let Inst{25-24} = 0b01;
3279  let Inst{23-22} = opc;
3280  let Inst{21-10} = offset;
3281  let Inst{9-5}   = Rn;
3282  let Inst{4-0}   = Rt;
3283
3284  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3285}
3286
3287multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3288                  Operand indextype, string asm, list<dag> pattern> {
3289  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3290  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3291                           (ins GPR64sp:$Rn, indextype:$offset),
3292                           asm, pattern>,
3293           Sched<[WriteLD]>;
3294
3295  def : InstAlias<asm # "\t$Rt, [$Rn]",
3296                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3297}
3298
3299multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3300             Operand indextype, string asm, list<dag> pattern> {
3301  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3302  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3303                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3304                           asm, pattern>,
3305           Sched<[WriteST]>;
3306
3307  def : InstAlias<asm # "\t$Rt, [$Rn]",
3308                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3309}
3310
3311// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3312// substitute zero-registers automatically.
3313//
3314// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3315//       into StoreUI.
3316multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3317             Operand indextype, string asm, list<dag> pattern> {
3318  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3319  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3320                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3321                           asm, pattern>,
3322           Sched<[WriteST]>;
3323
3324  def : InstAlias<asm # "\t$Rt, [$Rn]",
3325                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3326}
3327
3328def PrefetchOperand : AsmOperandClass {
3329  let Name = "Prefetch";
3330  let ParserMethod = "tryParsePrefetch";
3331}
3332def prfop : Operand<i32> {
3333  let PrintMethod = "printPrefetchOp";
3334  let ParserMatchClass = PrefetchOperand;
3335}
3336
3337let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3338class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3339    : BaseLoadStoreUI<sz, V, opc,
3340                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3341                      asm, pat>,
3342      Sched<[WriteLD]>;
3343
3344//---
3345// Load literal
3346//---
3347
3348// Load literal address: 19-bit immediate. The low two bits of the target
3349// offset are implied zero and so are not part of the immediate.
3350def am_ldrlit : Operand<iPTR> {
3351  let EncoderMethod = "getLoadLiteralOpValue";
3352  let DecoderMethod = "DecodePCRelLabel19";
3353  let PrintMethod = "printAlignedLabel";
3354  let ParserMatchClass = PCRelLabel19Operand;
3355  let OperandType = "OPERAND_PCREL";
3356}
3357
3358let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3359class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3360    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3361        asm, "\t$Rt, $label", "", pat>,
3362      Sched<[WriteLD]> {
3363  bits<5> Rt;
3364  bits<19> label;
3365  let Inst{31-30} = opc;
3366  let Inst{29-27} = 0b011;
3367  let Inst{26}    = V;
3368  let Inst{25-24} = 0b00;
3369  let Inst{23-5}  = label;
3370  let Inst{4-0}   = Rt;
3371}
3372
3373let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3374class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3375    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3376        asm, "\t$Rt, $label", "", pat>,
3377      Sched<[WriteLD]> {
3378  bits<5> Rt;
3379  bits<19> label;
3380  let Inst{31-30} = opc;
3381  let Inst{29-27} = 0b011;
3382  let Inst{26}    = V;
3383  let Inst{25-24} = 0b00;
3384  let Inst{23-5}  = label;
3385  let Inst{4-0}   = Rt;
3386}
3387
3388//---
3389// Load/store register offset
3390//---
3391
3392def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3393def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3394def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3395def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3396def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3397
3398def gi_ro_Xindexed8 :
3399    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3400    GIComplexPatternEquiv<ro_Xindexed8>;
3401def gi_ro_Xindexed16 :
3402    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3403    GIComplexPatternEquiv<ro_Xindexed16>;
3404def gi_ro_Xindexed32 :
3405    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3406    GIComplexPatternEquiv<ro_Xindexed32>;
3407def gi_ro_Xindexed64 :
3408    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3409    GIComplexPatternEquiv<ro_Xindexed64>;
3410def gi_ro_Xindexed128 :
3411    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3412    GIComplexPatternEquiv<ro_Xindexed128>;
3413
3414def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3415def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3416def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3417def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3418def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3419
3420def gi_ro_Windexed8 :
3421    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3422    GIComplexPatternEquiv<ro_Windexed8>;
3423def gi_ro_Windexed16 :
3424    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3425    GIComplexPatternEquiv<ro_Windexed16>;
3426def gi_ro_Windexed32 :
3427    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3428    GIComplexPatternEquiv<ro_Windexed32>;
3429def gi_ro_Windexed64 :
3430    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3431    GIComplexPatternEquiv<ro_Windexed64>;
3432def gi_ro_Windexed128 :
3433    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3434    GIComplexPatternEquiv<ro_Windexed128>;
3435
3436class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3437  let Name = "Mem" # Reg # "Extend" # Width;
3438  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3439  let RenderMethod = "addMemExtendOperands";
3440  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3441}
3442
3443def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3444  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3445  // the trivial shift.
3446  let RenderMethod = "addMemExtend8Operands";
3447}
3448def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3449def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3450def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3451def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3452
3453def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3454  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3455  // the trivial shift.
3456  let RenderMethod = "addMemExtend8Operands";
3457}
3458def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3459def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3460def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3461def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3462
3463class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3464        : Operand<i32> {
3465  let ParserMatchClass = ParserClass;
3466  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3467  let DecoderMethod = "DecodeMemExtend";
3468  let EncoderMethod = "getMemExtendOpValue";
3469  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3470}
3471
3472def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3473def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3474def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3475def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3476def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3477
3478def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3479def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3480def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3481def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3482def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3483
3484class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3485                  Operand wextend, Operand xextend>  {
3486  // CodeGen-level pattern covering the entire addressing mode.
3487  ComplexPattern Wpat = windex;
3488  ComplexPattern Xpat = xindex;
3489
3490  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3491  Operand Wext = wextend;
3492  Operand Xext = xextend;
3493}
3494
3495def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3496def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3497def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3498def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3499def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3500                       ro_Xextend128>;
3501
3502class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3503                   dag outs, list<dag> pat>
3504    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3505  bits<5> Rt;
3506  bits<5> Rn;
3507  bits<5> Rm;
3508  bits<2> extend;
3509  let Inst{31-30} = sz;
3510  let Inst{29-27} = 0b111;
3511  let Inst{26}    = V;
3512  let Inst{25-24} = 0b00;
3513  let Inst{23-22} = opc;
3514  let Inst{21}    = 1;
3515  let Inst{20-16} = Rm;
3516  let Inst{15}    = extend{1}; // sign extend Rm?
3517  let Inst{14}    = 1;
3518  let Inst{12}    = extend{0}; // do shift?
3519  let Inst{11-10} = 0b10;
3520  let Inst{9-5}   = Rn;
3521  let Inst{4-0}   = Rt;
3522}
3523
3524class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3525  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3526              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3527
3528multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3529                   string asm, ValueType Ty, SDPatternOperator loadop> {
3530  let AddedComplexity = 10 in
3531  def roW : LoadStore8RO<sz, V, opc, asm,
3532                 (outs regtype:$Rt),
3533                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3534                 [(set (Ty regtype:$Rt),
3535                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3536                                             ro_Wextend8:$extend)))]>,
3537           Sched<[WriteLDIdx, ReadAdrBase]> {
3538    let Inst{13} = 0b0;
3539  }
3540
3541  let AddedComplexity = 10 in
3542  def roX : LoadStore8RO<sz, V, opc, asm,
3543                 (outs regtype:$Rt),
3544                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3545                 [(set (Ty regtype:$Rt),
3546                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3547                                             ro_Xextend8:$extend)))]>,
3548           Sched<[WriteLDIdx, ReadAdrBase]> {
3549    let Inst{13} = 0b1;
3550  }
3551
3552  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3553}
3554
3555multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3556                    string asm, ValueType Ty, SDPatternOperator storeop> {
3557  let AddedComplexity = 10 in
3558  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
3559                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3560                 [(storeop (Ty regtype:$Rt),
3561                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3562                                         ro_Wextend8:$extend))]>,
3563            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3564    let Inst{13} = 0b0;
3565  }
3566
3567  let AddedComplexity = 10 in
3568  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
3569                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3570                 [(storeop (Ty regtype:$Rt),
3571                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3572                                         ro_Xextend8:$extend))]>,
3573            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3574    let Inst{13} = 0b1;
3575  }
3576
3577  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3578}
3579
3580class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3581                    dag outs, list<dag> pat>
3582    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3583  bits<5> Rt;
3584  bits<5> Rn;
3585  bits<5> Rm;
3586  bits<2> extend;
3587  let Inst{31-30} = sz;
3588  let Inst{29-27} = 0b111;
3589  let Inst{26}    = V;
3590  let Inst{25-24} = 0b00;
3591  let Inst{23-22} = opc;
3592  let Inst{21}    = 1;
3593  let Inst{20-16} = Rm;
3594  let Inst{15}    = extend{1}; // sign extend Rm?
3595  let Inst{14}    = 1;
3596  let Inst{12}    = extend{0}; // do shift?
3597  let Inst{11-10} = 0b10;
3598  let Inst{9-5}   = Rn;
3599  let Inst{4-0}   = Rt;
3600}
3601
3602multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3603                    string asm, ValueType Ty, SDPatternOperator loadop> {
3604  let AddedComplexity = 10 in
3605  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3606                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3607                 [(set (Ty regtype:$Rt),
3608                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3609                                              ro_Wextend16:$extend)))]>,
3610            Sched<[WriteLDIdx, ReadAdrBase]> {
3611    let Inst{13} = 0b0;
3612  }
3613
3614  let AddedComplexity = 10 in
3615  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3616                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3617                 [(set (Ty regtype:$Rt),
3618                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3619                                             ro_Xextend16:$extend)))]>,
3620            Sched<[WriteLDIdx, ReadAdrBase]> {
3621    let Inst{13} = 0b1;
3622  }
3623
3624  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3625}
3626
3627multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3628                     string asm, ValueType Ty, SDPatternOperator storeop> {
3629  let AddedComplexity = 10 in
3630  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
3631                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3632                [(storeop (Ty regtype:$Rt),
3633                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3634                                         ro_Wextend16:$extend))]>,
3635           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3636    let Inst{13} = 0b0;
3637  }
3638
3639  let AddedComplexity = 10 in
3640  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
3641                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3642                [(storeop (Ty regtype:$Rt),
3643                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3644                                         ro_Xextend16:$extend))]>,
3645           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3646    let Inst{13} = 0b1;
3647  }
3648
3649  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3650}
3651
3652class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3653                    dag outs, list<dag> pat>
3654    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3655  bits<5> Rt;
3656  bits<5> Rn;
3657  bits<5> Rm;
3658  bits<2> extend;
3659  let Inst{31-30} = sz;
3660  let Inst{29-27} = 0b111;
3661  let Inst{26}    = V;
3662  let Inst{25-24} = 0b00;
3663  let Inst{23-22} = opc;
3664  let Inst{21}    = 1;
3665  let Inst{20-16} = Rm;
3666  let Inst{15}    = extend{1}; // sign extend Rm?
3667  let Inst{14}    = 1;
3668  let Inst{12}    = extend{0}; // do shift?
3669  let Inst{11-10} = 0b10;
3670  let Inst{9-5}   = Rn;
3671  let Inst{4-0}   = Rt;
3672}
3673
3674multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3675                    string asm, ValueType Ty, SDPatternOperator loadop> {
3676  let AddedComplexity = 10 in
3677  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3678                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3679                 [(set (Ty regtype:$Rt),
3680                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3681                                              ro_Wextend32:$extend)))]>,
3682           Sched<[WriteLDIdx, ReadAdrBase]> {
3683    let Inst{13} = 0b0;
3684  }
3685
3686  let AddedComplexity = 10 in
3687  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3688                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3689                 [(set (Ty regtype:$Rt),
3690                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3691                                              ro_Xextend32:$extend)))]>,
3692           Sched<[WriteLDIdx, ReadAdrBase]> {
3693    let Inst{13} = 0b1;
3694  }
3695
3696  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3697}
3698
3699multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3700                     string asm, ValueType Ty, SDPatternOperator storeop> {
3701  let AddedComplexity = 10 in
3702  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
3703                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3704                [(storeop (Ty regtype:$Rt),
3705                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3706                                         ro_Wextend32:$extend))]>,
3707            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3708    let Inst{13} = 0b0;
3709  }
3710
3711  let AddedComplexity = 10 in
3712  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
3713                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3714                [(storeop (Ty regtype:$Rt),
3715                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3716                                        ro_Xextend32:$extend))]>,
3717            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3718    let Inst{13} = 0b1;
3719  }
3720
3721  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3722}
3723
3724class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3725                    dag outs, list<dag> pat>
3726    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3727  bits<5> Rt;
3728  bits<5> Rn;
3729  bits<5> Rm;
3730  bits<2> extend;
3731  let Inst{31-30} = sz;
3732  let Inst{29-27} = 0b111;
3733  let Inst{26}    = V;
3734  let Inst{25-24} = 0b00;
3735  let Inst{23-22} = opc;
3736  let Inst{21}    = 1;
3737  let Inst{20-16} = Rm;
3738  let Inst{15}    = extend{1}; // sign extend Rm?
3739  let Inst{14}    = 1;
3740  let Inst{12}    = extend{0}; // do shift?
3741  let Inst{11-10} = 0b10;
3742  let Inst{9-5}   = Rn;
3743  let Inst{4-0}   = Rt;
3744}
3745
3746multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3747                    string asm, ValueType Ty, SDPatternOperator loadop> {
3748  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3749  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3750                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3751                [(set (Ty regtype:$Rt),
3752                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3753                                             ro_Wextend64:$extend)))]>,
3754           Sched<[WriteLDIdx, ReadAdrBase]> {
3755    let Inst{13} = 0b0;
3756  }
3757
3758  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3759  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3760                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3761                 [(set (Ty regtype:$Rt),
3762                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3763                                              ro_Xextend64:$extend)))]>,
3764           Sched<[WriteLDIdx, ReadAdrBase]> {
3765    let Inst{13} = 0b1;
3766  }
3767
3768  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3769}
3770
3771multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3772                     string asm, ValueType Ty, SDPatternOperator storeop> {
3773  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3774  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
3775                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3776                [(storeop (Ty regtype:$Rt),
3777                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3778                                         ro_Wextend64:$extend))]>,
3779            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3780    let Inst{13} = 0b0;
3781  }
3782
3783  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3784  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
3785                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3786                [(storeop (Ty regtype:$Rt),
3787                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3788                                         ro_Xextend64:$extend))]>,
3789            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3790    let Inst{13} = 0b1;
3791  }
3792
3793  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3794}
3795
3796class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3797                     dag outs, list<dag> pat>
3798    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3799  bits<5> Rt;
3800  bits<5> Rn;
3801  bits<5> Rm;
3802  bits<2> extend;
3803  let Inst{31-30} = sz;
3804  let Inst{29-27} = 0b111;
3805  let Inst{26}    = V;
3806  let Inst{25-24} = 0b00;
3807  let Inst{23-22} = opc;
3808  let Inst{21}    = 1;
3809  let Inst{20-16} = Rm;
3810  let Inst{15}    = extend{1}; // sign extend Rm?
3811  let Inst{14}    = 1;
3812  let Inst{12}    = extend{0}; // do shift?
3813  let Inst{11-10} = 0b10;
3814  let Inst{9-5}   = Rn;
3815  let Inst{4-0}   = Rt;
3816}
3817
3818multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3819                     string asm, ValueType Ty, SDPatternOperator loadop> {
3820  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3821  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3822                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3823                 [(set (Ty regtype:$Rt),
3824                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3825                                               ro_Wextend128:$extend)))]>,
3826            Sched<[WriteLDIdx, ReadAdrBase]> {
3827    let Inst{13} = 0b0;
3828  }
3829
3830  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3831  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3832                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3833                 [(set (Ty regtype:$Rt),
3834                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3835                                               ro_Xextend128:$extend)))]>,
3836            Sched<[WriteLDIdx, ReadAdrBase]> {
3837    let Inst{13} = 0b1;
3838  }
3839
3840  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3841}
3842
3843multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3844                      string asm> {
3845  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3846  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
3847               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3848                []>,
3849            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3850    let Inst{13} = 0b0;
3851  }
3852
3853  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3854  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
3855               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3856                []>,
3857            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3858    let Inst{13} = 0b1;
3859  }
3860
3861  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3862}
3863
3864let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3865class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3866                     string asm, list<dag> pat>
3867    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3868      Sched<[WriteLD]> {
3869  bits<5> Rt;
3870  bits<5> Rn;
3871  bits<5> Rm;
3872  bits<2> extend;
3873  let Inst{31-30} = sz;
3874  let Inst{29-27} = 0b111;
3875  let Inst{26}    = V;
3876  let Inst{25-24} = 0b00;
3877  let Inst{23-22} = opc;
3878  let Inst{21}    = 1;
3879  let Inst{20-16} = Rm;
3880  let Inst{15}    = extend{1}; // sign extend Rm?
3881  let Inst{14}    = 1;
3882  let Inst{12}    = extend{0}; // do shift?
3883  let Inst{11-10} = 0b10;
3884  let Inst{9-5}   = Rn;
3885  let Inst{4-0}   = Rt;
3886}
3887
3888multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3889  def roW : BasePrefetchRO<sz, V, opc, (outs),
3890                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3891                asm, [(AArch64Prefetch imm:$Rt,
3892                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3893                                                    ro_Wextend64:$extend))]> {
3894    let Inst{13} = 0b0;
3895  }
3896
3897  def roX : BasePrefetchRO<sz, V, opc, (outs),
3898                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3899                asm,  [(AArch64Prefetch imm:$Rt,
3900                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3901                                                     ro_Xextend64:$extend))]> {
3902    let Inst{13} = 0b1;
3903  }
3904
3905  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3906               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3907                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3908}
3909
3910//---
3911// Load/store unscaled immediate
3912//---
3913
3914def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
3915def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
3916def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
3917def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
3918def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
3919
3920def gi_am_unscaled8 :
3921    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3922    GIComplexPatternEquiv<am_unscaled8>;
3923def gi_am_unscaled16 :
3924    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3925    GIComplexPatternEquiv<am_unscaled16>;
3926def gi_am_unscaled32 :
3927    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3928    GIComplexPatternEquiv<am_unscaled32>;
3929def gi_am_unscaled64 :
3930    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3931    GIComplexPatternEquiv<am_unscaled64>;
3932def gi_am_unscaled128 :
3933    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3934    GIComplexPatternEquiv<am_unscaled128>;
3935
3936
3937class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3938                           string asm, list<dag> pattern>
3939    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3940  bits<5> Rt;
3941  bits<5> Rn;
3942  bits<9> offset;
3943  let Inst{31-30} = sz;
3944  let Inst{29-27} = 0b111;
3945  let Inst{26}    = V;
3946  let Inst{25-24} = 0b00;
3947  let Inst{23-22} = opc;
3948  let Inst{21}    = 0;
3949  let Inst{20-12} = offset;
3950  let Inst{11-10} = 0b00;
3951  let Inst{9-5}   = Rn;
3952  let Inst{4-0}   = Rt;
3953
3954  let DecoderMethod = "DecodeSignedLdStInstruction";
3955}
3956
3957// Armv8.4 LDAPR & STLR with Immediate Offset instruction
3958multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3959                              DAGOperand regtype > {
3960  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3961                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3962          Sched<[WriteST]> {
3963    let Inst{29} = 0;
3964    let Inst{24} = 1;
3965  }
3966  def : InstAlias<asm # "\t$Rt, [$Rn]",
3967                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3968}
3969
3970multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3971                               DAGOperand regtype > {
3972  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3973                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3974                               asm, []>,
3975          Sched<[WriteST]> {
3976    let Inst{29} = 0;
3977    let Inst{24} = 1;
3978  }
3979  def : InstAlias<asm # "\t$Rt, [$Rn]",
3980                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3981}
3982
3983multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3984                   string asm, list<dag> pattern> {
3985  let AddedComplexity = 1 in // try this before LoadUI
3986  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3987                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3988          Sched<[WriteLD]>;
3989
3990  def : InstAlias<asm # "\t$Rt, [$Rn]",
3991                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3992}
3993
3994multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3995                         string asm, list<dag> pattern> {
3996  let AddedComplexity = 1 in // try this before StoreUI
3997  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3998                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3999                               asm, pattern>,
4000          Sched<[WriteST]>;
4001
4002  def : InstAlias<asm # "\t$Rt, [$Rn]",
4003                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4004}
4005
4006multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
4007                            list<dag> pat> {
4008  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4009  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4010                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
4011                               asm, pat>,
4012          Sched<[WriteLD]>;
4013
4014  def : InstAlias<asm # "\t$Rt, [$Rn]",
4015                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
4016}
4017
4018//---
4019// Load/store unscaled immediate, unprivileged
4020//---
4021
4022class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4023                                dag oops, dag iops, string asm>
4024    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
4025  bits<5> Rt;
4026  bits<5> Rn;
4027  bits<9> offset;
4028  let Inst{31-30} = sz;
4029  let Inst{29-27} = 0b111;
4030  let Inst{26}    = V;
4031  let Inst{25-24} = 0b00;
4032  let Inst{23-22} = opc;
4033  let Inst{21}    = 0;
4034  let Inst{20-12} = offset;
4035  let Inst{11-10} = 0b10;
4036  let Inst{9-5}   = Rn;
4037  let Inst{4-0}   = Rt;
4038
4039  let DecoderMethod = "DecodeSignedLdStInstruction";
4040}
4041
4042multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4043                            RegisterClass regtype, string asm> {
4044  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4045  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4046                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4047          Sched<[WriteLD]>;
4048
4049  def : InstAlias<asm # "\t$Rt, [$Rn]",
4050                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4051}
4052
4053multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4054                             RegisterClass regtype, string asm> {
4055  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4056  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4057                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4058                                 asm>,
4059          Sched<[WriteST]>;
4060
4061  def : InstAlias<asm # "\t$Rt, [$Rn]",
4062                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4063}
4064
4065//---
4066// Load/store pre-indexed
4067//---
4068
4069class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4070                          string asm, string cstr, list<dag> pat>
4071    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4072  bits<5> Rt;
4073  bits<5> Rn;
4074  bits<9> offset;
4075  let Inst{31-30} = sz;
4076  let Inst{29-27} = 0b111;
4077  let Inst{26}    = V;
4078  let Inst{25-24} = 0;
4079  let Inst{23-22} = opc;
4080  let Inst{21}    = 0;
4081  let Inst{20-12} = offset;
4082  let Inst{11-10} = 0b11;
4083  let Inst{9-5}   = Rn;
4084  let Inst{4-0}   = Rt;
4085
4086  let DecoderMethod = "DecodeSignedLdStInstruction";
4087}
4088
4089let hasSideEffects = 0 in {
4090let mayStore = 0, mayLoad = 1 in
4091class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4092             string asm>
4093    : BaseLoadStorePreIdx<sz, V, opc,
4094                     (outs GPR64sp:$wback, regtype:$Rt),
4095                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4096                     "$Rn = $wback,@earlyclobber $wback", []>,
4097      Sched<[WriteAdr, WriteLD]>;
4098
4099let mayStore = 1, mayLoad = 0 in
4100class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4101                  string asm, SDPatternOperator storeop, ValueType Ty>
4102    : BaseLoadStorePreIdx<sz, V, opc,
4103                      (outs GPR64sp:$wback),
4104                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4105                      asm, "$Rn = $wback,@earlyclobber $wback",
4106      [(set GPR64sp:$wback,
4107            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4108      Sched<[WriteAdr, WriteST]>;
4109} // hasSideEffects = 0
4110
4111//---
4112// Load/store post-indexed
4113//---
4114
4115class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4116                          string asm, string cstr, list<dag> pat>
4117    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4118  bits<5> Rt;
4119  bits<5> Rn;
4120  bits<9> offset;
4121  let Inst{31-30} = sz;
4122  let Inst{29-27} = 0b111;
4123  let Inst{26}    = V;
4124  let Inst{25-24} = 0b00;
4125  let Inst{23-22} = opc;
4126  let Inst{21}    = 0b0;
4127  let Inst{20-12} = offset;
4128  let Inst{11-10} = 0b01;
4129  let Inst{9-5}   = Rn;
4130  let Inst{4-0}   = Rt;
4131
4132  let DecoderMethod = "DecodeSignedLdStInstruction";
4133}
4134
4135let hasSideEffects = 0 in {
4136let mayStore = 0, mayLoad = 1 in
4137class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4138             string asm>
4139    : BaseLoadStorePostIdx<sz, V, opc,
4140                      (outs GPR64sp:$wback, regtype:$Rt),
4141                      (ins GPR64sp:$Rn, simm9:$offset),
4142                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4143      Sched<[WriteAdr, WriteLD]>;
4144
4145let mayStore = 1, mayLoad = 0 in
4146class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4147                   string asm, SDPatternOperator storeop, ValueType Ty>
4148    : BaseLoadStorePostIdx<sz, V, opc,
4149                      (outs GPR64sp:$wback),
4150                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4151                       asm, "$Rn = $wback,@earlyclobber $wback",
4152      [(set GPR64sp:$wback,
4153            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4154    Sched<[WriteAdr, WriteST]>;
4155} // hasSideEffects = 0
4156
4157
4158//---
4159// Load/store pair
4160//---
4161
4162// (indexed, offset)
4163
4164class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4165                              string asm>
4166    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4167  bits<5> Rt;
4168  bits<5> Rt2;
4169  bits<5> Rn;
4170  bits<7> offset;
4171  let Inst{31-30} = opc;
4172  let Inst{29-27} = 0b101;
4173  let Inst{26}    = V;
4174  let Inst{25-23} = 0b010;
4175  let Inst{22}    = L;
4176  let Inst{21-15} = offset;
4177  let Inst{14-10} = Rt2;
4178  let Inst{9-5}   = Rn;
4179  let Inst{4-0}   = Rt;
4180
4181  let DecoderMethod = "DecodePairLdStInstruction";
4182}
4183
4184multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4185                          Operand indextype, string asm> {
4186  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4187  def i : BaseLoadStorePairOffset<opc, V, 1,
4188                                  (outs regtype:$Rt, regtype:$Rt2),
4189                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4190          Sched<[WriteLD, WriteLDHi]>;
4191
4192  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4193                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4194                                                  GPR64sp:$Rn, 0)>;
4195}
4196
4197
4198multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4199                           Operand indextype, string asm> {
4200  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4201  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4202                                  (ins regtype:$Rt, regtype:$Rt2,
4203                                       GPR64sp:$Rn, indextype:$offset),
4204                                  asm>,
4205          Sched<[WriteSTP]>;
4206
4207  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4208                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4209                                                  GPR64sp:$Rn, 0)>;
4210}
4211
4212// (pre-indexed)
4213class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4214                              string asm>
4215    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4216  bits<5> Rt;
4217  bits<5> Rt2;
4218  bits<5> Rn;
4219  bits<7> offset;
4220  let Inst{31-30} = opc;
4221  let Inst{29-27} = 0b101;
4222  let Inst{26}    = V;
4223  let Inst{25-23} = 0b011;
4224  let Inst{22}    = L;
4225  let Inst{21-15} = offset;
4226  let Inst{14-10} = Rt2;
4227  let Inst{9-5}   = Rn;
4228  let Inst{4-0}   = Rt;
4229
4230  let DecoderMethod = "DecodePairLdStInstruction";
4231}
4232
4233let hasSideEffects = 0 in {
4234let mayStore = 0, mayLoad = 1 in
4235class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4236                     Operand indextype, string asm>
4237    : BaseLoadStorePairPreIdx<opc, V, 1,
4238                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4239                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4240      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4241
4242let mayStore = 1, mayLoad = 0 in
4243class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4244                      Operand indextype, string asm>
4245    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4246                             (ins regtype:$Rt, regtype:$Rt2,
4247                                  GPR64sp:$Rn, indextype:$offset),
4248                             asm>,
4249      Sched<[WriteAdr, WriteSTP]>;
4250} // hasSideEffects = 0
4251
4252// (post-indexed)
4253
4254class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4255                              string asm>
4256    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4257  bits<5> Rt;
4258  bits<5> Rt2;
4259  bits<5> Rn;
4260  bits<7> offset;
4261  let Inst{31-30} = opc;
4262  let Inst{29-27} = 0b101;
4263  let Inst{26}    = V;
4264  let Inst{25-23} = 0b001;
4265  let Inst{22}    = L;
4266  let Inst{21-15} = offset;
4267  let Inst{14-10} = Rt2;
4268  let Inst{9-5}   = Rn;
4269  let Inst{4-0}   = Rt;
4270
4271  let DecoderMethod = "DecodePairLdStInstruction";
4272}
4273
4274let hasSideEffects = 0 in {
4275let mayStore = 0, mayLoad = 1 in
4276class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4277                      Operand idxtype, string asm>
4278    : BaseLoadStorePairPostIdx<opc, V, 1,
4279                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4280                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4281      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4282
4283let mayStore = 1, mayLoad = 0 in
4284class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4285                       Operand idxtype, string asm>
4286    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4287                             (ins regtype:$Rt, regtype:$Rt2,
4288                                  GPR64sp:$Rn, idxtype:$offset),
4289                             asm>,
4290      Sched<[WriteAdr, WriteSTP]>;
4291} // hasSideEffects = 0
4292
4293//  (no-allocate)
4294
4295class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4296                              string asm>
4297    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4298  bits<5> Rt;
4299  bits<5> Rt2;
4300  bits<5> Rn;
4301  bits<7> offset;
4302  let Inst{31-30} = opc;
4303  let Inst{29-27} = 0b101;
4304  let Inst{26}    = V;
4305  let Inst{25-23} = 0b000;
4306  let Inst{22}    = L;
4307  let Inst{21-15} = offset;
4308  let Inst{14-10} = Rt2;
4309  let Inst{9-5}   = Rn;
4310  let Inst{4-0}   = Rt;
4311
4312  let DecoderMethod = "DecodePairLdStInstruction";
4313}
4314
4315multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4316                           Operand indextype, string asm> {
4317  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4318  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4319                                   (outs regtype:$Rt, regtype:$Rt2),
4320                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4321          Sched<[WriteLD, WriteLDHi]>;
4322
4323
4324  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4325                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4326                                                  GPR64sp:$Rn, 0)>;
4327}
4328
4329multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4330                      Operand indextype, string asm> {
4331  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4332  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4333                                   (ins regtype:$Rt, regtype:$Rt2,
4334                                        GPR64sp:$Rn, indextype:$offset),
4335                                   asm>,
4336          Sched<[WriteSTP]>;
4337
4338  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4339                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4340                                                  GPR64sp:$Rn, 0)>;
4341}
4342
4343//---
4344// Load/store exclusive
4345//---
4346
4347// True exclusive operations write to and/or read from the system's exclusive
4348// monitors, which as far as a compiler is concerned can be modelled as a
4349// random shared memory address. Hence LoadExclusive mayStore.
4350//
4351// Since these instructions have the undefined register bits set to 1 in
4352// their canonical form, we need a post encoder method to set those bits
4353// to 1 when encoding these instructions. We do this using the
4354// fixLoadStoreExclusive function. This function has template parameters:
4355//
4356// fixLoadStoreExclusive<int hasRs, int hasRt2>
4357//
4358// hasRs indicates that the instruction uses the Rs field, so we won't set
4359// it to 1 (and the same for Rt2). We don't need template parameters for
4360// the other register fields since Rt and Rn are always used.
4361//
4362let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4363class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4364                             dag oops, dag iops, string asm, string operands>
4365    : I<oops, iops, asm, operands, "", []> {
4366  let Inst{31-30} = sz;
4367  let Inst{29-24} = 0b001000;
4368  let Inst{23}    = o2;
4369  let Inst{22}    = L;
4370  let Inst{21}    = o1;
4371  let Inst{15}    = o0;
4372
4373  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4374}
4375
4376// Neither Rs nor Rt2 operands.
4377class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4378                               dag oops, dag iops, string asm, string operands>
4379    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4380  bits<5> Rt;
4381  bits<5> Rn;
4382  let Inst{20-16} = 0b11111;
4383  let Unpredictable{20-16} = 0b11111;
4384  let Inst{14-10} = 0b11111;
4385  let Unpredictable{14-10} = 0b11111;
4386  let Inst{9-5} = Rn;
4387  let Inst{4-0} = Rt;
4388
4389  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4390}
4391
4392// Simple load acquires don't set the exclusive monitor
4393let mayLoad = 1, mayStore = 0 in
4394class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4395                  RegisterClass regtype, string asm>
4396    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4397                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4398      Sched<[WriteLD]>;
4399
4400class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4401                    RegisterClass regtype, string asm>
4402    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4403                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4404      Sched<[WriteLD]>;
4405
4406class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4407                       RegisterClass regtype, string asm>
4408    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4409                             (outs regtype:$Rt, regtype:$Rt2),
4410                             (ins GPR64sp0:$Rn), asm,
4411                             "\t$Rt, $Rt2, [$Rn]">,
4412      Sched<[WriteLD, WriteLDHi]> {
4413  bits<5> Rt;
4414  bits<5> Rt2;
4415  bits<5> Rn;
4416  let Inst{14-10} = Rt2;
4417  let Inst{9-5} = Rn;
4418  let Inst{4-0} = Rt;
4419
4420  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4421}
4422
4423// Simple store release operations do not check the exclusive monitor.
4424let mayLoad = 0, mayStore = 1 in
4425class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4426                   RegisterClass regtype, string asm>
4427    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4428                               (ins regtype:$Rt, GPR64sp0:$Rn),
4429                               asm, "\t$Rt, [$Rn]">,
4430      Sched<[WriteST]>;
4431
4432let mayLoad = 1, mayStore = 1 in
4433class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4434                     RegisterClass regtype, string asm>
4435    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4436                             (ins regtype:$Rt, GPR64sp0:$Rn),
4437                             asm, "\t$Ws, $Rt, [$Rn]">,
4438      Sched<[WriteSTX]> {
4439  bits<5> Ws;
4440  bits<5> Rt;
4441  bits<5> Rn;
4442  let Inst{20-16} = Ws;
4443  let Inst{9-5} = Rn;
4444  let Inst{4-0} = Rt;
4445
4446  let Constraints = "@earlyclobber $Ws";
4447  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4448}
4449
4450class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4451                         RegisterClass regtype, string asm>
4452    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4453                             (outs GPR32:$Ws),
4454                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4455                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4456      Sched<[WriteSTX]> {
4457  bits<5> Ws;
4458  bits<5> Rt;
4459  bits<5> Rt2;
4460  bits<5> Rn;
4461  let Inst{20-16} = Ws;
4462  let Inst{14-10} = Rt2;
4463  let Inst{9-5} = Rn;
4464  let Inst{4-0} = Rt;
4465
4466  let Constraints = "@earlyclobber $Ws";
4467}
4468
4469// Armv8.5-A Memory Tagging Extension
4470class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4471                 string asm_opnds, string cstr, dag oops, dag iops>
4472    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4473      Sched<[]> {
4474  bits<5> Rn;
4475
4476  let Inst{31-24} = 0b11011001;
4477  let Inst{23-22} = opc1;
4478  let Inst{21}    = 1;
4479  // Inst{20-12} defined by subclass
4480  let Inst{11-10} = opc2;
4481  let Inst{9-5}   = Rn;
4482  // Inst{4-0} defined by subclass
4483}
4484
4485class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4486                   dag oops, dag iops>
4487    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4488                  "", oops, iops> {
4489  bits<5> Rt;
4490
4491  let Inst{20-12} = 0b000000000;
4492  let Inst{4-0}   = Rt;
4493
4494  let mayLoad = Load;
4495}
4496
4497class MemTagLoad<string asm_insn, string asm_opnds>
4498    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4499                 (outs GPR64:$wback),
4500                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4501  bits<5> Rt;
4502  bits<9> offset;
4503
4504  let Inst{20-12} = offset;
4505  let Inst{4-0}   = Rt;
4506
4507  let mayLoad = 1;
4508}
4509
4510class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4511                     string asm_opnds, string cstr, dag oops, dag iops>
4512    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4513  bits<5> Rt;
4514  bits<9> offset;
4515
4516  let Inst{20-12} = offset;
4517  let Inst{4-0}   = Rt;
4518
4519  let mayStore = 1;
4520}
4521
4522multiclass MemTagStore<bits<2> opc1, string insn> {
4523  def Offset :
4524    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4525                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4526  def PreIndex :
4527    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4528                    "$Rn = $wback",
4529                    (outs GPR64sp:$wback),
4530                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4531  def PostIndex :
4532    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4533                    "$Rn = $wback",
4534                    (outs GPR64sp:$wback),
4535                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4536
4537  def : InstAlias<insn # "\t$Rt, [$Rn]",
4538                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4539}
4540
4541//---
4542// Exception generation
4543//---
4544
4545let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4546class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm,
4547                          list<dag> pattern = []>
4548    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", pattern>,
4549      Sched<[WriteSys]> {
4550  bits<16> imm;
4551  let Inst{31-24} = 0b11010100;
4552  let Inst{23-21} = op1;
4553  let Inst{20-5}  = imm;
4554  let Inst{4-2}   = 0b000;
4555  let Inst{1-0}   = ll;
4556}
4557
4558//---
4559// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4560//--
4561let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4562class UDFType<bits<16> opc, string asm>
4563  : I<(outs), (ins uimm16:$imm),
4564       asm, "\t$imm", "", []>,
4565    Sched<[]> {
4566  bits<16> imm;
4567  let Inst{31-16} = opc;
4568  let Inst{15-0} = imm;
4569}
4570}
4571let Predicates = [HasFPARMv8] in {
4572
4573//---
4574// Floating point to integer conversion
4575//---
4576
4577let mayRaiseFPException = 1 in
4578class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4579                      RegisterClass srcType, RegisterClass dstType,
4580                      string asm, list<dag> pattern>
4581    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4582         asm, "\t$Rd, $Rn", "", pattern>,
4583      Sched<[WriteFCvt]> {
4584  bits<5> Rd;
4585  bits<5> Rn;
4586  let Inst{30-29} = 0b00;
4587  let Inst{28-24} = 0b11110;
4588  let Inst{23-22} = type;
4589  let Inst{21}    = 1;
4590  let Inst{20-19} = rmode;
4591  let Inst{18-16} = opcode;
4592  let Inst{15-10} = 0;
4593  let Inst{9-5}   = Rn;
4594  let Inst{4-0}   = Rd;
4595}
4596
4597let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
4598class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4599                      RegisterClass srcType, RegisterClass dstType,
4600                      Operand immType, string asm, list<dag> pattern>
4601    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4602         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4603      Sched<[WriteFCvt]> {
4604  bits<5> Rd;
4605  bits<5> Rn;
4606  bits<6> scale;
4607  let Inst{30-29} = 0b00;
4608  let Inst{28-24} = 0b11110;
4609  let Inst{23-22} = type;
4610  let Inst{21}    = 0;
4611  let Inst{20-19} = rmode;
4612  let Inst{18-16} = opcode;
4613  let Inst{15-10} = scale;
4614  let Inst{9-5}   = Rn;
4615  let Inst{4-0}   = Rd;
4616}
4617
4618multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4619           SDPatternOperator OpN> {
4620  // Unscaled half-precision to 32-bit
4621  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4622                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4623    let Inst{31} = 0; // 32-bit GPR flag
4624    let Predicates = [HasFullFP16];
4625  }
4626
4627  // Unscaled half-precision to 64-bit
4628  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4629                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4630    let Inst{31} = 1; // 64-bit GPR flag
4631    let Predicates = [HasFullFP16];
4632  }
4633
4634  // Unscaled single-precision to 32-bit
4635  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4636                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4637    let Inst{31} = 0; // 32-bit GPR flag
4638  }
4639
4640  // Unscaled single-precision to 64-bit
4641  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4642                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4643    let Inst{31} = 1; // 64-bit GPR flag
4644  }
4645
4646  // Unscaled double-precision to 32-bit
4647  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4648                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4649    let Inst{31} = 0; // 32-bit GPR flag
4650  }
4651
4652  // Unscaled double-precision to 64-bit
4653  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4654                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4655    let Inst{31} = 1; // 64-bit GPR flag
4656  }
4657}
4658
4659multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4660                             SDPatternOperator OpN> {
4661  // Scaled half-precision to 32-bit
4662  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4663                              fixedpoint_f16_i32, asm,
4664              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4665                                          fixedpoint_f16_i32:$scale)))]> {
4666    let Inst{31} = 0; // 32-bit GPR flag
4667    let scale{5} = 1;
4668    let Predicates = [HasFullFP16];
4669  }
4670
4671  // Scaled half-precision to 64-bit
4672  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4673                              fixedpoint_f16_i64, asm,
4674              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4675                                          fixedpoint_f16_i64:$scale)))]> {
4676    let Inst{31} = 1; // 64-bit GPR flag
4677    let Predicates = [HasFullFP16];
4678  }
4679
4680  // Scaled single-precision to 32-bit
4681  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4682                              fixedpoint_f32_i32, asm,
4683              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4684                                          fixedpoint_f32_i32:$scale)))]> {
4685    let Inst{31} = 0; // 32-bit GPR flag
4686    let scale{5} = 1;
4687  }
4688
4689  // Scaled single-precision to 64-bit
4690  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4691                              fixedpoint_f32_i64, asm,
4692              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4693                                          fixedpoint_f32_i64:$scale)))]> {
4694    let Inst{31} = 1; // 64-bit GPR flag
4695  }
4696
4697  // Scaled double-precision to 32-bit
4698  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4699                              fixedpoint_f64_i32, asm,
4700              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4701                                          fixedpoint_f64_i32:$scale)))]> {
4702    let Inst{31} = 0; // 32-bit GPR flag
4703    let scale{5} = 1;
4704  }
4705
4706  // Scaled double-precision to 64-bit
4707  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4708                              fixedpoint_f64_i64, asm,
4709              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4710                                          fixedpoint_f64_i64:$scale)))]> {
4711    let Inst{31} = 1; // 64-bit GPR flag
4712  }
4713}
4714
4715//---
4716// Integer to floating point conversion
4717//---
4718
4719let mayStore = 0, mayLoad = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
4720class BaseIntegerToFP<bit isUnsigned,
4721                      RegisterClass srcType, RegisterClass dstType,
4722                      Operand immType, string asm, list<dag> pattern>
4723    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4724         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4725      Sched<[WriteFCvt]> {
4726  bits<5> Rd;
4727  bits<5> Rn;
4728  bits<6> scale;
4729  let Inst{30-24} = 0b0011110;
4730  let Inst{21-17} = 0b00001;
4731  let Inst{16}    = isUnsigned;
4732  let Inst{15-10} = scale;
4733  let Inst{9-5}   = Rn;
4734  let Inst{4-0}   = Rd;
4735}
4736
4737let mayRaiseFPException = 1 in
4738class BaseIntegerToFPUnscaled<bit isUnsigned,
4739                      RegisterClass srcType, RegisterClass dstType,
4740                      ValueType dvt, string asm, SDPatternOperator node>
4741    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4742         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4743      Sched<[WriteFCvt]> {
4744  bits<5> Rd;
4745  bits<5> Rn;
4746  bits<6> scale;
4747  let Inst{30-24} = 0b0011110;
4748  let Inst{21-17} = 0b10001;
4749  let Inst{16}    = isUnsigned;
4750  let Inst{15-10} = 0b000000;
4751  let Inst{9-5}   = Rn;
4752  let Inst{4-0}   = Rd;
4753}
4754
4755multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
4756  // Unscaled
4757  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4758    let Inst{31} = 0; // 32-bit GPR flag
4759    let Inst{23-22} = 0b11; // 16-bit FPR flag
4760    let Predicates = [HasFullFP16];
4761  }
4762
4763  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4764    let Inst{31} = 0; // 32-bit GPR flag
4765    let Inst{23-22} = 0b00; // 32-bit FPR flag
4766  }
4767
4768  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4769    let Inst{31} = 0; // 32-bit GPR flag
4770    let Inst{23-22} = 0b01; // 64-bit FPR flag
4771  }
4772
4773  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4774    let Inst{31} = 1; // 64-bit GPR flag
4775    let Inst{23-22} = 0b11; // 16-bit FPR flag
4776    let Predicates = [HasFullFP16];
4777  }
4778
4779  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4780    let Inst{31} = 1; // 64-bit GPR flag
4781    let Inst{23-22} = 0b00; // 32-bit FPR flag
4782  }
4783
4784  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4785    let Inst{31} = 1; // 64-bit GPR flag
4786    let Inst{23-22} = 0b01; // 64-bit FPR flag
4787  }
4788
4789  // Scaled
4790  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4791                             [(set (f16 FPR16:$Rd),
4792                                   (fdiv (node GPR32:$Rn),
4793                                         fixedpoint_f16_i32:$scale))]> {
4794    let Inst{31} = 0; // 32-bit GPR flag
4795    let Inst{23-22} = 0b11; // 16-bit FPR flag
4796    let scale{5} = 1;
4797    let Predicates = [HasFullFP16];
4798  }
4799
4800  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4801                             [(set FPR32:$Rd,
4802                                   (fdiv (node GPR32:$Rn),
4803                                         fixedpoint_f32_i32:$scale))]> {
4804    let Inst{31} = 0; // 32-bit GPR flag
4805    let Inst{23-22} = 0b00; // 32-bit FPR flag
4806    let scale{5} = 1;
4807  }
4808
4809  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4810                             [(set FPR64:$Rd,
4811                                   (fdiv (node GPR32:$Rn),
4812                                         fixedpoint_f64_i32:$scale))]> {
4813    let Inst{31} = 0; // 32-bit GPR flag
4814    let Inst{23-22} = 0b01; // 64-bit FPR flag
4815    let scale{5} = 1;
4816  }
4817
4818  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4819                             [(set (f16 FPR16:$Rd),
4820                                   (fdiv (node GPR64:$Rn),
4821                                         fixedpoint_f16_i64:$scale))]> {
4822    let Inst{31} = 1; // 64-bit GPR flag
4823    let Inst{23-22} = 0b11; // 16-bit FPR flag
4824    let Predicates = [HasFullFP16];
4825  }
4826
4827  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4828                             [(set FPR32:$Rd,
4829                                   (fdiv (node GPR64:$Rn),
4830                                         fixedpoint_f32_i64:$scale))]> {
4831    let Inst{31} = 1; // 64-bit GPR flag
4832    let Inst{23-22} = 0b00; // 32-bit FPR flag
4833  }
4834
4835  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4836                             [(set FPR64:$Rd,
4837                                   (fdiv (node GPR64:$Rn),
4838                                         fixedpoint_f64_i64:$scale))]> {
4839    let Inst{31} = 1; // 64-bit GPR flag
4840    let Inst{23-22} = 0b01; // 64-bit FPR flag
4841  }
4842}
4843
4844//---
4845// Unscaled integer <-> floating point conversion (i.e. FMOV)
4846//---
4847
4848let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4849class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4850                      RegisterClass srcType, RegisterClass dstType,
4851                      string asm>
4852    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4853        // We use COPY_TO_REGCLASS for these bitconvert operations.
4854        // copyPhysReg() expands the resultant COPY instructions after
4855        // regalloc is done. This gives greater freedom for the allocator
4856        // and related passes (coalescing, copy propagation, et. al.) to
4857        // be more effective.
4858        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4859      Sched<[WriteFCopy]> {
4860  bits<5> Rd;
4861  bits<5> Rn;
4862  let Inst{30-24} = 0b0011110;
4863  let Inst{21}    = 1;
4864  let Inst{20-19} = rmode;
4865  let Inst{18-16} = opcode;
4866  let Inst{15-10} = 0b000000;
4867  let Inst{9-5}   = Rn;
4868  let Inst{4-0}   = Rd;
4869}
4870
4871let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4872class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4873                     RegisterClass srcType, RegisterOperand dstType, string asm,
4874                     string kind>
4875    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4876        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4877      Sched<[WriteFCopy]> {
4878  bits<5> Rd;
4879  bits<5> Rn;
4880  let Inst{30-23} = 0b00111101;
4881  let Inst{21}    = 1;
4882  let Inst{20-19} = rmode;
4883  let Inst{18-16} = opcode;
4884  let Inst{15-10} = 0b000000;
4885  let Inst{9-5}   = Rn;
4886  let Inst{4-0}   = Rd;
4887
4888  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4889}
4890
4891let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4892class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4893                     RegisterOperand srcType, RegisterClass dstType, string asm,
4894                     string kind>
4895    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4896        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4897      Sched<[WriteFCopy]> {
4898  bits<5> Rd;
4899  bits<5> Rn;
4900  let Inst{30-23} = 0b00111101;
4901  let Inst{21}    = 1;
4902  let Inst{20-19} = rmode;
4903  let Inst{18-16} = opcode;
4904  let Inst{15-10} = 0b000000;
4905  let Inst{9-5}   = Rn;
4906  let Inst{4-0}   = Rd;
4907
4908  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4909}
4910
4911
4912multiclass UnscaledConversion<string asm> {
4913  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4914    let Inst{31} = 0; // 32-bit GPR flag
4915    let Inst{23-22} = 0b11; // 16-bit FPR flag
4916    let Predicates = [HasFullFP16];
4917  }
4918
4919  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4920    let Inst{31} = 1; // 64-bit GPR flag
4921    let Inst{23-22} = 0b11; // 16-bit FPR flag
4922    let Predicates = [HasFullFP16];
4923  }
4924
4925  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4926    let Inst{31} = 0; // 32-bit GPR flag
4927    let Inst{23-22} = 0b00; // 32-bit FPR flag
4928  }
4929
4930  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4931    let Inst{31} = 1; // 64-bit GPR flag
4932    let Inst{23-22} = 0b01; // 64-bit FPR flag
4933  }
4934
4935  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4936    let Inst{31} = 0; // 32-bit GPR flag
4937    let Inst{23-22} = 0b11; // 16-bit FPR flag
4938    let Predicates = [HasFullFP16];
4939  }
4940
4941  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4942    let Inst{31} = 1; // 64-bit GPR flag
4943    let Inst{23-22} = 0b11; // 16-bit FPR flag
4944    let Predicates = [HasFullFP16];
4945  }
4946
4947  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4948    let Inst{31} = 0; // 32-bit GPR flag
4949    let Inst{23-22} = 0b00; // 32-bit FPR flag
4950  }
4951
4952  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4953    let Inst{31} = 1; // 64-bit GPR flag
4954    let Inst{23-22} = 0b01; // 64-bit FPR flag
4955  }
4956
4957  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4958                                             asm, ".d"> {
4959    let Inst{31} = 1;
4960    let Inst{22} = 0;
4961  }
4962
4963  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4964                                               asm, ".d"> {
4965    let Inst{31} = 1;
4966    let Inst{22} = 0;
4967  }
4968}
4969
4970//---
4971// Floating point conversion
4972//---
4973
4974let mayRaiseFPException = 1 in
4975class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4976                       RegisterClass srcType, string asm, list<dag> pattern>
4977    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4978      Sched<[WriteFCvt]> {
4979  bits<5> Rd;
4980  bits<5> Rn;
4981  let Inst{31-24} = 0b00011110;
4982  let Inst{23-22} = type;
4983  let Inst{21-17} = 0b10001;
4984  let Inst{16-15} = opcode;
4985  let Inst{14-10} = 0b10000;
4986  let Inst{9-5}   = Rn;
4987  let Inst{4-0}   = Rd;
4988}
4989
4990multiclass FPConversion<string asm> {
4991  // Double-precision to Half-precision
4992  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4993                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
4994
4995  // Double-precision to Single-precision
4996  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4997                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
4998
4999  // Half-precision to Double-precision
5000  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
5001                             [(set FPR64:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5002
5003  // Half-precision to Single-precision
5004  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
5005                             [(set FPR32:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5006
5007  // Single-precision to Double-precision
5008  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
5009                             [(set FPR64:$Rd, (any_fpextend FPR32:$Rn))]>;
5010
5011  // Single-precision to Half-precision
5012  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
5013                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
5014}
5015
5016//---
5017// Single operand floating point data processing
5018//---
5019
5020let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5021class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
5022                              ValueType vt, string asm, SDPatternOperator node>
5023    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
5024         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
5025      Sched<[WriteF]> {
5026  bits<5> Rd;
5027  bits<5> Rn;
5028  let Inst{31-24} = 0b00011110;
5029  let Inst{21}    = 0b1;
5030  let Inst{20-15} = opcode;
5031  let Inst{14-10} = 0b10000;
5032  let Inst{9-5}   = Rn;
5033  let Inst{4-0}   = Rd;
5034}
5035
5036multiclass SingleOperandFPData<bits<4> opcode, string asm,
5037                               SDPatternOperator node = null_frag,
5038                               int fpexceptions = 1> {
5039  let mayRaiseFPException = fpexceptions in {
5040  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5041    let Inst{23-22} = 0b11; // 16-bit size flag
5042    let Predicates = [HasFullFP16];
5043  }
5044
5045  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5046    let Inst{23-22} = 0b00; // 32-bit size flag
5047  }
5048
5049  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5050    let Inst{23-22} = 0b01; // 64-bit size flag
5051  }
5052  }
5053}
5054
5055multiclass SingleOperandFPDataNoException<bits<4> opcode, string asm,
5056                                       SDPatternOperator node = null_frag>
5057    : SingleOperandFPData<opcode, asm, node, 0>;
5058
5059let mayRaiseFPException = 1 in
5060multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5061                  SDPatternOperator node = null_frag>{
5062
5063  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5064    let Inst{23-22} = 0b00; // 32-bit registers
5065  }
5066
5067  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5068    let Inst{23-22} = 0b01; // 64-bit registers
5069  }
5070}
5071
5072// FRInt[32|64][Z|N] instructions
5073multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5074      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5075
5076//---
5077// Two operand floating point data processing
5078//---
5079
5080let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5081class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5082                           string asm, list<dag> pat>
5083    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5084         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5085      Sched<[WriteF]> {
5086  bits<5> Rd;
5087  bits<5> Rn;
5088  bits<5> Rm;
5089  let Inst{31-24} = 0b00011110;
5090  let Inst{21}    = 1;
5091  let Inst{20-16} = Rm;
5092  let Inst{15-12} = opcode;
5093  let Inst{11-10} = 0b10;
5094  let Inst{9-5}   = Rn;
5095  let Inst{4-0}   = Rd;
5096}
5097
5098multiclass TwoOperandFPData<bits<4> opcode, string asm,
5099                            SDPatternOperator node = null_frag> {
5100  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5101                         [(set (f16 FPR16:$Rd),
5102                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5103    let Inst{23-22} = 0b11; // 16-bit size flag
5104    let Predicates = [HasFullFP16];
5105  }
5106
5107  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5108                         [(set (f32 FPR32:$Rd),
5109                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5110    let Inst{23-22} = 0b00; // 32-bit size flag
5111  }
5112
5113  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5114                         [(set (f64 FPR64:$Rd),
5115                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5116    let Inst{23-22} = 0b01; // 64-bit size flag
5117  }
5118}
5119
5120multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm,
5121                               SDPatternOperator node> {
5122  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5123                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5124    let Inst{23-22} = 0b11; // 16-bit size flag
5125    let Predicates = [HasFullFP16];
5126  }
5127
5128  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5129                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5130    let Inst{23-22} = 0b00; // 32-bit size flag
5131  }
5132
5133  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5134                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5135    let Inst{23-22} = 0b01; // 64-bit size flag
5136  }
5137}
5138
5139
5140//---
5141// Three operand floating point data processing
5142//---
5143
5144let mayRaiseFPException = 1 in
5145class BaseThreeOperandFPData<bit isNegated, bit isSub,
5146                             RegisterClass regtype, string asm, list<dag> pat>
5147    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5148         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5149      Sched<[WriteFMul]> {
5150  bits<5> Rd;
5151  bits<5> Rn;
5152  bits<5> Rm;
5153  bits<5> Ra;
5154  let Inst{31-24} = 0b00011111;
5155  let Inst{21}    = isNegated;
5156  let Inst{20-16} = Rm;
5157  let Inst{15}    = isSub;
5158  let Inst{14-10} = Ra;
5159  let Inst{9-5}   = Rn;
5160  let Inst{4-0}   = Rd;
5161}
5162
5163multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5164                              SDPatternOperator node> {
5165  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5166            [(set (f16 FPR16:$Rd),
5167                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5168    let Inst{23-22} = 0b11; // 16-bit size flag
5169    let Predicates = [HasFullFP16];
5170  }
5171
5172  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5173            [(set FPR32:$Rd,
5174                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5175    let Inst{23-22} = 0b00; // 32-bit size flag
5176  }
5177
5178  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5179            [(set FPR64:$Rd,
5180                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5181    let Inst{23-22} = 0b01; // 64-bit size flag
5182  }
5183}
5184
5185//---
5186// Floating point data comparisons
5187//---
5188
5189let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5190class BaseOneOperandFPComparison<bit signalAllNans,
5191                                 RegisterClass regtype, string asm,
5192                                 list<dag> pat>
5193    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5194      Sched<[WriteFCmp]> {
5195  bits<5> Rn;
5196  let Inst{31-24} = 0b00011110;
5197  let Inst{21}    = 1;
5198
5199  let Inst{15-10} = 0b001000;
5200  let Inst{9-5}   = Rn;
5201  let Inst{4}     = signalAllNans;
5202  let Inst{3-0}   = 0b1000;
5203
5204  // Rm should be 0b00000 canonically, but we need to accept any value.
5205  let PostEncoderMethod = "fixOneOperandFPComparison";
5206}
5207
5208let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5209class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5210                                string asm, list<dag> pat>
5211    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5212      Sched<[WriteFCmp]> {
5213  bits<5> Rm;
5214  bits<5> Rn;
5215  let Inst{31-24} = 0b00011110;
5216  let Inst{21}    = 1;
5217  let Inst{20-16} = Rm;
5218  let Inst{15-10} = 0b001000;
5219  let Inst{9-5}   = Rn;
5220  let Inst{4}     = signalAllNans;
5221  let Inst{3-0}   = 0b0000;
5222}
5223
5224multiclass FPComparison<bit signalAllNans, string asm,
5225                        SDPatternOperator OpNode = null_frag> {
5226  let Defs = [NZCV] in {
5227  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5228      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5229    let Inst{23-22} = 0b11;
5230    let Predicates = [HasFullFP16];
5231  }
5232
5233  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5234      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5235    let Inst{23-22} = 0b11;
5236    let Predicates = [HasFullFP16];
5237  }
5238
5239  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5240      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5241    let Inst{23-22} = 0b00;
5242  }
5243
5244  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5245      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5246    let Inst{23-22} = 0b00;
5247  }
5248
5249  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5250      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5251    let Inst{23-22} = 0b01;
5252  }
5253
5254  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5255      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5256    let Inst{23-22} = 0b01;
5257  }
5258  } // Defs = [NZCV]
5259}
5260
5261//---
5262// Floating point conditional comparisons
5263//---
5264
5265let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5266class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5267                           string mnemonic, list<dag> pat>
5268    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5269         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5270      Sched<[WriteFCmp]> {
5271  let Uses = [NZCV];
5272  let Defs = [NZCV];
5273
5274  bits<5> Rn;
5275  bits<5> Rm;
5276  bits<4> nzcv;
5277  bits<4> cond;
5278
5279  let Inst{31-24} = 0b00011110;
5280  let Inst{21}    = 1;
5281  let Inst{20-16} = Rm;
5282  let Inst{15-12} = cond;
5283  let Inst{11-10} = 0b01;
5284  let Inst{9-5}   = Rn;
5285  let Inst{4}     = signalAllNans;
5286  let Inst{3-0}   = nzcv;
5287}
5288
5289multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5290                            SDPatternOperator OpNode = null_frag> {
5291  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5292      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5293                          (i32 imm:$cond), NZCV))]> {
5294    let Inst{23-22} = 0b11;
5295    let Predicates = [HasFullFP16];
5296  }
5297
5298  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5299      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5300                          (i32 imm:$cond), NZCV))]> {
5301    let Inst{23-22} = 0b00;
5302  }
5303
5304  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5305      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5306                          (i32 imm:$cond), NZCV))]> {
5307    let Inst{23-22} = 0b01;
5308  }
5309}
5310
5311//---
5312// Floating point conditional select
5313//---
5314
5315class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5316    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5317         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5318         [(set regtype:$Rd,
5319               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5320                          (i32 imm:$cond), NZCV))]>,
5321      Sched<[WriteF]> {
5322  bits<5> Rd;
5323  bits<5> Rn;
5324  bits<5> Rm;
5325  bits<4> cond;
5326
5327  let Inst{31-24} = 0b00011110;
5328  let Inst{21}    = 1;
5329  let Inst{20-16} = Rm;
5330  let Inst{15-12} = cond;
5331  let Inst{11-10} = 0b11;
5332  let Inst{9-5}   = Rn;
5333  let Inst{4-0}   = Rd;
5334}
5335
5336multiclass FPCondSelect<string asm> {
5337  let Uses = [NZCV] in {
5338  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5339    let Inst{23-22} = 0b11;
5340    let Predicates = [HasFullFP16];
5341  }
5342
5343  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5344    let Inst{23-22} = 0b00;
5345  }
5346
5347  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5348    let Inst{23-22} = 0b01;
5349  }
5350  } // Uses = [NZCV]
5351}
5352
5353//---
5354// Floating move immediate
5355//---
5356
5357class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5358  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5359      [(set regtype:$Rd, fpimmtype:$imm)]>,
5360    Sched<[WriteFImm]> {
5361  bits<5> Rd;
5362  bits<8> imm;
5363  let Inst{31-24} = 0b00011110;
5364  let Inst{21}    = 1;
5365  let Inst{20-13} = imm;
5366  let Inst{12-5}  = 0b10000000;
5367  let Inst{4-0}   = Rd;
5368}
5369
5370multiclass FPMoveImmediate<string asm> {
5371  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5372    let Inst{23-22} = 0b11;
5373    let Predicates = [HasFullFP16];
5374  }
5375
5376  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5377    let Inst{23-22} = 0b00;
5378  }
5379
5380  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5381    let Inst{23-22} = 0b01;
5382  }
5383}
5384} // end of 'let Predicates = [HasFPARMv8]'
5385
5386//----------------------------------------------------------------------------
5387// AdvSIMD
5388//----------------------------------------------------------------------------
5389
5390let Predicates = [HasNEON] in {
5391
5392//----------------------------------------------------------------------------
5393// AdvSIMD three register vector instructions
5394//----------------------------------------------------------------------------
5395
5396let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5397class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5398                        RegisterOperand regtype, string asm, string kind,
5399                        list<dag> pattern>
5400  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5401      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5402      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5403    Sched<[!if(Q, WriteVq, WriteVd)]> {
5404  bits<5> Rd;
5405  bits<5> Rn;
5406  bits<5> Rm;
5407  let Inst{31}    = 0;
5408  let Inst{30}    = Q;
5409  let Inst{29}    = U;
5410  let Inst{28-24} = 0b01110;
5411  let Inst{23-21} = size;
5412  let Inst{20-16} = Rm;
5413  let Inst{15-11} = opcode;
5414  let Inst{10}    = 1;
5415  let Inst{9-5}   = Rn;
5416  let Inst{4-0}   = Rd;
5417}
5418
5419let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5420class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5421                        RegisterOperand regtype, string asm, string kind,
5422                        list<dag> pattern>
5423  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5424      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5425      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5426    Sched<[!if(Q, WriteVq, WriteVd)]> {
5427  bits<5> Rd;
5428  bits<5> Rn;
5429  bits<5> Rm;
5430  let Inst{31}    = 0;
5431  let Inst{30}    = Q;
5432  let Inst{29}    = U;
5433  let Inst{28-24} = 0b01110;
5434  let Inst{23-21} = size;
5435  let Inst{20-16} = Rm;
5436  let Inst{15-11} = opcode;
5437  let Inst{10}    = 1;
5438  let Inst{9-5}   = Rn;
5439  let Inst{4-0}   = Rd;
5440}
5441
5442let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5443class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5444  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5445    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
5446
5447multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5448  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5449             [(set (v8i8 V64:$dst),
5450                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5451  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5452             [(set (v16i8 V128:$dst),
5453                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5454                           (v16i8 V128:$Rm)))]>;
5455
5456  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5457                           (v4i16 V64:$RHS))),
5458          (!cast<Instruction>(NAME#"v8i8")
5459            V64:$LHS, V64:$MHS, V64:$RHS)>;
5460  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5461                           (v2i32 V64:$RHS))),
5462          (!cast<Instruction>(NAME#"v8i8")
5463            V64:$LHS, V64:$MHS, V64:$RHS)>;
5464  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5465                           (v1i64 V64:$RHS))),
5466          (!cast<Instruction>(NAME#"v8i8")
5467            V64:$LHS, V64:$MHS, V64:$RHS)>;
5468
5469  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5470                           (v8i16 V128:$RHS))),
5471      (!cast<Instruction>(NAME#"v16i8")
5472        V128:$LHS, V128:$MHS, V128:$RHS)>;
5473  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5474                           (v4i32 V128:$RHS))),
5475      (!cast<Instruction>(NAME#"v16i8")
5476        V128:$LHS, V128:$MHS, V128:$RHS)>;
5477  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5478                           (v2i64 V128:$RHS))),
5479      (!cast<Instruction>(NAME#"v16i8")
5480        V128:$LHS, V128:$MHS, V128:$RHS)>;
5481}
5482
5483// All operand sizes distinguished in the encoding.
5484multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5485                               SDPatternOperator OpNode> {
5486  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5487                                      asm, ".8b",
5488         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5489  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5490                                      asm, ".16b",
5491         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5492  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5493                                      asm, ".4h",
5494         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5495  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5496                                      asm, ".8h",
5497         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5498  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5499                                      asm, ".2s",
5500         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5501  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5502                                      asm, ".4s",
5503         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5504  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5505                                      asm, ".2d",
5506         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5507}
5508
5509multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5510  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5511          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5512  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5513          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5514  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5515          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5516
5517  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5518          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5519  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5520          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5521  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5522          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5523  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5524          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5525}
5526
5527// As above, but D sized elements unsupported.
5528multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5529                                  SDPatternOperator OpNode> {
5530  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5531                                      asm, ".8b",
5532        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5533  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5534                                      asm, ".16b",
5535        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5536  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5537                                      asm, ".4h",
5538        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5539  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5540                                      asm, ".8h",
5541        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5542  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5543                                      asm, ".2s",
5544        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5545  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5546                                      asm, ".4s",
5547        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5548}
5549
5550multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5551                                  SDPatternOperator OpNode> {
5552  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5553                                      asm, ".8b",
5554      [(set (v8i8 V64:$dst),
5555            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5556  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5557                                      asm, ".16b",
5558      [(set (v16i8 V128:$dst),
5559            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5560  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5561                                      asm, ".4h",
5562      [(set (v4i16 V64:$dst),
5563            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5564  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5565                                      asm, ".8h",
5566      [(set (v8i16 V128:$dst),
5567            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5568  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5569                                      asm, ".2s",
5570      [(set (v2i32 V64:$dst),
5571            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5572  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5573                                      asm, ".4s",
5574      [(set (v4i32 V128:$dst),
5575            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5576}
5577
5578// As above, but only B sized elements supported.
5579multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5580                                SDPatternOperator OpNode> {
5581  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5582                                      asm, ".8b",
5583    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5584  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5585                                      asm, ".16b",
5586    [(set (v16i8 V128:$Rd),
5587          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5588}
5589
5590// As above, but only floating point elements supported.
5591let mayRaiseFPException = 1 in
5592multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5593                                 string asm, SDPatternOperator OpNode> {
5594  let Predicates = [HasNEON, HasFullFP16] in {
5595  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5596                                      asm, ".4h",
5597        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5598  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5599                                      asm, ".8h",
5600        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5601  } // Predicates = [HasNEON, HasFullFP16]
5602  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5603                                      asm, ".2s",
5604        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5605  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5606                                      asm, ".4s",
5607        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5608  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5609                                      asm, ".2d",
5610        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5611}
5612
5613let mayRaiseFPException = 1 in
5614multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5615                                    string asm,
5616                                    SDPatternOperator OpNode> {
5617  let Predicates = [HasNEON, HasFullFP16] in {
5618  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5619                                      asm, ".4h",
5620        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5621  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5622                                      asm, ".8h",
5623        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5624  } // Predicates = [HasNEON, HasFullFP16]
5625  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5626                                      asm, ".2s",
5627        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5628  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5629                                      asm, ".4s",
5630        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5631  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5632                                      asm, ".2d",
5633        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5634}
5635
5636let mayRaiseFPException = 1 in
5637multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5638                                 string asm, SDPatternOperator OpNode> {
5639  let Predicates = [HasNEON, HasFullFP16] in {
5640  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5641                                      asm, ".4h",
5642     [(set (v4f16 V64:$dst),
5643           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5644  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5645                                      asm, ".8h",
5646     [(set (v8f16 V128:$dst),
5647           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5648  } // Predicates = [HasNEON, HasFullFP16]
5649  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5650                                      asm, ".2s",
5651     [(set (v2f32 V64:$dst),
5652           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5653  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5654                                      asm, ".4s",
5655     [(set (v4f32 V128:$dst),
5656           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5657  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5658                                      asm, ".2d",
5659     [(set (v2f64 V128:$dst),
5660           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5661}
5662
5663// As above, but D and B sized elements unsupported.
5664let mayRaiseFPException = 1 in
5665multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5666                                SDPatternOperator OpNode> {
5667  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5668                                      asm, ".4h",
5669        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5670  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5671                                      asm, ".8h",
5672        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5673  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5674                                      asm, ".2s",
5675        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5676  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5677                                      asm, ".4s",
5678        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5679}
5680
5681// Logical three vector ops share opcode bits, and only use B sized elements.
5682multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5683                                  SDPatternOperator OpNode = null_frag> {
5684  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5685                                     asm, ".8b",
5686                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5687  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5688                                     asm, ".16b",
5689                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5690
5691  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5692          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5693  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5694          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5695  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5696          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5697
5698  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5699      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5700  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5701      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5702  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5703      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5704}
5705
5706multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5707                                  string asm, SDPatternOperator OpNode = null_frag> {
5708  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5709                                     asm, ".8b",
5710             [(set (v8i8 V64:$dst),
5711                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5712  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5713                                     asm, ".16b",
5714             [(set (v16i8 V128:$dst),
5715                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5716                           (v16i8 V128:$Rm)))]>;
5717
5718  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5719                           (v4i16 V64:$RHS))),
5720          (!cast<Instruction>(NAME#"v8i8")
5721            V64:$LHS, V64:$MHS, V64:$RHS)>;
5722  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5723                           (v2i32 V64:$RHS))),
5724          (!cast<Instruction>(NAME#"v8i8")
5725            V64:$LHS, V64:$MHS, V64:$RHS)>;
5726  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5727                           (v1i64 V64:$RHS))),
5728          (!cast<Instruction>(NAME#"v8i8")
5729            V64:$LHS, V64:$MHS, V64:$RHS)>;
5730
5731  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5732                           (v8i16 V128:$RHS))),
5733      (!cast<Instruction>(NAME#"v16i8")
5734        V128:$LHS, V128:$MHS, V128:$RHS)>;
5735  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5736                           (v4i32 V128:$RHS))),
5737      (!cast<Instruction>(NAME#"v16i8")
5738        V128:$LHS, V128:$MHS, V128:$RHS)>;
5739  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5740                           (v2i64 V128:$RHS))),
5741      (!cast<Instruction>(NAME#"v16i8")
5742        V128:$LHS, V128:$MHS, V128:$RHS)>;
5743}
5744
5745// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5746// bytes from S-sized elements.
5747class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5748                                 string kind2, RegisterOperand RegType,
5749                                 ValueType AccumType, ValueType InputType,
5750                                 SDPatternOperator OpNode> :
5751        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5752        [(set (AccumType RegType:$dst),
5753              (OpNode (AccumType RegType:$Rd),
5754                      (InputType RegType:$Rn),
5755                      (InputType RegType:$Rm)))]> {
5756  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5757}
5758
5759multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5760  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5761                                         v2i32, v8i8, OpNode>;
5762  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5763                                         v4i32, v16i8, OpNode>;
5764}
5765
5766// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5767// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5768// 8H to 4S, when Q=1).
5769let mayRaiseFPException = 1 in
5770class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5771                                 string kind2, RegisterOperand RegType,
5772                                 ValueType AccumType, ValueType InputType,
5773                                 SDPatternOperator OpNode> :
5774        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5775		[(set (AccumType RegType:$dst),
5776              (OpNode (AccumType RegType:$Rd),
5777                      (InputType RegType:$Rn),
5778                      (InputType RegType:$Rm)))]> {
5779  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5780  let Inst{13} = b13;
5781}
5782
5783multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5784                                  SDPatternOperator OpNode> {
5785  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5786                                         v2f32, v4f16, OpNode>;
5787  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5788                                         v4f32, v8f16, OpNode>;
5789}
5790
5791
5792//----------------------------------------------------------------------------
5793// AdvSIMD two register vector instructions.
5794//----------------------------------------------------------------------------
5795
5796let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5797class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5798                            bits<2> size2, RegisterOperand regtype, string asm,
5799                            string dstkind, string srckind, list<dag> pattern>
5800  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5801      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5802      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5803    Sched<[!if(Q, WriteVq, WriteVd)]> {
5804  bits<5> Rd;
5805  bits<5> Rn;
5806  let Inst{31}    = 0;
5807  let Inst{30}    = Q;
5808  let Inst{29}    = U;
5809  let Inst{28-24} = 0b01110;
5810  let Inst{23-22} = size;
5811  let Inst{21} = 0b1;
5812  let Inst{20-19} = size2;
5813  let Inst{18-17} = 0b00;
5814  let Inst{16-12} = opcode;
5815  let Inst{11-10} = 0b10;
5816  let Inst{9-5}   = Rn;
5817  let Inst{4-0}   = Rd;
5818}
5819
5820let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5821class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5822                                bits<2> size2, RegisterOperand regtype,
5823                                string asm, string dstkind, string srckind,
5824                                list<dag> pattern>
5825  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5826      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5827      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5828    Sched<[!if(Q, WriteVq, WriteVd)]> {
5829  bits<5> Rd;
5830  bits<5> Rn;
5831  let Inst{31}    = 0;
5832  let Inst{30}    = Q;
5833  let Inst{29}    = U;
5834  let Inst{28-24} = 0b01110;
5835  let Inst{23-22} = size;
5836  let Inst{21} = 0b1;
5837  let Inst{20-19} = size2;
5838  let Inst{18-17} = 0b00;
5839  let Inst{16-12} = opcode;
5840  let Inst{11-10} = 0b10;
5841  let Inst{9-5}   = Rn;
5842  let Inst{4-0}   = Rd;
5843}
5844
5845// Supports B, H, and S element sizes.
5846multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5847                            SDPatternOperator OpNode> {
5848  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5849                                      asm, ".8b", ".8b",
5850                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5851  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5852                                      asm, ".16b", ".16b",
5853                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5854  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5855                                      asm, ".4h", ".4h",
5856                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5857  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5858                                      asm, ".8h", ".8h",
5859                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5860  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5861                                      asm, ".2s", ".2s",
5862                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5863  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5864                                      asm, ".4s", ".4s",
5865                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5866}
5867
5868class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5869                            RegisterOperand regtype, string asm, string dstkind,
5870                            string srckind, string amount>
5871  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5872      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5873      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5874    Sched<[WriteVq]> {
5875  bits<5> Rd;
5876  bits<5> Rn;
5877  let Inst{31}    = 0;
5878  let Inst{30}    = Q;
5879  let Inst{29-24} = 0b101110;
5880  let Inst{23-22} = size;
5881  let Inst{21-10} = 0b100001001110;
5882  let Inst{9-5}   = Rn;
5883  let Inst{4-0}   = Rd;
5884}
5885
5886multiclass SIMDVectorLShiftLongBySizeBHS {
5887  let hasSideEffects = 0 in {
5888  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5889                                             "shll", ".8h",  ".8b", "8">;
5890  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5891                                             "shll2", ".8h", ".16b", "8">;
5892  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5893                                             "shll", ".4s",  ".4h", "16">;
5894  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5895                                             "shll2", ".4s", ".8h", "16">;
5896  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5897                                             "shll", ".2d",  ".2s", "32">;
5898  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5899                                             "shll2", ".2d", ".4s", "32">;
5900  }
5901}
5902
5903// Supports all element sizes.
5904multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5905                             SDPatternOperator OpNode> {
5906  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5907                                      asm, ".4h", ".8b",
5908               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5909  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5910                                      asm, ".8h", ".16b",
5911               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5912  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5913                                      asm, ".2s", ".4h",
5914               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5915  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5916                                      asm, ".4s", ".8h",
5917               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5918  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5919                                      asm, ".1d", ".2s",
5920               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5921  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5922                                      asm, ".2d", ".4s",
5923               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5924}
5925
5926multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5927                                 SDPatternOperator OpNode> {
5928  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5929                                          asm, ".4h", ".8b",
5930      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5931                                      (v8i8 V64:$Rn)))]>;
5932  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5933                                          asm, ".8h", ".16b",
5934      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5935                                      (v16i8 V128:$Rn)))]>;
5936  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5937                                          asm, ".2s", ".4h",
5938      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5939                                      (v4i16 V64:$Rn)))]>;
5940  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5941                                          asm, ".4s", ".8h",
5942      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5943                                      (v8i16 V128:$Rn)))]>;
5944  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5945                                          asm, ".1d", ".2s",
5946      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5947                                      (v2i32 V64:$Rn)))]>;
5948  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5949                                          asm, ".2d", ".4s",
5950      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5951                                      (v4i32 V128:$Rn)))]>;
5952}
5953
5954// Supports all element sizes, except 1xD.
5955multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5956                                  SDPatternOperator OpNode> {
5957  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5958                                    asm, ".8b", ".8b",
5959    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5960  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5961                                    asm, ".16b", ".16b",
5962    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5963  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5964                                    asm, ".4h", ".4h",
5965    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5966  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5967                                    asm, ".8h", ".8h",
5968    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5969  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5970                                    asm, ".2s", ".2s",
5971    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5972  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5973                                    asm, ".4s", ".4s",
5974    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5975  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5976                                    asm, ".2d", ".2d",
5977    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5978}
5979
5980multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5981                             SDPatternOperator OpNode = null_frag> {
5982  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5983                                asm, ".8b", ".8b",
5984    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5985  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5986                                asm, ".16b", ".16b",
5987    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5988  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5989                                asm, ".4h", ".4h",
5990    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5991  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5992                                asm, ".8h", ".8h",
5993    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5994  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5995                                asm, ".2s", ".2s",
5996    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5997  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5998                                asm, ".4s", ".4s",
5999    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6000  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
6001                                asm, ".2d", ".2d",
6002    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6003}
6004
6005
6006// Supports only B element sizes.
6007multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
6008                          SDPatternOperator OpNode> {
6009  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
6010                                asm, ".8b", ".8b",
6011                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6012  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
6013                                asm, ".16b", ".16b",
6014                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6015
6016}
6017
6018// Supports only B and H element sizes.
6019multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
6020                                SDPatternOperator OpNode> {
6021  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6022                                asm, ".8b", ".8b",
6023                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
6024  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6025                                asm, ".16b", ".16b",
6026                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
6027  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6028                                asm, ".4h", ".4h",
6029                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
6030  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6031                                asm, ".8h", ".8h",
6032                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
6033}
6034
6035// Supports H, S and D element sizes, uses high bit of the size field
6036// as an extra opcode bit.
6037multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
6038                           SDPatternOperator OpNode,
6039                           int fpexceptions = 1> {
6040  let mayRaiseFPException = fpexceptions in {
6041  let Predicates = [HasNEON, HasFullFP16] in {
6042  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6043                                asm, ".4h", ".4h",
6044                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6045  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6046                                asm, ".8h", ".8h",
6047                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6048  } // Predicates = [HasNEON, HasFullFP16]
6049  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6050                                asm, ".2s", ".2s",
6051                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6052  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6053                                asm, ".4s", ".4s",
6054                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6055  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6056                                asm, ".2d", ".2d",
6057                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6058  }
6059}
6060
6061multiclass SIMDTwoVectorFPNoException<bit U, bit S, bits<5> opc, string asm,
6062                                      SDPatternOperator OpNode>
6063    : SIMDTwoVectorFP<U, S, opc, asm, OpNode, 0>;
6064
6065// Supports only S and D element sizes
6066let mayRaiseFPException = 1 in
6067multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6068                           SDPatternOperator OpNode = null_frag> {
6069
6070  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6071                                asm, ".2s", ".2s",
6072                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6073  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6074                                asm, ".4s", ".4s",
6075                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6076  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6077                                asm, ".2d", ".2d",
6078                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6079}
6080
6081multiclass FRIntNNTVector<bit U, bit op, string asm,
6082                          SDPatternOperator OpNode = null_frag> :
6083           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6084
6085// Supports only S element size.
6086multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6087                           SDPatternOperator OpNode> {
6088  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6089                                asm, ".2s", ".2s",
6090                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6091  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6092                                asm, ".4s", ".4s",
6093                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6094}
6095
6096let mayRaiseFPException = 1 in
6097multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6098                           SDPatternOperator OpNode> {
6099  let Predicates = [HasNEON, HasFullFP16] in {
6100  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6101                                asm, ".4h", ".4h",
6102                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6103  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6104                                asm, ".8h", ".8h",
6105                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6106  } // Predicates = [HasNEON, HasFullFP16]
6107  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6108                                asm, ".2s", ".2s",
6109                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6110  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6111                                asm, ".4s", ".4s",
6112                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6113  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6114                                asm, ".2d", ".2d",
6115                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6116}
6117
6118let mayRaiseFPException = 1 in
6119multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6120                           SDPatternOperator OpNode> {
6121  let Predicates = [HasNEON, HasFullFP16] in {
6122  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6123                                asm, ".4h", ".4h",
6124                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6125  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6126                                asm, ".8h", ".8h",
6127                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6128  } // Predicates = [HasNEON, HasFullFP16]
6129  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6130                                asm, ".2s", ".2s",
6131                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6132  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6133                                asm, ".4s", ".4s",
6134                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6135  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6136                                asm, ".2d", ".2d",
6137                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6138}
6139
6140let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6141class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6142                           RegisterOperand inreg, RegisterOperand outreg,
6143                           string asm, string outkind, string inkind,
6144                           list<dag> pattern>
6145  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6146      "{\t$Rd" # outkind # ", $Rn" # inkind #
6147      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6148    Sched<[WriteVq]> {
6149  bits<5> Rd;
6150  bits<5> Rn;
6151  let Inst{31}    = 0;
6152  let Inst{30}    = Q;
6153  let Inst{29}    = U;
6154  let Inst{28-24} = 0b01110;
6155  let Inst{23-22} = size;
6156  let Inst{21-17} = 0b10000;
6157  let Inst{16-12} = opcode;
6158  let Inst{11-10} = 0b10;
6159  let Inst{9-5}   = Rn;
6160  let Inst{4-0}   = Rd;
6161}
6162
6163let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6164class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6165                           RegisterOperand inreg, RegisterOperand outreg,
6166                           string asm, string outkind, string inkind,
6167                           list<dag> pattern>
6168  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6169      "{\t$Rd" # outkind # ", $Rn" # inkind #
6170      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6171    Sched<[WriteVq]> {
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
6186multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6187                              SDPatternOperator OpNode> {
6188  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6189                                      asm, ".8b", ".8h",
6190        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6191  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6192                                      asm#"2", ".16b", ".8h", []>;
6193  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6194                                      asm, ".4h", ".4s",
6195        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6196  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6197                                      asm#"2", ".8h", ".4s", []>;
6198  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6199                                      asm, ".2s", ".2d",
6200        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6201  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6202                                      asm#"2", ".4s", ".2d", []>;
6203
6204  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6205            (!cast<Instruction>(NAME # "v16i8")
6206                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6207  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6208            (!cast<Instruction>(NAME # "v8i16")
6209                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6210  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6211            (!cast<Instruction>(NAME # "v4i32")
6212                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6213}
6214
6215class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6216                           bits<5> opcode, RegisterOperand regtype, string asm,
6217                           string kind, string zero, ValueType dty,
6218                           ValueType sty, SDNode OpNode>
6219  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6220      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6221      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6222      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6223    Sched<[!if(Q, WriteVq, WriteVd)]> {
6224  bits<5> Rd;
6225  bits<5> Rn;
6226  let Inst{31}    = 0;
6227  let Inst{30}    = Q;
6228  let Inst{29}    = U;
6229  let Inst{28-24} = 0b01110;
6230  let Inst{23-22} = size;
6231  let Inst{21} = 0b1;
6232  let Inst{20-19} = size2;
6233  let Inst{18-17} = 0b00;
6234  let Inst{16-12} = opcode;
6235  let Inst{11-10} = 0b10;
6236  let Inst{9-5}   = Rn;
6237  let Inst{4-0}   = Rd;
6238}
6239
6240// Comparisons support all element sizes, except 1xD.
6241multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6242                            SDNode OpNode> {
6243  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6244                                     asm, ".8b", "0",
6245                                     v8i8, v8i8, OpNode>;
6246  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6247                                     asm, ".16b", "0",
6248                                     v16i8, v16i8, OpNode>;
6249  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6250                                     asm, ".4h", "0",
6251                                     v4i16, v4i16, OpNode>;
6252  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6253                                     asm, ".8h", "0",
6254                                     v8i16, v8i16, OpNode>;
6255  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6256                                     asm, ".2s", "0",
6257                                     v2i32, v2i32, OpNode>;
6258  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6259                                     asm, ".4s", "0",
6260                                     v4i32, v4i32, OpNode>;
6261  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6262                                     asm, ".2d", "0",
6263                                     v2i64, v2i64, OpNode>;
6264}
6265
6266// FP Comparisons support only S and D element sizes (and H for v8.2a).
6267multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6268                              string asm, SDNode OpNode> {
6269
6270  let mayRaiseFPException = 1 in {
6271  let Predicates = [HasNEON, HasFullFP16] in {
6272  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6273                                     asm, ".4h", "0.0",
6274                                     v4i16, v4f16, OpNode>;
6275  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6276                                     asm, ".8h", "0.0",
6277                                     v8i16, v8f16, OpNode>;
6278  } // Predicates = [HasNEON, HasFullFP16]
6279  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6280                                     asm, ".2s", "0.0",
6281                                     v2i32, v2f32, OpNode>;
6282  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6283                                     asm, ".4s", "0.0",
6284                                     v4i32, v4f32, OpNode>;
6285  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6286                                     asm, ".2d", "0.0",
6287                                     v2i64, v2f64, OpNode>;
6288  }
6289
6290  let Predicates = [HasNEON, HasFullFP16] in {
6291  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6292                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6293  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6294                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6295  }
6296  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6297                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6298  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6299                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6300  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6301                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6302  let Predicates = [HasNEON, HasFullFP16] in {
6303  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6304                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6305  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6306                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6307  }
6308  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6309                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6310  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6311                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6312  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6313                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6314}
6315
6316let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
6317class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6318                             RegisterOperand outtype, RegisterOperand intype,
6319                             string asm, string VdTy, string VnTy,
6320                             list<dag> pattern>
6321  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6322      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6323    Sched<[WriteVq]> {
6324  bits<5> Rd;
6325  bits<5> Rn;
6326  let Inst{31}    = 0;
6327  let Inst{30}    = Q;
6328  let Inst{29}    = U;
6329  let Inst{28-24} = 0b01110;
6330  let Inst{23-22} = size;
6331  let Inst{21-17} = 0b10000;
6332  let Inst{16-12} = opcode;
6333  let Inst{11-10} = 0b10;
6334  let Inst{9-5}   = Rn;
6335  let Inst{4-0}   = Rd;
6336}
6337
6338let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
6339class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6340                             RegisterOperand outtype, RegisterOperand intype,
6341                             string asm, string VdTy, string VnTy,
6342                             list<dag> pattern>
6343  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6344      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6345    Sched<[WriteVq]> {
6346  bits<5> Rd;
6347  bits<5> Rn;
6348  let Inst{31}    = 0;
6349  let Inst{30}    = Q;
6350  let Inst{29}    = U;
6351  let Inst{28-24} = 0b01110;
6352  let Inst{23-22} = size;
6353  let Inst{21-17} = 0b10000;
6354  let Inst{16-12} = opcode;
6355  let Inst{11-10} = 0b10;
6356  let Inst{9-5}   = Rn;
6357  let Inst{4-0}   = Rd;
6358}
6359
6360multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6361  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6362                                    asm, ".4s", ".4h", []>;
6363  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6364                                    asm#"2", ".4s", ".8h", []>;
6365  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6366                                    asm, ".2d", ".2s", []>;
6367  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6368                                    asm#"2", ".2d", ".4s", []>;
6369}
6370
6371multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6372  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6373                                    asm, ".4h", ".4s", []>;
6374  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6375                                    asm#"2", ".8h", ".4s", []>;
6376  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6377                                    asm, ".2s", ".2d", []>;
6378  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6379                                    asm#"2", ".4s", ".2d", []>;
6380}
6381
6382multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6383                                     Intrinsic OpNode> {
6384  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6385                                     asm, ".2s", ".2d",
6386                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6387  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6388                                    asm#"2", ".4s", ".2d", []>;
6389
6390  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6391            (!cast<Instruction>(NAME # "v4f32")
6392                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6393}
6394
6395//----------------------------------------------------------------------------
6396// AdvSIMD three register different-size vector instructions.
6397//----------------------------------------------------------------------------
6398
6399let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6400class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6401                      RegisterOperand outtype, RegisterOperand intype1,
6402                      RegisterOperand intype2, string asm,
6403                      string outkind, string inkind1, string inkind2,
6404                      list<dag> pattern>
6405  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6406      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6407      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6408    Sched<[WriteVq]> {
6409  bits<5> Rd;
6410  bits<5> Rn;
6411  bits<5> Rm;
6412  let Inst{31}    = 0;
6413  let Inst{30}    = size{0};
6414  let Inst{29}    = U;
6415  let Inst{28-24} = 0b01110;
6416  let Inst{23-22} = size{2-1};
6417  let Inst{21}    = 1;
6418  let Inst{20-16} = Rm;
6419  let Inst{15-12} = opcode;
6420  let Inst{11-10} = 0b00;
6421  let Inst{9-5}   = Rn;
6422  let Inst{4-0}   = Rd;
6423}
6424
6425let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6426class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6427                      RegisterOperand outtype, RegisterOperand intype1,
6428                      RegisterOperand intype2, string asm,
6429                      string outkind, string inkind1, string inkind2,
6430                      list<dag> pattern>
6431  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6432      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6433      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6434    Sched<[WriteVq]> {
6435  bits<5> Rd;
6436  bits<5> Rn;
6437  bits<5> Rm;
6438  let Inst{31}    = 0;
6439  let Inst{30}    = size{0};
6440  let Inst{29}    = U;
6441  let Inst{28-24} = 0b01110;
6442  let Inst{23-22} = size{2-1};
6443  let Inst{21}    = 1;
6444  let Inst{20-16} = Rm;
6445  let Inst{15-12} = opcode;
6446  let Inst{11-10} = 0b00;
6447  let Inst{9-5}   = Rn;
6448  let Inst{4-0}   = Rd;
6449}
6450
6451// FIXME: TableGen doesn't know how to deal with expanded types that also
6452//        change the element count (in this case, placing the results in
6453//        the high elements of the result register rather than the low
6454//        elements). Until that's fixed, we can't code-gen those.
6455multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6456                                    Intrinsic IntOp> {
6457  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6458                                                  V64, V128, V128,
6459                                                  asm, ".8b", ".8h", ".8h",
6460     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6461  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6462                                                  V128, V128, V128,
6463                                                  asm#"2", ".16b", ".8h", ".8h",
6464     []>;
6465  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6466                                                  V64, V128, V128,
6467                                                  asm, ".4h", ".4s", ".4s",
6468     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6469  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6470                                                  V128, V128, V128,
6471                                                  asm#"2", ".8h", ".4s", ".4s",
6472     []>;
6473  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6474                                                  V64, V128, V128,
6475                                                  asm, ".2s", ".2d", ".2d",
6476     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6477  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6478                                                  V128, V128, V128,
6479                                                  asm#"2", ".4s", ".2d", ".2d",
6480     []>;
6481
6482
6483  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6484  // a version attached to an instruction.
6485  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6486                                                   (v8i16 V128:$Rm))),
6487            (!cast<Instruction>(NAME # "v8i16_v16i8")
6488                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6489                V128:$Rn, V128:$Rm)>;
6490  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6491                                                    (v4i32 V128:$Rm))),
6492            (!cast<Instruction>(NAME # "v4i32_v8i16")
6493                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6494                V128:$Rn, V128:$Rm)>;
6495  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6496                                                    (v2i64 V128:$Rm))),
6497            (!cast<Instruction>(NAME # "v2i64_v4i32")
6498                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6499                V128:$Rn, V128:$Rm)>;
6500}
6501
6502multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6503                                      Intrinsic IntOp> {
6504  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6505                                            V128, V64, V64,
6506                                            asm, ".8h", ".8b", ".8b",
6507      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6508  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6509                                            V128, V128, V128,
6510                                            asm#"2", ".8h", ".16b", ".16b", []>;
6511  let Predicates = [HasAES] in {
6512    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6513                                              V128, V64, V64,
6514                                              asm, ".1q", ".1d", ".1d", []>;
6515    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6516                                              V128, V128, V128,
6517                                              asm#"2", ".1q", ".2d", ".2d", []>;
6518  }
6519
6520  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 (v16i8 V128:$Rn))),
6521                          (v8i8 (extract_high_v16i8 (v16i8 V128:$Rm))))),
6522      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6523}
6524
6525multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6526                                 SDPatternOperator OpNode> {
6527  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6528                                                  V128, V64, V64,
6529                                                  asm, ".4s", ".4h", ".4h",
6530      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6531  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6532                                                  V128, V128, V128,
6533                                                  asm#"2", ".4s", ".8h", ".8h",
6534      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6535                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6536  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6537                                                  V128, V64, V64,
6538                                                  asm, ".2d", ".2s", ".2s",
6539      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6540  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6541                                                  V128, V128, V128,
6542                                                  asm#"2", ".2d", ".4s", ".4s",
6543      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6544                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6545}
6546
6547multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6548                                  SDPatternOperator OpNode = null_frag> {
6549  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6550                                                  V128, V64, V64,
6551                                                  asm, ".8h", ".8b", ".8b",
6552      [(set (v8i16 V128:$Rd),
6553            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6554  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6555                                                 V128, V128, V128,
6556                                                 asm#"2", ".8h", ".16b", ".16b",
6557      [(set (v8i16 V128:$Rd),
6558            (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6559                                (extract_high_v16i8 (v16i8 V128:$Rm))))))]>;
6560  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6561                                                  V128, V64, V64,
6562                                                  asm, ".4s", ".4h", ".4h",
6563      [(set (v4i32 V128:$Rd),
6564            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6565  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6566                                                  V128, V128, V128,
6567                                                  asm#"2", ".4s", ".8h", ".8h",
6568      [(set (v4i32 V128:$Rd),
6569            (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6570                                  (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6571  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6572                                                  V128, V64, V64,
6573                                                  asm, ".2d", ".2s", ".2s",
6574      [(set (v2i64 V128:$Rd),
6575            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6576  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6577                                                  V128, V128, V128,
6578                                                  asm#"2", ".2d", ".4s", ".4s",
6579      [(set (v2i64 V128:$Rd),
6580            (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6581                                 (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6582}
6583
6584multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6585                                          string asm,
6586                                          SDPatternOperator OpNode> {
6587  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6588                                                  V128, V64, V64,
6589                                                  asm, ".8h", ".8b", ".8b",
6590    [(set (v8i16 V128:$dst),
6591          (add (v8i16 V128:$Rd),
6592               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6593  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6594                                                 V128, V128, V128,
6595                                                 asm#"2", ".8h", ".16b", ".16b",
6596    [(set (v8i16 V128:$dst),
6597          (add (v8i16 V128:$Rd),
6598               (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6599                                   (extract_high_v16i8 (v16i8 V128:$Rm)))))))]>;
6600  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6601                                                  V128, V64, V64,
6602                                                  asm, ".4s", ".4h", ".4h",
6603    [(set (v4i32 V128:$dst),
6604          (add (v4i32 V128:$Rd),
6605               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6606  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6607                                                  V128, V128, V128,
6608                                                  asm#"2", ".4s", ".8h", ".8h",
6609    [(set (v4i32 V128:$dst),
6610          (add (v4i32 V128:$Rd),
6611               (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6612                                    (extract_high_v8i16 (v8i16 V128:$Rm)))))))]>;
6613  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6614                                                  V128, V64, V64,
6615                                                  asm, ".2d", ".2s", ".2s",
6616    [(set (v2i64 V128:$dst),
6617          (add (v2i64 V128:$Rd),
6618               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6619  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6620                                                  V128, V128, V128,
6621                                                  asm#"2", ".2d", ".4s", ".4s",
6622    [(set (v2i64 V128:$dst),
6623          (add (v2i64 V128:$Rd),
6624               (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6625                                    (extract_high_v4i32 (v4i32 V128:$Rm)))))))]>;
6626}
6627
6628multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6629                                  SDPatternOperator OpNode = null_frag> {
6630  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6631                                                  V128, V64, V64,
6632                                                  asm, ".8h", ".8b", ".8b",
6633      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6634  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6635                                                 V128, V128, V128,
6636                                                 asm#"2", ".8h", ".16b", ".16b",
6637      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6638                                      (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6639  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6640                                                  V128, V64, V64,
6641                                                  asm, ".4s", ".4h", ".4h",
6642      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6643  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6644                                                  V128, V128, V128,
6645                                                  asm#"2", ".4s", ".8h", ".8h",
6646      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6647                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6648  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6649                                                  V128, V64, V64,
6650                                                  asm, ".2d", ".2s", ".2s",
6651      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6652  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6653                                                  V128, V128, V128,
6654                                                  asm#"2", ".2d", ".4s", ".4s",
6655      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6656                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6657}
6658
6659multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6660                                      string asm,
6661                                      SDPatternOperator OpNode> {
6662  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6663                                                  V128, V64, V64,
6664                                                  asm, ".8h", ".8b", ".8b",
6665    [(set (v8i16 V128:$dst),
6666          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6667  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6668                                                 V128, V128, V128,
6669                                                 asm#"2", ".8h", ".16b", ".16b",
6670    [(set (v8i16 V128:$dst),
6671          (OpNode (v8i16 V128:$Rd),
6672                  (extract_high_v16i8 (v16i8 V128:$Rn)),
6673                  (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6674  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6675                                                  V128, V64, V64,
6676                                                  asm, ".4s", ".4h", ".4h",
6677    [(set (v4i32 V128:$dst),
6678          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6679  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6680                                                  V128, V128, V128,
6681                                                  asm#"2", ".4s", ".8h", ".8h",
6682    [(set (v4i32 V128:$dst),
6683          (OpNode (v4i32 V128:$Rd),
6684                  (extract_high_v8i16 (v8i16 V128:$Rn)),
6685                  (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6686  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6687                                                  V128, V64, V64,
6688                                                  asm, ".2d", ".2s", ".2s",
6689    [(set (v2i64 V128:$dst),
6690          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6691  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6692                                                  V128, V128, V128,
6693                                                  asm#"2", ".2d", ".4s", ".4s",
6694    [(set (v2i64 V128:$dst),
6695          (OpNode (v2i64 V128:$Rd),
6696                  (extract_high_v4i32 (v4i32 V128:$Rn)),
6697                  (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6698}
6699
6700multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6701                                           SDPatternOperator Accum> {
6702  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6703                                                  V128, V64, V64,
6704                                                  asm, ".4s", ".4h", ".4h",
6705    [(set (v4i32 V128:$dst),
6706          (Accum (v4i32 V128:$Rd),
6707                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6708                                                (v4i16 V64:$Rm)))))]>;
6709  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6710                                                  V128, V128, V128,
6711                                                  asm#"2", ".4s", ".8h", ".8h",
6712    [(set (v4i32 V128:$dst),
6713          (Accum (v4i32 V128:$Rd),
6714                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 (v8i16 V128:$Rn)),
6715                                            (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6716  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6717                                                  V128, V64, V64,
6718                                                  asm, ".2d", ".2s", ".2s",
6719    [(set (v2i64 V128:$dst),
6720          (Accum (v2i64 V128:$Rd),
6721                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6722                                                (v2i32 V64:$Rm)))))]>;
6723  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6724                                                  V128, V128, V128,
6725                                                  asm#"2", ".2d", ".4s", ".4s",
6726    [(set (v2i64 V128:$dst),
6727          (Accum (v2i64 V128:$Rd),
6728                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 (v4i32 V128:$Rn)),
6729                                            (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6730}
6731
6732multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6733                                  SDPatternOperator OpNode> {
6734  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6735                                                  V128, V128, V64,
6736                                                  asm, ".8h", ".8h", ".8b",
6737       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6738  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6739                                                  V128, V128, V128,
6740                                                  asm#"2", ".8h", ".8h", ".16b",
6741       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6742                                       (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6743  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6744                                                  V128, V128, V64,
6745                                                  asm, ".4s", ".4s", ".4h",
6746       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6747  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6748                                                  V128, V128, V128,
6749                                                  asm#"2", ".4s", ".4s", ".8h",
6750       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6751                                       (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6752  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6753                                                  V128, V128, V64,
6754                                                  asm, ".2d", ".2d", ".2s",
6755       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6756  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6757                                                  V128, V128, V128,
6758                                                  asm#"2", ".2d", ".2d", ".4s",
6759       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6760                                       (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6761}
6762
6763//----------------------------------------------------------------------------
6764// AdvSIMD bitwise extract from vector
6765//----------------------------------------------------------------------------
6766
6767class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6768                             string asm, string kind>
6769  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6770      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6771      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6772      [(set (vty regtype:$Rd),
6773            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6774    Sched<[!if(size, WriteVq, WriteVd)]> {
6775  bits<5> Rd;
6776  bits<5> Rn;
6777  bits<5> Rm;
6778  bits<4> imm;
6779  let Inst{31}    = 0;
6780  let Inst{30}    = size;
6781  let Inst{29-21} = 0b101110000;
6782  let Inst{20-16} = Rm;
6783  let Inst{15}    = 0;
6784  let Inst{14-11} = imm;
6785  let Inst{10}    = 0;
6786  let Inst{9-5}   = Rn;
6787  let Inst{4-0}   = Rd;
6788}
6789
6790
6791multiclass SIMDBitwiseExtract<string asm> {
6792  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6793    let imm{3} = 0;
6794  }
6795  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6796}
6797
6798//----------------------------------------------------------------------------
6799// AdvSIMD zip vector
6800//----------------------------------------------------------------------------
6801
6802class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6803                        string asm, string kind, SDNode OpNode, ValueType valty>
6804  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6805      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6806      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6807      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6808    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
6809  bits<5> Rd;
6810  bits<5> Rn;
6811  bits<5> Rm;
6812  let Inst{31}    = 0;
6813  let Inst{30}    = size{0};
6814  let Inst{29-24} = 0b001110;
6815  let Inst{23-22} = size{2-1};
6816  let Inst{21}    = 0;
6817  let Inst{20-16} = Rm;
6818  let Inst{15}    = 0;
6819  let Inst{14-12} = opc;
6820  let Inst{11-10} = 0b10;
6821  let Inst{9-5}   = Rn;
6822  let Inst{4-0}   = Rd;
6823}
6824
6825multiclass SIMDZipVector<bits<3>opc, string asm,
6826                         SDNode OpNode> {
6827  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6828      asm, ".8b", OpNode, v8i8>;
6829  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6830      asm, ".16b", OpNode, v16i8>;
6831  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6832      asm, ".4h", OpNode, v4i16>;
6833  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6834      asm, ".8h", OpNode, v8i16>;
6835  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6836      asm, ".2s", OpNode, v2i32>;
6837  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6838      asm, ".4s", OpNode, v4i32>;
6839  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6840      asm, ".2d", OpNode, v2i64>;
6841
6842  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6843        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6844  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6845        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6846  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6847        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6848  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6849        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6850  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6851        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6852}
6853
6854//----------------------------------------------------------------------------
6855// AdvSIMD three register scalar instructions
6856//----------------------------------------------------------------------------
6857
6858let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6859class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6860                        RegisterClass regtype, string asm,
6861                        list<dag> pattern>
6862  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6863      "\t$Rd, $Rn, $Rm", "", pattern>,
6864    Sched<[WriteVd]> {
6865  bits<5> Rd;
6866  bits<5> Rn;
6867  bits<5> Rm;
6868  let Inst{31-30} = 0b01;
6869  let Inst{29}    = U;
6870  let Inst{28-24} = 0b11110;
6871  let Inst{23-21} = size;
6872  let Inst{20-16} = Rm;
6873  let Inst{15-11} = opcode;
6874  let Inst{10}    = 1;
6875  let Inst{9-5}   = Rn;
6876  let Inst{4-0}   = Rd;
6877}
6878
6879let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6880class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6881                        dag oops, dag iops, string asm,
6882            list<dag> pattern>
6883  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6884    Sched<[WriteVd]> {
6885  bits<5> Rd;
6886  bits<5> Rn;
6887  bits<5> Rm;
6888  let Inst{31-30} = 0b01;
6889  let Inst{29}    = U;
6890  let Inst{28-24} = 0b11110;
6891  let Inst{23-22} = size;
6892  let Inst{21}    = R;
6893  let Inst{20-16} = Rm;
6894  let Inst{15-11} = opcode;
6895  let Inst{10}    = 1;
6896  let Inst{9-5}   = Rn;
6897  let Inst{4-0}   = Rd;
6898}
6899
6900multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6901                            SDPatternOperator OpNode> {
6902  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6903    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6904}
6905
6906multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6907                               SDPatternOperator OpNode> {
6908  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6909    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6910  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6911  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6912  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6913
6914  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6915            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6916  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6917            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6918}
6919
6920multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6921                             SDPatternOperator OpNode> {
6922  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6923                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6924  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6925}
6926
6927multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
6928  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6929                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6930                                     asm, []>;
6931  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6932                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6933                                     asm, []>;
6934}
6935
6936multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6937                             SDPatternOperator OpNode = null_frag,
6938                             Predicate pred = HasNEON> {
6939  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in {
6940    let Predicates = [pred] in {
6941    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6942      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6943    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6944      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6945    }
6946    let Predicates = [pred, HasFullFP16] in {
6947    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6948      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
6949    }
6950  }
6951
6952  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6953            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6954}
6955
6956multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6957                                SDPatternOperator OpNode = null_frag> {
6958  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in {
6959    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6960      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6961    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6962      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6963    let Predicates = [HasNEON, HasFullFP16] in {
6964    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6965      []>;
6966    } // Predicates = [HasNEON, HasFullFP16]
6967  }
6968
6969  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6970            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6971}
6972
6973class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6974              dag oops, dag iops, string asm, string cstr, list<dag> pat>
6975  : I<oops, iops, asm,
6976      "\t$Rd, $Rn, $Rm", cstr, pat>,
6977    Sched<[WriteVd]> {
6978  bits<5> Rd;
6979  bits<5> Rn;
6980  bits<5> Rm;
6981  let Inst{31-30} = 0b01;
6982  let Inst{29}    = U;
6983  let Inst{28-24} = 0b11110;
6984  let Inst{23-22} = size;
6985  let Inst{21}    = 1;
6986  let Inst{20-16} = Rm;
6987  let Inst{15-11} = opcode;
6988  let Inst{10}    = 0;
6989  let Inst{9-5}   = Rn;
6990  let Inst{4-0}   = Rd;
6991}
6992
6993let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6994multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6995                                  SDPatternOperator OpNode = null_frag> {
6996  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6997                                      (outs FPR32:$Rd),
6998                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6999  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7000                                      (outs FPR64:$Rd),
7001                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
7002            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7003}
7004
7005let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7006multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
7007                                  SDPatternOperator OpNode = null_frag> {
7008  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7009                                      (outs FPR32:$dst),
7010                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
7011                                      asm, "$Rd = $dst", []>;
7012  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7013                                      (outs FPR64:$dst),
7014                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
7015                                      asm, "$Rd = $dst",
7016            [(set (i64 FPR64:$dst),
7017                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7018}
7019
7020//----------------------------------------------------------------------------
7021// AdvSIMD two register scalar instructions
7022//----------------------------------------------------------------------------
7023
7024let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7025class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7026                        RegisterClass regtype, RegisterClass regtype2,
7027                        string asm, list<dag> pat>
7028  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
7029      "\t$Rd, $Rn", "", pat>,
7030    Sched<[WriteVd]> {
7031  bits<5> Rd;
7032  bits<5> Rn;
7033  let Inst{31-30} = 0b01;
7034  let Inst{29}    = U;
7035  let Inst{28-24} = 0b11110;
7036  let Inst{23-22} = size;
7037  let Inst{21} = 0b1;
7038  let Inst{20-19} = size2;
7039  let Inst{18-17} = 0b00;
7040  let Inst{16-12} = opcode;
7041  let Inst{11-10} = 0b10;
7042  let Inst{9-5}   = Rn;
7043  let Inst{4-0}   = Rd;
7044}
7045
7046let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7047class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
7048                        RegisterClass regtype, RegisterClass regtype2,
7049                        string asm, list<dag> pat>
7050  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
7051      "\t$Rd, $Rn", "$Rd = $dst", pat>,
7052    Sched<[WriteVd]> {
7053  bits<5> Rd;
7054  bits<5> Rn;
7055  let Inst{31-30} = 0b01;
7056  let Inst{29}    = U;
7057  let Inst{28-24} = 0b11110;
7058  let Inst{23-22} = size;
7059  let Inst{21-17} = 0b10000;
7060  let Inst{16-12} = opcode;
7061  let Inst{11-10} = 0b10;
7062  let Inst{9-5}   = Rn;
7063  let Inst{4-0}   = Rd;
7064}
7065
7066
7067let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7068class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7069                        RegisterClass regtype, string asm, string zero>
7070  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7071      "\t$Rd, $Rn, #" # zero, "", []>,
7072    Sched<[WriteVd]> {
7073  bits<5> Rd;
7074  bits<5> Rn;
7075  let Inst{31-30} = 0b01;
7076  let Inst{29}    = U;
7077  let Inst{28-24} = 0b11110;
7078  let Inst{23-22} = size;
7079  let Inst{21} = 0b1;
7080  let Inst{20-19} = size2;
7081  let Inst{18-17} = 0b00;
7082  let Inst{16-12} = opcode;
7083  let Inst{11-10} = 0b10;
7084  let Inst{9-5}   = Rn;
7085  let Inst{4-0}   = Rd;
7086}
7087
7088let mayRaiseFPException = 1 in
7089class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7090  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7091     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
7092    Sched<[WriteVd]> {
7093  bits<5> Rd;
7094  bits<5> Rn;
7095  let Inst{31-17} = 0b011111100110000;
7096  let Inst{16-12} = opcode;
7097  let Inst{11-10} = 0b10;
7098  let Inst{9-5}   = Rn;
7099  let Inst{4-0}   = Rd;
7100}
7101
7102multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7103                             SDPatternOperator OpNode> {
7104  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7105
7106  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7107            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7108}
7109
7110multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7111                              SDPatternOperator OpNode> {
7112  let mayRaiseFPException = 1 in {
7113  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7114  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7115  let Predicates = [HasNEON, HasFullFP16] in {
7116  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7117  }
7118  }
7119
7120  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7121                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7122  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7123                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7124  let Predicates = [HasNEON, HasFullFP16] in {
7125  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7126                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7127  }
7128
7129  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7130            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7131}
7132
7133multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7134                          SDPatternOperator OpNode = null_frag> {
7135  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7136    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7137
7138  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7139            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7140}
7141
7142let mayRaiseFPException = 1 in
7143multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm,
7144                           Predicate pred = HasNEON> {
7145  let Predicates = [pred] in {
7146  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7147  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7148  }
7149  let Predicates = [pred, HasFullFP16] in {
7150  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7151  }
7152}
7153
7154let mayRaiseFPException = 1 in
7155multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7156                              SDPatternOperator OpNode> {
7157  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7158                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7159  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7160                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7161  let Predicates = [HasNEON, HasFullFP16] in {
7162  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7163                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7164  }
7165}
7166
7167multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7168                             SDPatternOperator OpNode = null_frag> {
7169  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7170    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7171           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7172    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7173           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7174    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7175    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7176  }
7177
7178  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7179            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7180}
7181
7182multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7183                                 Intrinsic OpNode> {
7184  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7185    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7186        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7187    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7188        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7189    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7190    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7191  }
7192
7193  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7194            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7195}
7196
7197
7198
7199let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7200multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7201                                 SDPatternOperator OpNode = null_frag> {
7202  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7203        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7204  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7205  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7206}
7207
7208//----------------------------------------------------------------------------
7209// AdvSIMD scalar pairwise instructions
7210//----------------------------------------------------------------------------
7211
7212let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7213class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7214                        RegisterOperand regtype, RegisterOperand vectype,
7215                        string asm, string kind>
7216  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7217      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7218    Sched<[WriteVd]> {
7219  bits<5> Rd;
7220  bits<5> Rn;
7221  let Inst{31-30} = 0b01;
7222  let Inst{29}    = U;
7223  let Inst{28-24} = 0b11110;
7224  let Inst{23-22} = size;
7225  let Inst{21-17} = 0b11000;
7226  let Inst{16-12} = opcode;
7227  let Inst{11-10} = 0b10;
7228  let Inst{9-5}   = Rn;
7229  let Inst{4-0}   = Rd;
7230}
7231
7232multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7233  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7234                                      asm, ".2d">;
7235}
7236
7237let mayRaiseFPException = 1 in
7238multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7239  let Predicates = [HasNEON, HasFullFP16] in {
7240  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7241                                      asm, ".2h">;
7242  }
7243  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7244                                      asm, ".2s">;
7245  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7246                                      asm, ".2d">;
7247}
7248
7249//----------------------------------------------------------------------------
7250// AdvSIMD across lanes instructions
7251//----------------------------------------------------------------------------
7252
7253let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7254class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7255                          RegisterClass regtype, RegisterOperand vectype,
7256                          string asm, string kind, list<dag> pattern>
7257  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7258      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7259    Sched<[!if(Q, WriteVq, WriteVd)]> {
7260  bits<5> Rd;
7261  bits<5> Rn;
7262  let Inst{31}    = 0;
7263  let Inst{30}    = Q;
7264  let Inst{29}    = U;
7265  let Inst{28-24} = 0b01110;
7266  let Inst{23-22} = size;
7267  let Inst{21-17} = 0b11000;
7268  let Inst{16-12} = opcode;
7269  let Inst{11-10} = 0b10;
7270  let Inst{9-5}   = Rn;
7271  let Inst{4-0}   = Rd;
7272}
7273
7274multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7275                              string asm> {
7276  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7277                                   asm, ".8b", []>;
7278  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7279                                   asm, ".16b", []>;
7280  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7281                                   asm, ".4h", []>;
7282  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7283                                   asm, ".8h", []>;
7284  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7285                                   asm, ".4s", []>;
7286}
7287
7288multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7289  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7290                                   asm, ".8b", []>;
7291  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7292                                   asm, ".16b", []>;
7293  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7294                                   asm, ".4h", []>;
7295  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7296                                   asm, ".8h", []>;
7297  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7298                                   asm, ".4s", []>;
7299}
7300
7301let mayRaiseFPException = 1 in
7302multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7303                            Intrinsic intOp> {
7304  let Predicates = [HasNEON, HasFullFP16] in {
7305  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7306                                   asm, ".4h",
7307        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7308  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7309                                   asm, ".8h",
7310        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7311  } // Predicates = [HasNEON, HasFullFP16]
7312  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7313                                   asm, ".4s",
7314        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7315}
7316
7317//----------------------------------------------------------------------------
7318// AdvSIMD INS/DUP instructions
7319//----------------------------------------------------------------------------
7320
7321// FIXME: There has got to be a better way to factor these. ugh.
7322
7323class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7324                     string operands, string constraints, list<dag> pattern>
7325  : I<outs, ins, asm, operands, constraints, pattern>,
7326    Sched<[!if(Q, WriteVq, WriteVd)]> {
7327  bits<5> Rd;
7328  bits<5> Rn;
7329  let Inst{31} = 0;
7330  let Inst{30} = Q;
7331  let Inst{29} = op;
7332  let Inst{28-21} = 0b01110000;
7333  let Inst{15} = 0;
7334  let Inst{10} = 1;
7335  let Inst{9-5} = Rn;
7336  let Inst{4-0} = Rd;
7337}
7338
7339class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7340                      RegisterOperand vecreg, RegisterClass regtype>
7341  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7342                   "{\t$Rd" # size # ", $Rn" #
7343                   "|" # size # "\t$Rd, $Rn}", "",
7344                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7345  let Inst{20-16} = imm5;
7346  let Inst{14-11} = 0b0001;
7347}
7348
7349class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7350                         ValueType vectype, ValueType insreg,
7351                         RegisterOperand vecreg, Operand idxtype,
7352                         SDNode OpNode>
7353  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7354                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7355                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7356                 [(set (vectype vecreg:$Rd),
7357                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7358  let Inst{14-11} = 0b0000;
7359}
7360
7361class SIMDDup64FromElement
7362  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7363                       VectorIndexD, AArch64duplane64> {
7364  bits<1> idx;
7365  let Inst{20} = idx;
7366  let Inst{19-16} = 0b1000;
7367}
7368
7369class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7370                           RegisterOperand vecreg>
7371  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7372                       VectorIndexS, AArch64duplane32> {
7373  bits<2> idx;
7374  let Inst{20-19} = idx;
7375  let Inst{18-16} = 0b100;
7376}
7377
7378class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7379                           RegisterOperand vecreg>
7380  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7381                       VectorIndexH, AArch64duplane16> {
7382  bits<3> idx;
7383  let Inst{20-18} = idx;
7384  let Inst{17-16} = 0b10;
7385}
7386
7387class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7388                          RegisterOperand vecreg>
7389  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7390                       VectorIndexB, AArch64duplane8> {
7391  bits<4> idx;
7392  let Inst{20-17} = idx;
7393  let Inst{16} = 1;
7394}
7395
7396class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7397                  Operand idxtype, string asm, list<dag> pattern>
7398  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7399                   "{\t$Rd, $Rn" # size # "$idx" #
7400                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7401  let Inst{14-11} = imm4;
7402}
7403
7404class SIMDSMov<bit Q, string size, RegisterClass regtype,
7405               Operand idxtype>
7406  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7407class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7408               Operand idxtype>
7409  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7410      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7411
7412class SIMDMovAlias<string asm, string size, Instruction inst,
7413                   RegisterClass regtype, Operand idxtype>
7414    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7415                    "|" # size # "\t$dst, $src$idx}",
7416                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7417
7418multiclass SMov {
7419  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7420  // streaming mode.
7421  let Predicates = [HasNEONorSME] in {
7422    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
7423      let Inst{20-16} = 0b00001;
7424    }
7425    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
7426      let Inst{20-16} = 0b00001;
7427    }
7428    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
7429      let Inst{20-16} = 0b00010;
7430    }
7431    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
7432      let Inst{20-16} = 0b00010;
7433    }
7434    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
7435      let Inst{20-16} = 0b00100;
7436    }
7437  }
7438  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7439    bits<4> idx;
7440    let Inst{20-17} = idx;
7441    let Inst{16} = 1;
7442  }
7443  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7444    bits<4> idx;
7445    let Inst{20-17} = idx;
7446    let Inst{16} = 1;
7447  }
7448  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7449    bits<3> idx;
7450    let Inst{20-18} = idx;
7451    let Inst{17-16} = 0b10;
7452  }
7453  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7454    bits<3> idx;
7455    let Inst{20-18} = idx;
7456    let Inst{17-16} = 0b10;
7457  }
7458  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7459    bits<2> idx;
7460    let Inst{20-19} = idx;
7461    let Inst{18-16} = 0b100;
7462  }
7463}
7464
7465multiclass UMov {
7466  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7467  // streaming mode.
7468  let Predicates = [HasNEONorSME] in {
7469    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
7470      let Inst{20-16} = 0b00001;
7471    }
7472    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
7473      let Inst{20-16} = 0b00010;
7474    }
7475    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
7476      let Inst{20-16} = 0b00100;
7477    }
7478    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
7479      let Inst{20-16} = 0b01000;
7480    }
7481    def : SIMDMovAlias<"mov", ".s",
7482                       !cast<Instruction>(NAME # vi32_idx0),
7483                       GPR32, VectorIndex0>;
7484    def : SIMDMovAlias<"mov", ".d",
7485                       !cast<Instruction>(NAME # vi64_idx0),
7486                       GPR64, VectorIndex0>;
7487  }
7488  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7489    bits<4> idx;
7490    let Inst{20-17} = idx;
7491    let Inst{16} = 1;
7492  }
7493  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7494    bits<3> idx;
7495    let Inst{20-18} = idx;
7496    let Inst{17-16} = 0b10;
7497  }
7498  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7499    bits<2> idx;
7500    let Inst{20-19} = idx;
7501    let Inst{18-16} = 0b100;
7502  }
7503  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7504    bits<1> idx;
7505    let Inst{20} = idx;
7506    let Inst{19-16} = 0b1000;
7507  }
7508  def : SIMDMovAlias<"mov", ".s",
7509                     !cast<Instruction>(NAME#"vi32"),
7510                     GPR32, VectorIndexS>;
7511  def : SIMDMovAlias<"mov", ".d",
7512                     !cast<Instruction>(NAME#"vi64"),
7513                     GPR64, VectorIndexD>;
7514}
7515
7516class SIMDInsFromMain<string size, ValueType vectype,
7517                      RegisterClass regtype, Operand idxtype>
7518  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7519                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7520                   "{\t$Rd" # size # "$idx, $Rn" #
7521                   "|" # size # "\t$Rd$idx, $Rn}",
7522                   "$Rd = $dst",
7523            [(set V128:$dst,
7524              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7525  let Inst{14-11} = 0b0011;
7526}
7527
7528class SIMDInsFromElement<string size, ValueType vectype,
7529                         ValueType elttype, Operand idxtype>
7530  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7531                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7532                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7533                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7534                   "$Rd = $dst",
7535         [(set V128:$dst,
7536               (vector_insert
7537                 (vectype V128:$Rd),
7538                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7539                 idxtype:$idx))]>;
7540
7541class SIMDInsMainMovAlias<string size, Instruction inst,
7542                          RegisterClass regtype, Operand idxtype>
7543    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7544                        "|" # size #"\t$dst$idx, $src}",
7545                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7546class SIMDInsElementMovAlias<string size, Instruction inst,
7547                             Operand idxtype>
7548    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7549                      # "|" # size #"\t$dst$idx, $src$idx2}",
7550                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7551
7552
7553multiclass SIMDIns {
7554  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7555    bits<4> idx;
7556    let Inst{20-17} = idx;
7557    let Inst{16} = 1;
7558  }
7559  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7560    bits<3> idx;
7561    let Inst{20-18} = idx;
7562    let Inst{17-16} = 0b10;
7563  }
7564  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7565    bits<2> idx;
7566    let Inst{20-19} = idx;
7567    let Inst{18-16} = 0b100;
7568  }
7569  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7570    bits<1> idx;
7571    let Inst{20} = idx;
7572    let Inst{19-16} = 0b1000;
7573  }
7574
7575  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7576    bits<4> idx;
7577    bits<4> idx2;
7578    let Inst{20-17} = idx;
7579    let Inst{16} = 1;
7580    let Inst{14-11} = idx2;
7581  }
7582  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7583    bits<3> idx;
7584    bits<3> idx2;
7585    let Inst{20-18} = idx;
7586    let Inst{17-16} = 0b10;
7587    let Inst{14-12} = idx2;
7588    let Inst{11} = {?};
7589  }
7590  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7591    bits<2> idx;
7592    bits<2> idx2;
7593    let Inst{20-19} = idx;
7594    let Inst{18-16} = 0b100;
7595    let Inst{14-13} = idx2;
7596    let Inst{12-11} = {?,?};
7597  }
7598  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7599    bits<1> idx;
7600    bits<1> idx2;
7601    let Inst{20} = idx;
7602    let Inst{19-16} = 0b1000;
7603    let Inst{14} = idx2;
7604    let Inst{13-11} = {?,?,?};
7605  }
7606
7607  // For all forms of the INS instruction, the "mov" mnemonic is the
7608  // preferred alias. Why they didn't just call the instruction "mov" in
7609  // the first place is a very good question indeed...
7610  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7611                         GPR32, VectorIndexB>;
7612  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7613                         GPR32, VectorIndexH>;
7614  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7615                         GPR32, VectorIndexS>;
7616  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7617                         GPR64, VectorIndexD>;
7618
7619  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7620                         VectorIndexB>;
7621  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7622                         VectorIndexH>;
7623  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7624                         VectorIndexS>;
7625  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7626                         VectorIndexD>;
7627}
7628
7629//----------------------------------------------------------------------------
7630// AdvSIMD TBL/TBX
7631//----------------------------------------------------------------------------
7632
7633let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7634class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7635                          RegisterOperand listtype, string asm, string kind>
7636  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7637       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7638    Sched<[!if(Q, WriteVq, WriteVd)]> {
7639  bits<5> Vd;
7640  bits<5> Vn;
7641  bits<5> Vm;
7642  let Inst{31}    = 0;
7643  let Inst{30}    = Q;
7644  let Inst{29-21} = 0b001110000;
7645  let Inst{20-16} = Vm;
7646  let Inst{15}    = 0;
7647  let Inst{14-13} = len;
7648  let Inst{12}    = op;
7649  let Inst{11-10} = 0b00;
7650  let Inst{9-5}   = Vn;
7651  let Inst{4-0}   = Vd;
7652}
7653
7654let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7655class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7656                          RegisterOperand listtype, string asm, string kind>
7657  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7658       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7659    Sched<[!if(Q, WriteVq, WriteVd)]> {
7660  bits<5> Vd;
7661  bits<5> Vn;
7662  bits<5> Vm;
7663  let Inst{31}    = 0;
7664  let Inst{30}    = Q;
7665  let Inst{29-21} = 0b001110000;
7666  let Inst{20-16} = Vm;
7667  let Inst{15}    = 0;
7668  let Inst{14-13} = len;
7669  let Inst{12}    = op;
7670  let Inst{11-10} = 0b00;
7671  let Inst{9-5}   = Vn;
7672  let Inst{4-0}   = Vd;
7673}
7674
7675class SIMDTableLookupAlias<string asm, Instruction inst,
7676                          RegisterOperand vectype, RegisterOperand listtype>
7677    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7678                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7679
7680multiclass SIMDTableLookup<bit op, string asm> {
7681  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7682                                      asm, ".8b">;
7683  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7684                                      asm, ".8b">;
7685  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7686                                      asm, ".8b">;
7687  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7688                                      asm, ".8b">;
7689  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7690                                      asm, ".16b">;
7691  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7692                                      asm, ".16b">;
7693  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7694                                      asm, ".16b">;
7695  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7696                                      asm, ".16b">;
7697
7698  def : SIMDTableLookupAlias<asm # ".8b",
7699                         !cast<Instruction>(NAME#"v8i8One"),
7700                         V64, VecListOne128>;
7701  def : SIMDTableLookupAlias<asm # ".8b",
7702                         !cast<Instruction>(NAME#"v8i8Two"),
7703                         V64, VecListTwo128>;
7704  def : SIMDTableLookupAlias<asm # ".8b",
7705                         !cast<Instruction>(NAME#"v8i8Three"),
7706                         V64, VecListThree128>;
7707  def : SIMDTableLookupAlias<asm # ".8b",
7708                         !cast<Instruction>(NAME#"v8i8Four"),
7709                         V64, VecListFour128>;
7710  def : SIMDTableLookupAlias<asm # ".16b",
7711                         !cast<Instruction>(NAME#"v16i8One"),
7712                         V128, VecListOne128>;
7713  def : SIMDTableLookupAlias<asm # ".16b",
7714                         !cast<Instruction>(NAME#"v16i8Two"),
7715                         V128, VecListTwo128>;
7716  def : SIMDTableLookupAlias<asm # ".16b",
7717                         !cast<Instruction>(NAME#"v16i8Three"),
7718                         V128, VecListThree128>;
7719  def : SIMDTableLookupAlias<asm # ".16b",
7720                         !cast<Instruction>(NAME#"v16i8Four"),
7721                         V128, VecListFour128>;
7722}
7723
7724multiclass SIMDTableLookupTied<bit op, string asm> {
7725  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7726                                      asm, ".8b">;
7727  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7728                                      asm, ".8b">;
7729  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7730                                      asm, ".8b">;
7731  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7732                                      asm, ".8b">;
7733  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7734                                      asm, ".16b">;
7735  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7736                                      asm, ".16b">;
7737  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7738                                      asm, ".16b">;
7739  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7740                                      asm, ".16b">;
7741
7742  def : SIMDTableLookupAlias<asm # ".8b",
7743                         !cast<Instruction>(NAME#"v8i8One"),
7744                         V64, VecListOne128>;
7745  def : SIMDTableLookupAlias<asm # ".8b",
7746                         !cast<Instruction>(NAME#"v8i8Two"),
7747                         V64, VecListTwo128>;
7748  def : SIMDTableLookupAlias<asm # ".8b",
7749                         !cast<Instruction>(NAME#"v8i8Three"),
7750                         V64, VecListThree128>;
7751  def : SIMDTableLookupAlias<asm # ".8b",
7752                         !cast<Instruction>(NAME#"v8i8Four"),
7753                         V64, VecListFour128>;
7754  def : SIMDTableLookupAlias<asm # ".16b",
7755                         !cast<Instruction>(NAME#"v16i8One"),
7756                         V128, VecListOne128>;
7757  def : SIMDTableLookupAlias<asm # ".16b",
7758                         !cast<Instruction>(NAME#"v16i8Two"),
7759                         V128, VecListTwo128>;
7760  def : SIMDTableLookupAlias<asm # ".16b",
7761                         !cast<Instruction>(NAME#"v16i8Three"),
7762                         V128, VecListThree128>;
7763  def : SIMDTableLookupAlias<asm # ".16b",
7764                         !cast<Instruction>(NAME#"v16i8Four"),
7765                         V128, VecListFour128>;
7766}
7767
7768
7769//----------------------------------------------------------------------------
7770// AdvSIMD scalar DUP
7771//----------------------------------------------------------------------------
7772let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7773class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
7774                        string asm, string kind, Operand idxtype>
7775  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
7776       "{\t$dst, $src" # kind # "$idx" #
7777       "|\t$dst, $src$idx}", "", []>,
7778    Sched<[WriteVd]> {
7779  bits<5> dst;
7780  bits<5> src;
7781  let Inst{31-21} = 0b01011110000;
7782  let Inst{15-10} = 0b000001;
7783  let Inst{9-5}   = src;
7784  let Inst{4-0}   = dst;
7785}
7786
7787class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
7788      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7789    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7790                    # "|\t$dst, $src$index}",
7791                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7792
7793
7794multiclass SIMDScalarDUP<string asm> {
7795  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
7796    bits<4> idx;
7797    let Inst{20-17} = idx;
7798    let Inst{16} = 1;
7799  }
7800  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
7801    bits<3> idx;
7802    let Inst{20-18} = idx;
7803    let Inst{17-16} = 0b10;
7804  }
7805  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
7806    bits<2> idx;
7807    let Inst{20-19} = idx;
7808    let Inst{18-16} = 0b100;
7809  }
7810  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
7811    bits<1> idx;
7812    let Inst{20} = idx;
7813    let Inst{19-16} = 0b1000;
7814  }
7815
7816  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7817                                                          VectorIndexD:$idx)))),
7818            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7819
7820  // 'DUP' mnemonic aliases.
7821  def : SIMDScalarDUPAlias<"dup", ".b",
7822                           !cast<Instruction>(NAME#"i8"),
7823                           FPR8, V128, VectorIndexB>;
7824  def : SIMDScalarDUPAlias<"dup", ".h",
7825                           !cast<Instruction>(NAME#"i16"),
7826                           FPR16, V128, VectorIndexH>;
7827  def : SIMDScalarDUPAlias<"dup", ".s",
7828                           !cast<Instruction>(NAME#"i32"),
7829                           FPR32, V128, VectorIndexS>;
7830  def : SIMDScalarDUPAlias<"dup", ".d",
7831                           !cast<Instruction>(NAME#"i64"),
7832                           FPR64, V128, VectorIndexD>;
7833}
7834
7835//----------------------------------------------------------------------------
7836// AdvSIMD modified immediate instructions
7837//----------------------------------------------------------------------------
7838
7839class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7840                          string asm, string op_string,
7841                          string cstr, list<dag> pattern>
7842  : I<oops, iops, asm, op_string, cstr, pattern>,
7843    Sched<[!if(Q, WriteVq, WriteVd)]> {
7844  bits<5> Rd;
7845  bits<8> imm8;
7846  let Inst{31}    = 0;
7847  let Inst{30}    = Q;
7848  let Inst{29}    = op;
7849  let Inst{28-19} = 0b0111100000;
7850  let Inst{18-16} = imm8{7-5};
7851  let Inst{11} = op2;
7852  let Inst{10} = 1;
7853  let Inst{9-5}   = imm8{4-0};
7854  let Inst{4-0}   = Rd;
7855}
7856
7857class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7858                                Operand immtype, dag opt_shift_iop,
7859                                string opt_shift, string asm, string kind,
7860                                list<dag> pattern>
7861  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7862                        !con((ins immtype:$imm8), opt_shift_iop), asm,
7863                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
7864                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7865                        "", pattern> {
7866  let DecoderMethod = "DecodeModImmInstruction";
7867}
7868
7869class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7870                                Operand immtype, dag opt_shift_iop,
7871                                string opt_shift, string asm, string kind,
7872                                list<dag> pattern>
7873  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7874                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7875                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7876                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7877                        "$Rd = $dst", pattern> {
7878  let DecoderMethod = "DecodeModImmTiedInstruction";
7879}
7880
7881class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7882                                     RegisterOperand vectype, string asm,
7883                                     string kind, list<dag> pattern>
7884  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7885                              (ins logical_vec_shift:$shift),
7886                              "$shift", asm, kind, pattern> {
7887  bits<2> shift;
7888  let Inst{15}    = b15_b12{1};
7889  let Inst{14-13} = shift;
7890  let Inst{12}    = b15_b12{0};
7891}
7892
7893class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7894                                     RegisterOperand vectype, string asm,
7895                                     string kind, list<dag> pattern>
7896  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7897                              (ins logical_vec_shift:$shift),
7898                              "$shift", asm, kind, pattern> {
7899  bits<2> shift;
7900  let Inst{15}    = b15_b12{1};
7901  let Inst{14-13} = shift;
7902  let Inst{12}    = b15_b12{0};
7903}
7904
7905
7906class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7907                                         RegisterOperand vectype, string asm,
7908                                         string kind, list<dag> pattern>
7909  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7910                              (ins logical_vec_hw_shift:$shift),
7911                              "$shift", asm, kind, pattern> {
7912  bits<2> shift;
7913  let Inst{15} = b15_b12{1};
7914  let Inst{14} = 0;
7915  let Inst{13} = shift{0};
7916  let Inst{12} = b15_b12{0};
7917}
7918
7919class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7920                                         RegisterOperand vectype, string asm,
7921                                         string kind, list<dag> pattern>
7922  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7923                              (ins logical_vec_hw_shift:$shift),
7924                              "$shift", asm, kind, pattern> {
7925  bits<2> shift;
7926  let Inst{15} = b15_b12{1};
7927  let Inst{14} = 0;
7928  let Inst{13} = shift{0};
7929  let Inst{12} = b15_b12{0};
7930}
7931
7932multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7933                                      string asm> {
7934  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7935                                                 asm, ".4h", []>;
7936  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7937                                                 asm, ".8h", []>;
7938
7939  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7940                                             asm, ".2s", []>;
7941  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7942                                             asm, ".4s", []>;
7943}
7944
7945multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7946                                      bits<2> w_cmode, string asm,
7947                                      SDNode OpNode> {
7948  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7949                                                 asm, ".4h",
7950             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7951                                             imm0_255:$imm8,
7952                                             (i32 imm:$shift)))]>;
7953  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7954                                                 asm, ".8h",
7955             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7956                                              imm0_255:$imm8,
7957                                              (i32 imm:$shift)))]>;
7958
7959  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7960                                             asm, ".2s",
7961             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7962                                             imm0_255:$imm8,
7963                                             (i32 imm:$shift)))]>;
7964  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7965                                             asm, ".4s",
7966             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7967                                              imm0_255:$imm8,
7968                                              (i32 imm:$shift)))]>;
7969}
7970
7971class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7972                             RegisterOperand vectype, string asm,
7973                             string kind, list<dag> pattern>
7974  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7975                              (ins move_vec_shift:$shift),
7976                              "$shift", asm, kind, pattern> {
7977  bits<1> shift;
7978  let Inst{15-13} = cmode{3-1};
7979  let Inst{12}    = shift;
7980}
7981
7982class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7983                                   RegisterOperand vectype,
7984                                   Operand imm_type, string asm,
7985                                   string kind, list<dag> pattern>
7986  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7987                              asm, kind, pattern> {
7988  let Inst{15-12} = cmode;
7989}
7990
7991class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7992                                   list<dag> pattern>
7993  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7994                        "\t$Rd, $imm8", "", pattern> {
7995  let Inst{15-12} = cmode;
7996  let DecoderMethod = "DecodeModImmInstruction";
7997}
7998
7999//----------------------------------------------------------------------------
8000// AdvSIMD indexed element
8001//----------------------------------------------------------------------------
8002
8003let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8004class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8005                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8006                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8007                      string apple_kind, string dst_kind, string lhs_kind,
8008                      string rhs_kind, list<dag> pattern>
8009  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
8010      asm,
8011      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8012      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
8013    Sched<[WriteVd]> {
8014  bits<5> Rd;
8015  bits<5> Rn;
8016  bits<5> Rm;
8017
8018  let Inst{31}    = 0;
8019  let Inst{30}    = Q;
8020  let Inst{29}    = U;
8021  let Inst{28}    = Scalar;
8022  let Inst{27-24} = 0b1111;
8023  let Inst{23-22} = size;
8024  // Bit 21 must be set by the derived class.
8025  let Inst{20-16} = Rm;
8026  let Inst{15-12} = opc;
8027  // Bit 11 must be set by the derived class.
8028  let Inst{10}    = 0;
8029  let Inst{9-5}   = Rn;
8030  let Inst{4-0}   = Rd;
8031}
8032
8033let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8034class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8035                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8036                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8037                      string apple_kind, string dst_kind, string lhs_kind,
8038                      string rhs_kind, list<dag> pattern>
8039  : I<(outs dst_reg:$dst),
8040      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
8041      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8042      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
8043    Sched<[WriteVd]> {
8044  bits<5> Rd;
8045  bits<5> Rn;
8046  bits<5> Rm;
8047
8048  let Inst{31}    = 0;
8049  let Inst{30}    = Q;
8050  let Inst{29}    = U;
8051  let Inst{28}    = Scalar;
8052  let Inst{27-24} = 0b1111;
8053  let Inst{23-22} = size;
8054  // Bit 21 must be set by the derived class.
8055  let Inst{20-16} = Rm;
8056  let Inst{15-12} = opc;
8057  // Bit 11 must be set by the derived class.
8058  let Inst{10}    = 0;
8059  let Inst{9-5}   = Rn;
8060  let Inst{4-0}   = Rd;
8061}
8062
8063
8064//----------------------------------------------------------------------------
8065// Armv8.6 BFloat16 Extension
8066//----------------------------------------------------------------------------
8067let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8068
8069class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8070                                   string kind2, RegisterOperand RegType,
8071                                   ValueType AccumType, ValueType InputType>
8072  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8073                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8074                                            (InputType RegType:$Rn),
8075                                            (InputType RegType:$Rm)))]> {
8076  let AsmString = !strconcat(asm,
8077                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8078                               ", $Rm" # kind2 # "}");
8079}
8080
8081multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8082  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8083                                           v2f32, v4bf16>;
8084  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8085                                           v4f32, v8bf16>;
8086}
8087
8088class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
8089                                      string dst_kind, string lhs_kind,
8090                                      string rhs_kind,
8091                                      RegisterOperand RegType,
8092                                      ValueType AccumType,
8093                                      ValueType InputType>
8094  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
8095                        RegType, RegType, V128, VectorIndexS,
8096                        asm, "", dst_kind, lhs_kind, rhs_kind,
8097        [(set (AccumType RegType:$dst),
8098              (AccumType (int_aarch64_neon_bfdot
8099                                 (AccumType RegType:$Rd),
8100                                 (InputType RegType:$Rn),
8101                                 (InputType (bitconvert (AccumType
8102                                    (AArch64duplane32 (v4f32 V128:$Rm),
8103                                        VectorIndexS:$idx)))))))]> {
8104
8105  bits<2> idx;
8106  let Inst{21}    = idx{0};  // L
8107  let Inst{11}    = idx{1};  // H
8108}
8109
8110multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
8111
8112  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
8113                                               ".2h", V64, v2f32, v4bf16>;
8114  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
8115                                              ".2h", V128, v4f32, v8bf16>;
8116}
8117
8118let mayRaiseFPException = 1 in
8119class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
8120  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
8121              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
8122                                               (v8bf16 V128:$Rn),
8123                                               (v8bf16 V128:$Rm)))]> {
8124  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
8125}
8126
8127let mayRaiseFPException = 1 in
8128class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
8129  : I<(outs V128:$dst),
8130      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
8131      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
8132          [(set (v4f32 V128:$dst),
8133                (v4f32 (OpNode (v4f32 V128:$Rd),
8134                               (v8bf16 V128:$Rn),
8135                               (v8bf16
8136                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
8137                                      VectorIndexH:$idx)))))]>,
8138    Sched<[WriteVq]> {
8139  bits<5> Rd;
8140  bits<5> Rn;
8141  bits<4> Rm;
8142  bits<3> idx;
8143
8144  let Inst{31}    = 0;
8145  let Inst{30}    = Q;
8146  let Inst{29-22} = 0b00111111;
8147  let Inst{21-20} = idx{1-0};
8148  let Inst{19-16} = Rm;
8149  let Inst{15-12} = 0b1111;
8150  let Inst{11}    = idx{2};   // H
8151  let Inst{10}    = 0;
8152  let Inst{9-5}   = Rn;
8153  let Inst{4-0}   = Rd;
8154}
8155
8156class SIMDThreeSameVectorBF16MatrixMul<string asm>
8157  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
8158                                V128, asm, ".4s",
8159                          [(set (v4f32 V128:$dst),
8160                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
8161                                                         (v8bf16 V128:$Rn),
8162                                                         (v8bf16 V128:$Rm)))]> {
8163  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8164                                    ", $Rm", ".8h", "}");
8165}
8166
8167let mayRaiseFPException = 1 in
8168class SIMD_BFCVTN
8169  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8170                           "bfcvtn", ".4h", ".4s",
8171    [(set (v8bf16 V128:$Rd),
8172          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8173
8174let mayRaiseFPException = 1 in
8175class SIMD_BFCVTN2
8176  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8177                           "bfcvtn2", ".8h", ".4s",
8178    [(set (v8bf16 V128:$dst),
8179          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8180
8181let mayRaiseFPException = 1 in
8182class BF16ToSinglePrecision<string asm>
8183  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8184    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8185    Sched<[WriteFCvt]> {
8186  bits<5> Rd;
8187  bits<5> Rn;
8188  let Inst{31-10} = 0b0001111001100011010000;
8189  let Inst{9-5}   = Rn;
8190  let Inst{4-0}   = Rd;
8191}
8192} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8193
8194//----------------------------------------------------------------------------
8195// Armv8.6 Matrix Multiply Extension
8196//----------------------------------------------------------------------------
8197
8198class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8199  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8200              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8201                                               (v16i8 V128:$Rn),
8202                                               (v16i8 V128:$Rm)))]> {
8203  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8204}
8205
8206//----------------------------------------------------------------------------
8207// ARMv8.2-A Dot Product Instructions (Indexed)
8208class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
8209                                      string dst_kind, string lhs_kind, string rhs_kind,
8210                                      RegisterOperand RegType,
8211                                      ValueType AccumType, ValueType InputType,
8212                                      SDPatternOperator OpNode> :
8213        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
8214                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8215        [(set (AccumType RegType:$dst),
8216              (AccumType (OpNode (AccumType RegType:$Rd),
8217                                 (InputType RegType:$Rn),
8218                                 (InputType (bitconvert (AccumType
8219                                    (AArch64duplane32 (v4i32 V128:$Rm),
8220                                        VectorIndexS:$idx)))))))]> {
8221  bits<2> idx;
8222  let Inst{21}    = idx{0};  // L
8223  let Inst{11}    = idx{1};  // H
8224}
8225
8226multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8227                                       SDPatternOperator OpNode> {
8228  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
8229                                              V64, v2i32, v8i8, OpNode>;
8230  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
8231                                              V128, v4i32, v16i8, OpNode>;
8232}
8233
8234// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8235let mayRaiseFPException = 1 in
8236class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
8237                                      string dst_kind, string lhs_kind,
8238                                      string rhs_kind, RegisterOperand RegType,
8239                                      ValueType AccumType, ValueType InputType,
8240                                      SDPatternOperator OpNode> :
8241        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
8242                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8243          [(set (AccumType RegType:$dst),
8244                (AccumType (OpNode (AccumType RegType:$Rd),
8245                                   (InputType RegType:$Rn),
8246                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
8247                                                VectorIndexH:$idx)))))]> {
8248  // idx = H:L:M
8249  bits<3> idx;
8250  let Inst{11} = idx{2}; // H
8251  let Inst{21} = idx{1}; // L
8252  let Inst{20} = idx{0}; // M
8253}
8254
8255multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8256                                       SDPatternOperator OpNode> {
8257  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8258                                              V64, v2f32, v4f16, OpNode>;
8259  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8260                                              V128, v4f32, v8f16, OpNode>;
8261}
8262
8263let mayRaiseFPException = 1 in
8264multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8265                         SDPatternOperator OpNode> {
8266  let Predicates = [HasNEON, HasFullFP16] in {
8267  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8268                                      V64, V64,
8269                                      V128_lo, VectorIndexH,
8270                                      asm, ".4h", ".4h", ".4h", ".h",
8271    [(set (v4f16 V64:$Rd),
8272        (OpNode (v4f16 V64:$Rn),
8273         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8274    bits<3> idx;
8275    let Inst{11} = idx{2};
8276    let Inst{21} = idx{1};
8277    let Inst{20} = idx{0};
8278  }
8279
8280  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8281                                      V128, V128,
8282                                      V128_lo, VectorIndexH,
8283                                      asm, ".8h", ".8h", ".8h", ".h",
8284    [(set (v8f16 V128:$Rd),
8285        (OpNode (v8f16 V128:$Rn),
8286         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8287    bits<3> idx;
8288    let Inst{11} = idx{2};
8289    let Inst{21} = idx{1};
8290    let Inst{20} = idx{0};
8291  }
8292  } // Predicates = [HasNEON, HasFullFP16]
8293
8294  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8295                                      V64, V64,
8296                                      V128, VectorIndexS,
8297                                      asm, ".2s", ".2s", ".2s", ".s",
8298    [(set (v2f32 V64:$Rd),
8299        (OpNode (v2f32 V64:$Rn),
8300         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8301    bits<2> idx;
8302    let Inst{11} = idx{1};
8303    let Inst{21} = idx{0};
8304  }
8305
8306  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8307                                      V128, V128,
8308                                      V128, VectorIndexS,
8309                                      asm, ".4s", ".4s", ".4s", ".s",
8310    [(set (v4f32 V128:$Rd),
8311        (OpNode (v4f32 V128:$Rn),
8312         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8313    bits<2> idx;
8314    let Inst{11} = idx{1};
8315    let Inst{21} = idx{0};
8316  }
8317
8318  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8319                                      V128, V128,
8320                                      V128, VectorIndexD,
8321                                      asm, ".2d", ".2d", ".2d", ".d",
8322    [(set (v2f64 V128:$Rd),
8323        (OpNode (v2f64 V128:$Rn),
8324         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8325    bits<1> idx;
8326    let Inst{11} = idx{0};
8327    let Inst{21} = 0;
8328  }
8329
8330  let Predicates = [HasNEON, HasFullFP16] in {
8331  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8332                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8333                                      asm, ".h", "", "", ".h",
8334    [(set (f16 FPR16Op:$Rd),
8335          (OpNode (f16 FPR16Op:$Rn),
8336                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8337                                       VectorIndexH:$idx))))]> {
8338    bits<3> idx;
8339    let Inst{11} = idx{2};
8340    let Inst{21} = idx{1};
8341    let Inst{20} = idx{0};
8342  }
8343  } // Predicates = [HasNEON, HasFullFP16]
8344
8345  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8346                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8347                                      asm, ".s", "", "", ".s",
8348    [(set (f32 FPR32Op:$Rd),
8349          (OpNode (f32 FPR32Op:$Rn),
8350                  (f32 (vector_extract (v4f32 V128:$Rm),
8351                                       VectorIndexS:$idx))))]> {
8352    bits<2> idx;
8353    let Inst{11} = idx{1};
8354    let Inst{21} = idx{0};
8355  }
8356
8357  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8358                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8359                                      asm, ".d", "", "", ".d",
8360    [(set (f64 FPR64Op:$Rd),
8361          (OpNode (f64 FPR64Op:$Rn),
8362                  (f64 (vector_extract (v2f64 V128:$Rm),
8363                                       VectorIndexD:$idx))))]> {
8364    bits<1> idx;
8365    let Inst{11} = idx{0};
8366    let Inst{21} = 0;
8367  }
8368}
8369
8370multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8371  let Predicates = [HasNEON, HasFullFP16] in {
8372  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8373  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8374                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8375                                           VectorIndexH:$idx))),
8376            (!cast<Instruction>(INST # "v8i16_indexed")
8377                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8378  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8379                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8380            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8381                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8382
8383  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8384                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8385                                           VectorIndexH:$idx))),
8386            (!cast<Instruction>(INST # "v4i16_indexed")
8387                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8388  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8389                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8390            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8391                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8392
8393  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8394                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8395            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8396                V128_lo:$Rm, VectorIndexH:$idx)>;
8397  } // Predicates = [HasNEON, HasFullFP16]
8398
8399  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8400  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8401                           (AArch64duplane32 (v4f32 V128:$Rm),
8402                                           VectorIndexS:$idx))),
8403            (!cast<Instruction>(INST # v2i32_indexed)
8404                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8405  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8406                           (AArch64dup (f32 FPR32Op:$Rm)))),
8407            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8408                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8409
8410
8411  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8412  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8413                           (AArch64duplane32 (v4f32 V128:$Rm),
8414                                           VectorIndexS:$idx))),
8415            (!cast<Instruction>(INST # "v4i32_indexed")
8416                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8417  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8418                           (AArch64dup (f32 FPR32Op:$Rm)))),
8419            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8420                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8421
8422  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8423  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8424                           (AArch64duplane64 (v2f64 V128:$Rm),
8425                                           VectorIndexD:$idx))),
8426            (!cast<Instruction>(INST # "v2i64_indexed")
8427                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8428  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8429                           (AArch64dup (f64 FPR64Op:$Rm)))),
8430            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8431                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8432
8433  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8434  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8435                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8436            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8437                V128:$Rm, VectorIndexS:$idx)>;
8438
8439  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8440  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8441                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8442            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8443                V128:$Rm, VectorIndexD:$idx)>;
8444}
8445
8446let mayRaiseFPException = 1 in
8447multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8448  let Predicates = [HasNEON, HasFullFP16] in {
8449  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8450                                          V128_lo, VectorIndexH,
8451                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8452    bits<3> idx;
8453    let Inst{11} = idx{2};
8454    let Inst{21} = idx{1};
8455    let Inst{20} = idx{0};
8456  }
8457
8458  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8459                                          V128, V128,
8460                                          V128_lo, VectorIndexH,
8461                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8462    bits<3> idx;
8463    let Inst{11} = idx{2};
8464    let Inst{21} = idx{1};
8465    let Inst{20} = idx{0};
8466  }
8467  } // Predicates = [HasNEON, HasFullFP16]
8468
8469  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8470                                          V128, VectorIndexS,
8471                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8472    bits<2> idx;
8473    let Inst{11} = idx{1};
8474    let Inst{21} = idx{0};
8475  }
8476
8477  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8478                                      V128, V128,
8479                                      V128, VectorIndexS,
8480                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8481    bits<2> idx;
8482    let Inst{11} = idx{1};
8483    let Inst{21} = idx{0};
8484  }
8485
8486  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8487                                      V128, V128,
8488                                      V128, VectorIndexD,
8489                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8490    bits<1> idx;
8491    let Inst{11} = idx{0};
8492    let Inst{21} = 0;
8493  }
8494
8495  let Predicates = [HasNEON, HasFullFP16] in {
8496  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8497                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8498                                      asm, ".h", "", "", ".h", []> {
8499    bits<3> idx;
8500    let Inst{11} = idx{2};
8501    let Inst{21} = idx{1};
8502    let Inst{20} = idx{0};
8503  }
8504  } // Predicates = [HasNEON, HasFullFP16]
8505
8506  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8507                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8508                                      asm, ".s", "", "", ".s", []> {
8509    bits<2> idx;
8510    let Inst{11} = idx{1};
8511    let Inst{21} = idx{0};
8512  }
8513
8514  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8515                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8516                                      asm, ".d", "", "", ".d", []> {
8517    bits<1> idx;
8518    let Inst{11} = idx{0};
8519    let Inst{21} = 0;
8520  }
8521}
8522
8523multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8524                                 SDPatternOperator OpNodeLaneQ> {
8525
8526  def : Pat<(v4i16 (OpNodeLane
8527                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8528                     VectorIndexS32b:$idx)),
8529            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8530              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8531              (UImmS1XForm $idx))>;
8532
8533  def : Pat<(v4i16 (OpNodeLaneQ
8534                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8535                     VectorIndexH32b:$idx)),
8536            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8537              (UImmS1XForm $idx))>;
8538
8539  def : Pat<(v8i16 (OpNodeLane
8540                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8541                     VectorIndexS32b:$idx)),
8542            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8543              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8544              (UImmS1XForm $idx))>;
8545
8546  def : Pat<(v8i16 (OpNodeLaneQ
8547                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8548                     VectorIndexH32b:$idx)),
8549            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8550              (UImmS1XForm $idx))>;
8551
8552  def : Pat<(v2i32 (OpNodeLane
8553                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8554                     VectorIndexD32b:$idx)),
8555            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8556              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8557              (UImmS1XForm $idx))>;
8558
8559  def : Pat<(v2i32 (OpNodeLaneQ
8560                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8561                     VectorIndexS32b:$idx)),
8562            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8563              (UImmS1XForm $idx))>;
8564
8565  def : Pat<(v4i32 (OpNodeLane
8566                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8567                     VectorIndexD32b:$idx)),
8568            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8569              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8570              (UImmS1XForm $idx))>;
8571
8572  def : Pat<(v4i32 (OpNodeLaneQ
8573                     (v4i32 V128:$Rn),
8574                     (v4i32 V128:$Rm),
8575                     VectorIndexS32b:$idx)),
8576            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8577              (UImmS1XForm $idx))>;
8578
8579}
8580
8581multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8582                         SDPatternOperator OpNode> {
8583  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8584                                      V128_lo, VectorIndexH,
8585                                      asm, ".4h", ".4h", ".4h", ".h",
8586    [(set (v4i16 V64:$Rd),
8587        (OpNode (v4i16 V64:$Rn),
8588         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8589    bits<3> idx;
8590    let Inst{11} = idx{2};
8591    let Inst{21} = idx{1};
8592    let Inst{20} = idx{0};
8593  }
8594
8595  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8596                                      V128, V128,
8597                                      V128_lo, VectorIndexH,
8598                                      asm, ".8h", ".8h", ".8h", ".h",
8599    [(set (v8i16 V128:$Rd),
8600       (OpNode (v8i16 V128:$Rn),
8601         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8602    bits<3> idx;
8603    let Inst{11} = idx{2};
8604    let Inst{21} = idx{1};
8605    let Inst{20} = idx{0};
8606  }
8607
8608  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8609                                      V64, V64,
8610                                      V128, VectorIndexS,
8611                                      asm, ".2s", ".2s", ".2s",  ".s",
8612    [(set (v2i32 V64:$Rd),
8613       (OpNode (v2i32 V64:$Rn),
8614          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8615    bits<2> idx;
8616    let Inst{11} = idx{1};
8617    let Inst{21} = idx{0};
8618  }
8619
8620  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8621                                      V128, V128,
8622                                      V128, VectorIndexS,
8623                                      asm, ".4s", ".4s", ".4s", ".s",
8624    [(set (v4i32 V128:$Rd),
8625       (OpNode (v4i32 V128:$Rn),
8626          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8627    bits<2> idx;
8628    let Inst{11} = idx{1};
8629    let Inst{21} = idx{0};
8630  }
8631
8632  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8633                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8634                                      asm, ".h", "", "", ".h", []> {
8635    bits<3> idx;
8636    let Inst{11} = idx{2};
8637    let Inst{21} = idx{1};
8638    let Inst{20} = idx{0};
8639  }
8640
8641  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8642                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8643                                      asm, ".s", "", "", ".s",
8644      [(set (i32 FPR32Op:$Rd),
8645            (OpNode FPR32Op:$Rn,
8646                    (i32 (vector_extract (v4i32 V128:$Rm),
8647                                         VectorIndexS:$idx))))]> {
8648    bits<2> idx;
8649    let Inst{11} = idx{1};
8650    let Inst{21} = idx{0};
8651  }
8652}
8653
8654multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8655                               SDPatternOperator OpNode> {
8656  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8657                                      V64, V64,
8658                                      V128_lo, VectorIndexH,
8659                                      asm, ".4h", ".4h", ".4h", ".h",
8660    [(set (v4i16 V64:$Rd),
8661        (OpNode (v4i16 V64:$Rn),
8662         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8663    bits<3> idx;
8664    let Inst{11} = idx{2};
8665    let Inst{21} = idx{1};
8666    let Inst{20} = idx{0};
8667  }
8668
8669  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8670                                      V128, V128,
8671                                      V128_lo, VectorIndexH,
8672                                      asm, ".8h", ".8h", ".8h", ".h",
8673    [(set (v8i16 V128:$Rd),
8674       (OpNode (v8i16 V128:$Rn),
8675         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8676    bits<3> idx;
8677    let Inst{11} = idx{2};
8678    let Inst{21} = idx{1};
8679    let Inst{20} = idx{0};
8680  }
8681
8682  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8683                                      V64, V64,
8684                                      V128, VectorIndexS,
8685                                      asm, ".2s", ".2s", ".2s", ".s",
8686    [(set (v2i32 V64:$Rd),
8687       (OpNode (v2i32 V64:$Rn),
8688          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8689    bits<2> idx;
8690    let Inst{11} = idx{1};
8691    let Inst{21} = idx{0};
8692  }
8693
8694  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8695                                      V128, V128,
8696                                      V128, VectorIndexS,
8697                                      asm, ".4s", ".4s", ".4s", ".s",
8698    [(set (v4i32 V128:$Rd),
8699       (OpNode (v4i32 V128:$Rn),
8700          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8701    bits<2> idx;
8702    let Inst{11} = idx{1};
8703    let Inst{21} = idx{0};
8704  }
8705}
8706
8707multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8708                                   SDPatternOperator OpNode> {
8709  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8710                                          V128_lo, VectorIndexH,
8711                                          asm, ".4h", ".4h", ".4h", ".h",
8712    [(set (v4i16 V64:$dst),
8713        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8714         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8715    bits<3> idx;
8716    let Inst{11} = idx{2};
8717    let Inst{21} = idx{1};
8718    let Inst{20} = idx{0};
8719  }
8720
8721  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8722                                      V128, V128,
8723                                      V128_lo, VectorIndexH,
8724                                      asm, ".8h", ".8h", ".8h", ".h",
8725    [(set (v8i16 V128:$dst),
8726       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8727         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8728    bits<3> idx;
8729    let Inst{11} = idx{2};
8730    let Inst{21} = idx{1};
8731    let Inst{20} = idx{0};
8732  }
8733
8734  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8735                                      V64, V64,
8736                                      V128, VectorIndexS,
8737                                      asm, ".2s", ".2s", ".2s", ".s",
8738    [(set (v2i32 V64:$dst),
8739       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8740          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8741    bits<2> idx;
8742    let Inst{11} = idx{1};
8743    let Inst{21} = idx{0};
8744  }
8745
8746  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8747                                      V128, V128,
8748                                      V128, VectorIndexS,
8749                                      asm, ".4s", ".4s", ".4s", ".s",
8750    [(set (v4i32 V128:$dst),
8751       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8752          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8753    bits<2> idx;
8754    let Inst{11} = idx{1};
8755    let Inst{21} = idx{0};
8756  }
8757}
8758
8759multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8760                             SDPatternOperator OpNode> {
8761  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8762                                      V128, V64,
8763                                      V128_lo, VectorIndexH,
8764                                      asm, ".4s", ".4s", ".4h", ".h",
8765    [(set (v4i32 V128:$Rd),
8766        (OpNode (v4i16 V64:$Rn),
8767         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8768    bits<3> idx;
8769    let Inst{11} = idx{2};
8770    let Inst{21} = idx{1};
8771    let Inst{20} = idx{0};
8772  }
8773
8774  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8775                                      V128, V128,
8776                                      V128_lo, VectorIndexH,
8777                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8778    [(set (v4i32 V128:$Rd),
8779          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
8780                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8781
8782    bits<3> idx;
8783    let Inst{11} = idx{2};
8784    let Inst{21} = idx{1};
8785    let Inst{20} = idx{0};
8786  }
8787
8788  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8789                                      V128, V64,
8790                                      V128, VectorIndexS,
8791                                      asm, ".2d", ".2d", ".2s", ".s",
8792    [(set (v2i64 V128:$Rd),
8793        (OpNode (v2i32 V64:$Rn),
8794         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8795    bits<2> idx;
8796    let Inst{11} = idx{1};
8797    let Inst{21} = idx{0};
8798  }
8799
8800  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8801                                      V128, V128,
8802                                      V128, VectorIndexS,
8803                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8804    [(set (v2i64 V128:$Rd),
8805          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
8806                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8807    bits<2> idx;
8808    let Inst{11} = idx{1};
8809    let Inst{21} = idx{0};
8810  }
8811
8812  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8813                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8814                                      asm, ".h", "", "", ".h", []> {
8815    bits<3> idx;
8816    let Inst{11} = idx{2};
8817    let Inst{21} = idx{1};
8818    let Inst{20} = idx{0};
8819  }
8820
8821  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8822                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8823                                      asm, ".s", "", "", ".s", []> {
8824    bits<2> idx;
8825    let Inst{11} = idx{1};
8826    let Inst{21} = idx{0};
8827  }
8828}
8829
8830multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8831                                       SDPatternOperator Accum> {
8832  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8833                                      V128, V64,
8834                                      V128_lo, VectorIndexH,
8835                                      asm, ".4s", ".4s", ".4h", ".h",
8836    [(set (v4i32 V128:$dst),
8837          (Accum (v4i32 V128:$Rd),
8838                 (v4i32 (int_aarch64_neon_sqdmull
8839                             (v4i16 V64:$Rn),
8840                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8841                                                    VectorIndexH:$idx))))))]> {
8842    bits<3> idx;
8843    let Inst{11} = idx{2};
8844    let Inst{21} = idx{1};
8845    let Inst{20} = idx{0};
8846  }
8847
8848  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8849  // intermediate EXTRACT_SUBREG would be untyped.
8850  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8851                (i32 (vector_extract (v4i32
8852                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8853                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8854                                                    VectorIndexH:$idx)))),
8855                         (i64 0))))),
8856            (EXTRACT_SUBREG
8857                (!cast<Instruction>(NAME # v4i16_indexed)
8858                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8859                    V128_lo:$Rm, VectorIndexH:$idx),
8860                ssub)>;
8861
8862  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8863                                      V128, V128,
8864                                      V128_lo, VectorIndexH,
8865                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8866    [(set (v4i32 V128:$dst),
8867          (Accum (v4i32 V128:$Rd),
8868                 (v4i32 (int_aarch64_neon_sqdmull
8869                            (extract_high_v8i16 (v8i16 V128:$Rn)),
8870                            (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))))]> {
8871    bits<3> idx;
8872    let Inst{11} = idx{2};
8873    let Inst{21} = idx{1};
8874    let Inst{20} = idx{0};
8875  }
8876
8877  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8878                                      V128, V64,
8879                                      V128, VectorIndexS,
8880                                      asm, ".2d", ".2d", ".2s", ".s",
8881    [(set (v2i64 V128:$dst),
8882        (Accum (v2i64 V128:$Rd),
8883               (v2i64 (int_aarch64_neon_sqdmull
8884                          (v2i32 V64:$Rn),
8885                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8886                                                 VectorIndexS:$idx))))))]> {
8887    bits<2> idx;
8888    let Inst{11} = idx{1};
8889    let Inst{21} = idx{0};
8890  }
8891
8892  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8893                                      V128, V128,
8894                                      V128, VectorIndexS,
8895                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8896    [(set (v2i64 V128:$dst),
8897          (Accum (v2i64 V128:$Rd),
8898                 (v2i64 (int_aarch64_neon_sqdmull
8899                            (extract_high_v4i32 (v4i32 V128:$Rn)),
8900                            (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
8901    bits<2> idx;
8902    let Inst{11} = idx{1};
8903    let Inst{21} = idx{0};
8904  }
8905
8906  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8907                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8908                                      asm, ".h", "", "", ".h", []> {
8909    bits<3> idx;
8910    let Inst{11} = idx{2};
8911    let Inst{21} = idx{1};
8912    let Inst{20} = idx{0};
8913  }
8914
8915
8916  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8917                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8918                                      asm, ".s", "", "", ".s",
8919    [(set (i64 FPR64Op:$dst),
8920          (Accum (i64 FPR64Op:$Rd),
8921                 (i64 (int_aarch64_neon_sqdmulls_scalar
8922                            (i32 FPR32Op:$Rn),
8923                            (i32 (vector_extract (v4i32 V128:$Rm),
8924                                                 VectorIndexS:$idx))))))]> {
8925
8926    bits<2> idx;
8927    let Inst{11} = idx{1};
8928    let Inst{21} = idx{0};
8929  }
8930}
8931
8932multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8933                                   SDPatternOperator OpNode> {
8934  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8935  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8936                                      V128, V64,
8937                                      V128_lo, VectorIndexH,
8938                                      asm, ".4s", ".4s", ".4h", ".h",
8939    [(set (v4i32 V128:$Rd),
8940        (OpNode (v4i16 V64:$Rn),
8941         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8942    bits<3> idx;
8943    let Inst{11} = idx{2};
8944    let Inst{21} = idx{1};
8945    let Inst{20} = idx{0};
8946  }
8947
8948  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8949                                      V128, V128,
8950                                      V128_lo, VectorIndexH,
8951                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8952    [(set (v4i32 V128:$Rd),
8953          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
8954                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8955
8956    bits<3> idx;
8957    let Inst{11} = idx{2};
8958    let Inst{21} = idx{1};
8959    let Inst{20} = idx{0};
8960  }
8961
8962  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8963                                      V128, V64,
8964                                      V128, VectorIndexS,
8965                                      asm, ".2d", ".2d", ".2s", ".s",
8966    [(set (v2i64 V128:$Rd),
8967        (OpNode (v2i32 V64:$Rn),
8968         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8969    bits<2> idx;
8970    let Inst{11} = idx{1};
8971    let Inst{21} = idx{0};
8972  }
8973
8974  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8975                                      V128, V128,
8976                                      V128, VectorIndexS,
8977                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8978    [(set (v2i64 V128:$Rd),
8979          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
8980                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8981    bits<2> idx;
8982    let Inst{11} = idx{1};
8983    let Inst{21} = idx{0};
8984  }
8985  }
8986}
8987
8988multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8989                                       SDPatternOperator OpNode> {
8990  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8991  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8992                                      V128, V64,
8993                                      V128_lo, VectorIndexH,
8994                                      asm, ".4s", ".4s", ".4h", ".h",
8995    [(set (v4i32 V128:$dst),
8996        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8997         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8998    bits<3> idx;
8999    let Inst{11} = idx{2};
9000    let Inst{21} = idx{1};
9001    let Inst{20} = idx{0};
9002  }
9003
9004  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9005                                      V128, V128,
9006                                      V128_lo, VectorIndexH,
9007                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9008    [(set (v4i32 V128:$dst),
9009          (OpNode (v4i32 V128:$Rd),
9010                  (extract_high_v8i16 (v8i16 V128:$Rn)),
9011                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9012    bits<3> idx;
9013    let Inst{11} = idx{2};
9014    let Inst{21} = idx{1};
9015    let Inst{20} = idx{0};
9016  }
9017
9018  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9019                                      V128, V64,
9020                                      V128, VectorIndexS,
9021                                      asm, ".2d", ".2d", ".2s", ".s",
9022    [(set (v2i64 V128:$dst),
9023        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
9024         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9025    bits<2> idx;
9026    let Inst{11} = idx{1};
9027    let Inst{21} = idx{0};
9028  }
9029
9030  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9031                                      V128, V128,
9032                                      V128, VectorIndexS,
9033                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9034    [(set (v2i64 V128:$dst),
9035          (OpNode (v2i64 V128:$Rd),
9036                  (extract_high_v4i32 (v4i32 V128:$Rn)),
9037                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9038    bits<2> idx;
9039    let Inst{11} = idx{1};
9040    let Inst{21} = idx{0};
9041  }
9042  }
9043}
9044
9045//----------------------------------------------------------------------------
9046// AdvSIMD scalar shift by immediate
9047//----------------------------------------------------------------------------
9048
9049let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9050class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
9051                     RegisterClass regtype1, RegisterClass regtype2,
9052                     Operand immtype, string asm, list<dag> pattern>
9053  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
9054      asm, "\t$Rd, $Rn, $imm", "", pattern>,
9055    Sched<[WriteVd]> {
9056  bits<5> Rd;
9057  bits<5> Rn;
9058  bits<7> imm;
9059  let Inst{31-30} = 0b01;
9060  let Inst{29}    = U;
9061  let Inst{28-23} = 0b111110;
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
9069let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9070class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
9071                     RegisterClass regtype1, RegisterClass regtype2,
9072                     Operand immtype, string asm, list<dag> pattern>
9073  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
9074      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
9075    Sched<[WriteVd]> {
9076  bits<5> Rd;
9077  bits<5> Rn;
9078  bits<7> imm;
9079  let Inst{31-30} = 0b01;
9080  let Inst{29}    = U;
9081  let Inst{28-23} = 0b111110;
9082  let Inst{22-16} = fixed_imm;
9083  let Inst{15-11} = opc;
9084  let Inst{10}    = 1;
9085  let Inst{9-5} = Rn;
9086  let Inst{4-0} = Rd;
9087}
9088
9089
9090multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
9091  let Predicates = [HasNEON, HasFullFP16] in {
9092  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9093                              FPR16, FPR16, vecshiftR16, asm, []> {
9094    let Inst{19-16} = imm{3-0};
9095  }
9096  } // Predicates = [HasNEON, HasFullFP16]
9097  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9098                              FPR32, FPR32, vecshiftR32, asm, []> {
9099    let Inst{20-16} = imm{4-0};
9100  }
9101  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9102                              FPR64, FPR64, vecshiftR64, asm, []> {
9103    let Inst{21-16} = imm{5-0};
9104  }
9105}
9106
9107multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
9108                             SDPatternOperator OpNode> {
9109  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9110                              FPR64, FPR64, vecshiftR64, asm,
9111  [(set (i64 FPR64:$Rd),
9112     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
9113    let Inst{21-16} = imm{5-0};
9114  }
9115
9116  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
9117            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
9118}
9119
9120multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
9121                                 SDPatternOperator OpNode = null_frag> {
9122  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9123                              FPR64, FPR64, vecshiftR64, asm,
9124  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
9125                                                   (i32 vecshiftR64:$imm)))]> {
9126    let Inst{21-16} = imm{5-0};
9127  }
9128
9129  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
9130                           (i32 vecshiftR64:$imm))),
9131            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
9132                                            vecshiftR64:$imm)>;
9133}
9134
9135multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
9136                             SDPatternOperator OpNode> {
9137  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9138                              FPR64, FPR64, vecshiftL64, asm,
9139    [(set (i64 FPR64:$Rd),
9140       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9141    let Inst{21-16} = imm{5-0};
9142  }
9143
9144  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9145            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9146}
9147
9148let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9149multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
9150  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9151                              FPR64, FPR64, vecshiftL64, asm, []> {
9152    let Inst{21-16} = imm{5-0};
9153  }
9154}
9155
9156let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9157multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
9158                               SDPatternOperator OpNode = null_frag> {
9159  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9160                              FPR8, FPR16, vecshiftR8, asm, []> {
9161    let Inst{18-16} = imm{2-0};
9162  }
9163
9164  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9165                              FPR16, FPR32, vecshiftR16, asm, []> {
9166    let Inst{19-16} = imm{3-0};
9167  }
9168
9169  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9170                              FPR32, FPR64, vecshiftR32, asm,
9171    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9172    let Inst{20-16} = imm{4-0};
9173  }
9174}
9175
9176multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9177                                SDPatternOperator OpNode> {
9178  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9179                              FPR8, FPR8, vecshiftL8, asm, []> {
9180    let Inst{18-16} = imm{2-0};
9181  }
9182
9183  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9184                              FPR16, FPR16, vecshiftL16, asm, []> {
9185    let Inst{19-16} = imm{3-0};
9186  }
9187
9188  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9189                              FPR32, FPR32, vecshiftL32, asm,
9190    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9191    let Inst{20-16} = imm{4-0};
9192  }
9193
9194  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9195                              FPR64, FPR64, vecshiftL64, asm,
9196    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9197    let Inst{21-16} = imm{5-0};
9198  }
9199
9200  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9201            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9202}
9203
9204multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9205  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9206                              FPR8, FPR8, vecshiftR8, asm, []> {
9207    let Inst{18-16} = imm{2-0};
9208  }
9209
9210  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9211                              FPR16, FPR16, vecshiftR16, asm, []> {
9212    let Inst{19-16} = imm{3-0};
9213  }
9214
9215  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9216                              FPR32, FPR32, vecshiftR32, asm, []> {
9217    let Inst{20-16} = imm{4-0};
9218  }
9219
9220  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9221                              FPR64, FPR64, vecshiftR64, asm, []> {
9222    let Inst{21-16} = imm{5-0};
9223  }
9224}
9225
9226//----------------------------------------------------------------------------
9227// AdvSIMD vector x indexed element
9228//----------------------------------------------------------------------------
9229
9230let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9231class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9232                     RegisterOperand dst_reg, RegisterOperand src_reg,
9233                     Operand immtype,
9234                     string asm, string dst_kind, string src_kind,
9235                     list<dag> pattern>
9236  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9237      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9238           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9239    Sched<[!if(Q, WriteVq, WriteVd)]> {
9240  bits<5> Rd;
9241  bits<5> Rn;
9242  let Inst{31}    = 0;
9243  let Inst{30}    = Q;
9244  let Inst{29}    = U;
9245  let Inst{28-23} = 0b011110;
9246  let Inst{22-16} = fixed_imm;
9247  let Inst{15-11} = opc;
9248  let Inst{10}    = 1;
9249  let Inst{9-5}   = Rn;
9250  let Inst{4-0}   = Rd;
9251}
9252
9253let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9254class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9255                     RegisterOperand vectype1, RegisterOperand vectype2,
9256                     Operand immtype,
9257                     string asm, string dst_kind, string src_kind,
9258                     list<dag> pattern>
9259  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9260      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9261           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9262    Sched<[!if(Q, WriteVq, WriteVd)]> {
9263  bits<5> Rd;
9264  bits<5> Rn;
9265  let Inst{31}    = 0;
9266  let Inst{30}    = Q;
9267  let Inst{29}    = U;
9268  let Inst{28-23} = 0b011110;
9269  let Inst{22-16} = fixed_imm;
9270  let Inst{15-11} = opc;
9271  let Inst{10}    = 1;
9272  let Inst{9-5}   = Rn;
9273  let Inst{4-0}   = Rd;
9274}
9275
9276multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9277                              Intrinsic OpNode> {
9278  let Predicates = [HasNEON, HasFullFP16] in {
9279  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9280                                  V64, V64, vecshiftR16,
9281                                  asm, ".4h", ".4h",
9282      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9283    bits<4> imm;
9284    let Inst{19-16} = imm;
9285  }
9286
9287  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9288                                  V128, V128, vecshiftR16,
9289                                  asm, ".8h", ".8h",
9290      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9291    bits<4> imm;
9292    let Inst{19-16} = imm;
9293  }
9294  } // Predicates = [HasNEON, HasFullFP16]
9295  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9296                                  V64, V64, vecshiftR32,
9297                                  asm, ".2s", ".2s",
9298      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9299    bits<5> imm;
9300    let Inst{20-16} = imm;
9301  }
9302
9303  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9304                                  V128, V128, vecshiftR32,
9305                                  asm, ".4s", ".4s",
9306      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9307    bits<5> imm;
9308    let Inst{20-16} = imm;
9309  }
9310
9311  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9312                                  V128, V128, vecshiftR64,
9313                                  asm, ".2d", ".2d",
9314      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9315    bits<6> imm;
9316    let Inst{21-16} = imm;
9317  }
9318}
9319
9320multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9321                                  Intrinsic OpNode> {
9322  let Predicates = [HasNEON, HasFullFP16] in {
9323  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9324                                  V64, V64, vecshiftR16,
9325                                  asm, ".4h", ".4h",
9326      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9327    bits<4> imm;
9328    let Inst{19-16} = imm;
9329  }
9330
9331  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9332                                  V128, V128, vecshiftR16,
9333                                  asm, ".8h", ".8h",
9334      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9335    bits<4> imm;
9336    let Inst{19-16} = imm;
9337  }
9338  } // Predicates = [HasNEON, HasFullFP16]
9339
9340  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9341                                  V64, V64, vecshiftR32,
9342                                  asm, ".2s", ".2s",
9343      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9344    bits<5> imm;
9345    let Inst{20-16} = imm;
9346  }
9347
9348  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9349                                  V128, V128, vecshiftR32,
9350                                  asm, ".4s", ".4s",
9351      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9352    bits<5> imm;
9353    let Inst{20-16} = imm;
9354  }
9355
9356  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9357                                  V128, V128, vecshiftR64,
9358                                  asm, ".2d", ".2d",
9359      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9360    bits<6> imm;
9361    let Inst{21-16} = imm;
9362  }
9363}
9364
9365multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9366                                     SDPatternOperator OpNode> {
9367  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9368                                  V64, V128, vecshiftR16Narrow,
9369                                  asm, ".8b", ".8h",
9370      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9371    bits<3> imm;
9372    let Inst{18-16} = imm;
9373  }
9374
9375  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9376                                  V128, V128, vecshiftR16Narrow,
9377                                  asm#"2", ".16b", ".8h", []> {
9378    bits<3> imm;
9379    let Inst{18-16} = imm;
9380    let hasSideEffects = 0;
9381  }
9382
9383  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9384                                  V64, V128, vecshiftR32Narrow,
9385                                  asm, ".4h", ".4s",
9386      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9387    bits<4> imm;
9388    let Inst{19-16} = imm;
9389  }
9390
9391  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9392                                  V128, V128, vecshiftR32Narrow,
9393                                  asm#"2", ".8h", ".4s", []> {
9394    bits<4> imm;
9395    let Inst{19-16} = imm;
9396    let hasSideEffects = 0;
9397  }
9398
9399  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9400                                  V64, V128, vecshiftR64Narrow,
9401                                  asm, ".2s", ".2d",
9402      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9403    bits<5> imm;
9404    let Inst{20-16} = imm;
9405  }
9406
9407  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9408                                  V128, V128, vecshiftR64Narrow,
9409                                  asm#"2", ".4s", ".2d", []> {
9410    bits<5> imm;
9411    let Inst{20-16} = imm;
9412    let hasSideEffects = 0;
9413  }
9414
9415  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9416  // themselves, so put them here instead.
9417
9418  // Patterns involving what's effectively an insert high and a normal
9419  // intrinsic, represented by CONCAT_VECTORS.
9420  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9421                                                   vecshiftR16Narrow:$imm)),
9422            (!cast<Instruction>(NAME # "v16i8_shift")
9423                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9424                V128:$Rn, vecshiftR16Narrow:$imm)>;
9425  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9426                                                     vecshiftR32Narrow:$imm)),
9427            (!cast<Instruction>(NAME # "v8i16_shift")
9428                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9429                V128:$Rn, vecshiftR32Narrow:$imm)>;
9430  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9431                                                     vecshiftR64Narrow:$imm)),
9432            (!cast<Instruction>(NAME # "v4i32_shift")
9433                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9434                V128:$Rn, vecshiftR64Narrow:$imm)>;
9435}
9436
9437multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9438                                SDPatternOperator OpNode> {
9439  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9440                                  V64, V64, vecshiftL8,
9441                                  asm, ".8b", ".8b",
9442                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9443                       (i32 vecshiftL8:$imm)))]> {
9444    bits<3> imm;
9445    let Inst{18-16} = imm;
9446  }
9447
9448  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9449                                  V128, V128, vecshiftL8,
9450                                  asm, ".16b", ".16b",
9451             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9452                   (i32 vecshiftL8:$imm)))]> {
9453    bits<3> imm;
9454    let Inst{18-16} = imm;
9455  }
9456
9457  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9458                                  V64, V64, vecshiftL16,
9459                                  asm, ".4h", ".4h",
9460              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9461                    (i32 vecshiftL16:$imm)))]> {
9462    bits<4> imm;
9463    let Inst{19-16} = imm;
9464  }
9465
9466  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9467                                  V128, V128, vecshiftL16,
9468                                  asm, ".8h", ".8h",
9469            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9470                  (i32 vecshiftL16:$imm)))]> {
9471    bits<4> imm;
9472    let Inst{19-16} = imm;
9473  }
9474
9475  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9476                                  V64, V64, vecshiftL32,
9477                                  asm, ".2s", ".2s",
9478              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9479                    (i32 vecshiftL32:$imm)))]> {
9480    bits<5> imm;
9481    let Inst{20-16} = imm;
9482  }
9483
9484  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9485                                  V128, V128, vecshiftL32,
9486                                  asm, ".4s", ".4s",
9487            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9488                  (i32 vecshiftL32:$imm)))]> {
9489    bits<5> imm;
9490    let Inst{20-16} = imm;
9491  }
9492
9493  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9494                                  V128, V128, vecshiftL64,
9495                                  asm, ".2d", ".2d",
9496            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9497                  (i32 vecshiftL64:$imm)))]> {
9498    bits<6> imm;
9499    let Inst{21-16} = imm;
9500  }
9501}
9502
9503multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9504                                SDPatternOperator OpNode> {
9505  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9506                                  V64, V64, vecshiftR8,
9507                                  asm, ".8b", ".8b",
9508                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9509                       (i32 vecshiftR8:$imm)))]> {
9510    bits<3> imm;
9511    let Inst{18-16} = imm;
9512  }
9513
9514  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9515                                  V128, V128, vecshiftR8,
9516                                  asm, ".16b", ".16b",
9517             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9518                   (i32 vecshiftR8:$imm)))]> {
9519    bits<3> imm;
9520    let Inst{18-16} = imm;
9521  }
9522
9523  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9524                                  V64, V64, vecshiftR16,
9525                                  asm, ".4h", ".4h",
9526              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9527                    (i32 vecshiftR16:$imm)))]> {
9528    bits<4> imm;
9529    let Inst{19-16} = imm;
9530  }
9531
9532  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9533                                  V128, V128, vecshiftR16,
9534                                  asm, ".8h", ".8h",
9535            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9536                  (i32 vecshiftR16:$imm)))]> {
9537    bits<4> imm;
9538    let Inst{19-16} = imm;
9539  }
9540
9541  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9542                                  V64, V64, vecshiftR32,
9543                                  asm, ".2s", ".2s",
9544              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9545                    (i32 vecshiftR32:$imm)))]> {
9546    bits<5> imm;
9547    let Inst{20-16} = imm;
9548  }
9549
9550  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9551                                  V128, V128, vecshiftR32,
9552                                  asm, ".4s", ".4s",
9553            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9554                  (i32 vecshiftR32:$imm)))]> {
9555    bits<5> imm;
9556    let Inst{20-16} = imm;
9557  }
9558
9559  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9560                                  V128, V128, vecshiftR64,
9561                                  asm, ".2d", ".2d",
9562            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9563                  (i32 vecshiftR64:$imm)))]> {
9564    bits<6> imm;
9565    let Inst{21-16} = imm;
9566  }
9567}
9568
9569let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9570multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9571                                    SDPatternOperator OpNode = null_frag> {
9572  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9573                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9574                 [(set (v8i8 V64:$dst),
9575                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9576                           (i32 vecshiftR8:$imm)))]> {
9577    bits<3> imm;
9578    let Inst{18-16} = imm;
9579  }
9580
9581  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9582                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9583             [(set (v16i8 V128:$dst),
9584               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9585                       (i32 vecshiftR8:$imm)))]> {
9586    bits<3> imm;
9587    let Inst{18-16} = imm;
9588  }
9589
9590  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9591                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9592              [(set (v4i16 V64:$dst),
9593                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9594                        (i32 vecshiftR16:$imm)))]> {
9595    bits<4> imm;
9596    let Inst{19-16} = imm;
9597  }
9598
9599  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9600                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9601            [(set (v8i16 V128:$dst),
9602              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9603                      (i32 vecshiftR16:$imm)))]> {
9604    bits<4> imm;
9605    let Inst{19-16} = imm;
9606  }
9607
9608  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9609                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9610              [(set (v2i32 V64:$dst),
9611                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9612                        (i32 vecshiftR32:$imm)))]> {
9613    bits<5> imm;
9614    let Inst{20-16} = imm;
9615  }
9616
9617  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9618                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9619            [(set (v4i32 V128:$dst),
9620              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9621                      (i32 vecshiftR32:$imm)))]> {
9622    bits<5> imm;
9623    let Inst{20-16} = imm;
9624  }
9625
9626  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9627                                  V128, V128, vecshiftR64,
9628                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9629              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9630                      (i32 vecshiftR64:$imm)))]> {
9631    bits<6> imm;
9632    let Inst{21-16} = imm;
9633  }
9634}
9635
9636multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9637                                    SDPatternOperator OpNode = null_frag> {
9638  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9639                                  V64, V64, vecshiftL8,
9640                                  asm, ".8b", ".8b",
9641                    [(set (v8i8 V64:$dst),
9642                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9643                                  (i32 vecshiftL8:$imm)))]> {
9644    bits<3> imm;
9645    let Inst{18-16} = imm;
9646  }
9647
9648  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9649                                  V128, V128, vecshiftL8,
9650                                  asm, ".16b", ".16b",
9651                    [(set (v16i8 V128:$dst),
9652                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9653                                  (i32 vecshiftL8:$imm)))]> {
9654    bits<3> imm;
9655    let Inst{18-16} = imm;
9656  }
9657
9658  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9659                                  V64, V64, vecshiftL16,
9660                                  asm, ".4h", ".4h",
9661                    [(set (v4i16 V64:$dst),
9662                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9663                                   (i32 vecshiftL16:$imm)))]> {
9664    bits<4> imm;
9665    let Inst{19-16} = imm;
9666  }
9667
9668  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9669                                  V128, V128, vecshiftL16,
9670                                  asm, ".8h", ".8h",
9671                    [(set (v8i16 V128:$dst),
9672                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9673                                  (i32 vecshiftL16:$imm)))]> {
9674    bits<4> imm;
9675    let Inst{19-16} = imm;
9676  }
9677
9678  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9679                                  V64, V64, vecshiftL32,
9680                                  asm, ".2s", ".2s",
9681                    [(set (v2i32 V64:$dst),
9682                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9683                                  (i32 vecshiftL32:$imm)))]> {
9684    bits<5> imm;
9685    let Inst{20-16} = imm;
9686  }
9687
9688  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9689                                  V128, V128, vecshiftL32,
9690                                  asm, ".4s", ".4s",
9691                    [(set (v4i32 V128:$dst),
9692                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9693                                  (i32 vecshiftL32:$imm)))]> {
9694    bits<5> imm;
9695    let Inst{20-16} = imm;
9696  }
9697
9698  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9699                                  V128, V128, vecshiftL64,
9700                                  asm, ".2d", ".2d",
9701                    [(set (v2i64 V128:$dst),
9702                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9703                                  (i32 vecshiftL64:$imm)))]> {
9704    bits<6> imm;
9705    let Inst{21-16} = imm;
9706  }
9707}
9708
9709multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9710                                   SDPatternOperator OpNode> {
9711  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9712                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9713      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9714    bits<3> imm;
9715    let Inst{18-16} = imm;
9716  }
9717
9718  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9719                                  V128, V128, vecshiftL8,
9720                                  asm#"2", ".8h", ".16b",
9721      [(set (v8i16 V128:$Rd),
9722            (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)), vecshiftL8:$imm))]> {
9723    bits<3> imm;
9724    let Inst{18-16} = imm;
9725  }
9726
9727  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9728                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9729      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9730    bits<4> imm;
9731    let Inst{19-16} = imm;
9732  }
9733
9734  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9735                                  V128, V128, vecshiftL16,
9736                                  asm#"2", ".4s", ".8h",
9737      [(set (v4i32 V128:$Rd),
9738            (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)), vecshiftL16:$imm))]> {
9739
9740    bits<4> imm;
9741    let Inst{19-16} = imm;
9742  }
9743
9744  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9745                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9746      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9747    bits<5> imm;
9748    let Inst{20-16} = imm;
9749  }
9750
9751  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9752                                  V128, V128, vecshiftL32,
9753                                  asm#"2", ".2d", ".4s",
9754      [(set (v2i64 V128:$Rd),
9755            (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)), vecshiftL32:$imm))]> {
9756    bits<5> imm;
9757    let Inst{20-16} = imm;
9758  }
9759}
9760
9761
9762//---
9763// Vector load/store
9764//---
9765// SIMD ldX/stX no-index memory references don't allow the optional
9766// ", #0" constant and handle post-indexing explicitly, so we use
9767// a more specialized parse method for them. Otherwise, it's the same as
9768// the general GPR64sp handling.
9769
9770class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9771                   string asm, dag oops, dag iops, list<dag> pattern>
9772  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9773  bits<5> Vt;
9774  bits<5> Rn;
9775  let Inst{31} = 0;
9776  let Inst{30} = Q;
9777  let Inst{29-23} = 0b0011000;
9778  let Inst{22} = L;
9779  let Inst{21-16} = 0b000000;
9780  let Inst{15-12} = opcode;
9781  let Inst{11-10} = size;
9782  let Inst{9-5} = Rn;
9783  let Inst{4-0} = Vt;
9784}
9785
9786class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9787                       string asm, dag oops, dag iops>
9788  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9789  bits<5> Vt;
9790  bits<5> Rn;
9791  bits<5> Xm;
9792  let Inst{31} = 0;
9793  let Inst{30} = Q;
9794  let Inst{29-23} = 0b0011001;
9795  let Inst{22} = L;
9796  let Inst{21} = 0;
9797  let Inst{20-16} = Xm;
9798  let Inst{15-12} = opcode;
9799  let Inst{11-10} = size;
9800  let Inst{9-5} = Rn;
9801  let Inst{4-0} = Vt;
9802}
9803
9804// The immediate form of AdvSIMD post-indexed addressing is encoded with
9805// register post-index addressing from the zero register.
9806multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9807                           int Offset, int Size> {
9808  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9809  //      "ld1\t$Vt, [$Rn], #16"
9810  // may get mapped to
9811  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9812  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9813                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9814                      GPR64sp:$Rn,
9815                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9816                      XZR), 1>;
9817
9818  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9819  //      "ld1.8b\t$Vt, [$Rn], #16"
9820  // may get mapped to
9821  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9822  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9823                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9824                      GPR64sp:$Rn,
9825                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9826                      XZR), 0>;
9827
9828  // E.g. "ld1.8b { v0, v1 }, [x1]"
9829  //      "ld1\t$Vt, [$Rn]"
9830  // may get mapped to
9831  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9832  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9833                  (!cast<Instruction>(BaseName # Count # "v" # layout)
9834                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9835                      GPR64sp:$Rn), 0>;
9836
9837  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9838  //      "ld1\t$Vt, [$Rn], $Xm"
9839  // may get mapped to
9840  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9841  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9842                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9843                      GPR64sp:$Rn,
9844                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9845                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9846}
9847
9848multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9849                       int Offset128, int Offset64, bits<4> opcode> {
9850  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9851    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9852                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9853                           (ins GPR64sp:$Rn), []>;
9854    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9855                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9856                           (ins GPR64sp:$Rn), []>;
9857    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9858                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9859                           (ins GPR64sp:$Rn), []>;
9860    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9861                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9862                           (ins GPR64sp:$Rn), []>;
9863    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9864                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9865                           (ins GPR64sp:$Rn), []>;
9866    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9867                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9868                           (ins GPR64sp:$Rn), []>;
9869    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9870                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9871                           (ins GPR64sp:$Rn), []>;
9872
9873
9874    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9875                       (outs GPR64sp:$wback,
9876                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
9877                       (ins GPR64sp:$Rn,
9878                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9879    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9880                       (outs GPR64sp:$wback,
9881                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
9882                       (ins GPR64sp:$Rn,
9883                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9884    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9885                       (outs GPR64sp:$wback,
9886                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
9887                       (ins GPR64sp:$Rn,
9888                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9889    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9890                       (outs GPR64sp:$wback,
9891                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
9892                       (ins GPR64sp:$Rn,
9893                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9894    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9895                       (outs GPR64sp:$wback,
9896                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
9897                       (ins GPR64sp:$Rn,
9898                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9899    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9900                       (outs GPR64sp:$wback,
9901                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
9902                       (ins GPR64sp:$Rn,
9903                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9904    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9905                       (outs GPR64sp:$wback,
9906                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
9907                       (ins GPR64sp:$Rn,
9908                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9909  }
9910
9911  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9912  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9913  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9914  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9915  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9916  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9917  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9918}
9919
9920// Only ld1/st1 has a v1d version.
9921multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9922                       int Offset128, int Offset64, bits<4> opcode> {
9923  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9924    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9925                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9926                                 GPR64sp:$Rn), []>;
9927    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9928                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9929                                GPR64sp:$Rn), []>;
9930    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9931                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9932                                GPR64sp:$Rn), []>;
9933    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9934                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9935                                GPR64sp:$Rn), []>;
9936    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9937                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9938                                GPR64sp:$Rn), []>;
9939    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9940                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9941                                GPR64sp:$Rn), []>;
9942    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9943                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9944                                GPR64sp:$Rn), []>;
9945
9946    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9947                       (outs GPR64sp:$wback),
9948                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9949                            GPR64sp:$Rn,
9950                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9951    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9952                       (outs GPR64sp:$wback),
9953                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9954                            GPR64sp:$Rn,
9955                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9956    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9957                       (outs GPR64sp:$wback),
9958                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9959                            GPR64sp:$Rn,
9960                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9961    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9962                       (outs GPR64sp:$wback),
9963                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9964                            GPR64sp:$Rn,
9965                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9966    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9967                       (outs GPR64sp:$wback),
9968                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9969                            GPR64sp:$Rn,
9970                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9971    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9972                       (outs GPR64sp:$wback),
9973                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9974                            GPR64sp:$Rn,
9975                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9976    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9977                       (outs GPR64sp:$wback),
9978                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9979                            GPR64sp:$Rn,
9980                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9981  }
9982
9983  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9984  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9985  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9986  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9987  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9988  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9989  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9990}
9991
9992multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9993                       int Offset128, int Offset64, bits<4> opcode>
9994  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9995
9996  // LD1 instructions have extra "1d" variants.
9997  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9998    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9999                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
10000                           (ins GPR64sp:$Rn), []>;
10001
10002    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
10003                       (outs GPR64sp:$wback,
10004                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
10005                       (ins GPR64sp:$Rn,
10006                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10007  }
10008
10009  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10010}
10011
10012multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
10013                       int Offset128, int Offset64, bits<4> opcode>
10014  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10015
10016  // ST1 instructions have extra "1d" variants.
10017  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
10018    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
10019                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10020                                GPR64sp:$Rn), []>;
10021
10022    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
10023                       (outs GPR64sp:$wback),
10024                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10025                            GPR64sp:$Rn,
10026                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10027  }
10028
10029  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10030}
10031
10032multiclass SIMDLd1Multiple<string asm> {
10033  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10034  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10035  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10036  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10037}
10038
10039multiclass SIMDSt1Multiple<string asm> {
10040  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10041  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10042  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10043  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10044}
10045
10046multiclass SIMDLd2Multiple<string asm> {
10047  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10048}
10049
10050multiclass SIMDSt2Multiple<string asm> {
10051  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10052}
10053
10054multiclass SIMDLd3Multiple<string asm> {
10055  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10056}
10057
10058multiclass SIMDSt3Multiple<string asm> {
10059  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10060}
10061
10062multiclass SIMDLd4Multiple<string asm> {
10063  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10064}
10065
10066multiclass SIMDSt4Multiple<string asm> {
10067  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10068}
10069
10070//---
10071// AdvSIMD Load/store single-element
10072//---
10073
10074class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
10075                         string asm, string operands, string cst,
10076                         dag oops, dag iops, list<dag> pattern>
10077  : I<oops, iops, asm, operands, cst, pattern> {
10078  bits<5> Vt;
10079  bits<5> Rn;
10080  let Inst{31} = 0;
10081  let Inst{29-24} = 0b001101;
10082  let Inst{22} = L;
10083  let Inst{21} = R;
10084  let Inst{15-13} = opcode;
10085  let Inst{9-5} = Rn;
10086  let Inst{4-0} = Vt;
10087}
10088
10089class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
10090                         string asm, string operands, string cst,
10091                         dag oops, dag iops, list<dag> pattern>
10092  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
10093  bits<5> Vt;
10094  bits<5> Rn;
10095  let Inst{31} = 0;
10096  let Inst{29-24} = 0b001101;
10097  let Inst{22} = L;
10098  let Inst{21} = R;
10099  let Inst{15-13} = opcode;
10100  let Inst{9-5} = Rn;
10101  let Inst{4-0} = Vt;
10102}
10103
10104
10105let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10106class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
10107                  DAGOperand listtype>
10108  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
10109                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
10110                       []> {
10111  let Inst{30} = Q;
10112  let Inst{23} = 0;
10113  let Inst{20-16} = 0b00000;
10114  let Inst{12} = S;
10115  let Inst{11-10} = size;
10116}
10117let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10118class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
10119                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
10120  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
10121                       "$Rn = $wback",
10122                       (outs GPR64sp:$wback, listtype:$Vt),
10123                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
10124  bits<5> Xm;
10125  let Inst{30} = Q;
10126  let Inst{23} = 1;
10127  let Inst{20-16} = Xm;
10128  let Inst{12} = S;
10129  let Inst{11-10} = size;
10130}
10131
10132multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
10133                          int Offset, int Size> {
10134  // E.g. "ld1r { v0.8b }, [x1], #1"
10135  //      "ld1r.8b\t$Vt, [$Rn], #1"
10136  // may get mapped to
10137  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10138  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10139                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10140                      GPR64sp:$Rn,
10141                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10142                      XZR), 1>;
10143
10144  // E.g. "ld1r.8b { v0 }, [x1], #1"
10145  //      "ld1r.8b\t$Vt, [$Rn], #1"
10146  // may get mapped to
10147  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10148  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10149                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10150                      GPR64sp:$Rn,
10151                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10152                      XZR), 0>;
10153
10154  // E.g. "ld1r.8b { v0 }, [x1]"
10155  //      "ld1r.8b\t$Vt, [$Rn]"
10156  // may get mapped to
10157  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10158  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10159                  (!cast<Instruction>(BaseName # "v" # layout)
10160                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10161                      GPR64sp:$Rn), 0>;
10162
10163  // E.g. "ld1r.8b { v0 }, [x1], x2"
10164  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10165  // may get mapped to
10166  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10167  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10168                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10169                      GPR64sp:$Rn,
10170                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10171                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10172}
10173
10174multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10175  int Offset1, int Offset2, int Offset4, int Offset8> {
10176  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10177                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10178  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10179                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10180  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10181                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10182  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10183                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10184  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10185                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10186  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10187                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10188  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10189                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10190  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10191                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10192
10193  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10194                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10195                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10196  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10197                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10198                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10199  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10200                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10201                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10202  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10203                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10204                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10205  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10206                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10207                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10208  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10209                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10210                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10211  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10212                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10213                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10214  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10215                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10216                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10217
10218  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10219  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10220  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10221  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10222  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10223  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10224  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10225  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10226}
10227
10228class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10229                      dag oops, dag iops, list<dag> pattern>
10230  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10231                       pattern> {
10232  // idx encoded in Q:S:size fields.
10233  bits<4> idx;
10234  let Inst{30} = idx{3};
10235  let Inst{23} = 0;
10236  let Inst{20-16} = 0b00000;
10237  let Inst{12} = idx{2};
10238  let Inst{11-10} = idx{1-0};
10239}
10240class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10241                      dag oops, dag iops, list<dag> pattern>
10242  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10243                           oops, iops, pattern> {
10244  // idx encoded in Q:S:size fields.
10245  bits<4> idx;
10246  let Inst{30} = idx{3};
10247  let Inst{23} = 0;
10248  let Inst{20-16} = 0b00000;
10249  let Inst{12} = idx{2};
10250  let Inst{11-10} = idx{1-0};
10251}
10252class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10253                          dag oops, dag iops>
10254  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10255                       "$Rn = $wback", oops, iops, []> {
10256  // idx encoded in Q:S:size fields.
10257  bits<4> idx;
10258  bits<5> Xm;
10259  let Inst{30} = idx{3};
10260  let Inst{23} = 1;
10261  let Inst{20-16} = Xm;
10262  let Inst{12} = idx{2};
10263  let Inst{11-10} = idx{1-0};
10264}
10265class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10266                          dag oops, dag iops>
10267  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10268                           "$Rn = $wback", oops, iops, []> {
10269  // idx encoded in Q:S:size fields.
10270  bits<4> idx;
10271  bits<5> Xm;
10272  let Inst{30} = idx{3};
10273  let Inst{23} = 1;
10274  let Inst{20-16} = Xm;
10275  let Inst{12} = idx{2};
10276  let Inst{11-10} = idx{1-0};
10277}
10278
10279class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10280                      dag oops, dag iops, list<dag> pattern>
10281  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10282                       pattern> {
10283  // idx encoded in Q:S:size<1> fields.
10284  bits<3> idx;
10285  let Inst{30} = idx{2};
10286  let Inst{23} = 0;
10287  let Inst{20-16} = 0b00000;
10288  let Inst{12} = idx{1};
10289  let Inst{11} = idx{0};
10290  let Inst{10} = size;
10291}
10292class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10293                      dag oops, dag iops, list<dag> pattern>
10294  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10295                           oops, iops, pattern> {
10296  // idx encoded in Q:S:size<1> fields.
10297  bits<3> idx;
10298  let Inst{30} = idx{2};
10299  let Inst{23} = 0;
10300  let Inst{20-16} = 0b00000;
10301  let Inst{12} = idx{1};
10302  let Inst{11} = idx{0};
10303  let Inst{10} = size;
10304}
10305
10306class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10307                          dag oops, dag iops>
10308  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10309                       "$Rn = $wback", oops, iops, []> {
10310  // idx encoded in Q:S:size<1> fields.
10311  bits<3> idx;
10312  bits<5> Xm;
10313  let Inst{30} = idx{2};
10314  let Inst{23} = 1;
10315  let Inst{20-16} = Xm;
10316  let Inst{12} = idx{1};
10317  let Inst{11} = idx{0};
10318  let Inst{10} = size;
10319}
10320class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10321                          dag oops, dag iops>
10322  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10323                           "$Rn = $wback", oops, iops, []> {
10324  // idx encoded in Q:S:size<1> fields.
10325  bits<3> idx;
10326  bits<5> Xm;
10327  let Inst{30} = idx{2};
10328  let Inst{23} = 1;
10329  let Inst{20-16} = Xm;
10330  let Inst{12} = idx{1};
10331  let Inst{11} = idx{0};
10332  let Inst{10} = size;
10333}
10334class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10335                      dag oops, dag iops, list<dag> pattern>
10336  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10337                       pattern> {
10338  // idx encoded in Q:S fields.
10339  bits<2> idx;
10340  let Inst{30} = idx{1};
10341  let Inst{23} = 0;
10342  let Inst{20-16} = 0b00000;
10343  let Inst{12} = idx{0};
10344  let Inst{11-10} = size;
10345}
10346class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10347                      dag oops, dag iops, list<dag> pattern>
10348  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10349                           oops, iops, pattern> {
10350  // idx encoded in Q:S fields.
10351  bits<2> idx;
10352  let Inst{30} = idx{1};
10353  let Inst{23} = 0;
10354  let Inst{20-16} = 0b00000;
10355  let Inst{12} = idx{0};
10356  let Inst{11-10} = size;
10357}
10358class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10359                          string asm, dag oops, dag iops>
10360  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10361                       "$Rn = $wback", oops, iops, []> {
10362  // idx encoded in Q:S fields.
10363  bits<2> idx;
10364  bits<5> Xm;
10365  let Inst{30} = idx{1};
10366  let Inst{23} = 1;
10367  let Inst{20-16} = Xm;
10368  let Inst{12} = idx{0};
10369  let Inst{11-10} = size;
10370}
10371class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10372                          string asm, dag oops, dag iops>
10373  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10374                           "$Rn = $wback", oops, iops, []> {
10375  // idx encoded in Q:S fields.
10376  bits<2> idx;
10377  bits<5> Xm;
10378  let Inst{30} = idx{1};
10379  let Inst{23} = 1;
10380  let Inst{20-16} = Xm;
10381  let Inst{12} = idx{0};
10382  let Inst{11-10} = size;
10383}
10384class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10385                      dag oops, dag iops, list<dag> pattern>
10386  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10387                       pattern> {
10388  // idx encoded in Q field.
10389  bits<1> idx;
10390  let Inst{30} = idx;
10391  let Inst{23} = 0;
10392  let Inst{20-16} = 0b00000;
10393  let Inst{12} = 0;
10394  let Inst{11-10} = size;
10395}
10396class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10397                      dag oops, dag iops, list<dag> pattern>
10398  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10399                           oops, iops, pattern> {
10400  // idx encoded in Q field.
10401  bits<1> idx;
10402  let Inst{30} = idx;
10403  let Inst{23} = 0;
10404  let Inst{20-16} = 0b00000;
10405  let Inst{12} = 0;
10406  let Inst{11-10} = size;
10407}
10408class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10409                          string asm, dag oops, dag iops>
10410  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10411                       "$Rn = $wback", oops, iops, []> {
10412  // idx encoded in Q field.
10413  bits<1> idx;
10414  bits<5> Xm;
10415  let Inst{30} = idx;
10416  let Inst{23} = 1;
10417  let Inst{20-16} = Xm;
10418  let Inst{12} = 0;
10419  let Inst{11-10} = size;
10420}
10421class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10422                          string asm, dag oops, dag iops>
10423  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10424                           "$Rn = $wback", oops, iops, []> {
10425  // idx encoded in Q field.
10426  bits<1> idx;
10427  bits<5> Xm;
10428  let Inst{30} = idx;
10429  let Inst{23} = 1;
10430  let Inst{20-16} = Xm;
10431  let Inst{12} = 0;
10432  let Inst{11-10} = size;
10433}
10434
10435let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10436multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10437                         RegisterOperand listtype,
10438                         RegisterOperand GPR64pi> {
10439  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10440                           (outs listtype:$dst),
10441                           (ins listtype:$Vt, VectorIndexB:$idx,
10442                                GPR64sp:$Rn), []>;
10443
10444  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10445                            (outs GPR64sp:$wback, listtype:$dst),
10446                            (ins listtype:$Vt, VectorIndexB:$idx,
10447                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10448}
10449let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10450multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10451                         RegisterOperand listtype,
10452                         RegisterOperand GPR64pi> {
10453  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10454                            (outs listtype:$dst),
10455                            (ins listtype:$Vt, VectorIndexH:$idx,
10456                                 GPR64sp:$Rn), []>;
10457
10458  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10459                            (outs GPR64sp:$wback, listtype:$dst),
10460                            (ins listtype:$Vt, VectorIndexH:$idx,
10461                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10462}
10463let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10464multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10465                         RegisterOperand listtype,
10466                         RegisterOperand GPR64pi> {
10467  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10468                            (outs listtype:$dst),
10469                            (ins listtype:$Vt, VectorIndexS:$idx,
10470                                 GPR64sp:$Rn), []>;
10471
10472  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10473                            (outs GPR64sp:$wback, listtype:$dst),
10474                            (ins listtype:$Vt, VectorIndexS:$idx,
10475                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10476}
10477let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10478multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10479                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10480  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10481                            (outs listtype:$dst),
10482                            (ins listtype:$Vt, VectorIndexD:$idx,
10483                                 GPR64sp:$Rn), []>;
10484
10485  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10486                            (outs GPR64sp:$wback, listtype:$dst),
10487                            (ins listtype:$Vt, VectorIndexD:$idx,
10488                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10489}
10490let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10491multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10492                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10493  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10494                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10495                                        GPR64sp:$Rn), []>;
10496
10497  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10498                                    (outs GPR64sp:$wback),
10499                                    (ins listtype:$Vt, VectorIndexB:$idx,
10500                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10501}
10502let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10503multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10504                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10505  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10506                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10507                                         GPR64sp:$Rn), []>;
10508
10509  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10510                            (outs GPR64sp:$wback),
10511                            (ins listtype:$Vt, VectorIndexH:$idx,
10512                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10513}
10514let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10515multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10516                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10517  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10518                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10519                                         GPR64sp:$Rn), []>;
10520
10521  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10522                            (outs GPR64sp:$wback),
10523                            (ins listtype:$Vt, VectorIndexS:$idx,
10524                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10525}
10526let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10527multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10528                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10529  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10530                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10531                                         GPR64sp:$Rn), []>;
10532
10533  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10534                            (outs GPR64sp:$wback),
10535                            (ins listtype:$Vt, VectorIndexD:$idx,
10536                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10537}
10538
10539multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10540                                 string Count, int Offset, Operand idxtype> {
10541  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10542  //      "ld1\t$Vt, [$Rn], #1"
10543  // may get mapped to
10544  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10545  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10546                  (!cast<Instruction>(NAME # Type  # "_POST")
10547                      GPR64sp:$Rn,
10548                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10549                      idxtype:$idx, XZR), 1>;
10550
10551  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10552  //      "ld1.8b\t$Vt, [$Rn], #1"
10553  // may get mapped to
10554  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10555  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10556                  (!cast<Instruction>(NAME # Type # "_POST")
10557                      GPR64sp:$Rn,
10558                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10559                      idxtype:$idx, XZR), 0>;
10560
10561  // E.g. "ld1.8b { v0 }[0], [x1]"
10562  //      "ld1.8b\t$Vt, [$Rn]"
10563  // may get mapped to
10564  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10565  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10566                      (!cast<Instruction>(NAME # Type)
10567                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10568                         idxtype:$idx, GPR64sp:$Rn), 0>;
10569
10570  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10571  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10572  // may get mapped to
10573  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10574  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10575                      (!cast<Instruction>(NAME # Type # "_POST")
10576                         GPR64sp:$Rn,
10577                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10578                         idxtype:$idx,
10579                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10580}
10581
10582multiclass SIMDLdSt1SingleAliases<string asm> {
10583  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10584  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10585  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10586  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10587}
10588
10589multiclass SIMDLdSt2SingleAliases<string asm> {
10590  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10591  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10592  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10593  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10594}
10595
10596multiclass SIMDLdSt3SingleAliases<string asm> {
10597  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10598  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10599  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10600  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10601}
10602
10603multiclass SIMDLdSt4SingleAliases<string asm> {
10604  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10605  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10606  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10607  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10608}
10609} // end of 'let Predicates = [HasNEON]'
10610
10611//----------------------------------------------------------------------------
10612// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10613//----------------------------------------------------------------------------
10614
10615let Predicates = [HasNEON, HasRDM] in {
10616
10617class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10618                                    RegisterOperand regtype, string asm,
10619                                    string kind, list<dag> pattern>
10620  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10621                                pattern> {
10622}
10623multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10624                                             SDPatternOperator op> {
10625  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10626    [(set (v4i16 V64:$dst),
10627          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
10628  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10629    [(set (v8i16 V128:$dst),
10630          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
10631  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10632    [(set (v2i32 V64:$dst),
10633          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
10634  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10635    [(set (v4i32 V128:$dst),
10636          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
10637}
10638
10639multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10640                                     SDPatternOperator op> {
10641  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10642                                          V64, V64, V128_lo, VectorIndexH,
10643                                          asm, ".4h", ".4h", ".4h", ".h",
10644    [(set (v4i16 V64:$dst),
10645          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10646                     (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10647                                              VectorIndexH:$idx)))))]> {
10648    bits<3> idx;
10649    let Inst{11} = idx{2};
10650    let Inst{21} = idx{1};
10651    let Inst{20} = idx{0};
10652  }
10653
10654  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10655                                          V128, V128, V128_lo, VectorIndexH,
10656                                          asm, ".8h", ".8h", ".8h", ".h",
10657    [(set (v8i16 V128:$dst),
10658          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10659                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10660                                              VectorIndexH:$idx)))))]> {
10661    bits<3> idx;
10662    let Inst{11} = idx{2};
10663    let Inst{21} = idx{1};
10664    let Inst{20} = idx{0};
10665  }
10666
10667  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10668                                          V64, V64, V128, VectorIndexS,
10669                                          asm, ".2s", ".2s", ".2s", ".s",
10670    [(set (v2i32 V64:$dst),
10671          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10672                     (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10673                                              VectorIndexS:$idx)))))]> {
10674    bits<2> idx;
10675    let Inst{11} = idx{1};
10676    let Inst{21} = idx{0};
10677  }
10678
10679  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10680                                          V128, V128, V128, VectorIndexS,
10681                                          asm, ".4s", ".4s", ".4s", ".s",
10682    [(set (v4i32 V128:$dst),
10683          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10684                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10685                                              VectorIndexS:$idx)))))]> {
10686    bits<2> idx;
10687    let Inst{11} = idx{1};
10688    let Inst{21} = idx{0};
10689  }
10690
10691  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10692                                        FPR16Op, FPR16Op, V128_lo,
10693                                        VectorIndexH, asm, ".h", "", "", ".h",
10694                                        []> {
10695    bits<3> idx;
10696    let Inst{11} = idx{2};
10697    let Inst{21} = idx{1};
10698    let Inst{20} = idx{0};
10699  }
10700
10701  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10702                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10703                                        asm, ".s", "", "", ".s",
10704    [(set (i32 FPR32Op:$dst),
10705          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
10706                   (i32 (vector_extract (v4i32 V128:$Rm),
10707                                        VectorIndexS:$idx)))))]> {
10708    bits<2> idx;
10709    let Inst{11} = idx{1};
10710    let Inst{21} = idx{0};
10711  }
10712}
10713} // let Predicates = [HasNeon, HasRDM]
10714
10715//----------------------------------------------------------------------------
10716// ARMv8.3 Complex ADD/MLA instructions
10717//----------------------------------------------------------------------------
10718
10719class ComplexRotationOperand<int Angle, int Remainder, string Type>
10720  : AsmOperandClass {
10721  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10722  let DiagnosticType = "InvalidComplexRotation" # Type;
10723  let Name = "ComplexRotation" # Type;
10724}
10725def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10726                                                  SDNodeXForm<imm, [{
10727  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10728}]>> {
10729  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10730  let PrintMethod = "printComplexRotationOp<90, 0>";
10731}
10732def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10733                                                  SDNodeXForm<imm, [{
10734  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10735}]>> {
10736  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10737  let PrintMethod = "printComplexRotationOp<180, 90>";
10738}
10739let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
10740class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10741                                     RegisterOperand regtype, Operand rottype,
10742                                     string asm, string kind, list<dag> pattern>
10743  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10744      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10745      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10746    Sched<[!if(Q, WriteVq, WriteVd)]> {
10747  bits<5> Rd;
10748  bits<5> Rn;
10749  bits<5> Rm;
10750  bits<1> rot;
10751  let Inst{31}    = 0;
10752  let Inst{30}    = Q;
10753  let Inst{29}    = U;
10754  let Inst{28-24} = 0b01110;
10755  let Inst{23-22} = size;
10756  let Inst{21}    = 0;
10757  let Inst{20-16} = Rm;
10758  let Inst{15-13} = opcode;
10759  // Non-tied version (FCADD) only has one rotation bit
10760  let Inst{12}    = rot;
10761  let Inst{11}    = 0;
10762  let Inst{10}    = 1;
10763  let Inst{9-5}   = Rn;
10764  let Inst{4-0}   = Rd;
10765}
10766
10767//8.3 CompNum - Floating-point complex number support
10768multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10769                                          string asm, SDPatternOperator OpNode>{
10770  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10771  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10772              asm, ".4h",
10773              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10774                                              (v4f16 V64:$Rn),
10775                                              (v4f16 V64:$Rm),
10776                                              (i32 rottype:$rot)))]>;
10777
10778  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10779              asm, ".8h",
10780              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10781                                               (v8f16 V128:$Rn),
10782                                               (v8f16 V128:$Rm),
10783                                               (i32 rottype:$rot)))]>;
10784  }
10785
10786  let Predicates = [HasComplxNum, HasNEON] in {
10787  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10788              asm, ".2s",
10789              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10790                                              (v2f32 V64:$Rn),
10791                                              (v2f32 V64:$Rm),
10792                                              (i32 rottype:$rot)))]>;
10793
10794  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10795              asm, ".4s",
10796              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10797                                               (v4f32 V128:$Rn),
10798                                               (v4f32 V128:$Rm),
10799                                               (i32 rottype:$rot)))]>;
10800
10801  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10802              asm, ".2d",
10803              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10804                                               (v2f64 V128:$Rn),
10805                                               (v2f64 V128:$Rm),
10806                                               (i32 rottype:$rot)))]>;
10807  }
10808}
10809
10810let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
10811class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10812                                         bits<3> opcode,
10813                                         RegisterOperand regtype,
10814                                         Operand rottype, string asm,
10815                                         string kind, list<dag> pattern>
10816  : I<(outs regtype:$dst),
10817      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10818      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10819      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10820    Sched<[!if(Q, WriteVq, WriteVd)]> {
10821  bits<5> Rd;
10822  bits<5> Rn;
10823  bits<5> Rm;
10824  bits<2> rot;
10825  let Inst{31}    = 0;
10826  let Inst{30}    = Q;
10827  let Inst{29}    = U;
10828  let Inst{28-24} = 0b01110;
10829  let Inst{23-22} = size;
10830  let Inst{21}    = 0;
10831  let Inst{20-16} = Rm;
10832  let Inst{15-13} = opcode;
10833  let Inst{12-11} = rot;
10834  let Inst{10}    = 1;
10835  let Inst{9-5}   = Rn;
10836  let Inst{4-0}   = Rd;
10837}
10838
10839multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10840                                             Operand rottype, string asm,
10841                                             SDPatternOperator OpNode> {
10842  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10843  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10844              rottype, asm, ".4h",
10845              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10846                                              (v4f16 V64:$Rn),
10847                                              (v4f16 V64:$Rm),
10848                                              (i32 rottype:$rot)))]>;
10849
10850  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10851              rottype, asm, ".8h",
10852              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10853                                               (v8f16 V128:$Rn),
10854                                               (v8f16 V128:$Rm),
10855                                               (i32 rottype:$rot)))]>;
10856  }
10857
10858  let Predicates = [HasComplxNum, HasNEON] in {
10859  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10860              rottype, asm, ".2s",
10861              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10862                                              (v2f32 V64:$Rn),
10863                                              (v2f32 V64:$Rm),
10864                                              (i32 rottype:$rot)))]>;
10865
10866  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10867              rottype, asm, ".4s",
10868              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10869                                               (v4f32 V128:$Rn),
10870                                               (v4f32 V128:$Rm),
10871                                               (i32 rottype:$rot)))]>;
10872
10873  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10874              rottype, asm, ".2d",
10875              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10876                                               (v2f64 V128:$Rn),
10877                                               (v2f64 V128:$Rm),
10878                                               (i32 rottype:$rot)))]>;
10879  }
10880}
10881
10882let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
10883class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10884                                 bit opc1, bit opc2, RegisterOperand dst_reg,
10885                                 RegisterOperand lhs_reg,
10886                                 RegisterOperand rhs_reg, Operand vec_idx,
10887                                 Operand rottype, string asm, string apple_kind,
10888                                 string dst_kind, string lhs_kind,
10889                                 string rhs_kind, list<dag> pattern>
10890  : I<(outs dst_reg:$dst),
10891      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10892      asm,
10893      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10894      "$idx, $rot" # "|" # apple_kind #
10895      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10896    Sched<[!if(Q, WriteVq, WriteVd)]> {
10897  bits<5> Rd;
10898  bits<5> Rn;
10899  bits<5> Rm;
10900  bits<2> rot;
10901
10902  let Inst{31}    = 0;
10903  let Inst{30}    = Q;
10904  let Inst{29}    = U;
10905  let Inst{28}    = Scalar;
10906  let Inst{27-24} = 0b1111;
10907  let Inst{23-22} = size;
10908  // Bit 21 must be set by the derived class.
10909  let Inst{20-16} = Rm;
10910  let Inst{15}    = opc1;
10911  let Inst{14-13} = rot;
10912  let Inst{12}    = opc2;
10913  // Bit 11 must be set by the derived class.
10914  let Inst{10}    = 0;
10915  let Inst{9-5}   = Rn;
10916  let Inst{4-0}   = Rd;
10917}
10918
10919// The complex instructions index by pairs of elements, so the VectorIndexes
10920// don't match the lane types, and the index bits are different to the other
10921// classes.
10922multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
10923                                     string asm> {
10924  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10925  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10926                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10927                      ".4h", ".h", []> {
10928    bits<1> idx;
10929    let Inst{11} = 0;
10930    let Inst{21} = idx{0};
10931  }
10932
10933  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10934                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10935                      ".8h", ".8h", ".h", []> {
10936    bits<2> idx;
10937    let Inst{11} = idx{1};
10938    let Inst{21} = idx{0};
10939  }
10940  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10941
10942  let Predicates = [HasComplxNum, HasNEON] in {
10943  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10944                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10945                      ".4s", ".4s", ".s", []> {
10946    bits<1> idx;
10947    let Inst{11} = idx{0};
10948    let Inst{21} = 0;
10949  }
10950  } // Predicates = [HasComplxNum, HasNEON]
10951}
10952
10953//----------------------------------------------------------------------------
10954// Crypto extensions
10955//----------------------------------------------------------------------------
10956
10957let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10958class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10959              list<dag> pat>
10960  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10961    Sched<[WriteVq]>{
10962  bits<5> Rd;
10963  bits<5> Rn;
10964  let Inst{31-16} = 0b0100111000101000;
10965  let Inst{15-12} = opc;
10966  let Inst{11-10} = 0b10;
10967  let Inst{9-5}   = Rn;
10968  let Inst{4-0}   = Rd;
10969}
10970
10971class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10972  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10973            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10974
10975class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10976  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10977            "$Rd = $dst",
10978            [(set (v16i8 V128:$dst),
10979                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10980
10981let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10982class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10983                     dag oops, dag iops, list<dag> pat>
10984  : I<oops, iops, asm,
10985      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10986      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10987    Sched<[WriteVq]>{
10988  bits<5> Rd;
10989  bits<5> Rn;
10990  bits<5> Rm;
10991  let Inst{31-21} = 0b01011110000;
10992  let Inst{20-16} = Rm;
10993  let Inst{15}    = 0;
10994  let Inst{14-12} = opc;
10995  let Inst{11-10} = 0b00;
10996  let Inst{9-5}   = Rn;
10997  let Inst{4-0}   = Rd;
10998}
10999
11000class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
11001  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11002                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
11003                   [(set (v4i32 FPR128:$dst),
11004                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
11005                                 (v4i32 V128:$Rm)))]>;
11006
11007class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
11008  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
11009                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
11010                   [(set (v4i32 V128:$dst),
11011                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11012                                 (v4i32 V128:$Rm)))]>;
11013
11014class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
11015  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11016                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
11017                   [(set (v4i32 FPR128:$dst),
11018                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
11019                                 (v4i32 V128:$Rm)))]>;
11020
11021let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11022class SHA2OpInst<bits<4> opc, string asm, string kind,
11023                 string cstr, dag oops, dag iops,
11024                 list<dag> pat>
11025  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
11026                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
11027    Sched<[WriteVq]>{
11028  bits<5> Rd;
11029  bits<5> Rn;
11030  let Inst{31-16} = 0b0101111000101000;
11031  let Inst{15-12} = opc;
11032  let Inst{11-10} = 0b10;
11033  let Inst{9-5}   = Rn;
11034  let Inst{4-0}   = Rd;
11035}
11036
11037class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
11038  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
11039               (ins V128:$Rd, V128:$Rn),
11040               [(set (v4i32 V128:$dst),
11041                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
11042
11043class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
11044  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
11045               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
11046
11047// Armv8.2-A Crypto extensions
11048class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
11049                    list<dag> pattern>
11050  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
11051  bits<5> Vd;
11052  bits<5> Vn;
11053  let Inst{31-25} = 0b1100111;
11054  let Inst{9-5}   = Vn;
11055  let Inst{4-0}   = Vd;
11056}
11057
11058class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
11059  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
11060                  "$Vd = $Vdst", []> {
11061  let Inst{31-25} = 0b1100111;
11062  let Inst{24-21} = 0b0110;
11063  let Inst{20-15} = 0b000001;
11064  let Inst{14}    = op0;
11065  let Inst{13-12} = 0b00;
11066  let Inst{11-10} = op1;
11067}
11068class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
11069  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
11070class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
11071  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
11072
11073class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
11074                string asmops, string cst>
11075  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
11076  bits<5> Vm;
11077  let Inst{24-21} = 0b0011;
11078  let Inst{20-16} = Vm;
11079  let Inst{15}    = 0b1;
11080  let Inst{14}    = op0;
11081  let Inst{13-12} = 0b00;
11082  let Inst{11-10} = op1;
11083}
11084class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
11085  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11086              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
11087class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
11088  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11089              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11090class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
11091  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11092              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
11093class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
11094  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11095              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11096class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11097  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11098              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11099
11100class CryptoRRRR<bits<2>op0, string asm, string asmops>
11101  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11102                  asmops, "", []> {
11103  bits<5> Vm;
11104  bits<5> Va;
11105  let Inst{24-23} = 0b00;
11106  let Inst{22-21} = op0;
11107  let Inst{20-16} = Vm;
11108  let Inst{15}    = 0b0;
11109  let Inst{14-10} = Va;
11110}
11111class CryptoRRRR_16B<bits<2>op0, string asm>
11112 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11113                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11114}
11115class CryptoRRRR_4S<bits<2>op0, string asm>
11116 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11117                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11118}
11119
11120class CryptoRRRi6<string asm>
11121  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11122                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11123                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11124  bits<6> imm;
11125  bits<5> Vm;
11126  let Inst{24-21} = 0b0100;
11127  let Inst{20-16} = Vm;
11128  let Inst{15-10} = imm;
11129  let Inst{9-5}   = Vn;
11130  let Inst{4-0}   = Vd;
11131}
11132
11133class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11134  : BaseCryptoV82<(outs V128:$Vdst),
11135                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11136                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11137                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11138  bits<2> imm;
11139  bits<5> Vm;
11140  let Inst{24-21} = 0b0010;
11141  let Inst{20-16} = Vm;
11142  let Inst{15}    = 0b1;
11143  let Inst{14}    = op0;
11144  let Inst{13-12} = imm;
11145  let Inst{11-10} = op1;
11146}
11147
11148//----------------------------------------------------------------------------
11149// v8.1 atomic instructions extension:
11150// * CAS
11151// * CASP
11152// * SWP
11153// * LDOPregister<OP>, and aliases STOPregister<OP>
11154
11155// Instruction encodings:
11156//
11157//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11158// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11159// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11160// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11161// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11162// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11163
11164// Instruction syntax:
11165//
11166// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11167// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11168// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11169// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11170// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11171// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11172// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11173// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11174// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11175// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11176
11177let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11178class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11179                      string cstr, list<dag> pattern>
11180      : I<oops, iops, asm, operands, cstr, pattern> {
11181  bits<2> Sz;
11182  bit NP;
11183  bit Acq;
11184  bit Rel;
11185  bits<5> Rs;
11186  bits<5> Rn;
11187  bits<5> Rt;
11188  let Inst{31-30} = Sz;
11189  let Inst{29-24} = 0b001000;
11190  let Inst{23} = NP;
11191  let Inst{22} = Acq;
11192  let Inst{21} = 0b1;
11193  let Inst{20-16} = Rs;
11194  let Inst{15} = Rel;
11195  let Inst{14-10} = 0b11111;
11196  let Inst{9-5} = Rn;
11197  let Inst{4-0} = Rt;
11198  let Predicates = [HasLSE];
11199}
11200
11201class BaseCAS<string order, string size, RegisterClass RC>
11202      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11203                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11204                        "$out = $Rs",[]>,
11205        Sched<[WriteAtomic]> {
11206  let NP = 1;
11207}
11208
11209multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11210  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11211  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11212  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11213  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11214}
11215
11216class BaseCASP<string order, string size, RegisterOperand RC>
11217      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11218                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11219                        "$out = $Rs",[]>,
11220        Sched<[WriteAtomic]> {
11221  let NP = 0;
11222}
11223
11224multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11225  let Sz = 0b00, Acq = Acq, Rel = Rel in
11226    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11227  let Sz = 0b01, Acq = Acq, Rel = Rel in
11228    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11229}
11230
11231let Predicates = [HasLSE] in
11232class BaseSWP<string order, string size, RegisterClass RC>
11233      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11234          "\t$Rs, $Rt, [$Rn]","",[]>,
11235        Sched<[WriteAtomic]> {
11236  bits<2> Sz;
11237  bit Acq;
11238  bit Rel;
11239  bits<5> Rs;
11240  bits<3> opc = 0b000;
11241  bits<5> Rn;
11242  bits<5> Rt;
11243  let Inst{31-30} = Sz;
11244  let Inst{29-24} = 0b111000;
11245  let Inst{23} = Acq;
11246  let Inst{22} = Rel;
11247  let Inst{21} = 0b1;
11248  let Inst{20-16} = Rs;
11249  let Inst{15} = 0b1;
11250  let Inst{14-12} = opc;
11251  let Inst{11-10} = 0b00;
11252  let Inst{9-5} = Rn;
11253  let Inst{4-0} = Rt;
11254  let Predicates = [HasLSE];
11255}
11256
11257multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11258  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11259  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11260  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11261  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11262}
11263
11264let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11265class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11266      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11267          "\t$Rs, $Rt, [$Rn]","",[]>,
11268        Sched<[WriteAtomic]> {
11269  bits<2> Sz;
11270  bit Acq;
11271  bit Rel;
11272  bits<5> Rs;
11273  bits<3> opc;
11274  bits<5> Rn;
11275  bits<5> Rt;
11276  let Inst{31-30} = Sz;
11277  let Inst{29-24} = 0b111000;
11278  let Inst{23} = Acq;
11279  let Inst{22} = Rel;
11280  let Inst{21} = 0b1;
11281  let Inst{20-16} = Rs;
11282  let Inst{15} = 0b0;
11283  let Inst{14-12} = opc;
11284  let Inst{11-10} = 0b00;
11285  let Inst{9-5} = Rn;
11286  let Inst{4-0} = Rt;
11287  let Predicates = [HasLSE];
11288}
11289
11290multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11291                        string order> {
11292  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11293    def B : BaseLDOPregister<op, order, "b", GPR32>;
11294  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11295    def H : BaseLDOPregister<op, order, "h", GPR32>;
11296  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11297    def W : BaseLDOPregister<op, order, "", GPR32>;
11298  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11299    def X : BaseLDOPregister<op, order, "", GPR64>;
11300}
11301
11302// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11303// complex DAG for DstRHS.
11304let Predicates = [HasLSE] in
11305multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11306                                         string size, dag SrcRHS, dag DstRHS> {
11307  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11308            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11309  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11310            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11311  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11312            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11313  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11314            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11315  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11316            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11317}
11318
11319multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11320                                     string size, dag RHS> {
11321  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11322}
11323
11324multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11325                                         string size, dag LHS, dag RHS> {
11326  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11327}
11328
11329multiclass LDOPregister_patterns<string inst, string op> {
11330  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11331  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11332  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11333  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11334}
11335
11336multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11337  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11338                        (i64 GPR64:$Rm),
11339                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11340  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11341                        (i32 GPR32:$Rm),
11342                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11343  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11344                        (i32 GPR32:$Rm),
11345                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11346  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11347                        (i32 GPR32:$Rm),
11348                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11349}
11350
11351let Predicates = [HasLSE] in
11352multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11353                                        string size, dag OLD, dag NEW> {
11354  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11355            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11356  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11357            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11358  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11359            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11360  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11361            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11362  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11363            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11364}
11365
11366multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11367                                    string size, dag OLD, dag NEW> {
11368  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11369}
11370
11371multiclass CASregister_patterns<string inst, string op> {
11372  defm : CASregister_patterns_ord<inst, "X", op, "64",
11373                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11374  defm : CASregister_patterns_ord<inst, "W", op, "32",
11375                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11376  defm : CASregister_patterns_ord<inst, "H", op, "16",
11377                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11378  defm : CASregister_patterns_ord<inst, "B", op, "8",
11379                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11380}
11381
11382let Predicates = [HasLSE] in
11383class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11384                        Instruction inst> :
11385      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11386
11387multiclass STOPregister<string asm, string instr> {
11388  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11389                    !cast<Instruction>(instr # "LB")>;
11390  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11391                    !cast<Instruction>(instr # "LH")>;
11392  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11393                    !cast<Instruction>(instr # "LW")>;
11394  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11395                    !cast<Instruction>(instr # "LX")>;
11396  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11397                    !cast<Instruction>(instr # "B")>;
11398  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11399                    !cast<Instruction>(instr # "H")>;
11400  def : BaseSTOPregister<asm,        GPR32, WZR,
11401                    !cast<Instruction>(instr # "W")>;
11402  def : BaseSTOPregister<asm,        GPR64, XZR,
11403                    !cast<Instruction>(instr # "X")>;
11404}
11405
11406class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11407                        dag iops, dag oops, list<dag> pat>
11408    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11409      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11410  bits<5> Rt;
11411  bits<5> Rn;
11412  let Inst{31-21} = 0b11111000001;
11413  let Inst{15}    = 1;
11414  let Inst{14-12} = opc;
11415  let Inst{11-10} = 0b00;
11416  let Inst{9-5}   = Rn;
11417  let Inst{4-0}   = Rt;
11418
11419  let Predicates = [HasV8_7a];
11420}
11421
11422class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11423                      list<dag> pat = []>
11424    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11425  let Inst{20-16} = 0b11111;
11426}
11427
11428class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11429    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11430                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11431  bits<5> Rs;
11432  let Inst{20-16} = Rs;
11433}
11434
11435class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
11436                             bits<2> op2, string asm>
11437  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
11438      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
11439      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
11440      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
11441    Sched<[]> {
11442  bits<5> Rd;
11443  bits<5> Rs;
11444  bits<5> Rn;
11445  let Inst{31-27} = 0b00011;
11446  let Inst{26} = isMove;
11447  let Inst{25-24} = 0b01;
11448  let Inst{23-22} = opcode;
11449  let Inst{21} = 0b0;
11450  let Inst{20-16} = Rs;
11451  let Inst{15-14} = op2;
11452  let Inst{13-12} = op1;
11453  let Inst{11-10} = 0b01;
11454  let Inst{9-5} = Rn;
11455  let Inst{4-0} = Rd;
11456
11457  let DecoderMethod = "DecodeCPYMemOpInstruction";
11458  let mayLoad = 1;
11459  let mayStore = 1;
11460}
11461
11462class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11463  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
11464
11465class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11466  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
11467
11468class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
11469                        string asm>
11470  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
11471      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
11472      asm, "\t[$Rd]!, $Rn!, $Rm",
11473      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
11474    Sched<[]> {
11475  bits<5> Rd;
11476  bits<5> Rn;
11477  bits<5> Rm;
11478  let Inst{31-27} = 0b00011;
11479  let Inst{26} = isTagging;
11480  let Inst{25-21} = 0b01110;
11481  let Inst{20-16} = Rm;
11482  let Inst{15-14} = opcode;
11483  let Inst{13} = op2;
11484  let Inst{12} = op1;
11485  let Inst{11-10} = 0b01;
11486  let Inst{9-5} = Rn;
11487  let Inst{4-0} = Rd;
11488
11489  let DecoderMethod = "DecodeSETMemOpInstruction";
11490  let mayLoad = 0;
11491  let mayStore = 1;
11492}
11493
11494class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
11495  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
11496
11497class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
11498  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
11499
11500multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
11501  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
11502  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
11503  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
11504  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
11505  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
11506  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
11507  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
11508  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
11509  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
11510  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
11511  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
11512  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
11513  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
11514  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
11515  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
11516  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
11517}
11518
11519multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
11520  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
11521  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
11522  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
11523  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
11524  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
11525  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
11526  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
11527  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
11528  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
11529  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
11530  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
11531  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
11532  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
11533  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
11534  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
11535  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
11536}
11537
11538multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
11539  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
11540  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
11541  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
11542  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
11543}
11544
11545multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
11546  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
11547  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
11548  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
11549  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
11550}
11551
11552//----------------------------------------------------------------------------
11553// Allow the size specifier tokens to be upper case, not just lower.
11554def : TokenAlias<".4B", ".4b">;  // Add dot product
11555def : TokenAlias<".8B", ".8b">;
11556def : TokenAlias<".4H", ".4h">;
11557def : TokenAlias<".2S", ".2s">;
11558def : TokenAlias<".1D", ".1d">;
11559def : TokenAlias<".16B", ".16b">;
11560def : TokenAlias<".8H", ".8h">;
11561def : TokenAlias<".4S", ".4s">;
11562def : TokenAlias<".2D", ".2d">;
11563def : TokenAlias<".1Q", ".1q">;
11564def : TokenAlias<".2H", ".2h">;
11565def : TokenAlias<".B", ".b">;
11566def : TokenAlias<".H", ".h">;
11567def : TokenAlias<".S", ".s">;
11568def : TokenAlias<".D", ".d">;
11569def : TokenAlias<".Q", ".q">;
11570