xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64InstrFormats.td (revision 4d846d260e2b9a3d4d0a701462568268cbfe7a5b)
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
1171def arith_uxtx : ComplexPattern<i64, 2, "SelectArithUXTXRegister", []>;
1172
1173// Floating-point immediate.
1174
1175def fpimm16XForm : SDNodeXForm<fpimm, [{
1176      APFloat InVal = N->getValueAPF();
1177      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1178      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1179    }]>;
1180
1181def fpimm32XForm : SDNodeXForm<fpimm, [{
1182      APFloat InVal = N->getValueAPF();
1183      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1184      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1185    }]>;
1186
1187def fpimm32SIMDModImmType4XForm : SDNodeXForm<fpimm, [{
1188      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType4(N->getValueAPF()
1189                                                          .bitcastToAPInt()
1190                                                          .getZExtValue());
1191      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1192    }]>;
1193
1194def fpimm64XForm : SDNodeXForm<fpimm, [{
1195      APFloat InVal = N->getValueAPF();
1196      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1197      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1198    }]>;
1199
1200def fpimm16 : Operand<f16>,
1201              FPImmLeaf<f16, [{
1202      return AArch64_AM::getFP16Imm(Imm) != -1;
1203    }], fpimm16XForm> {
1204  let ParserMatchClass = FPImmOperand;
1205  let PrintMethod = "printFPImmOperand";
1206}
1207
1208def fpimm32 : Operand<f32>,
1209              FPImmLeaf<f32, [{
1210      return AArch64_AM::getFP32Imm(Imm) != -1;
1211    }], fpimm32XForm> {
1212  let ParserMatchClass = FPImmOperand;
1213  let PrintMethod = "printFPImmOperand";
1214}
1215
1216def fpimm32SIMDModImmType4 : FPImmLeaf<f32, [{
1217      uint64_t Enc = Imm.bitcastToAPInt().getZExtValue();
1218      return Enc != 0 && AArch64_AM::isAdvSIMDModImmType4(Enc << 32 | Enc);
1219    }], fpimm32SIMDModImmType4XForm> {
1220}
1221
1222def fpimm64 : Operand<f64>,
1223              FPImmLeaf<f64, [{
1224      return AArch64_AM::getFP64Imm(Imm) != -1;
1225    }], fpimm64XForm> {
1226  let ParserMatchClass = FPImmOperand;
1227  let PrintMethod = "printFPImmOperand";
1228}
1229
1230def fpimm8 : Operand<i32> {
1231  let ParserMatchClass = FPImmOperand;
1232  let PrintMethod = "printFPImmOperand";
1233}
1234
1235def fpimm0 : FPImmLeaf<fAny, [{
1236  return Imm.isExactlyValue(+0.0);
1237}]>;
1238
1239def fpimm_minus0 : FPImmLeaf<fAny, [{
1240  return Imm.isExactlyValue(-0.0);
1241}]>;
1242
1243def fpimm_half : FPImmLeaf<fAny, [{
1244  return Imm.isExactlyValue(+0.5);
1245}]>;
1246
1247def fpimm_one : FPImmLeaf<fAny, [{
1248  return Imm.isExactlyValue(+1.0);
1249}]>;
1250
1251def fpimm_two : FPImmLeaf<fAny, [{
1252  return Imm.isExactlyValue(+2.0);
1253}]>;
1254
1255def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1256  GISDNodeXFormEquiv<fpimm16XForm>;
1257def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1258  GISDNodeXFormEquiv<fpimm32XForm>;
1259def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1260  GISDNodeXFormEquiv<fpimm64XForm>;
1261def gi_fpimm32SIMDModImmType4 :
1262    GICustomOperandRenderer<"renderFPImm32SIMDModImmType4">,
1263  GISDNodeXFormEquiv<fpimm32SIMDModImmType4XForm>;
1264
1265// Vector lane operands
1266class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1267  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1268  let DiagnosticType = "Invalid" # Name;
1269  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1270  let RenderMethod = "addVectorIndexOperands";
1271}
1272
1273class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1274    : Operand<ty> {
1275  let ParserMatchClass = mc;
1276  let PrintMethod = "printVectorIndex";
1277}
1278
1279multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1280  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1281  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1282}
1283
1284def VectorIndex0Operand : AsmVectorIndex<0, 0>;
1285def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1286def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1287def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1288def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1289def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1290
1291let OperandNamespace = "AArch64" in {
1292  let OperandType = "OPERAND_IMPLICIT_IMM_0" in {
1293    defm VectorIndex0 : VectorIndex<i64, VectorIndex0Operand,
1294                                [{ return ((uint64_t)Imm) == 0; }]>;
1295  }
1296}
1297defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1298                                [{ return ((uint64_t)Imm) == 1; }]>;
1299defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1300                                [{ return ((uint64_t)Imm) < 16; }]>;
1301defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1302                                [{ return ((uint64_t)Imm) < 8; }]>;
1303defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1304                                [{ return ((uint64_t)Imm) < 4; }]>;
1305defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1306                                [{ return ((uint64_t)Imm) < 2; }]>;
1307
1308defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1309                                   [{ return ((uint64_t)Imm) == 1; }]>;
1310defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1311                                   [{ return ((uint64_t)Imm) < 16; }]>;
1312defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1313                                   [{ return ((uint64_t)Imm) < 8; }]>;
1314defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1315                                   [{ return ((uint64_t)Imm) < 4; }]>;
1316defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1317                                   [{ return ((uint64_t)Imm) < 2; }]>;
1318
1319def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1320def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1321def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1322def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1323def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1324
1325defm sve_elm_idx_extdup_b
1326  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1327                [{ return ((uint64_t)Imm) < 64; }]>;
1328defm sve_elm_idx_extdup_h
1329  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1330                [{ return ((uint64_t)Imm) < 32; }]>;
1331defm sve_elm_idx_extdup_s
1332  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1333                [{ return ((uint64_t)Imm) < 16; }]>;
1334defm sve_elm_idx_extdup_d
1335  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1336                [{ return ((uint64_t)Imm) < 8; }]>;
1337defm sve_elm_idx_extdup_q
1338  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1339                [{ return ((uint64_t)Imm) < 4; }]>;
1340
1341def sme_elm_idx0_0 : Operand<i64>, ImmLeaf<i64, [{
1342  return ((uint64_t)Imm) == 0;
1343}]> {
1344  let ParserMatchClass = Imm0_0Operand;
1345  let PrintMethod = "printMatrixIndex";
1346  let OperandNamespace = "AArch64";
1347  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1348}
1349def sme_elm_idx0_1 : Operand<i64>, ImmLeaf<i64, [{
1350  return ((uint64_t)Imm) <= 1;
1351}]> {
1352  let ParserMatchClass = Imm0_1Operand;
1353  let PrintMethod = "printMatrixIndex";
1354}
1355def sme_elm_idx0_3 : Operand<i64>, ImmLeaf<i64, [{
1356  return ((uint64_t)Imm) <= 3;
1357}]> {
1358  let ParserMatchClass = Imm0_3Operand;
1359  let PrintMethod = "printMatrixIndex";
1360}
1361def sme_elm_idx0_7 : Operand<i64>, ImmLeaf<i64, [{
1362  return ((uint64_t)Imm) <= 7;
1363}]> {
1364  let ParserMatchClass = Imm0_7Operand;
1365  let PrintMethod = "printMatrixIndex";
1366}
1367def sme_elm_idx0_15 : Operand<i64>, ImmLeaf<i64, [{
1368  return ((uint64_t)Imm) <= 15;
1369}]> {
1370  let ParserMatchClass = Imm0_15Operand;
1371  let PrintMethod = "printMatrixIndex";
1372}
1373
1374// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1375// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1376// are encoded as the eight bit value 'abcdefgh'.
1377def simdimmtype10 : Operand<i32>,
1378                    FPImmLeaf<f64, [{
1379      return AArch64_AM::isAdvSIMDModImmType10(
1380                 Imm.bitcastToAPInt().getZExtValue());
1381    }], SDNodeXForm<fpimm, [{
1382      APFloat InVal = N->getValueAPF();
1383      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1384                                                           .bitcastToAPInt()
1385                                                           .getZExtValue());
1386      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1387    }]>> {
1388  let ParserMatchClass = SIMDImmType10Operand;
1389  let PrintMethod = "printSIMDType10Operand";
1390}
1391
1392
1393//---
1394// System management
1395//---
1396
1397// Base encoding for system instruction operands.
1398let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1399class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1400                  list<dag> pattern = []>
1401    : I<oops, iops, asm, operands, "", pattern> {
1402  let Inst{31-22} = 0b1101010100;
1403  let Inst{21}    = L;
1404}
1405
1406// System instructions which do not have an Rt register.
1407class SimpleSystemI<bit L, dag iops, string asm, string operands,
1408                    list<dag> pattern = []>
1409    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1410  let Inst{4-0} = 0b11111;
1411}
1412
1413// System instructions which have an Rt register.
1414class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1415                list<dag> pattern = []>
1416    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1417      Sched<[WriteSys]> {
1418  bits<5> Rt;
1419  let Inst{4-0} = Rt;
1420}
1421
1422// System instructions for transactional memory extension
1423class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1424                    string asm, string operands, list<dag> pattern>
1425    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1426      Sched<[WriteSys]> {
1427  let Inst{20-12} = 0b000110011;
1428  let Inst{11-8} = CRm;
1429  let Inst{7-5} = op2;
1430  let DecoderMethod = "";
1431
1432  let mayLoad = 1;
1433  let mayStore = 1;
1434}
1435
1436// System instructions for transactional memory - single input operand
1437class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1438    : TMBaseSystemI<0b1, CRm, 0b011,
1439                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1440  bits<5> Rt;
1441  let Inst{4-0} = Rt;
1442}
1443
1444// System instructions that pass a register argument
1445// This class assumes the register is for input rather than output.
1446class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1447                      list<dag> pattern = []>
1448    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1449  let Inst{20-12} = 0b000110001;
1450  let Inst{11-8} = CRm;
1451  let Inst{7-5} = Op2;
1452}
1453
1454// System instructions for transactional memory - no operand
1455class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1456    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1457  let Inst{4-0} = 0b11111;
1458}
1459
1460// System instructions for exit from transactions
1461class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1462    : I<(outs), (ins timm64_0_65535:$imm), asm, "\t$imm", "", pattern>,
1463      Sched<[WriteSys]> {
1464  bits<16> imm;
1465  let Inst{31-24} = 0b11010100;
1466  let Inst{23-21} = op1;
1467  let Inst{20-5}  = imm;
1468  let Inst{4-0}   = 0b00000;
1469}
1470
1471// Hint instructions that take both a CRm and a 3-bit immediate.
1472// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1473// model patterns with sufficiently fine granularity
1474let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1475  class HintI<string mnemonic>
1476      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1477                      [(int_aarch64_hint imm0_127:$imm)]>,
1478        Sched<[WriteHint]> {
1479    bits <7> imm;
1480    let Inst{20-12} = 0b000110010;
1481    let Inst{11-5} = imm;
1482  }
1483
1484// System instructions taking a single literal operand which encodes into
1485// CRm. op2 differentiates the opcodes.
1486def BarrierAsmOperand : AsmOperandClass {
1487  let Name = "Barrier";
1488  let ParserMethod = "tryParseBarrierOperand";
1489}
1490def barrier_op : Operand<i32> {
1491  let PrintMethod = "printBarrierOption";
1492  let ParserMatchClass = BarrierAsmOperand;
1493}
1494def BarriernXSAsmOperand : AsmOperandClass {
1495  let Name = "BarriernXS";
1496  let ParserMethod = "tryParseBarriernXSOperand";
1497}
1498def barrier_nxs_op : Operand<i32> {
1499  let PrintMethod = "printBarriernXSOption";
1500  let ParserMatchClass = BarriernXSAsmOperand;
1501}
1502class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1503                 list<dag> pattern = []>
1504    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1505      Sched<[WriteBarrier]> {
1506  bits<4> CRm;
1507  let Inst{20-12} = 0b000110011;
1508  let Inst{11-8} = CRm;
1509  let Inst{7-5} = opc;
1510}
1511
1512class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1513    : SimpleSystemI<0, (ins), asm, "", pattern>,
1514      Sched<[WriteHint]> {
1515  bits<4> CRm;
1516  let CRm = 0b0011;
1517  let Inst{31-12} = 0b11010101000000110010;
1518  let Inst{11-8} = CRm;
1519  let Inst{7-5} = op2;
1520  let Inst{4-0} = 0b11111;
1521}
1522
1523// MRS/MSR system instructions. These have different operand classes because
1524// a different subset of registers can be accessed through each instruction.
1525def MRSSystemRegisterOperand : AsmOperandClass {
1526  let Name = "MRSSystemRegister";
1527  let ParserMethod = "tryParseSysReg";
1528  let DiagnosticType = "MRS";
1529}
1530// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1531def mrs_sysreg_op : Operand<i32> {
1532  let ParserMatchClass = MRSSystemRegisterOperand;
1533  let DecoderMethod = "DecodeMRSSystemRegister";
1534  let PrintMethod = "printMRSSystemRegister";
1535}
1536
1537def MSRSystemRegisterOperand : AsmOperandClass {
1538  let Name = "MSRSystemRegister";
1539  let ParserMethod = "tryParseSysReg";
1540  let DiagnosticType = "MSR";
1541}
1542def msr_sysreg_op : Operand<i32> {
1543  let ParserMatchClass = MSRSystemRegisterOperand;
1544  let DecoderMethod = "DecodeMSRSystemRegister";
1545  let PrintMethod = "printMSRSystemRegister";
1546}
1547
1548def PSBHintOperand : AsmOperandClass {
1549  let Name = "PSBHint";
1550  let ParserMethod = "tryParsePSBHint";
1551}
1552def psbhint_op : Operand<i32> {
1553  let ParserMatchClass = PSBHintOperand;
1554  let PrintMethod = "printPSBHintOp";
1555  let MCOperandPredicate = [{
1556    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1557    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1558    if (!MCOp.isImm())
1559      return false;
1560    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1561  }];
1562}
1563
1564def BTIHintOperand : AsmOperandClass {
1565  let Name = "BTIHint";
1566  let ParserMethod = "tryParseBTIHint";
1567}
1568def btihint_op : Operand<i32> {
1569  let ParserMatchClass = BTIHintOperand;
1570  let PrintMethod = "printBTIHintOp";
1571  let MCOperandPredicate = [{
1572    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1573    if (!MCOp.isImm())
1574      return false;
1575    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1576  }];
1577}
1578
1579class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1580                       "mrs", "\t$Rt, $systemreg"> {
1581  bits<16> systemreg;
1582  let Inst{20-5} = systemreg;
1583  let DecoderNamespace = "Fallback";
1584  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1585  // require doing this. The alternative was to explicitly model each one, but
1586  // it feels like it is unnecessary because it seems there are no negative
1587  // consequences setting these flags for all.
1588  let Defs = [NZCV];
1589}
1590
1591// FIXME: Some of these def NZCV, others don't. Best way to model that?
1592// Explicitly modeling each of the system register as a register class
1593// would do it, but feels like overkill at this point.
1594class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1595                       "msr", "\t$systemreg, $Rt"> {
1596  bits<16> systemreg;
1597  let Inst{20-5} = systemreg;
1598  let DecoderNamespace = "Fallback";
1599}
1600
1601def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1602  let Name = "SystemPStateFieldWithImm0_15";
1603  let ParserMethod = "tryParseSysReg";
1604}
1605def pstatefield4_op : Operand<i32> {
1606  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1607  let PrintMethod = "printSystemPStateField";
1608}
1609
1610// Instructions to modify PSTATE, no input reg
1611let Defs = [NZCV] in
1612class PstateWriteSimple<dag iops, string asm, string operands>
1613  : SimpleSystemI<0, iops, asm, operands> {
1614
1615  let Inst{20-19} = 0b00;
1616  let Inst{15-12} = 0b0100;
1617}
1618
1619class MSRpstateImm0_15
1620  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1621                  "\t$pstatefield, $imm">,
1622    Sched<[WriteSys]> {
1623
1624  bits<6> pstatefield;
1625  bits<4> imm;
1626  let Inst{18-16} = pstatefield{5-3};
1627  let Inst{11-8} = imm;
1628  let Inst{7-5} = pstatefield{2-0};
1629
1630  let DecoderMethod = "DecodeSystemPStateInstruction";
1631  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1632  // Fail the decoder should attempt to decode the instruction as MSRI.
1633  let hasCompleteDecoder = 0;
1634}
1635
1636def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1637  let Name = "SystemPStateFieldWithImm0_1";
1638  let ParserMethod = "tryParseSysReg";
1639}
1640def pstatefield1_op : Operand<i32> {
1641  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1642  let PrintMethod = "printSystemPStateField";
1643}
1644
1645class MSRpstateImm0_1
1646  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1647                 "\t$pstatefield, $imm">,
1648    Sched<[WriteSys]> {
1649
1650  bits<6> pstatefield;
1651  bit imm;
1652  let Inst{18-16} = pstatefield{5-3};
1653  let Inst{11-9} = 0b000;
1654  let Inst{8} = imm;
1655  let Inst{7-5} = pstatefield{2-0};
1656
1657  let DecoderMethod = "DecodeSystemPStateInstruction";
1658  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1659  // Fail the decoder should attempt to decode the instruction as MSRI.
1660  let hasCompleteDecoder = 0;
1661}
1662
1663// SYS and SYSL generic system instructions.
1664def SysCRAsmOperand : AsmOperandClass {
1665  let Name = "SysCR";
1666  let ParserMethod = "tryParseSysCROperand";
1667}
1668
1669def sys_cr_op : Operand<i32> {
1670  let PrintMethod = "printSysCROperand";
1671  let ParserMatchClass = SysCRAsmOperand;
1672}
1673
1674class SystemXtI<bit L, string asm>
1675  : RtSystemI<L, (outs),
1676       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1677       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1678  bits<3> op1;
1679  bits<4> Cn;
1680  bits<4> Cm;
1681  bits<3> op2;
1682  let Inst{20-19} = 0b01;
1683  let Inst{18-16} = op1;
1684  let Inst{15-12} = Cn;
1685  let Inst{11-8}  = Cm;
1686  let Inst{7-5}   = op2;
1687}
1688
1689class SystemLXtI<bit L, string asm>
1690  : RtSystemI<L, (outs),
1691       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1692       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1693  bits<3> op1;
1694  bits<4> Cn;
1695  bits<4> Cm;
1696  bits<3> op2;
1697  let Inst{20-19} = 0b01;
1698  let Inst{18-16} = op1;
1699  let Inst{15-12} = Cn;
1700  let Inst{11-8}  = Cm;
1701  let Inst{7-5}   = op2;
1702}
1703
1704
1705// Branch (register) instructions:
1706//
1707//  case opc of
1708//    0001 blr
1709//    0000 br
1710//    0101 dret
1711//    0100 eret
1712//    0010 ret
1713//    otherwise UNDEFINED
1714class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1715                    string operands, list<dag> pattern>
1716    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1717  let Inst{31-25} = 0b1101011;
1718  let Inst{24-21} = opc;
1719  let Inst{20-16} = 0b11111;
1720  let Inst{15-10} = 0b000000;
1721  let Inst{4-0}   = 0b00000;
1722}
1723
1724class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1725    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1726  bits<5> Rn;
1727  let Inst{9-5} = Rn;
1728}
1729
1730let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1731class SpecialReturn<bits<4> opc, string asm>
1732    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1733  let Inst{9-5} = 0b11111;
1734}
1735
1736let mayLoad = 1 in
1737class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1738  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1739  Sched<[]> {
1740  bits<5> Rn;
1741  bits<5> Rt;
1742  let Inst{31-30} = sz;
1743  let Inst{29-10} = 0b11100010111111110000;
1744  let Inst{9-5} = Rn;
1745  let Inst{4-0} = Rt;
1746}
1747
1748class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1749               list<dag> pattern>
1750  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1751  let isAuthenticated = 1;
1752  let Inst{31-25} = 0b1101011;
1753  let Inst{20-11} = 0b1111100001;
1754  let Inst{10} = M;
1755  let Inst{4-0} = 0b11111;
1756}
1757
1758class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1759  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1760  bits<5> Rn;
1761  bits<5> Rm;
1762  let Inst{24-22} = 0b100;
1763  let Inst{21} = op;
1764  let Inst{9-5} = Rn;
1765  let Inst{4-0} = Rm;
1766}
1767
1768class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1769  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1770  bits<5> Rn;
1771  let Inst{24} = 0;
1772  let Inst{23-21} = opc;
1773  let Inst{9-5} = Rn;
1774}
1775
1776let Uses = [LR,SP] in
1777class AuthReturn<bits<3> op, bits<1> M, string asm>
1778  : AuthBase<M, (outs), (ins), asm, "", []> {
1779  let Inst{24} = 0;
1780  let Inst{23-21} = op;
1781  let Inst{9-0} = 0b1111111111;
1782}
1783
1784let mayLoad = 1 in
1785class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1786                   string operands, string cstr>
1787  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1788  bits<10> offset;
1789  bits<5> Rn;
1790  bits<5> Rt;
1791  let isAuthenticated = 1;
1792  let Inst{31-24} = 0b11111000;
1793  let Inst{23} = M;
1794  let Inst{22} = offset{9};
1795  let Inst{21} = 1;
1796  let Inst{20-12} = offset{8-0};
1797  let Inst{11} = W;
1798  let Inst{10} = 1;
1799  let Inst{9-5} = Rn;
1800  let Inst{4-0} = Rt;
1801
1802  let DecoderMethod = "DecodeAuthLoadInstruction";
1803}
1804
1805multiclass AuthLoad<bit M, string asm, Operand opr> {
1806  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1807                               (ins GPR64sp:$Rn, opr:$offset),
1808                               asm, "\t$Rt, [$Rn, $offset]", "">;
1809  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1810                               (ins GPR64sp:$Rn, opr:$offset),
1811                               asm, "\t$Rt, [$Rn, $offset]!",
1812                               "$Rn = $wback,@earlyclobber $wback">;
1813
1814  def : InstAlias<asm # "\t$Rt, [$Rn]",
1815                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1816
1817  def : InstAlias<asm # "\t$Rt, [$wback]!",
1818                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1819}
1820
1821//---
1822// Conditional branch instruction.
1823//---
1824
1825// Condition code.
1826// 4-bit immediate. Pretty-printed as <cc>
1827def ccode : Operand<i32> {
1828  let PrintMethod = "printCondCode";
1829  let ParserMatchClass = CondCode;
1830}
1831def inv_ccode : Operand<i32> {
1832  // AL and NV are invalid in the aliases which use inv_ccode
1833  let PrintMethod = "printInverseCondCode";
1834  let ParserMatchClass = CondCode;
1835  let MCOperandPredicate = [{
1836    return MCOp.isImm() &&
1837           MCOp.getImm() != AArch64CC::AL &&
1838           MCOp.getImm() != AArch64CC::NV;
1839  }];
1840}
1841
1842// Conditional branch target. 19-bit immediate. The low two bits of the target
1843// offset are implied zero and so are not part of the immediate.
1844def am_brcond : Operand<OtherVT> {
1845  let EncoderMethod = "getCondBranchTargetOpValue";
1846  let DecoderMethod = "DecodePCRelLabel19";
1847  let PrintMethod = "printAlignedLabel";
1848  let ParserMatchClass = PCRelLabel19Operand;
1849  let OperandType = "OPERAND_PCREL";
1850}
1851
1852class BranchCond<bit bit4, string mnemonic>
1853   : I<(outs), (ins ccode:$cond, am_brcond:$target),
1854       mnemonic, ".$cond\t$target", "",
1855       [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> {
1856  let isBranch = 1;
1857  let isTerminator = 1;
1858  let Uses = [NZCV];
1859
1860  bits<4> cond;
1861  bits<19> target;
1862  let Inst{31-24} = 0b01010100;
1863  let Inst{23-5} = target;
1864  let Inst{4} = bit4;
1865  let Inst{3-0} = cond;
1866}
1867
1868//---
1869// Compare-and-branch instructions.
1870//---
1871class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1872    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1873         asm, "\t$Rt, $target", "",
1874         [(node regtype:$Rt, bb:$target)]>,
1875      Sched<[WriteBr]> {
1876  let isBranch = 1;
1877  let isTerminator = 1;
1878
1879  bits<5> Rt;
1880  bits<19> target;
1881  let Inst{30-25} = 0b011010;
1882  let Inst{24}    = op;
1883  let Inst{23-5}  = target;
1884  let Inst{4-0}   = Rt;
1885}
1886
1887multiclass CmpBranch<bit op, string asm, SDNode node> {
1888  def W : BaseCmpBranch<GPR32, op, asm, node> {
1889    let Inst{31} = 0;
1890  }
1891  def X : BaseCmpBranch<GPR64, op, asm, node> {
1892    let Inst{31} = 1;
1893  }
1894}
1895
1896//---
1897// Test-bit-and-branch instructions.
1898//---
1899// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1900// the target offset are implied zero and so are not part of the immediate.
1901def am_tbrcond : Operand<OtherVT> {
1902  let EncoderMethod = "getTestBranchTargetOpValue";
1903  let PrintMethod = "printAlignedLabel";
1904  let ParserMatchClass = BranchTarget14Operand;
1905  let OperandType = "OPERAND_PCREL";
1906}
1907
1908// AsmOperand classes to emit (or not) special diagnostics
1909def TBZImm0_31Operand : AsmOperandClass {
1910  let Name = "TBZImm0_31";
1911  let PredicateMethod = "isImmInRange<0,31>";
1912  let RenderMethod = "addImmOperands";
1913}
1914def TBZImm32_63Operand : AsmOperandClass {
1915  let Name = "Imm32_63";
1916  let PredicateMethod = "isImmInRange<32,63>";
1917  let DiagnosticType = "InvalidImm0_63";
1918  let RenderMethod = "addImmOperands";
1919}
1920
1921class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1922  return (((uint32_t)Imm) < 32);
1923}]> {
1924  let ParserMatchClass = matcher;
1925}
1926
1927def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1928def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1929
1930def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1931  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1932}]> {
1933  let ParserMatchClass = TBZImm32_63Operand;
1934}
1935
1936class BaseTestBranch<RegisterClass regtype, Operand immtype,
1937                     bit op, string asm, SDNode node>
1938    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1939       asm, "\t$Rt, $bit_off, $target", "",
1940       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1941      Sched<[WriteBr]> {
1942  let isBranch = 1;
1943  let isTerminator = 1;
1944
1945  bits<5> Rt;
1946  bits<6> bit_off;
1947  bits<14> target;
1948
1949  let Inst{30-25} = 0b011011;
1950  let Inst{24}    = op;
1951  let Inst{23-19} = bit_off{4-0};
1952  let Inst{18-5}  = target;
1953  let Inst{4-0}   = Rt;
1954
1955  let DecoderMethod = "DecodeTestAndBranch";
1956}
1957
1958multiclass TestBranch<bit op, string asm, SDNode node> {
1959  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1960    let Inst{31} = 0;
1961  }
1962
1963  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1964    let Inst{31} = 1;
1965  }
1966
1967  // Alias X-reg with 0-31 imm to W-Reg.
1968  def : InstAlias<asm # "\t$Rd, $imm, $target",
1969                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1970                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1971  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1972            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1973            tbz_imm0_31_diag:$imm, bb:$target)>;
1974}
1975
1976//---
1977// Unconditional branch (immediate) instructions.
1978//---
1979def am_b_target : Operand<OtherVT> {
1980  let EncoderMethod = "getBranchTargetOpValue";
1981  let PrintMethod = "printAlignedLabel";
1982  let ParserMatchClass = BranchTarget26Operand;
1983  let OperandType = "OPERAND_PCREL";
1984}
1985def am_bl_target : Operand<i64> {
1986  let EncoderMethod = "getBranchTargetOpValue";
1987  let PrintMethod = "printAlignedLabel";
1988  let ParserMatchClass = BranchTarget26Operand;
1989  let OperandType = "OPERAND_PCREL";
1990}
1991
1992class BImm<bit op, dag iops, string asm, list<dag> pattern>
1993    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1994  bits<26> addr;
1995  let Inst{31}    = op;
1996  let Inst{30-26} = 0b00101;
1997  let Inst{25-0}  = addr;
1998
1999  let DecoderMethod = "DecodeUnconditionalBranch";
2000}
2001
2002class BranchImm<bit op, string asm, list<dag> pattern>
2003    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
2004class CallImm<bit op, string asm, list<dag> pattern>
2005    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
2006
2007//---
2008// Basic one-operand data processing instructions.
2009//---
2010
2011let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2012class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
2013                         SDPatternOperator node>
2014  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
2015      [(set regtype:$Rd, (node regtype:$Rn))]>,
2016    Sched<[WriteI, ReadI]> {
2017  bits<5> Rd;
2018  bits<5> Rn;
2019
2020  let Inst{30-13} = 0b101101011000000000;
2021  let Inst{12-10} = opc;
2022  let Inst{9-5}   = Rn;
2023  let Inst{4-0}   = Rd;
2024}
2025
2026let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2027multiclass OneOperandData<bits<3> opc, string asm,
2028                          SDPatternOperator node = null_frag> {
2029  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
2030    let Inst{31} = 0;
2031  }
2032
2033  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
2034    let Inst{31} = 1;
2035  }
2036}
2037
2038class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
2039    : BaseOneOperandData<opc, GPR32, asm, node> {
2040  let Inst{31} = 0;
2041}
2042
2043class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
2044    : BaseOneOperandData<opc, GPR64, asm, node> {
2045  let Inst{31} = 1;
2046}
2047
2048class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm,
2049                      SDPatternOperator op>
2050  : I<(outs GPR64:$dst), (ins GPR64:$Rd, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
2051      "$dst = $Rd", [(set GPR64:$dst, (op GPR64:$Rd, opcode, GPR64sp:$Rn))]>,
2052    Sched<[WriteI, ReadI]> {
2053  bits<5> Rd;
2054  bits<5> Rn;
2055  let Inst{31-15} = 0b11011010110000010;
2056  let Inst{14-12} = opcode_prefix;
2057  let Inst{11-10} = opcode;
2058  let Inst{9-5} = Rn;
2059  let Inst{4-0} = Rd;
2060}
2061
2062class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm,
2063                   SDPatternOperator op>
2064  : I<(outs GPR64:$dst), (ins GPR64:$Rd), asm, "\t$Rd", "$dst = $Rd",
2065      [(set GPR64:$dst, (op GPR64:$Rd, opcode, (i64 0)))]>,
2066    Sched<[]> {
2067  bits<5> Rd;
2068  let Inst{31-15} = 0b11011010110000010;
2069  let Inst{14-12} = opcode_prefix;
2070  let Inst{11-10} = opcode;
2071  let Inst{9-5} = 0b11111;
2072  let Inst{4-0} = Rd;
2073}
2074
2075class SignAuthTwoOperand<bits<4> opc, string asm,
2076                         SDPatternOperator OpNode>
2077  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
2078      asm, "\t$Rd, $Rn, $Rm", "",
2079      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
2080    Sched<[WriteI, ReadI, ReadI]> {
2081  bits<5> Rd;
2082  bits<5> Rn;
2083  bits<5> Rm;
2084  let Inst{31-21} = 0b10011010110;
2085  let Inst{20-16} = Rm;
2086  let Inst{15-14} = 0b00;
2087  let Inst{13-10} = opc;
2088  let Inst{9-5}   = Rn;
2089  let Inst{4-0}   = Rd;
2090}
2091
2092class ClearAuth<bits<1> data, string asm>
2093  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2094  bits<5> Rd;
2095  let Inst{31-11} = 0b110110101100000101000;
2096  let Inst{10} = data;
2097  let Inst{9-5} = 0b11111;
2098  let Inst{4-0} = Rd;
2099}
2100
2101// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2102class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2103    : I<(outs), iops, asm, ops, "", []>,
2104      Sched<[WriteI, ReadI, ReadI]> {
2105  let Uses = [NZCV];
2106  let Defs = [NZCV];
2107  bits<5> Rn;
2108  let Inst{31}    = sf;
2109  let Inst{30-15} = 0b0111010000000000;
2110  let Inst{14}    = sz;
2111  let Inst{13-10} = 0b0010;
2112  let Inst{9-5}   = Rn;
2113  let Inst{4-0}   = 0b01101;
2114}
2115
2116class FlagRotate<dag iops, string asm, string ops>
2117    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2118  bits<6> imm;
2119  bits<4> mask;
2120  let Inst{20-15} = imm;
2121  let Inst{13-10} = 0b0001;
2122  let Inst{4}     = 0b0;
2123  let Inst{3-0}   = mask;
2124}
2125
2126//---
2127// Basic two-operand data processing instructions.
2128//---
2129class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2130                          list<dag> pattern>
2131    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2132        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2133      Sched<[WriteI, ReadI, ReadI]> {
2134  let Uses = [NZCV];
2135  bits<5> Rd;
2136  bits<5> Rn;
2137  bits<5> Rm;
2138  let Inst{30}    = isSub;
2139  let Inst{28-21} = 0b11010000;
2140  let Inst{20-16} = Rm;
2141  let Inst{15-10} = 0;
2142  let Inst{9-5}   = Rn;
2143  let Inst{4-0}   = Rd;
2144}
2145
2146class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2147                      SDNode OpNode>
2148    : BaseBaseAddSubCarry<isSub, regtype, asm,
2149        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2150
2151class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2152                              SDNode OpNode>
2153    : BaseBaseAddSubCarry<isSub, regtype, asm,
2154        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2155         (implicit NZCV)]> {
2156  let Defs = [NZCV];
2157}
2158
2159multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2160                       SDNode OpNode, SDNode OpNode_setflags> {
2161  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2162    let Inst{31} = 0;
2163    let Inst{29} = 0;
2164  }
2165  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2166    let Inst{31} = 1;
2167    let Inst{29} = 0;
2168  }
2169
2170  // Sets flags.
2171  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2172                                    OpNode_setflags> {
2173    let Inst{31} = 0;
2174    let Inst{29} = 1;
2175  }
2176  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2177                                    OpNode_setflags> {
2178    let Inst{31} = 1;
2179    let Inst{29} = 1;
2180  }
2181}
2182
2183class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
2184                     SDPatternOperator OpNode,
2185                     RegisterClass in1regtype = regtype,
2186                     RegisterClass in2regtype = regtype>
2187  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2188      asm, "\t$Rd, $Rn, $Rm", "",
2189      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2190  bits<5> Rd;
2191  bits<5> Rn;
2192  bits<5> Rm;
2193  let Inst{30-21} = 0b0011010110;
2194  let Inst{20-16} = Rm;
2195  let Inst{15-14} = 0b00;
2196  let Inst{13-10} = opc;
2197  let Inst{9-5}   = Rn;
2198  let Inst{4-0}   = Rd;
2199}
2200
2201class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
2202              SDPatternOperator OpNode>
2203    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
2204  let Inst{10}    = isSigned;
2205}
2206
2207multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2208  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
2209           Sched<[WriteID32, ReadID, ReadID]> {
2210    let Inst{31} = 0;
2211  }
2212  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
2213           Sched<[WriteID64, ReadID, ReadID]> {
2214    let Inst{31} = 1;
2215  }
2216}
2217
2218class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
2219                SDPatternOperator OpNode = null_frag>
2220  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
2221    Sched<[WriteIS, ReadI]> {
2222  let Inst{11-10} = shift_type;
2223}
2224
2225multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2226  def Wr : BaseShift<shift_type, GPR32, asm> {
2227    let Inst{31} = 0;
2228  }
2229
2230  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
2231    let Inst{31} = 1;
2232  }
2233
2234  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2235            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2236                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2237
2238  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2239            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2240
2241  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2242            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2243
2244  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2245            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2246
2247  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2248            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2249                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2250
2251  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2252            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2253                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2254}
2255
2256class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2257    : InstAlias<asm#"\t$dst, $src1, $src2",
2258                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2259
2260class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2261                       RegisterClass addtype, string asm,
2262                       list<dag> pattern>
2263  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2264      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2265  bits<5> Rd;
2266  bits<5> Rn;
2267  bits<5> Rm;
2268  bits<5> Ra;
2269  let Inst{30-24} = 0b0011011;
2270  let Inst{23-21} = opc;
2271  let Inst{20-16} = Rm;
2272  let Inst{15}    = isSub;
2273  let Inst{14-10} = Ra;
2274  let Inst{9-5}   = Rn;
2275  let Inst{4-0}   = Rd;
2276}
2277
2278multiclass MulAccum<bit isSub, string asm> {
2279  // MADD/MSUB generation is decided by MachineCombiner.cpp
2280  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, []>,
2281      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2282    let Inst{31} = 0;
2283  }
2284
2285  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, []>,
2286      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2287    let Inst{31} = 1;
2288  }
2289}
2290
2291class WideMulAccum<bit isSub, bits<3> opc, string asm,
2292                   SDNode AccNode, SDNode ExtNode>
2293  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2294    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2295                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2296    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2297  let Inst{31} = 1;
2298}
2299
2300class MulHi<bits<3> opc, string asm, SDNode OpNode>
2301  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2302      asm, "\t$Rd, $Rn, $Rm", "",
2303      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2304    Sched<[WriteIM64, ReadIM, ReadIM]> {
2305  bits<5> Rd;
2306  bits<5> Rn;
2307  bits<5> Rm;
2308  let Inst{31-24} = 0b10011011;
2309  let Inst{23-21} = opc;
2310  let Inst{20-16} = Rm;
2311  let Inst{15}    = 0;
2312  let Inst{9-5}   = Rn;
2313  let Inst{4-0}   = Rd;
2314
2315  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2316  // (i.e. all bits 1) but is ignored by the processor.
2317  let PostEncoderMethod = "fixMulHigh";
2318}
2319
2320class MulAccumWAlias<string asm, Instruction inst>
2321    : InstAlias<asm#"\t$dst, $src1, $src2",
2322                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2323class MulAccumXAlias<string asm, Instruction inst>
2324    : InstAlias<asm#"\t$dst, $src1, $src2",
2325                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2326class WideMulAccumAlias<string asm, Instruction inst>
2327    : InstAlias<asm#"\t$dst, $src1, $src2",
2328                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2329
2330class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2331              SDPatternOperator OpNode, string asm>
2332  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2333      asm, "\t$Rd, $Rn, $Rm", "",
2334      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2335    Sched<[WriteISReg, ReadI, ReadISReg]> {
2336  bits<5> Rd;
2337  bits<5> Rn;
2338  bits<5> Rm;
2339
2340  let Inst{31} = sf;
2341  let Inst{30-21} = 0b0011010110;
2342  let Inst{20-16} = Rm;
2343  let Inst{15-13} = 0b010;
2344  let Inst{12} = C;
2345  let Inst{11-10} = sz;
2346  let Inst{9-5} = Rn;
2347  let Inst{4-0} = Rd;
2348  let Predicates = [HasCRC];
2349}
2350
2351//---
2352// Address generation.
2353//---
2354
2355class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2356    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2357        pattern>,
2358      Sched<[WriteI]> {
2359  bits<5>  Xd;
2360  bits<21> label;
2361  let Inst{31}    = page;
2362  let Inst{30-29} = label{1-0};
2363  let Inst{28-24} = 0b10000;
2364  let Inst{23-5}  = label{20-2};
2365  let Inst{4-0}   = Xd;
2366
2367  let DecoderMethod = "DecodeAdrInstruction";
2368}
2369
2370//---
2371// Move immediate.
2372//---
2373
2374def movimm32_imm : Operand<i32> {
2375  let ParserMatchClass = AsmImmRange<0, 65535>;
2376  let EncoderMethod = "getMoveWideImmOpValue";
2377  let PrintMethod = "printImm";
2378}
2379def movimm32_shift : Operand<i32> {
2380  let PrintMethod = "printShifter";
2381  let ParserMatchClass = MovImm32ShifterOperand;
2382}
2383def movimm64_shift : Operand<i32> {
2384  let PrintMethod = "printShifter";
2385  let ParserMatchClass = MovImm64ShifterOperand;
2386}
2387
2388let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2389class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2390                        string asm>
2391  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2392       asm, "\t$Rd, $imm$shift", "", []>,
2393    Sched<[WriteImm]> {
2394  bits<5> Rd;
2395  bits<16> imm;
2396  bits<6> shift;
2397  let Inst{30-29} = opc;
2398  let Inst{28-23} = 0b100101;
2399  let Inst{22-21} = shift{5-4};
2400  let Inst{20-5}  = imm;
2401  let Inst{4-0}   = Rd;
2402
2403  let DecoderMethod = "DecodeMoveImmInstruction";
2404}
2405
2406multiclass MoveImmediate<bits<2> opc, string asm> {
2407  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2408    let Inst{31} = 0;
2409  }
2410
2411  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2412    let Inst{31} = 1;
2413  }
2414}
2415
2416let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2417class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2418                          string asm>
2419  : I<(outs regtype:$Rd),
2420      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2421       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2422    Sched<[WriteI, ReadI]> {
2423  bits<5> Rd;
2424  bits<16> imm;
2425  bits<6> shift;
2426  let Inst{30-29} = opc;
2427  let Inst{28-23} = 0b100101;
2428  let Inst{22-21} = shift{5-4};
2429  let Inst{20-5}  = imm;
2430  let Inst{4-0}   = Rd;
2431
2432  let DecoderMethod = "DecodeMoveImmInstruction";
2433}
2434
2435multiclass InsertImmediate<bits<2> opc, string asm> {
2436  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2437    let Inst{31} = 0;
2438  }
2439
2440  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2441    let Inst{31} = 1;
2442  }
2443}
2444
2445//---
2446// Add/Subtract
2447//---
2448
2449class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2450                    string asm_inst, string asm_ops,
2451                    dag inputs, dag pattern>
2452    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2453      Sched<[WriteI, ReadI]> {
2454  bits<5>  Rd;
2455  bits<5>  Rn;
2456  let Inst{30}    = isSub;
2457  let Inst{29}    = setFlags;
2458  let Inst{28-24} = 0b10001;
2459  let Inst{9-5}   = Rn;
2460  let Inst{4-0}   = Rd;
2461}
2462
2463class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2464                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2465                     string asm_inst, SDPatternOperator OpNode>
2466    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2467                    (ins srcRegtype:$Rn, immtype:$imm),
2468                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2469  bits<14> imm;
2470  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2471  let Inst{21-10} = imm{11-0};
2472  let DecoderMethod = "DecodeAddSubImmShift";
2473}
2474
2475class BaseAddSubRegPseudo<RegisterClass regtype,
2476                          SDPatternOperator OpNode>
2477    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2478             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2479      Sched<[WriteI, ReadI, ReadI]>;
2480
2481class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2482                     arith_shifted_reg shifted_regtype, string asm,
2483                     SDPatternOperator OpNode>
2484    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2485        asm, "\t$Rd, $Rn, $Rm", "",
2486        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2487      Sched<[WriteISReg, ReadI, ReadISReg]> {
2488  // The operands are in order to match the 'addr' MI operands, so we
2489  // don't need an encoder method and by-name matching. Just use the default
2490  // in-order handling. Since we're using by-order, make sure the names
2491  // do not match.
2492  bits<5> dst;
2493  bits<5> src1;
2494  bits<5> src2;
2495  bits<8> shift;
2496  let Inst{30}    = isSub;
2497  let Inst{29}    = setFlags;
2498  let Inst{28-24} = 0b01011;
2499  let Inst{23-22} = shift{7-6};
2500  let Inst{21}    = 0;
2501  let Inst{20-16} = src2;
2502  let Inst{15-10} = shift{5-0};
2503  let Inst{9-5}   = src1;
2504  let Inst{4-0}   = dst;
2505
2506  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2507}
2508
2509class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2510                     RegisterClass src1Regtype, Operand src2Regtype,
2511                     string asm, SDPatternOperator OpNode>
2512    : I<(outs dstRegtype:$R1),
2513        (ins src1Regtype:$R2, src2Regtype:$R3),
2514        asm, "\t$R1, $R2, $R3", "",
2515        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2516      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2517  bits<5> Rd;
2518  bits<5> Rn;
2519  bits<5> Rm;
2520  bits<6> ext;
2521  let Inst{30}    = isSub;
2522  let Inst{29}    = setFlags;
2523  let Inst{28-24} = 0b01011;
2524  let Inst{23-21} = 0b001;
2525  let Inst{20-16} = Rm;
2526  let Inst{15-13} = ext{5-3};
2527  let Inst{12-10} = ext{2-0};
2528  let Inst{9-5}   = Rn;
2529  let Inst{4-0}   = Rd;
2530
2531  let DecoderMethod = "DecodeAddSubERegInstruction";
2532}
2533
2534let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2535class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2536                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2537                       Operand ext_op, string asm>
2538    : I<(outs dstRegtype:$Rd),
2539        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2540        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2541      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2542  bits<5> Rd;
2543  bits<5> Rn;
2544  bits<5> Rm;
2545  bits<6> ext;
2546  let Inst{30}    = isSub;
2547  let Inst{29}    = setFlags;
2548  let Inst{28-24} = 0b01011;
2549  let Inst{23-21} = 0b001;
2550  let Inst{20-16} = Rm;
2551  let Inst{15}    = ext{5};
2552  let Inst{12-10} = ext{2-0};
2553  let Inst{9-5}   = Rn;
2554  let Inst{4-0}   = Rd;
2555
2556  let DecoderMethod = "DecodeAddSubERegInstruction";
2557}
2558
2559// Aliases for register+register add/subtract.
2560class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2561                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2562                     int shiftExt>
2563    : InstAlias<asm#"\t$dst, $src1, $src2",
2564                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2565                      shiftExt)>;
2566
2567multiclass AddSub<bit isSub, string mnemonic, string alias,
2568                  SDPatternOperator OpNode = null_frag> {
2569  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2570  // Add/Subtract immediate
2571  // Increase the weight of the immediate variant to try to match it before
2572  // the extended register variant.
2573  // We used to match the register variant before the immediate when the
2574  // register argument could be implicitly zero-extended.
2575  let AddedComplexity = 6 in
2576  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2577                           mnemonic, OpNode> {
2578    let Inst{31} = 0;
2579  }
2580  let AddedComplexity = 6 in
2581  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2582                           mnemonic, OpNode> {
2583    let Inst{31} = 1;
2584  }
2585
2586  // Add/Subtract register - Only used for CodeGen
2587  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2588  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2589
2590  // Add/Subtract shifted register
2591  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2592                           OpNode> {
2593    let Inst{31} = 0;
2594  }
2595  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2596                           OpNode> {
2597    let Inst{31} = 1;
2598  }
2599  }
2600
2601  // Add/Subtract extended register
2602  let AddedComplexity = 1, hasSideEffects = 0 in {
2603  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2604                           arith_extended_reg32_i32, mnemonic, OpNode> {
2605    let Inst{31} = 0;
2606  }
2607  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2608                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2609    let Inst{31} = 1;
2610  }
2611  }
2612
2613  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2614                               arith_extendlsl64, mnemonic> {
2615    // UXTX and SXTX only.
2616    let Inst{14-13} = 0b11;
2617    let Inst{31} = 1;
2618  }
2619
2620  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2621  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2622                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2623                      addsub_shifted_imm32_neg:$imm), 0>;
2624  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2625                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2626                       addsub_shifted_imm64_neg:$imm), 0>;
2627
2628  // Register/register aliases with no shift when SP is not used.
2629  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2630                       GPR32, GPR32, GPR32, 0>;
2631  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2632                       GPR64, GPR64, GPR64, 0>;
2633
2634  // Register/register aliases with no shift when either the destination or
2635  // first source register is SP.
2636  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2637                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2638  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2639                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2640  def : AddSubRegAlias<mnemonic,
2641                       !cast<Instruction>(NAME#"Xrx64"),
2642                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2643  def : AddSubRegAlias<mnemonic,
2644                       !cast<Instruction>(NAME#"Xrx64"),
2645                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2646}
2647
2648multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2649                   string alias, string cmpAlias> {
2650  let isCompare = 1, Defs = [NZCV] in {
2651  // Add/Subtract immediate
2652  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2653                           mnemonic, OpNode> {
2654    let Inst{31} = 0;
2655  }
2656  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2657                           mnemonic, OpNode> {
2658    let Inst{31} = 1;
2659  }
2660
2661  // Add/Subtract register
2662  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2663  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2664
2665  // Add/Subtract shifted register
2666  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2667                           OpNode> {
2668    let Inst{31} = 0;
2669  }
2670  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2671                           OpNode> {
2672    let Inst{31} = 1;
2673  }
2674
2675  // Add/Subtract extended register
2676  let AddedComplexity = 1 in {
2677  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2678                           arith_extended_reg32_i32, mnemonic, OpNode> {
2679    let Inst{31} = 0;
2680  }
2681  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2682                           arith_extended_reg32_i64, mnemonic, OpNode> {
2683    let Inst{31} = 1;
2684  }
2685  }
2686
2687  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2688                               arith_extendlsl64, mnemonic> {
2689    // UXTX and SXTX only.
2690    let Inst{14-13} = 0b11;
2691    let Inst{31} = 1;
2692  }
2693  } // Defs = [NZCV]
2694
2695  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2696  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2697                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2698                      addsub_shifted_imm32_neg:$imm), 0>;
2699  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2700                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2701                       addsub_shifted_imm64_neg:$imm), 0>;
2702
2703  // Compare aliases
2704  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2705                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2706  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2707                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2708  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2709                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2710  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2711                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2712  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2713                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2714  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2715                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2716  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2717                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2718
2719  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2720  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2721                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2722  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2723                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2724
2725  // Compare shorthands
2726  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2727                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2728  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2729                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2730  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2731                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2732  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2733                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2734
2735  // Register/register aliases with no shift when SP is not used.
2736  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2737                       GPR32, GPR32, GPR32, 0>;
2738  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2739                       GPR64, GPR64, GPR64, 0>;
2740
2741  // Register/register aliases with no shift when the first source register
2742  // is SP.
2743  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2744                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2745  def : AddSubRegAlias<mnemonic,
2746                       !cast<Instruction>(NAME#"Xrx64"),
2747                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2748}
2749
2750class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2751      : BaseAddSubImm<
2752          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2753          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2754          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2755  bits<6> imm6;
2756  bits<4> imm4;
2757  let Inst{31} = 1;
2758  let Inst{23-22} = 0b10;
2759  let Inst{21-16} = imm6;
2760  let Inst{15-14} = 0b00;
2761  let Inst{13-10} = imm4;
2762  let Unpredictable{15-14} = 0b11;
2763}
2764
2765class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2766      : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2767  let Inst{31} = 1;
2768  let Inst{29} = setsFlags;
2769}
2770
2771//---
2772// Extract
2773//---
2774def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2775                                      SDTCisPtrTy<3>]>;
2776def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2777
2778class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2779                     list<dag> patterns>
2780    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2781         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2782      Sched<[WriteExtr, ReadExtrHi]> {
2783  bits<5> Rd;
2784  bits<5> Rn;
2785  bits<5> Rm;
2786  bits<6> imm;
2787
2788  let Inst{30-23} = 0b00100111;
2789  let Inst{21}    = 0;
2790  let Inst{20-16} = Rm;
2791  let Inst{15-10} = imm;
2792  let Inst{9-5}   = Rn;
2793  let Inst{4-0}   = Rd;
2794}
2795
2796multiclass ExtractImm<string asm> {
2797  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2798                      [(set GPR32:$Rd,
2799                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2800    let Inst{31} = 0;
2801    let Inst{22} = 0;
2802    // imm<5> must be zero.
2803    let imm{5}   = 0;
2804  }
2805  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2806                      [(set GPR64:$Rd,
2807                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2808
2809    let Inst{31} = 1;
2810    let Inst{22} = 1;
2811  }
2812}
2813
2814//---
2815// Bitfield
2816//---
2817
2818let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2819class BaseBitfieldImm<bits<2> opc,
2820                      RegisterClass regtype, Operand imm_type, string asm>
2821    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2822         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2823      Sched<[WriteIS, ReadI]> {
2824  bits<5> Rd;
2825  bits<5> Rn;
2826  bits<6> immr;
2827  bits<6> imms;
2828
2829  let Inst{30-29} = opc;
2830  let Inst{28-23} = 0b100110;
2831  let Inst{21-16} = immr;
2832  let Inst{15-10} = imms;
2833  let Inst{9-5}   = Rn;
2834  let Inst{4-0}   = Rd;
2835}
2836
2837multiclass BitfieldImm<bits<2> opc, string asm> {
2838  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2839    let Inst{31} = 0;
2840    let Inst{22} = 0;
2841    // imms<5> and immr<5> must be zero, else ReservedValue().
2842    let Inst{21} = 0;
2843    let Inst{15} = 0;
2844  }
2845  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2846    let Inst{31} = 1;
2847    let Inst{22} = 1;
2848  }
2849}
2850
2851let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2852class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2853                      RegisterClass regtype, Operand imm_type, string asm>
2854    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2855                             imm_type:$imms),
2856         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2857      Sched<[WriteIS, ReadI]> {
2858  bits<5> Rd;
2859  bits<5> Rn;
2860  bits<6> immr;
2861  bits<6> imms;
2862
2863  let Inst{30-29} = opc;
2864  let Inst{28-23} = 0b100110;
2865  let Inst{21-16} = immr;
2866  let Inst{15-10} = imms;
2867  let Inst{9-5}   = Rn;
2868  let Inst{4-0}   = Rd;
2869}
2870
2871multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2872  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2873    let Inst{31} = 0;
2874    let Inst{22} = 0;
2875    // imms<5> and immr<5> must be zero, else ReservedValue().
2876    let Inst{21} = 0;
2877    let Inst{15} = 0;
2878  }
2879  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2880    let Inst{31} = 1;
2881    let Inst{22} = 1;
2882  }
2883}
2884
2885//---
2886// Logical
2887//---
2888
2889// Logical (immediate)
2890class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2891                     RegisterClass sregtype, Operand imm_type, string asm,
2892                     list<dag> pattern>
2893    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2894         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2895      Sched<[WriteI, ReadI]> {
2896  bits<5>  Rd;
2897  bits<5>  Rn;
2898  bits<13> imm;
2899  let Inst{30-29} = opc;
2900  let Inst{28-23} = 0b100100;
2901  let Inst{22}    = imm{12};
2902  let Inst{21-16} = imm{11-6};
2903  let Inst{15-10} = imm{5-0};
2904  let Inst{9-5}   = Rn;
2905  let Inst{4-0}   = Rd;
2906
2907  let DecoderMethod = "DecodeLogicalImmInstruction";
2908}
2909
2910// Logical (shifted register)
2911class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2912                      logical_shifted_reg shifted_regtype, string asm,
2913                      list<dag> pattern>
2914    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2915        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2916      Sched<[WriteISReg, ReadI, ReadISReg]> {
2917  // The operands are in order to match the 'addr' MI operands, so we
2918  // don't need an encoder method and by-name matching. Just use the default
2919  // in-order handling. Since we're using by-order, make sure the names
2920  // do not match.
2921  bits<5> dst;
2922  bits<5> src1;
2923  bits<5> src2;
2924  bits<8> shift;
2925  let Inst{30-29} = opc;
2926  let Inst{28-24} = 0b01010;
2927  let Inst{23-22} = shift{7-6};
2928  let Inst{21}    = N;
2929  let Inst{20-16} = src2;
2930  let Inst{15-10} = shift{5-0};
2931  let Inst{9-5}   = src1;
2932  let Inst{4-0}   = dst;
2933
2934  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2935}
2936
2937// Aliases for register+register logical instructions.
2938class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2939    : InstAlias<asm#"\t$dst, $src1, $src2",
2940                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2941
2942multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2943                      string Alias> {
2944  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2945  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2946                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2947                                               logical_imm32:$imm))]> {
2948    let Inst{31} = 0;
2949    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2950  }
2951  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2952  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2953                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2954                                               logical_imm64:$imm))]> {
2955    let Inst{31} = 1;
2956  }
2957
2958  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2959                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2960                      logical_imm32_not:$imm), 0>;
2961  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2962                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2963                       logical_imm64_not:$imm), 0>;
2964}
2965
2966multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2967                       string Alias> {
2968  let isCompare = 1, Defs = [NZCV] in {
2969  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2970      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2971    let Inst{31} = 0;
2972    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2973  }
2974  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2975      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2976    let Inst{31} = 1;
2977  }
2978  } // end Defs = [NZCV]
2979
2980  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2981                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2982                      logical_imm32_not:$imm), 0>;
2983  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2984                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2985                       logical_imm64_not:$imm), 0>;
2986}
2987
2988class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2989    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2990             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2991      Sched<[WriteI, ReadI, ReadI]>;
2992
2993// Split from LogicalImm as not all instructions have both.
2994multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2995                      SDPatternOperator OpNode> {
2996  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2997  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2998  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2999  }
3000
3001  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3002                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
3003                                                 logical_shifted_reg32:$Rm))]> {
3004    let Inst{31} = 0;
3005  }
3006  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3007                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
3008                                                 logical_shifted_reg64:$Rm))]> {
3009    let Inst{31} = 1;
3010  }
3011
3012  def : LogicalRegAlias<mnemonic,
3013                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3014  def : LogicalRegAlias<mnemonic,
3015                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3016}
3017
3018// Split from LogicalReg to allow setting NZCV Defs
3019multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
3020                       SDPatternOperator OpNode = null_frag> {
3021  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
3022  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3023  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3024
3025  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3026            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
3027    let Inst{31} = 0;
3028  }
3029  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3030            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
3031    let Inst{31} = 1;
3032  }
3033  } // Defs = [NZCV]
3034
3035  def : LogicalRegAlias<mnemonic,
3036                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3037  def : LogicalRegAlias<mnemonic,
3038                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3039}
3040
3041//---
3042// Conditionally set flags
3043//---
3044
3045let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3046class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3047                            string mnemonic, SDNode OpNode>
3048    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3049         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3050         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3051                             (i32 imm:$cond), NZCV))]>,
3052      Sched<[WriteI, ReadI]> {
3053  let Uses = [NZCV];
3054  let Defs = [NZCV];
3055
3056  bits<5> Rn;
3057  bits<5> imm;
3058  bits<4> nzcv;
3059  bits<4> cond;
3060
3061  let Inst{30}    = op;
3062  let Inst{29-21} = 0b111010010;
3063  let Inst{20-16} = imm;
3064  let Inst{15-12} = cond;
3065  let Inst{11-10} = 0b10;
3066  let Inst{9-5}   = Rn;
3067  let Inst{4}     = 0b0;
3068  let Inst{3-0}   = nzcv;
3069}
3070
3071let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3072class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3073                            SDNode OpNode>
3074    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3075         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3076         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3077                             (i32 imm:$cond), NZCV))]>,
3078      Sched<[WriteI, ReadI, ReadI]> {
3079  let Uses = [NZCV];
3080  let Defs = [NZCV];
3081
3082  bits<5> Rn;
3083  bits<5> Rm;
3084  bits<4> nzcv;
3085  bits<4> cond;
3086
3087  let Inst{30}    = op;
3088  let Inst{29-21} = 0b111010010;
3089  let Inst{20-16} = Rm;
3090  let Inst{15-12} = cond;
3091  let Inst{11-10} = 0b00;
3092  let Inst{9-5}   = Rn;
3093  let Inst{4}     = 0b0;
3094  let Inst{3-0}   = nzcv;
3095}
3096
3097multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3098  // immediate operand variants
3099  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3100    let Inst{31} = 0;
3101  }
3102  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3103    let Inst{31} = 1;
3104  }
3105  // register operand variants
3106  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3107    let Inst{31} = 0;
3108  }
3109  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3110    let Inst{31} = 1;
3111  }
3112}
3113
3114//---
3115// Conditional select
3116//---
3117
3118class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3119    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3120         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3121         [(set regtype:$Rd,
3122               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3123      Sched<[WriteI, ReadI, ReadI]> {
3124  let Uses = [NZCV];
3125
3126  bits<5> Rd;
3127  bits<5> Rn;
3128  bits<5> Rm;
3129  bits<4> cond;
3130
3131  let Inst{30}    = op;
3132  let Inst{29-21} = 0b011010100;
3133  let Inst{20-16} = Rm;
3134  let Inst{15-12} = cond;
3135  let Inst{11-10} = op2;
3136  let Inst{9-5}   = Rn;
3137  let Inst{4-0}   = Rd;
3138}
3139
3140multiclass CondSelect<bit op, bits<2> op2, string asm> {
3141  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3142    let Inst{31} = 0;
3143  }
3144  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3145    let Inst{31} = 1;
3146  }
3147}
3148
3149class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3150                       PatFrag frag>
3151    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3152         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3153         [(set regtype:$Rd,
3154               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3155               (i32 imm:$cond), NZCV))]>,
3156      Sched<[WriteI, ReadI, ReadI]> {
3157  let Uses = [NZCV];
3158
3159  bits<5> Rd;
3160  bits<5> Rn;
3161  bits<5> Rm;
3162  bits<4> cond;
3163
3164  let Inst{30}    = op;
3165  let Inst{29-21} = 0b011010100;
3166  let Inst{20-16} = Rm;
3167  let Inst{15-12} = cond;
3168  let Inst{11-10} = op2;
3169  let Inst{9-5}   = Rn;
3170  let Inst{4-0}   = Rd;
3171}
3172
3173def inv_cond_XFORM : SDNodeXForm<imm, [{
3174  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3175  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3176                                   MVT::i32);
3177}]>;
3178
3179multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3180  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3181    let Inst{31} = 0;
3182  }
3183  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3184    let Inst{31} = 1;
3185  }
3186
3187  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3188            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3189                                           (inv_cond_XFORM imm:$cond))>;
3190
3191  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3192            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3193                                           (inv_cond_XFORM imm:$cond))>;
3194}
3195
3196//---
3197// Special Mask Value
3198//---
3199def maski8_or_more : Operand<i32>,
3200  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3201}
3202def maski16_or_more : Operand<i32>,
3203  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3204}
3205
3206
3207//---
3208// Load/store
3209//---
3210
3211// (unsigned immediate)
3212// Indexed for 8-bit registers. offset is in range [0,4095].
3213def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3214def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3215def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3216def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3217def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3218
3219// (unsigned immediate)
3220// Indexed for 8-bit registers. offset is in range [0,63].
3221def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3222def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3223def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3224def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3225
3226def gi_am_indexed8 :
3227    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3228    GIComplexPatternEquiv<am_indexed8>;
3229def gi_am_indexed16 :
3230    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3231    GIComplexPatternEquiv<am_indexed16>;
3232def gi_am_indexed32 :
3233    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3234    GIComplexPatternEquiv<am_indexed32>;
3235def gi_am_indexed64 :
3236    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3237    GIComplexPatternEquiv<am_indexed64>;
3238def gi_am_indexed128 :
3239    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3240    GIComplexPatternEquiv<am_indexed128>;
3241
3242class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3243  let Name = "UImm12Offset" # Scale;
3244  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3245  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3246  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3247}
3248
3249def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3250def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3251def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3252def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3253def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3254
3255class uimm12_scaled<int Scale> : Operand<i64> {
3256  let ParserMatchClass
3257   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3258  let EncoderMethod
3259   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3260  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3261}
3262
3263def uimm12s1 : uimm12_scaled<1>;
3264def uimm12s2 : uimm12_scaled<2>;
3265def uimm12s4 : uimm12_scaled<4>;
3266def uimm12s8 : uimm12_scaled<8>;
3267def uimm12s16 : uimm12_scaled<16>;
3268
3269class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3270                      string asm, list<dag> pattern>
3271    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3272  bits<5> Rt;
3273
3274  bits<5> Rn;
3275  bits<12> offset;
3276
3277  let Inst{31-30} = sz;
3278  let Inst{29-27} = 0b111;
3279  let Inst{26}    = V;
3280  let Inst{25-24} = 0b01;
3281  let Inst{23-22} = opc;
3282  let Inst{21-10} = offset;
3283  let Inst{9-5}   = Rn;
3284  let Inst{4-0}   = Rt;
3285
3286  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3287}
3288
3289multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3290                  Operand indextype, string asm, list<dag> pattern> {
3291  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3292  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3293                           (ins GPR64sp:$Rn, indextype:$offset),
3294                           asm, pattern>,
3295           Sched<[WriteLD]>;
3296
3297  def : InstAlias<asm # "\t$Rt, [$Rn]",
3298                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3299}
3300
3301multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3302             Operand indextype, string asm, list<dag> pattern> {
3303  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3304  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3305                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3306                           asm, pattern>,
3307           Sched<[WriteST]>;
3308
3309  def : InstAlias<asm # "\t$Rt, [$Rn]",
3310                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3311}
3312
3313// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3314// substitute zero-registers automatically.
3315//
3316// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3317//       into StoreUI.
3318multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3319             Operand indextype, string asm, list<dag> pattern> {
3320  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3321  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3322                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3323                           asm, pattern>,
3324           Sched<[WriteST]>;
3325
3326  def : InstAlias<asm # "\t$Rt, [$Rn]",
3327                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3328}
3329
3330def PrefetchOperand : AsmOperandClass {
3331  let Name = "Prefetch";
3332  let ParserMethod = "tryParsePrefetch";
3333}
3334def prfop : Operand<i32> {
3335  let PrintMethod = "printPrefetchOp";
3336  let ParserMatchClass = PrefetchOperand;
3337}
3338
3339let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3340class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3341    : BaseLoadStoreUI<sz, V, opc,
3342                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3343                      asm, pat>,
3344      Sched<[WriteLD]>;
3345
3346//---
3347// Load literal
3348//---
3349
3350// Load literal address: 19-bit immediate. The low two bits of the target
3351// offset are implied zero and so are not part of the immediate.
3352def am_ldrlit : Operand<iPTR> {
3353  let EncoderMethod = "getLoadLiteralOpValue";
3354  let DecoderMethod = "DecodePCRelLabel19";
3355  let PrintMethod = "printAlignedLabel";
3356  let ParserMatchClass = PCRelLabel19Operand;
3357  let OperandType = "OPERAND_PCREL";
3358}
3359
3360let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3361class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3362    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3363        asm, "\t$Rt, $label", "", pat>,
3364      Sched<[WriteLD]> {
3365  bits<5> Rt;
3366  bits<19> label;
3367  let Inst{31-30} = opc;
3368  let Inst{29-27} = 0b011;
3369  let Inst{26}    = V;
3370  let Inst{25-24} = 0b00;
3371  let Inst{23-5}  = label;
3372  let Inst{4-0}   = Rt;
3373}
3374
3375let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3376class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3377    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3378        asm, "\t$Rt, $label", "", pat>,
3379      Sched<[WriteLD]> {
3380  bits<5> Rt;
3381  bits<19> label;
3382  let Inst{31-30} = opc;
3383  let Inst{29-27} = 0b011;
3384  let Inst{26}    = V;
3385  let Inst{25-24} = 0b00;
3386  let Inst{23-5}  = label;
3387  let Inst{4-0}   = Rt;
3388}
3389
3390//---
3391// Load/store register offset
3392//---
3393
3394def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3395def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3396def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3397def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3398def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3399
3400def gi_ro_Xindexed8 :
3401    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3402    GIComplexPatternEquiv<ro_Xindexed8>;
3403def gi_ro_Xindexed16 :
3404    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3405    GIComplexPatternEquiv<ro_Xindexed16>;
3406def gi_ro_Xindexed32 :
3407    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3408    GIComplexPatternEquiv<ro_Xindexed32>;
3409def gi_ro_Xindexed64 :
3410    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3411    GIComplexPatternEquiv<ro_Xindexed64>;
3412def gi_ro_Xindexed128 :
3413    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3414    GIComplexPatternEquiv<ro_Xindexed128>;
3415
3416def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3417def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3418def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3419def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3420def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3421
3422def gi_ro_Windexed8 :
3423    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3424    GIComplexPatternEquiv<ro_Windexed8>;
3425def gi_ro_Windexed16 :
3426    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3427    GIComplexPatternEquiv<ro_Windexed16>;
3428def gi_ro_Windexed32 :
3429    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3430    GIComplexPatternEquiv<ro_Windexed32>;
3431def gi_ro_Windexed64 :
3432    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3433    GIComplexPatternEquiv<ro_Windexed64>;
3434def gi_ro_Windexed128 :
3435    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3436    GIComplexPatternEquiv<ro_Windexed128>;
3437
3438class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3439  let Name = "Mem" # Reg # "Extend" # Width;
3440  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3441  let RenderMethod = "addMemExtendOperands";
3442  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3443}
3444
3445def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3446  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3447  // the trivial shift.
3448  let RenderMethod = "addMemExtend8Operands";
3449}
3450def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3451def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3452def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3453def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3454
3455def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3456  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3457  // the trivial shift.
3458  let RenderMethod = "addMemExtend8Operands";
3459}
3460def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3461def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3462def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3463def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3464
3465class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3466        : Operand<i32> {
3467  let ParserMatchClass = ParserClass;
3468  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3469  let DecoderMethod = "DecodeMemExtend";
3470  let EncoderMethod = "getMemExtendOpValue";
3471  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3472}
3473
3474def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3475def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3476def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3477def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3478def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3479
3480def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3481def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3482def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3483def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3484def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3485
3486class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3487                  Operand wextend, Operand xextend>  {
3488  // CodeGen-level pattern covering the entire addressing mode.
3489  ComplexPattern Wpat = windex;
3490  ComplexPattern Xpat = xindex;
3491
3492  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3493  Operand Wext = wextend;
3494  Operand Xext = xextend;
3495}
3496
3497def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3498def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3499def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3500def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3501def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3502                       ro_Xextend128>;
3503
3504class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3505                   dag outs, list<dag> pat>
3506    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3507  bits<5> Rt;
3508  bits<5> Rn;
3509  bits<5> Rm;
3510  bits<2> extend;
3511  let Inst{31-30} = sz;
3512  let Inst{29-27} = 0b111;
3513  let Inst{26}    = V;
3514  let Inst{25-24} = 0b00;
3515  let Inst{23-22} = opc;
3516  let Inst{21}    = 1;
3517  let Inst{20-16} = Rm;
3518  let Inst{15}    = extend{1}; // sign extend Rm?
3519  let Inst{14}    = 1;
3520  let Inst{12}    = extend{0}; // do shift?
3521  let Inst{11-10} = 0b10;
3522  let Inst{9-5}   = Rn;
3523  let Inst{4-0}   = Rt;
3524}
3525
3526class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3527  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3528              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3529
3530multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3531                   string asm, ValueType Ty, SDPatternOperator loadop> {
3532  let AddedComplexity = 10 in
3533  def roW : LoadStore8RO<sz, V, opc, asm,
3534                 (outs regtype:$Rt),
3535                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3536                 [(set (Ty regtype:$Rt),
3537                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3538                                             ro_Wextend8:$extend)))]>,
3539           Sched<[WriteLDIdx, ReadAdrBase]> {
3540    let Inst{13} = 0b0;
3541  }
3542
3543  let AddedComplexity = 10 in
3544  def roX : LoadStore8RO<sz, V, opc, asm,
3545                 (outs regtype:$Rt),
3546                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3547                 [(set (Ty regtype:$Rt),
3548                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3549                                             ro_Xextend8:$extend)))]>,
3550           Sched<[WriteLDIdx, ReadAdrBase]> {
3551    let Inst{13} = 0b1;
3552  }
3553
3554  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3555}
3556
3557multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3558                    string asm, ValueType Ty, SDPatternOperator storeop> {
3559  let AddedComplexity = 10 in
3560  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
3561                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3562                 [(storeop (Ty regtype:$Rt),
3563                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3564                                         ro_Wextend8:$extend))]>,
3565            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3566    let Inst{13} = 0b0;
3567  }
3568
3569  let AddedComplexity = 10 in
3570  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
3571                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3572                 [(storeop (Ty regtype:$Rt),
3573                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3574                                         ro_Xextend8:$extend))]>,
3575            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3576    let Inst{13} = 0b1;
3577  }
3578
3579  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3580}
3581
3582class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3583                    dag outs, list<dag> pat>
3584    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3585  bits<5> Rt;
3586  bits<5> Rn;
3587  bits<5> Rm;
3588  bits<2> extend;
3589  let Inst{31-30} = sz;
3590  let Inst{29-27} = 0b111;
3591  let Inst{26}    = V;
3592  let Inst{25-24} = 0b00;
3593  let Inst{23-22} = opc;
3594  let Inst{21}    = 1;
3595  let Inst{20-16} = Rm;
3596  let Inst{15}    = extend{1}; // sign extend Rm?
3597  let Inst{14}    = 1;
3598  let Inst{12}    = extend{0}; // do shift?
3599  let Inst{11-10} = 0b10;
3600  let Inst{9-5}   = Rn;
3601  let Inst{4-0}   = Rt;
3602}
3603
3604multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3605                    string asm, ValueType Ty, SDPatternOperator loadop> {
3606  let AddedComplexity = 10 in
3607  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3608                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3609                 [(set (Ty regtype:$Rt),
3610                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3611                                              ro_Wextend16:$extend)))]>,
3612            Sched<[WriteLDIdx, ReadAdrBase]> {
3613    let Inst{13} = 0b0;
3614  }
3615
3616  let AddedComplexity = 10 in
3617  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3618                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3619                 [(set (Ty regtype:$Rt),
3620                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3621                                             ro_Xextend16:$extend)))]>,
3622            Sched<[WriteLDIdx, ReadAdrBase]> {
3623    let Inst{13} = 0b1;
3624  }
3625
3626  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3627}
3628
3629multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3630                     string asm, ValueType Ty, SDPatternOperator storeop> {
3631  let AddedComplexity = 10 in
3632  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
3633                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3634                [(storeop (Ty regtype:$Rt),
3635                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3636                                         ro_Wextend16:$extend))]>,
3637           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3638    let Inst{13} = 0b0;
3639  }
3640
3641  let AddedComplexity = 10 in
3642  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
3643                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3644                [(storeop (Ty regtype:$Rt),
3645                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3646                                         ro_Xextend16:$extend))]>,
3647           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3648    let Inst{13} = 0b1;
3649  }
3650
3651  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3652}
3653
3654class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3655                    dag outs, list<dag> pat>
3656    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3657  bits<5> Rt;
3658  bits<5> Rn;
3659  bits<5> Rm;
3660  bits<2> extend;
3661  let Inst{31-30} = sz;
3662  let Inst{29-27} = 0b111;
3663  let Inst{26}    = V;
3664  let Inst{25-24} = 0b00;
3665  let Inst{23-22} = opc;
3666  let Inst{21}    = 1;
3667  let Inst{20-16} = Rm;
3668  let Inst{15}    = extend{1}; // sign extend Rm?
3669  let Inst{14}    = 1;
3670  let Inst{12}    = extend{0}; // do shift?
3671  let Inst{11-10} = 0b10;
3672  let Inst{9-5}   = Rn;
3673  let Inst{4-0}   = Rt;
3674}
3675
3676multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3677                    string asm, ValueType Ty, SDPatternOperator loadop> {
3678  let AddedComplexity = 10 in
3679  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3680                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3681                 [(set (Ty regtype:$Rt),
3682                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3683                                              ro_Wextend32:$extend)))]>,
3684           Sched<[WriteLDIdx, ReadAdrBase]> {
3685    let Inst{13} = 0b0;
3686  }
3687
3688  let AddedComplexity = 10 in
3689  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3690                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3691                 [(set (Ty regtype:$Rt),
3692                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3693                                              ro_Xextend32:$extend)))]>,
3694           Sched<[WriteLDIdx, ReadAdrBase]> {
3695    let Inst{13} = 0b1;
3696  }
3697
3698  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3699}
3700
3701multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3702                     string asm, ValueType Ty, SDPatternOperator storeop> {
3703  let AddedComplexity = 10 in
3704  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
3705                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3706                [(storeop (Ty regtype:$Rt),
3707                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3708                                         ro_Wextend32:$extend))]>,
3709            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3710    let Inst{13} = 0b0;
3711  }
3712
3713  let AddedComplexity = 10 in
3714  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
3715                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3716                [(storeop (Ty regtype:$Rt),
3717                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3718                                        ro_Xextend32:$extend))]>,
3719            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3720    let Inst{13} = 0b1;
3721  }
3722
3723  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3724}
3725
3726class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3727                    dag outs, list<dag> pat>
3728    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3729  bits<5> Rt;
3730  bits<5> Rn;
3731  bits<5> Rm;
3732  bits<2> extend;
3733  let Inst{31-30} = sz;
3734  let Inst{29-27} = 0b111;
3735  let Inst{26}    = V;
3736  let Inst{25-24} = 0b00;
3737  let Inst{23-22} = opc;
3738  let Inst{21}    = 1;
3739  let Inst{20-16} = Rm;
3740  let Inst{15}    = extend{1}; // sign extend Rm?
3741  let Inst{14}    = 1;
3742  let Inst{12}    = extend{0}; // do shift?
3743  let Inst{11-10} = 0b10;
3744  let Inst{9-5}   = Rn;
3745  let Inst{4-0}   = Rt;
3746}
3747
3748multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3749                    string asm, ValueType Ty, SDPatternOperator loadop> {
3750  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3751  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3752                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3753                [(set (Ty regtype:$Rt),
3754                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3755                                             ro_Wextend64:$extend)))]>,
3756           Sched<[WriteLDIdx, ReadAdrBase]> {
3757    let Inst{13} = 0b0;
3758  }
3759
3760  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3761  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3762                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3763                 [(set (Ty regtype:$Rt),
3764                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3765                                              ro_Xextend64:$extend)))]>,
3766           Sched<[WriteLDIdx, ReadAdrBase]> {
3767    let Inst{13} = 0b1;
3768  }
3769
3770  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3771}
3772
3773multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3774                     string asm, ValueType Ty, SDPatternOperator storeop> {
3775  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3776  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
3777                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3778                [(storeop (Ty regtype:$Rt),
3779                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3780                                         ro_Wextend64:$extend))]>,
3781            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3782    let Inst{13} = 0b0;
3783  }
3784
3785  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3786  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
3787                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3788                [(storeop (Ty regtype:$Rt),
3789                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3790                                         ro_Xextend64:$extend))]>,
3791            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3792    let Inst{13} = 0b1;
3793  }
3794
3795  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3796}
3797
3798class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3799                     dag outs, list<dag> pat>
3800    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3801  bits<5> Rt;
3802  bits<5> Rn;
3803  bits<5> Rm;
3804  bits<2> extend;
3805  let Inst{31-30} = sz;
3806  let Inst{29-27} = 0b111;
3807  let Inst{26}    = V;
3808  let Inst{25-24} = 0b00;
3809  let Inst{23-22} = opc;
3810  let Inst{21}    = 1;
3811  let Inst{20-16} = Rm;
3812  let Inst{15}    = extend{1}; // sign extend Rm?
3813  let Inst{14}    = 1;
3814  let Inst{12}    = extend{0}; // do shift?
3815  let Inst{11-10} = 0b10;
3816  let Inst{9-5}   = Rn;
3817  let Inst{4-0}   = Rt;
3818}
3819
3820multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3821                     string asm, ValueType Ty, SDPatternOperator loadop> {
3822  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3823  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3824                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3825                 [(set (Ty regtype:$Rt),
3826                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3827                                               ro_Wextend128:$extend)))]>,
3828            Sched<[WriteLDIdx, ReadAdrBase]> {
3829    let Inst{13} = 0b0;
3830  }
3831
3832  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3833  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3834                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3835                 [(set (Ty regtype:$Rt),
3836                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3837                                               ro_Xextend128:$extend)))]>,
3838            Sched<[WriteLDIdx, ReadAdrBase]> {
3839    let Inst{13} = 0b1;
3840  }
3841
3842  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3843}
3844
3845multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3846                      string asm> {
3847  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3848  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
3849               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3850                []>,
3851            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3852    let Inst{13} = 0b0;
3853  }
3854
3855  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3856  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
3857               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3858                []>,
3859            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3860    let Inst{13} = 0b1;
3861  }
3862
3863  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3864}
3865
3866let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3867class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3868                     string asm, list<dag> pat>
3869    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3870      Sched<[WriteLD]> {
3871  bits<5> Rt;
3872  bits<5> Rn;
3873  bits<5> Rm;
3874  bits<2> extend;
3875  let Inst{31-30} = sz;
3876  let Inst{29-27} = 0b111;
3877  let Inst{26}    = V;
3878  let Inst{25-24} = 0b00;
3879  let Inst{23-22} = opc;
3880  let Inst{21}    = 1;
3881  let Inst{20-16} = Rm;
3882  let Inst{15}    = extend{1}; // sign extend Rm?
3883  let Inst{14}    = 1;
3884  let Inst{12}    = extend{0}; // do shift?
3885  let Inst{11-10} = 0b10;
3886  let Inst{9-5}   = Rn;
3887  let Inst{4-0}   = Rt;
3888}
3889
3890multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3891  def roW : BasePrefetchRO<sz, V, opc, (outs),
3892                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3893                asm, [(AArch64Prefetch imm:$Rt,
3894                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3895                                                    ro_Wextend64:$extend))]> {
3896    let Inst{13} = 0b0;
3897  }
3898
3899  def roX : BasePrefetchRO<sz, V, opc, (outs),
3900                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3901                asm,  [(AArch64Prefetch imm:$Rt,
3902                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3903                                                     ro_Xextend64:$extend))]> {
3904    let Inst{13} = 0b1;
3905  }
3906
3907  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3908               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3909                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3910}
3911
3912//---
3913// Load/store unscaled immediate
3914//---
3915
3916def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
3917def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
3918def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
3919def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
3920def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
3921
3922def gi_am_unscaled8 :
3923    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3924    GIComplexPatternEquiv<am_unscaled8>;
3925def gi_am_unscaled16 :
3926    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3927    GIComplexPatternEquiv<am_unscaled16>;
3928def gi_am_unscaled32 :
3929    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3930    GIComplexPatternEquiv<am_unscaled32>;
3931def gi_am_unscaled64 :
3932    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3933    GIComplexPatternEquiv<am_unscaled64>;
3934def gi_am_unscaled128 :
3935    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3936    GIComplexPatternEquiv<am_unscaled128>;
3937
3938
3939class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3940                           string asm, list<dag> pattern>
3941    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3942  bits<5> Rt;
3943  bits<5> Rn;
3944  bits<9> offset;
3945  let Inst{31-30} = sz;
3946  let Inst{29-27} = 0b111;
3947  let Inst{26}    = V;
3948  let Inst{25-24} = 0b00;
3949  let Inst{23-22} = opc;
3950  let Inst{21}    = 0;
3951  let Inst{20-12} = offset;
3952  let Inst{11-10} = 0b00;
3953  let Inst{9-5}   = Rn;
3954  let Inst{4-0}   = Rt;
3955
3956  let DecoderMethod = "DecodeSignedLdStInstruction";
3957}
3958
3959// Armv8.4 LDAPR & STLR with Immediate Offset instruction
3960multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3961                              DAGOperand regtype > {
3962  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3963                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3964          Sched<[WriteST]> {
3965    let Inst{29} = 0;
3966    let Inst{24} = 1;
3967  }
3968  def : InstAlias<asm # "\t$Rt, [$Rn]",
3969                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3970}
3971
3972multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3973                               DAGOperand regtype > {
3974  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3975                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3976                               asm, []>,
3977          Sched<[WriteST]> {
3978    let Inst{29} = 0;
3979    let Inst{24} = 1;
3980  }
3981  def : InstAlias<asm # "\t$Rt, [$Rn]",
3982                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3983}
3984
3985multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3986                   string asm, list<dag> pattern> {
3987  let AddedComplexity = 1 in // try this before LoadUI
3988  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3989                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3990          Sched<[WriteLD]>;
3991
3992  def : InstAlias<asm # "\t$Rt, [$Rn]",
3993                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3994}
3995
3996multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3997                         string asm, list<dag> pattern> {
3998  let AddedComplexity = 1 in // try this before StoreUI
3999  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4000                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4001                               asm, pattern>,
4002          Sched<[WriteST]>;
4003
4004  def : InstAlias<asm # "\t$Rt, [$Rn]",
4005                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4006}
4007
4008multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
4009                            list<dag> pat> {
4010  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4011  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4012                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
4013                               asm, pat>,
4014          Sched<[WriteLD]>;
4015
4016  def : InstAlias<asm # "\t$Rt, [$Rn]",
4017                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
4018}
4019
4020//---
4021// Load/store unscaled immediate, unprivileged
4022//---
4023
4024class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4025                                dag oops, dag iops, string asm>
4026    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
4027  bits<5> Rt;
4028  bits<5> Rn;
4029  bits<9> offset;
4030  let Inst{31-30} = sz;
4031  let Inst{29-27} = 0b111;
4032  let Inst{26}    = V;
4033  let Inst{25-24} = 0b00;
4034  let Inst{23-22} = opc;
4035  let Inst{21}    = 0;
4036  let Inst{20-12} = offset;
4037  let Inst{11-10} = 0b10;
4038  let Inst{9-5}   = Rn;
4039  let Inst{4-0}   = Rt;
4040
4041  let DecoderMethod = "DecodeSignedLdStInstruction";
4042}
4043
4044multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4045                            RegisterClass regtype, string asm> {
4046  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4047  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4048                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4049          Sched<[WriteLD]>;
4050
4051  def : InstAlias<asm # "\t$Rt, [$Rn]",
4052                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4053}
4054
4055multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4056                             RegisterClass regtype, string asm> {
4057  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4058  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4059                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4060                                 asm>,
4061          Sched<[WriteST]>;
4062
4063  def : InstAlias<asm # "\t$Rt, [$Rn]",
4064                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4065}
4066
4067//---
4068// Load/store pre-indexed
4069//---
4070
4071class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4072                          string asm, string cstr, list<dag> pat>
4073    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4074  bits<5> Rt;
4075  bits<5> Rn;
4076  bits<9> offset;
4077  let Inst{31-30} = sz;
4078  let Inst{29-27} = 0b111;
4079  let Inst{26}    = V;
4080  let Inst{25-24} = 0;
4081  let Inst{23-22} = opc;
4082  let Inst{21}    = 0;
4083  let Inst{20-12} = offset;
4084  let Inst{11-10} = 0b11;
4085  let Inst{9-5}   = Rn;
4086  let Inst{4-0}   = Rt;
4087
4088  let DecoderMethod = "DecodeSignedLdStInstruction";
4089}
4090
4091let hasSideEffects = 0 in {
4092let mayStore = 0, mayLoad = 1 in
4093class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4094             string asm>
4095    : BaseLoadStorePreIdx<sz, V, opc,
4096                     (outs GPR64sp:$wback, regtype:$Rt),
4097                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4098                     "$Rn = $wback,@earlyclobber $wback", []>,
4099      Sched<[WriteAdr, WriteLD]>;
4100
4101let mayStore = 1, mayLoad = 0 in
4102class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4103                  string asm, SDPatternOperator storeop, ValueType Ty>
4104    : BaseLoadStorePreIdx<sz, V, opc,
4105                      (outs GPR64sp:$wback),
4106                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4107                      asm, "$Rn = $wback,@earlyclobber $wback",
4108      [(set GPR64sp:$wback,
4109            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4110      Sched<[WriteAdr, WriteST]>;
4111} // hasSideEffects = 0
4112
4113//---
4114// Load/store post-indexed
4115//---
4116
4117class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4118                          string asm, string cstr, list<dag> pat>
4119    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4120  bits<5> Rt;
4121  bits<5> Rn;
4122  bits<9> offset;
4123  let Inst{31-30} = sz;
4124  let Inst{29-27} = 0b111;
4125  let Inst{26}    = V;
4126  let Inst{25-24} = 0b00;
4127  let Inst{23-22} = opc;
4128  let Inst{21}    = 0b0;
4129  let Inst{20-12} = offset;
4130  let Inst{11-10} = 0b01;
4131  let Inst{9-5}   = Rn;
4132  let Inst{4-0}   = Rt;
4133
4134  let DecoderMethod = "DecodeSignedLdStInstruction";
4135}
4136
4137let hasSideEffects = 0 in {
4138let mayStore = 0, mayLoad = 1 in
4139class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4140             string asm>
4141    : BaseLoadStorePostIdx<sz, V, opc,
4142                      (outs GPR64sp:$wback, regtype:$Rt),
4143                      (ins GPR64sp:$Rn, simm9:$offset),
4144                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4145      Sched<[WriteAdr, WriteLD]>;
4146
4147let mayStore = 1, mayLoad = 0 in
4148class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4149                   string asm, SDPatternOperator storeop, ValueType Ty>
4150    : BaseLoadStorePostIdx<sz, V, opc,
4151                      (outs GPR64sp:$wback),
4152                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4153                       asm, "$Rn = $wback,@earlyclobber $wback",
4154      [(set GPR64sp:$wback,
4155            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4156    Sched<[WriteAdr, WriteST]>;
4157} // hasSideEffects = 0
4158
4159
4160//---
4161// Load/store pair
4162//---
4163
4164// (indexed, offset)
4165
4166class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4167                              string asm>
4168    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4169  bits<5> Rt;
4170  bits<5> Rt2;
4171  bits<5> Rn;
4172  bits<7> offset;
4173  let Inst{31-30} = opc;
4174  let Inst{29-27} = 0b101;
4175  let Inst{26}    = V;
4176  let Inst{25-23} = 0b010;
4177  let Inst{22}    = L;
4178  let Inst{21-15} = offset;
4179  let Inst{14-10} = Rt2;
4180  let Inst{9-5}   = Rn;
4181  let Inst{4-0}   = Rt;
4182
4183  let DecoderMethod = "DecodePairLdStInstruction";
4184}
4185
4186multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4187                          Operand indextype, string asm> {
4188  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4189  def i : BaseLoadStorePairOffset<opc, V, 1,
4190                                  (outs regtype:$Rt, regtype:$Rt2),
4191                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4192          Sched<[WriteLD, WriteLDHi]>;
4193
4194  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4195                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4196                                                  GPR64sp:$Rn, 0)>;
4197}
4198
4199
4200multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4201                           Operand indextype, string asm> {
4202  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4203  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4204                                  (ins regtype:$Rt, regtype:$Rt2,
4205                                       GPR64sp:$Rn, indextype:$offset),
4206                                  asm>,
4207          Sched<[WriteSTP]>;
4208
4209  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4210                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4211                                                  GPR64sp:$Rn, 0)>;
4212}
4213
4214// (pre-indexed)
4215class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4216                              string asm>
4217    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4218  bits<5> Rt;
4219  bits<5> Rt2;
4220  bits<5> Rn;
4221  bits<7> offset;
4222  let Inst{31-30} = opc;
4223  let Inst{29-27} = 0b101;
4224  let Inst{26}    = V;
4225  let Inst{25-23} = 0b011;
4226  let Inst{22}    = L;
4227  let Inst{21-15} = offset;
4228  let Inst{14-10} = Rt2;
4229  let Inst{9-5}   = Rn;
4230  let Inst{4-0}   = Rt;
4231
4232  let DecoderMethod = "DecodePairLdStInstruction";
4233}
4234
4235let hasSideEffects = 0 in {
4236let mayStore = 0, mayLoad = 1 in
4237class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4238                     Operand indextype, string asm>
4239    : BaseLoadStorePairPreIdx<opc, V, 1,
4240                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4241                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4242      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4243
4244let mayStore = 1, mayLoad = 0 in
4245class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4246                      Operand indextype, string asm>
4247    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4248                             (ins regtype:$Rt, regtype:$Rt2,
4249                                  GPR64sp:$Rn, indextype:$offset),
4250                             asm>,
4251      Sched<[WriteAdr, WriteSTP]>;
4252} // hasSideEffects = 0
4253
4254// (post-indexed)
4255
4256class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4257                              string asm>
4258    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4259  bits<5> Rt;
4260  bits<5> Rt2;
4261  bits<5> Rn;
4262  bits<7> offset;
4263  let Inst{31-30} = opc;
4264  let Inst{29-27} = 0b101;
4265  let Inst{26}    = V;
4266  let Inst{25-23} = 0b001;
4267  let Inst{22}    = L;
4268  let Inst{21-15} = offset;
4269  let Inst{14-10} = Rt2;
4270  let Inst{9-5}   = Rn;
4271  let Inst{4-0}   = Rt;
4272
4273  let DecoderMethod = "DecodePairLdStInstruction";
4274}
4275
4276let hasSideEffects = 0 in {
4277let mayStore = 0, mayLoad = 1 in
4278class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4279                      Operand idxtype, string asm>
4280    : BaseLoadStorePairPostIdx<opc, V, 1,
4281                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4282                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4283      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4284
4285let mayStore = 1, mayLoad = 0 in
4286class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4287                       Operand idxtype, string asm>
4288    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4289                             (ins regtype:$Rt, regtype:$Rt2,
4290                                  GPR64sp:$Rn, idxtype:$offset),
4291                             asm>,
4292      Sched<[WriteAdr, WriteSTP]>;
4293} // hasSideEffects = 0
4294
4295//  (no-allocate)
4296
4297class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4298                              string asm>
4299    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4300  bits<5> Rt;
4301  bits<5> Rt2;
4302  bits<5> Rn;
4303  bits<7> offset;
4304  let Inst{31-30} = opc;
4305  let Inst{29-27} = 0b101;
4306  let Inst{26}    = V;
4307  let Inst{25-23} = 0b000;
4308  let Inst{22}    = L;
4309  let Inst{21-15} = offset;
4310  let Inst{14-10} = Rt2;
4311  let Inst{9-5}   = Rn;
4312  let Inst{4-0}   = Rt;
4313
4314  let DecoderMethod = "DecodePairLdStInstruction";
4315}
4316
4317multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4318                           Operand indextype, string asm> {
4319  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4320  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4321                                   (outs regtype:$Rt, regtype:$Rt2),
4322                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4323          Sched<[WriteLD, WriteLDHi]>;
4324
4325
4326  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4327                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4328                                                  GPR64sp:$Rn, 0)>;
4329}
4330
4331multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4332                      Operand indextype, string asm> {
4333  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4334  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4335                                   (ins regtype:$Rt, regtype:$Rt2,
4336                                        GPR64sp:$Rn, indextype:$offset),
4337                                   asm>,
4338          Sched<[WriteSTP]>;
4339
4340  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4341                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4342                                                  GPR64sp:$Rn, 0)>;
4343}
4344
4345//---
4346// Load/store exclusive
4347//---
4348
4349// True exclusive operations write to and/or read from the system's exclusive
4350// monitors, which as far as a compiler is concerned can be modelled as a
4351// random shared memory address. Hence LoadExclusive mayStore.
4352//
4353// Since these instructions have the undefined register bits set to 1 in
4354// their canonical form, we need a post encoder method to set those bits
4355// to 1 when encoding these instructions. We do this using the
4356// fixLoadStoreExclusive function. This function has template parameters:
4357//
4358// fixLoadStoreExclusive<int hasRs, int hasRt2>
4359//
4360// hasRs indicates that the instruction uses the Rs field, so we won't set
4361// it to 1 (and the same for Rt2). We don't need template parameters for
4362// the other register fields since Rt and Rn are always used.
4363//
4364let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4365class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4366                             dag oops, dag iops, string asm, string operands>
4367    : I<oops, iops, asm, operands, "", []> {
4368  let Inst{31-30} = sz;
4369  let Inst{29-24} = 0b001000;
4370  let Inst{23}    = o2;
4371  let Inst{22}    = L;
4372  let Inst{21}    = o1;
4373  let Inst{15}    = o0;
4374
4375  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4376}
4377
4378// Neither Rs nor Rt2 operands.
4379class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4380                               dag oops, dag iops, string asm, string operands>
4381    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4382  bits<5> Rt;
4383  bits<5> Rn;
4384  let Inst{20-16} = 0b11111;
4385  let Unpredictable{20-16} = 0b11111;
4386  let Inst{14-10} = 0b11111;
4387  let Unpredictable{14-10} = 0b11111;
4388  let Inst{9-5} = Rn;
4389  let Inst{4-0} = Rt;
4390
4391  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4392}
4393
4394// Simple load acquires don't set the exclusive monitor
4395let mayLoad = 1, mayStore = 0 in
4396class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4397                  RegisterClass regtype, string asm>
4398    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4399                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4400      Sched<[WriteLD]>;
4401
4402class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4403                    RegisterClass regtype, string asm>
4404    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4405                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4406      Sched<[WriteLD]>;
4407
4408class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4409                       RegisterClass regtype, string asm>
4410    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4411                             (outs regtype:$Rt, regtype:$Rt2),
4412                             (ins GPR64sp0:$Rn), asm,
4413                             "\t$Rt, $Rt2, [$Rn]">,
4414      Sched<[WriteLD, WriteLDHi]> {
4415  bits<5> Rt;
4416  bits<5> Rt2;
4417  bits<5> Rn;
4418  let Inst{14-10} = Rt2;
4419  let Inst{9-5} = Rn;
4420  let Inst{4-0} = Rt;
4421
4422  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4423}
4424
4425// Simple store release operations do not check the exclusive monitor.
4426let mayLoad = 0, mayStore = 1 in
4427class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4428                   RegisterClass regtype, string asm>
4429    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4430                               (ins regtype:$Rt, GPR64sp0:$Rn),
4431                               asm, "\t$Rt, [$Rn]">,
4432      Sched<[WriteST]>;
4433
4434let mayLoad = 1, mayStore = 1 in
4435class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4436                     RegisterClass regtype, string asm>
4437    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4438                             (ins regtype:$Rt, GPR64sp0:$Rn),
4439                             asm, "\t$Ws, $Rt, [$Rn]">,
4440      Sched<[WriteSTX]> {
4441  bits<5> Ws;
4442  bits<5> Rt;
4443  bits<5> Rn;
4444  let Inst{20-16} = Ws;
4445  let Inst{9-5} = Rn;
4446  let Inst{4-0} = Rt;
4447
4448  let Constraints = "@earlyclobber $Ws";
4449  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4450}
4451
4452class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4453                         RegisterClass regtype, string asm>
4454    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4455                             (outs GPR32:$Ws),
4456                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4457                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4458      Sched<[WriteSTX]> {
4459  bits<5> Ws;
4460  bits<5> Rt;
4461  bits<5> Rt2;
4462  bits<5> Rn;
4463  let Inst{20-16} = Ws;
4464  let Inst{14-10} = Rt2;
4465  let Inst{9-5} = Rn;
4466  let Inst{4-0} = Rt;
4467
4468  let Constraints = "@earlyclobber $Ws";
4469}
4470
4471// Armv8.5-A Memory Tagging Extension
4472class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4473                 string asm_opnds, string cstr, dag oops, dag iops>
4474    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4475      Sched<[]> {
4476  bits<5> Rn;
4477
4478  let Inst{31-24} = 0b11011001;
4479  let Inst{23-22} = opc1;
4480  let Inst{21}    = 1;
4481  // Inst{20-12} defined by subclass
4482  let Inst{11-10} = opc2;
4483  let Inst{9-5}   = Rn;
4484  // Inst{4-0} defined by subclass
4485}
4486
4487class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4488                   dag oops, dag iops>
4489    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4490                  "", oops, iops> {
4491  bits<5> Rt;
4492
4493  let Inst{20-12} = 0b000000000;
4494  let Inst{4-0}   = Rt;
4495
4496  let mayLoad = Load;
4497}
4498
4499class MemTagLoad<string asm_insn, string asm_opnds>
4500    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4501                 (outs GPR64:$wback),
4502                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4503  bits<5> Rt;
4504  bits<9> offset;
4505
4506  let Inst{20-12} = offset;
4507  let Inst{4-0}   = Rt;
4508
4509  let mayLoad = 1;
4510}
4511
4512class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4513                     string asm_opnds, string cstr, dag oops, dag iops>
4514    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4515  bits<5> Rt;
4516  bits<9> offset;
4517
4518  let Inst{20-12} = offset;
4519  let Inst{4-0}   = Rt;
4520
4521  let mayStore = 1;
4522}
4523
4524multiclass MemTagStore<bits<2> opc1, string insn> {
4525  def Offset :
4526    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4527                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4528  def PreIndex :
4529    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4530                    "$Rn = $wback",
4531                    (outs GPR64sp:$wback),
4532                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4533  def PostIndex :
4534    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4535                    "$Rn = $wback",
4536                    (outs GPR64sp:$wback),
4537                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4538
4539  def : InstAlias<insn # "\t$Rt, [$Rn]",
4540                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4541}
4542
4543//---
4544// Exception generation
4545//---
4546
4547let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4548class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm,
4549                          list<dag> pattern = []>
4550    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", pattern>,
4551      Sched<[WriteSys]> {
4552  bits<16> imm;
4553  let Inst{31-24} = 0b11010100;
4554  let Inst{23-21} = op1;
4555  let Inst{20-5}  = imm;
4556  let Inst{4-2}   = 0b000;
4557  let Inst{1-0}   = ll;
4558}
4559
4560//---
4561// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4562//--
4563let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4564class UDFType<bits<16> opc, string asm>
4565  : I<(outs), (ins uimm16:$imm),
4566       asm, "\t$imm", "", []>,
4567    Sched<[]> {
4568  bits<16> imm;
4569  let Inst{31-16} = opc;
4570  let Inst{15-0} = imm;
4571}
4572}
4573let Predicates = [HasFPARMv8] in {
4574
4575//---
4576// Floating point to integer conversion
4577//---
4578
4579let mayRaiseFPException = 1 in
4580class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4581                      RegisterClass srcType, RegisterClass dstType,
4582                      string asm, list<dag> pattern>
4583    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4584         asm, "\t$Rd, $Rn", "", pattern>,
4585      Sched<[WriteFCvt]> {
4586  bits<5> Rd;
4587  bits<5> Rn;
4588  let Inst{30-29} = 0b00;
4589  let Inst{28-24} = 0b11110;
4590  let Inst{23-22} = type;
4591  let Inst{21}    = 1;
4592  let Inst{20-19} = rmode;
4593  let Inst{18-16} = opcode;
4594  let Inst{15-10} = 0;
4595  let Inst{9-5}   = Rn;
4596  let Inst{4-0}   = Rd;
4597}
4598
4599let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
4600class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4601                      RegisterClass srcType, RegisterClass dstType,
4602                      Operand immType, string asm, list<dag> pattern>
4603    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4604         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4605      Sched<[WriteFCvt]> {
4606  bits<5> Rd;
4607  bits<5> Rn;
4608  bits<6> scale;
4609  let Inst{30-29} = 0b00;
4610  let Inst{28-24} = 0b11110;
4611  let Inst{23-22} = type;
4612  let Inst{21}    = 0;
4613  let Inst{20-19} = rmode;
4614  let Inst{18-16} = opcode;
4615  let Inst{15-10} = scale;
4616  let Inst{9-5}   = Rn;
4617  let Inst{4-0}   = Rd;
4618}
4619
4620multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4621           SDPatternOperator OpN> {
4622  // Unscaled half-precision to 32-bit
4623  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4624                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4625    let Inst{31} = 0; // 32-bit GPR flag
4626    let Predicates = [HasFullFP16];
4627  }
4628
4629  // Unscaled half-precision to 64-bit
4630  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4631                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4632    let Inst{31} = 1; // 64-bit GPR flag
4633    let Predicates = [HasFullFP16];
4634  }
4635
4636  // Unscaled single-precision to 32-bit
4637  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4638                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4639    let Inst{31} = 0; // 32-bit GPR flag
4640  }
4641
4642  // Unscaled single-precision to 64-bit
4643  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4644                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4645    let Inst{31} = 1; // 64-bit GPR flag
4646  }
4647
4648  // Unscaled double-precision to 32-bit
4649  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4650                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4651    let Inst{31} = 0; // 32-bit GPR flag
4652  }
4653
4654  // Unscaled double-precision to 64-bit
4655  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4656                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4657    let Inst{31} = 1; // 64-bit GPR flag
4658  }
4659}
4660
4661multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4662                             SDPatternOperator OpN> {
4663  // Scaled half-precision to 32-bit
4664  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4665                              fixedpoint_f16_i32, asm,
4666              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4667                                          fixedpoint_f16_i32:$scale)))]> {
4668    let Inst{31} = 0; // 32-bit GPR flag
4669    let scale{5} = 1;
4670    let Predicates = [HasFullFP16];
4671  }
4672
4673  // Scaled half-precision to 64-bit
4674  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4675                              fixedpoint_f16_i64, asm,
4676              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4677                                          fixedpoint_f16_i64:$scale)))]> {
4678    let Inst{31} = 1; // 64-bit GPR flag
4679    let Predicates = [HasFullFP16];
4680  }
4681
4682  // Scaled single-precision to 32-bit
4683  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4684                              fixedpoint_f32_i32, asm,
4685              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4686                                          fixedpoint_f32_i32:$scale)))]> {
4687    let Inst{31} = 0; // 32-bit GPR flag
4688    let scale{5} = 1;
4689  }
4690
4691  // Scaled single-precision to 64-bit
4692  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4693                              fixedpoint_f32_i64, asm,
4694              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4695                                          fixedpoint_f32_i64:$scale)))]> {
4696    let Inst{31} = 1; // 64-bit GPR flag
4697  }
4698
4699  // Scaled double-precision to 32-bit
4700  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4701                              fixedpoint_f64_i32, asm,
4702              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4703                                          fixedpoint_f64_i32:$scale)))]> {
4704    let Inst{31} = 0; // 32-bit GPR flag
4705    let scale{5} = 1;
4706  }
4707
4708  // Scaled double-precision to 64-bit
4709  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4710                              fixedpoint_f64_i64, asm,
4711              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4712                                          fixedpoint_f64_i64:$scale)))]> {
4713    let Inst{31} = 1; // 64-bit GPR flag
4714  }
4715}
4716
4717//---
4718// Integer to floating point conversion
4719//---
4720
4721let mayStore = 0, mayLoad = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
4722class BaseIntegerToFP<bit isUnsigned,
4723                      RegisterClass srcType, RegisterClass dstType,
4724                      Operand immType, string asm, list<dag> pattern>
4725    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4726         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4727      Sched<[WriteFCvt]> {
4728  bits<5> Rd;
4729  bits<5> Rn;
4730  bits<6> scale;
4731  let Inst{30-24} = 0b0011110;
4732  let Inst{21-17} = 0b00001;
4733  let Inst{16}    = isUnsigned;
4734  let Inst{15-10} = scale;
4735  let Inst{9-5}   = Rn;
4736  let Inst{4-0}   = Rd;
4737}
4738
4739let mayRaiseFPException = 1 in
4740class BaseIntegerToFPUnscaled<bit isUnsigned,
4741                      RegisterClass srcType, RegisterClass dstType,
4742                      ValueType dvt, string asm, SDPatternOperator node>
4743    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4744         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4745      Sched<[WriteFCvt]> {
4746  bits<5> Rd;
4747  bits<5> Rn;
4748  bits<6> scale;
4749  let Inst{30-24} = 0b0011110;
4750  let Inst{21-17} = 0b10001;
4751  let Inst{16}    = isUnsigned;
4752  let Inst{15-10} = 0b000000;
4753  let Inst{9-5}   = Rn;
4754  let Inst{4-0}   = Rd;
4755}
4756
4757multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
4758  // Unscaled
4759  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4760    let Inst{31} = 0; // 32-bit GPR flag
4761    let Inst{23-22} = 0b11; // 16-bit FPR flag
4762    let Predicates = [HasFullFP16];
4763  }
4764
4765  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4766    let Inst{31} = 0; // 32-bit GPR flag
4767    let Inst{23-22} = 0b00; // 32-bit FPR flag
4768  }
4769
4770  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4771    let Inst{31} = 0; // 32-bit GPR flag
4772    let Inst{23-22} = 0b01; // 64-bit FPR flag
4773  }
4774
4775  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4776    let Inst{31} = 1; // 64-bit GPR flag
4777    let Inst{23-22} = 0b11; // 16-bit FPR flag
4778    let Predicates = [HasFullFP16];
4779  }
4780
4781  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4782    let Inst{31} = 1; // 64-bit GPR flag
4783    let Inst{23-22} = 0b00; // 32-bit FPR flag
4784  }
4785
4786  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4787    let Inst{31} = 1; // 64-bit GPR flag
4788    let Inst{23-22} = 0b01; // 64-bit FPR flag
4789  }
4790
4791  // Scaled
4792  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4793                             [(set (f16 FPR16:$Rd),
4794                                   (fdiv (node GPR32:$Rn),
4795                                         fixedpoint_f16_i32:$scale))]> {
4796    let Inst{31} = 0; // 32-bit GPR flag
4797    let Inst{23-22} = 0b11; // 16-bit FPR flag
4798    let scale{5} = 1;
4799    let Predicates = [HasFullFP16];
4800  }
4801
4802  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4803                             [(set FPR32:$Rd,
4804                                   (fdiv (node GPR32:$Rn),
4805                                         fixedpoint_f32_i32:$scale))]> {
4806    let Inst{31} = 0; // 32-bit GPR flag
4807    let Inst{23-22} = 0b00; // 32-bit FPR flag
4808    let scale{5} = 1;
4809  }
4810
4811  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4812                             [(set FPR64:$Rd,
4813                                   (fdiv (node GPR32:$Rn),
4814                                         fixedpoint_f64_i32:$scale))]> {
4815    let Inst{31} = 0; // 32-bit GPR flag
4816    let Inst{23-22} = 0b01; // 64-bit FPR flag
4817    let scale{5} = 1;
4818  }
4819
4820  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4821                             [(set (f16 FPR16:$Rd),
4822                                   (fdiv (node GPR64:$Rn),
4823                                         fixedpoint_f16_i64:$scale))]> {
4824    let Inst{31} = 1; // 64-bit GPR flag
4825    let Inst{23-22} = 0b11; // 16-bit FPR flag
4826    let Predicates = [HasFullFP16];
4827  }
4828
4829  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4830                             [(set FPR32:$Rd,
4831                                   (fdiv (node GPR64:$Rn),
4832                                         fixedpoint_f32_i64:$scale))]> {
4833    let Inst{31} = 1; // 64-bit GPR flag
4834    let Inst{23-22} = 0b00; // 32-bit FPR flag
4835  }
4836
4837  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4838                             [(set FPR64:$Rd,
4839                                   (fdiv (node GPR64:$Rn),
4840                                         fixedpoint_f64_i64:$scale))]> {
4841    let Inst{31} = 1; // 64-bit GPR flag
4842    let Inst{23-22} = 0b01; // 64-bit FPR flag
4843  }
4844}
4845
4846//---
4847// Unscaled integer <-> floating point conversion (i.e. FMOV)
4848//---
4849
4850let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4851class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4852                      RegisterClass srcType, RegisterClass dstType,
4853                      string asm>
4854    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4855        // We use COPY_TO_REGCLASS for these bitconvert operations.
4856        // copyPhysReg() expands the resultant COPY instructions after
4857        // regalloc is done. This gives greater freedom for the allocator
4858        // and related passes (coalescing, copy propagation, et. al.) to
4859        // be more effective.
4860        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4861      Sched<[WriteFCopy]> {
4862  bits<5> Rd;
4863  bits<5> Rn;
4864  let Inst{30-24} = 0b0011110;
4865  let Inst{21}    = 1;
4866  let Inst{20-19} = rmode;
4867  let Inst{18-16} = opcode;
4868  let Inst{15-10} = 0b000000;
4869  let Inst{9-5}   = Rn;
4870  let Inst{4-0}   = Rd;
4871}
4872
4873let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4874class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4875                     RegisterClass srcType, RegisterOperand dstType, string asm,
4876                     string kind>
4877    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4878        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4879      Sched<[WriteFCopy]> {
4880  bits<5> Rd;
4881  bits<5> Rn;
4882  let Inst{30-23} = 0b00111101;
4883  let Inst{21}    = 1;
4884  let Inst{20-19} = rmode;
4885  let Inst{18-16} = opcode;
4886  let Inst{15-10} = 0b000000;
4887  let Inst{9-5}   = Rn;
4888  let Inst{4-0}   = Rd;
4889
4890  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4891}
4892
4893let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4894class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4895                     RegisterOperand srcType, RegisterClass dstType, string asm,
4896                     string kind>
4897    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4898        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4899      Sched<[WriteFCopy]> {
4900  bits<5> Rd;
4901  bits<5> Rn;
4902  let Inst{30-23} = 0b00111101;
4903  let Inst{21}    = 1;
4904  let Inst{20-19} = rmode;
4905  let Inst{18-16} = opcode;
4906  let Inst{15-10} = 0b000000;
4907  let Inst{9-5}   = Rn;
4908  let Inst{4-0}   = Rd;
4909
4910  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4911}
4912
4913
4914multiclass UnscaledConversion<string asm> {
4915  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4916    let Inst{31} = 0; // 32-bit GPR flag
4917    let Inst{23-22} = 0b11; // 16-bit FPR flag
4918    let Predicates = [HasFullFP16];
4919  }
4920
4921  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4922    let Inst{31} = 1; // 64-bit GPR flag
4923    let Inst{23-22} = 0b11; // 16-bit FPR flag
4924    let Predicates = [HasFullFP16];
4925  }
4926
4927  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4928    let Inst{31} = 0; // 32-bit GPR flag
4929    let Inst{23-22} = 0b00; // 32-bit FPR flag
4930  }
4931
4932  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4933    let Inst{31} = 1; // 64-bit GPR flag
4934    let Inst{23-22} = 0b01; // 64-bit FPR flag
4935  }
4936
4937  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4938    let Inst{31} = 0; // 32-bit GPR flag
4939    let Inst{23-22} = 0b11; // 16-bit FPR flag
4940    let Predicates = [HasFullFP16];
4941  }
4942
4943  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4944    let Inst{31} = 1; // 64-bit GPR flag
4945    let Inst{23-22} = 0b11; // 16-bit FPR flag
4946    let Predicates = [HasFullFP16];
4947  }
4948
4949  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4950    let Inst{31} = 0; // 32-bit GPR flag
4951    let Inst{23-22} = 0b00; // 32-bit FPR flag
4952  }
4953
4954  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4955    let Inst{31} = 1; // 64-bit GPR flag
4956    let Inst{23-22} = 0b01; // 64-bit FPR flag
4957  }
4958
4959  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4960                                             asm, ".d"> {
4961    let Inst{31} = 1;
4962    let Inst{22} = 0;
4963  }
4964
4965  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4966                                               asm, ".d"> {
4967    let Inst{31} = 1;
4968    let Inst{22} = 0;
4969  }
4970}
4971
4972//---
4973// Floating point conversion
4974//---
4975
4976let mayRaiseFPException = 1 in
4977class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4978                       RegisterClass srcType, string asm, list<dag> pattern>
4979    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4980      Sched<[WriteFCvt]> {
4981  bits<5> Rd;
4982  bits<5> Rn;
4983  let Inst{31-24} = 0b00011110;
4984  let Inst{23-22} = type;
4985  let Inst{21-17} = 0b10001;
4986  let Inst{16-15} = opcode;
4987  let Inst{14-10} = 0b10000;
4988  let Inst{9-5}   = Rn;
4989  let Inst{4-0}   = Rd;
4990}
4991
4992multiclass FPConversion<string asm> {
4993  // Double-precision to Half-precision
4994  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4995                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
4996
4997  // Double-precision to Single-precision
4998  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4999                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
5000
5001  // Half-precision to Double-precision
5002  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
5003                             [(set FPR64:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5004
5005  // Half-precision to Single-precision
5006  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
5007                             [(set FPR32:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5008
5009  // Single-precision to Double-precision
5010  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
5011                             [(set FPR64:$Rd, (any_fpextend FPR32:$Rn))]>;
5012
5013  // Single-precision to Half-precision
5014  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
5015                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
5016}
5017
5018//---
5019// Single operand floating point data processing
5020//---
5021
5022let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5023class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
5024                              ValueType vt, string asm, SDPatternOperator node>
5025    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
5026         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
5027      Sched<[WriteF]> {
5028  bits<5> Rd;
5029  bits<5> Rn;
5030  let Inst{31-24} = 0b00011110;
5031  let Inst{21}    = 0b1;
5032  let Inst{20-15} = opcode;
5033  let Inst{14-10} = 0b10000;
5034  let Inst{9-5}   = Rn;
5035  let Inst{4-0}   = Rd;
5036}
5037
5038multiclass SingleOperandFPData<bits<4> opcode, string asm,
5039                               SDPatternOperator node = null_frag,
5040                               int fpexceptions = 1> {
5041  let mayRaiseFPException = fpexceptions in {
5042  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5043    let Inst{23-22} = 0b11; // 16-bit size flag
5044    let Predicates = [HasFullFP16];
5045  }
5046
5047  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5048    let Inst{23-22} = 0b00; // 32-bit size flag
5049  }
5050
5051  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5052    let Inst{23-22} = 0b01; // 64-bit size flag
5053  }
5054  }
5055}
5056
5057multiclass SingleOperandFPDataNoException<bits<4> opcode, string asm,
5058                                       SDPatternOperator node = null_frag>
5059    : SingleOperandFPData<opcode, asm, node, 0>;
5060
5061let mayRaiseFPException = 1 in
5062multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5063                  SDPatternOperator node = null_frag>{
5064
5065  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5066    let Inst{23-22} = 0b00; // 32-bit registers
5067  }
5068
5069  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5070    let Inst{23-22} = 0b01; // 64-bit registers
5071  }
5072}
5073
5074// FRInt[32|64][Z|N] instructions
5075multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5076      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5077
5078//---
5079// Two operand floating point data processing
5080//---
5081
5082let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5083class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5084                           string asm, list<dag> pat>
5085    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5086         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5087      Sched<[WriteF]> {
5088  bits<5> Rd;
5089  bits<5> Rn;
5090  bits<5> Rm;
5091  let Inst{31-24} = 0b00011110;
5092  let Inst{21}    = 1;
5093  let Inst{20-16} = Rm;
5094  let Inst{15-12} = opcode;
5095  let Inst{11-10} = 0b10;
5096  let Inst{9-5}   = Rn;
5097  let Inst{4-0}   = Rd;
5098}
5099
5100multiclass TwoOperandFPData<bits<4> opcode, string asm,
5101                            SDPatternOperator node = null_frag> {
5102  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5103                         [(set (f16 FPR16:$Rd),
5104                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5105    let Inst{23-22} = 0b11; // 16-bit size flag
5106    let Predicates = [HasFullFP16];
5107  }
5108
5109  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5110                         [(set (f32 FPR32:$Rd),
5111                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5112    let Inst{23-22} = 0b00; // 32-bit size flag
5113  }
5114
5115  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5116                         [(set (f64 FPR64:$Rd),
5117                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5118    let Inst{23-22} = 0b01; // 64-bit size flag
5119  }
5120}
5121
5122multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm,
5123                               SDPatternOperator node> {
5124  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5125                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5126    let Inst{23-22} = 0b11; // 16-bit size flag
5127    let Predicates = [HasFullFP16];
5128  }
5129
5130  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5131                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5132    let Inst{23-22} = 0b00; // 32-bit size flag
5133  }
5134
5135  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5136                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5137    let Inst{23-22} = 0b01; // 64-bit size flag
5138  }
5139}
5140
5141
5142//---
5143// Three operand floating point data processing
5144//---
5145
5146let mayRaiseFPException = 1 in
5147class BaseThreeOperandFPData<bit isNegated, bit isSub,
5148                             RegisterClass regtype, string asm, list<dag> pat>
5149    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5150         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5151      Sched<[WriteFMul]> {
5152  bits<5> Rd;
5153  bits<5> Rn;
5154  bits<5> Rm;
5155  bits<5> Ra;
5156  let Inst{31-24} = 0b00011111;
5157  let Inst{21}    = isNegated;
5158  let Inst{20-16} = Rm;
5159  let Inst{15}    = isSub;
5160  let Inst{14-10} = Ra;
5161  let Inst{9-5}   = Rn;
5162  let Inst{4-0}   = Rd;
5163}
5164
5165multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5166                              SDPatternOperator node> {
5167  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5168            [(set (f16 FPR16:$Rd),
5169                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5170    let Inst{23-22} = 0b11; // 16-bit size flag
5171    let Predicates = [HasFullFP16];
5172  }
5173
5174  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5175            [(set FPR32:$Rd,
5176                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5177    let Inst{23-22} = 0b00; // 32-bit size flag
5178  }
5179
5180  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5181            [(set FPR64:$Rd,
5182                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5183    let Inst{23-22} = 0b01; // 64-bit size flag
5184  }
5185}
5186
5187//---
5188// Floating point data comparisons
5189//---
5190
5191let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5192class BaseOneOperandFPComparison<bit signalAllNans,
5193                                 RegisterClass regtype, string asm,
5194                                 list<dag> pat>
5195    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5196      Sched<[WriteFCmp]> {
5197  bits<5> Rn;
5198  let Inst{31-24} = 0b00011110;
5199  let Inst{21}    = 1;
5200
5201  let Inst{15-10} = 0b001000;
5202  let Inst{9-5}   = Rn;
5203  let Inst{4}     = signalAllNans;
5204  let Inst{3-0}   = 0b1000;
5205
5206  // Rm should be 0b00000 canonically, but we need to accept any value.
5207  let PostEncoderMethod = "fixOneOperandFPComparison";
5208}
5209
5210let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5211class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5212                                string asm, list<dag> pat>
5213    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5214      Sched<[WriteFCmp]> {
5215  bits<5> Rm;
5216  bits<5> Rn;
5217  let Inst{31-24} = 0b00011110;
5218  let Inst{21}    = 1;
5219  let Inst{20-16} = Rm;
5220  let Inst{15-10} = 0b001000;
5221  let Inst{9-5}   = Rn;
5222  let Inst{4}     = signalAllNans;
5223  let Inst{3-0}   = 0b0000;
5224}
5225
5226multiclass FPComparison<bit signalAllNans, string asm,
5227                        SDPatternOperator OpNode = null_frag> {
5228  let Defs = [NZCV] in {
5229  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5230      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5231    let Inst{23-22} = 0b11;
5232    let Predicates = [HasFullFP16];
5233  }
5234
5235  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5236      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5237    let Inst{23-22} = 0b11;
5238    let Predicates = [HasFullFP16];
5239  }
5240
5241  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5242      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5243    let Inst{23-22} = 0b00;
5244  }
5245
5246  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5247      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5248    let Inst{23-22} = 0b00;
5249  }
5250
5251  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5252      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5253    let Inst{23-22} = 0b01;
5254  }
5255
5256  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5257      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5258    let Inst{23-22} = 0b01;
5259  }
5260  } // Defs = [NZCV]
5261}
5262
5263//---
5264// Floating point conditional comparisons
5265//---
5266
5267let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5268class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5269                           string mnemonic, list<dag> pat>
5270    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5271         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5272      Sched<[WriteFCmp]> {
5273  let Uses = [NZCV];
5274  let Defs = [NZCV];
5275
5276  bits<5> Rn;
5277  bits<5> Rm;
5278  bits<4> nzcv;
5279  bits<4> cond;
5280
5281  let Inst{31-24} = 0b00011110;
5282  let Inst{21}    = 1;
5283  let Inst{20-16} = Rm;
5284  let Inst{15-12} = cond;
5285  let Inst{11-10} = 0b01;
5286  let Inst{9-5}   = Rn;
5287  let Inst{4}     = signalAllNans;
5288  let Inst{3-0}   = nzcv;
5289}
5290
5291multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5292                            SDPatternOperator OpNode = null_frag> {
5293  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5294      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5295                          (i32 imm:$cond), NZCV))]> {
5296    let Inst{23-22} = 0b11;
5297    let Predicates = [HasFullFP16];
5298  }
5299
5300  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5301      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5302                          (i32 imm:$cond), NZCV))]> {
5303    let Inst{23-22} = 0b00;
5304  }
5305
5306  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5307      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5308                          (i32 imm:$cond), NZCV))]> {
5309    let Inst{23-22} = 0b01;
5310  }
5311}
5312
5313//---
5314// Floating point conditional select
5315//---
5316
5317class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5318    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5319         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5320         [(set regtype:$Rd,
5321               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5322                          (i32 imm:$cond), NZCV))]>,
5323      Sched<[WriteF]> {
5324  bits<5> Rd;
5325  bits<5> Rn;
5326  bits<5> Rm;
5327  bits<4> cond;
5328
5329  let Inst{31-24} = 0b00011110;
5330  let Inst{21}    = 1;
5331  let Inst{20-16} = Rm;
5332  let Inst{15-12} = cond;
5333  let Inst{11-10} = 0b11;
5334  let Inst{9-5}   = Rn;
5335  let Inst{4-0}   = Rd;
5336}
5337
5338multiclass FPCondSelect<string asm> {
5339  let Uses = [NZCV] in {
5340  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5341    let Inst{23-22} = 0b11;
5342    let Predicates = [HasFullFP16];
5343  }
5344
5345  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5346    let Inst{23-22} = 0b00;
5347  }
5348
5349  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5350    let Inst{23-22} = 0b01;
5351  }
5352  } // Uses = [NZCV]
5353}
5354
5355//---
5356// Floating move immediate
5357//---
5358
5359class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5360  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5361      [(set regtype:$Rd, fpimmtype:$imm)]>,
5362    Sched<[WriteFImm]> {
5363  bits<5> Rd;
5364  bits<8> imm;
5365  let Inst{31-24} = 0b00011110;
5366  let Inst{21}    = 1;
5367  let Inst{20-13} = imm;
5368  let Inst{12-5}  = 0b10000000;
5369  let Inst{4-0}   = Rd;
5370}
5371
5372multiclass FPMoveImmediate<string asm> {
5373  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5374    let Inst{23-22} = 0b11;
5375    let Predicates = [HasFullFP16];
5376  }
5377
5378  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5379    let Inst{23-22} = 0b00;
5380  }
5381
5382  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5383    let Inst{23-22} = 0b01;
5384  }
5385}
5386} // end of 'let Predicates = [HasFPARMv8]'
5387
5388//----------------------------------------------------------------------------
5389// AdvSIMD
5390//----------------------------------------------------------------------------
5391
5392let Predicates = [HasNEON] in {
5393
5394//----------------------------------------------------------------------------
5395// AdvSIMD three register vector instructions
5396//----------------------------------------------------------------------------
5397
5398let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5399class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5400                        RegisterOperand regtype, string asm, string kind,
5401                        list<dag> pattern>
5402  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5403      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5404      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5405    Sched<[!if(Q, WriteVq, WriteVd)]> {
5406  bits<5> Rd;
5407  bits<5> Rn;
5408  bits<5> Rm;
5409  let Inst{31}    = 0;
5410  let Inst{30}    = Q;
5411  let Inst{29}    = U;
5412  let Inst{28-24} = 0b01110;
5413  let Inst{23-21} = size;
5414  let Inst{20-16} = Rm;
5415  let Inst{15-11} = opcode;
5416  let Inst{10}    = 1;
5417  let Inst{9-5}   = Rn;
5418  let Inst{4-0}   = Rd;
5419}
5420
5421let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5422class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5423                        RegisterOperand regtype, string asm, string kind,
5424                        list<dag> pattern>
5425  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5426      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5427      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5428    Sched<[!if(Q, WriteVq, WriteVd)]> {
5429  bits<5> Rd;
5430  bits<5> Rn;
5431  bits<5> Rm;
5432  let Inst{31}    = 0;
5433  let Inst{30}    = Q;
5434  let Inst{29}    = U;
5435  let Inst{28-24} = 0b01110;
5436  let Inst{23-21} = size;
5437  let Inst{20-16} = Rm;
5438  let Inst{15-11} = opcode;
5439  let Inst{10}    = 1;
5440  let Inst{9-5}   = Rn;
5441  let Inst{4-0}   = Rd;
5442}
5443
5444let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5445class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5446  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5447    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
5448
5449multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5450  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5451             [(set (v8i8 V64:$dst),
5452                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5453  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5454             [(set (v16i8 V128:$dst),
5455                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5456                           (v16i8 V128:$Rm)))]>;
5457
5458  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5459                           (v4i16 V64:$RHS))),
5460          (!cast<Instruction>(NAME#"v8i8")
5461            V64:$LHS, V64:$MHS, V64:$RHS)>;
5462  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5463                           (v2i32 V64:$RHS))),
5464          (!cast<Instruction>(NAME#"v8i8")
5465            V64:$LHS, V64:$MHS, V64:$RHS)>;
5466  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5467                           (v1i64 V64:$RHS))),
5468          (!cast<Instruction>(NAME#"v8i8")
5469            V64:$LHS, V64:$MHS, V64:$RHS)>;
5470
5471  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5472                           (v8i16 V128:$RHS))),
5473      (!cast<Instruction>(NAME#"v16i8")
5474        V128:$LHS, V128:$MHS, V128:$RHS)>;
5475  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5476                           (v4i32 V128:$RHS))),
5477      (!cast<Instruction>(NAME#"v16i8")
5478        V128:$LHS, V128:$MHS, V128:$RHS)>;
5479  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5480                           (v2i64 V128:$RHS))),
5481      (!cast<Instruction>(NAME#"v16i8")
5482        V128:$LHS, V128:$MHS, V128:$RHS)>;
5483}
5484
5485// All operand sizes distinguished in the encoding.
5486multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5487                               SDPatternOperator OpNode> {
5488  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5489                                      asm, ".8b",
5490         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5491  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5492                                      asm, ".16b",
5493         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5494  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5495                                      asm, ".4h",
5496         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5497  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5498                                      asm, ".8h",
5499         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5500  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5501                                      asm, ".2s",
5502         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5503  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5504                                      asm, ".4s",
5505         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5506  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5507                                      asm, ".2d",
5508         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5509}
5510
5511multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5512  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5513          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5514  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5515          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5516  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5517          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5518
5519  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5520          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5521  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5522          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5523  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5524          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5525  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5526          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5527}
5528
5529// As above, but D sized elements unsupported.
5530multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5531                                  SDPatternOperator OpNode> {
5532  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5533                                      asm, ".8b",
5534        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5535  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5536                                      asm, ".16b",
5537        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5538  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5539                                      asm, ".4h",
5540        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5541  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5542                                      asm, ".8h",
5543        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5544  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5545                                      asm, ".2s",
5546        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5547  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5548                                      asm, ".4s",
5549        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5550}
5551
5552multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5553                                  SDPatternOperator OpNode> {
5554  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5555                                      asm, ".8b",
5556      [(set (v8i8 V64:$dst),
5557            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5558  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5559                                      asm, ".16b",
5560      [(set (v16i8 V128:$dst),
5561            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5562  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5563                                      asm, ".4h",
5564      [(set (v4i16 V64:$dst),
5565            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5566  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5567                                      asm, ".8h",
5568      [(set (v8i16 V128:$dst),
5569            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5570  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5571                                      asm, ".2s",
5572      [(set (v2i32 V64:$dst),
5573            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5574  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5575                                      asm, ".4s",
5576      [(set (v4i32 V128:$dst),
5577            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5578}
5579
5580// As above, but only B sized elements supported.
5581multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5582                                SDPatternOperator OpNode> {
5583  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5584                                      asm, ".8b",
5585    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5586  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5587                                      asm, ".16b",
5588    [(set (v16i8 V128:$Rd),
5589          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5590}
5591
5592// As above, but only floating point elements supported.
5593let mayRaiseFPException = 1 in
5594multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5595                                 string asm, SDPatternOperator OpNode> {
5596  let Predicates = [HasNEON, HasFullFP16] in {
5597  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5598                                      asm, ".4h",
5599        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5600  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5601                                      asm, ".8h",
5602        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5603  } // Predicates = [HasNEON, HasFullFP16]
5604  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5605                                      asm, ".2s",
5606        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5607  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5608                                      asm, ".4s",
5609        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5610  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5611                                      asm, ".2d",
5612        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5613}
5614
5615let mayRaiseFPException = 1 in
5616multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5617                                    string asm,
5618                                    SDPatternOperator OpNode> {
5619  let Predicates = [HasNEON, HasFullFP16] in {
5620  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5621                                      asm, ".4h",
5622        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5623  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5624                                      asm, ".8h",
5625        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5626  } // Predicates = [HasNEON, HasFullFP16]
5627  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5628                                      asm, ".2s",
5629        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5630  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5631                                      asm, ".4s",
5632        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5633  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5634                                      asm, ".2d",
5635        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5636}
5637
5638let mayRaiseFPException = 1 in
5639multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5640                                 string asm, SDPatternOperator OpNode> {
5641  let Predicates = [HasNEON, HasFullFP16] in {
5642  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5643                                      asm, ".4h",
5644     [(set (v4f16 V64:$dst),
5645           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5646  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5647                                      asm, ".8h",
5648     [(set (v8f16 V128:$dst),
5649           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5650  } // Predicates = [HasNEON, HasFullFP16]
5651  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5652                                      asm, ".2s",
5653     [(set (v2f32 V64:$dst),
5654           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5655  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5656                                      asm, ".4s",
5657     [(set (v4f32 V128:$dst),
5658           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5659  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5660                                      asm, ".2d",
5661     [(set (v2f64 V128:$dst),
5662           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5663}
5664
5665// As above, but D and B sized elements unsupported.
5666let mayRaiseFPException = 1 in
5667multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5668                                SDPatternOperator OpNode> {
5669  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5670                                      asm, ".4h",
5671        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5672  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5673                                      asm, ".8h",
5674        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5675  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5676                                      asm, ".2s",
5677        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5678  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5679                                      asm, ".4s",
5680        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5681}
5682
5683// Logical three vector ops share opcode bits, and only use B sized elements.
5684multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5685                                  SDPatternOperator OpNode = null_frag> {
5686  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5687                                     asm, ".8b",
5688                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5689  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5690                                     asm, ".16b",
5691                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5692
5693  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5694          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5695  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5696          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5697  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5698          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5699
5700  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5701      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5702  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5703      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5704  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5705      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5706}
5707
5708multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5709                                  string asm, SDPatternOperator OpNode = null_frag> {
5710  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5711                                     asm, ".8b",
5712             [(set (v8i8 V64:$dst),
5713                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5714  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5715                                     asm, ".16b",
5716             [(set (v16i8 V128:$dst),
5717                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5718                           (v16i8 V128:$Rm)))]>;
5719
5720  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5721                           (v4i16 V64:$RHS))),
5722          (!cast<Instruction>(NAME#"v8i8")
5723            V64:$LHS, V64:$MHS, V64:$RHS)>;
5724  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5725                           (v2i32 V64:$RHS))),
5726          (!cast<Instruction>(NAME#"v8i8")
5727            V64:$LHS, V64:$MHS, V64:$RHS)>;
5728  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5729                           (v1i64 V64:$RHS))),
5730          (!cast<Instruction>(NAME#"v8i8")
5731            V64:$LHS, V64:$MHS, V64:$RHS)>;
5732
5733  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5734                           (v8i16 V128:$RHS))),
5735      (!cast<Instruction>(NAME#"v16i8")
5736        V128:$LHS, V128:$MHS, V128:$RHS)>;
5737  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5738                           (v4i32 V128:$RHS))),
5739      (!cast<Instruction>(NAME#"v16i8")
5740        V128:$LHS, V128:$MHS, V128:$RHS)>;
5741  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5742                           (v2i64 V128:$RHS))),
5743      (!cast<Instruction>(NAME#"v16i8")
5744        V128:$LHS, V128:$MHS, V128:$RHS)>;
5745}
5746
5747// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5748// bytes from S-sized elements.
5749class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5750                                 string kind2, RegisterOperand RegType,
5751                                 ValueType AccumType, ValueType InputType,
5752                                 SDPatternOperator OpNode> :
5753        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5754        [(set (AccumType RegType:$dst),
5755              (OpNode (AccumType RegType:$Rd),
5756                      (InputType RegType:$Rn),
5757                      (InputType RegType:$Rm)))]> {
5758  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5759}
5760
5761multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5762  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5763                                         v2i32, v8i8, OpNode>;
5764  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5765                                         v4i32, v16i8, OpNode>;
5766}
5767
5768// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5769// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5770// 8H to 4S, when Q=1).
5771let mayRaiseFPException = 1 in
5772class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5773                                 string kind2, RegisterOperand RegType,
5774                                 ValueType AccumType, ValueType InputType,
5775                                 SDPatternOperator OpNode> :
5776        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5777		[(set (AccumType RegType:$dst),
5778              (OpNode (AccumType RegType:$Rd),
5779                      (InputType RegType:$Rn),
5780                      (InputType RegType:$Rm)))]> {
5781  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5782  let Inst{13} = b13;
5783}
5784
5785multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5786                                  SDPatternOperator OpNode> {
5787  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5788                                         v2f32, v4f16, OpNode>;
5789  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5790                                         v4f32, v8f16, OpNode>;
5791}
5792
5793
5794//----------------------------------------------------------------------------
5795// AdvSIMD two register vector instructions.
5796//----------------------------------------------------------------------------
5797
5798let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5799class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5800                            bits<2> size2, RegisterOperand regtype, string asm,
5801                            string dstkind, string srckind, list<dag> pattern>
5802  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5803      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5804      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5805    Sched<[!if(Q, WriteVq, WriteVd)]> {
5806  bits<5> Rd;
5807  bits<5> Rn;
5808  let Inst{31}    = 0;
5809  let Inst{30}    = Q;
5810  let Inst{29}    = U;
5811  let Inst{28-24} = 0b01110;
5812  let Inst{23-22} = size;
5813  let Inst{21} = 0b1;
5814  let Inst{20-19} = size2;
5815  let Inst{18-17} = 0b00;
5816  let Inst{16-12} = opcode;
5817  let Inst{11-10} = 0b10;
5818  let Inst{9-5}   = Rn;
5819  let Inst{4-0}   = Rd;
5820}
5821
5822let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5823class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5824                                bits<2> size2, RegisterOperand regtype,
5825                                string asm, string dstkind, string srckind,
5826                                list<dag> pattern>
5827  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5828      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5829      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5830    Sched<[!if(Q, WriteVq, WriteVd)]> {
5831  bits<5> Rd;
5832  bits<5> Rn;
5833  let Inst{31}    = 0;
5834  let Inst{30}    = Q;
5835  let Inst{29}    = U;
5836  let Inst{28-24} = 0b01110;
5837  let Inst{23-22} = size;
5838  let Inst{21} = 0b1;
5839  let Inst{20-19} = size2;
5840  let Inst{18-17} = 0b00;
5841  let Inst{16-12} = opcode;
5842  let Inst{11-10} = 0b10;
5843  let Inst{9-5}   = Rn;
5844  let Inst{4-0}   = Rd;
5845}
5846
5847// Supports B, H, and S element sizes.
5848multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5849                            SDPatternOperator OpNode> {
5850  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5851                                      asm, ".8b", ".8b",
5852                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5853  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5854                                      asm, ".16b", ".16b",
5855                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5856  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5857                                      asm, ".4h", ".4h",
5858                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5859  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5860                                      asm, ".8h", ".8h",
5861                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5862  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5863                                      asm, ".2s", ".2s",
5864                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5865  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5866                                      asm, ".4s", ".4s",
5867                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5868}
5869
5870class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5871                            RegisterOperand regtype, string asm, string dstkind,
5872                            string srckind, string amount>
5873  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5874      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5875      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5876    Sched<[WriteVq]> {
5877  bits<5> Rd;
5878  bits<5> Rn;
5879  let Inst{31}    = 0;
5880  let Inst{30}    = Q;
5881  let Inst{29-24} = 0b101110;
5882  let Inst{23-22} = size;
5883  let Inst{21-10} = 0b100001001110;
5884  let Inst{9-5}   = Rn;
5885  let Inst{4-0}   = Rd;
5886}
5887
5888multiclass SIMDVectorLShiftLongBySizeBHS {
5889  let hasSideEffects = 0 in {
5890  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5891                                             "shll", ".8h",  ".8b", "8">;
5892  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5893                                             "shll2", ".8h", ".16b", "8">;
5894  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5895                                             "shll", ".4s",  ".4h", "16">;
5896  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5897                                             "shll2", ".4s", ".8h", "16">;
5898  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5899                                             "shll", ".2d",  ".2s", "32">;
5900  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5901                                             "shll2", ".2d", ".4s", "32">;
5902  }
5903}
5904
5905// Supports all element sizes.
5906multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5907                             SDPatternOperator OpNode> {
5908  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5909                                      asm, ".4h", ".8b",
5910               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5911  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5912                                      asm, ".8h", ".16b",
5913               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5914  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5915                                      asm, ".2s", ".4h",
5916               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5917  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5918                                      asm, ".4s", ".8h",
5919               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5920  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5921                                      asm, ".1d", ".2s",
5922               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5923  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5924                                      asm, ".2d", ".4s",
5925               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5926}
5927
5928multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5929                                 SDPatternOperator OpNode> {
5930  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5931                                          asm, ".4h", ".8b",
5932      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5933                                      (v8i8 V64:$Rn)))]>;
5934  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5935                                          asm, ".8h", ".16b",
5936      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5937                                      (v16i8 V128:$Rn)))]>;
5938  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5939                                          asm, ".2s", ".4h",
5940      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5941                                      (v4i16 V64:$Rn)))]>;
5942  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5943                                          asm, ".4s", ".8h",
5944      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5945                                      (v8i16 V128:$Rn)))]>;
5946  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5947                                          asm, ".1d", ".2s",
5948      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5949                                      (v2i32 V64:$Rn)))]>;
5950  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5951                                          asm, ".2d", ".4s",
5952      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5953                                      (v4i32 V128:$Rn)))]>;
5954}
5955
5956// Supports all element sizes, except 1xD.
5957multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5958                                  SDPatternOperator OpNode> {
5959  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5960                                    asm, ".8b", ".8b",
5961    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5962  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5963                                    asm, ".16b", ".16b",
5964    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5965  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5966                                    asm, ".4h", ".4h",
5967    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5968  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5969                                    asm, ".8h", ".8h",
5970    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5971  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5972                                    asm, ".2s", ".2s",
5973    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5974  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5975                                    asm, ".4s", ".4s",
5976    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5977  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5978                                    asm, ".2d", ".2d",
5979    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5980}
5981
5982multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5983                             SDPatternOperator OpNode = null_frag> {
5984  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5985                                asm, ".8b", ".8b",
5986    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5987  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5988                                asm, ".16b", ".16b",
5989    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5990  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5991                                asm, ".4h", ".4h",
5992    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5993  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5994                                asm, ".8h", ".8h",
5995    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5996  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5997                                asm, ".2s", ".2s",
5998    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5999  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6000                                asm, ".4s", ".4s",
6001    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6002  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
6003                                asm, ".2d", ".2d",
6004    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6005}
6006
6007
6008// Supports only B element sizes.
6009multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
6010                          SDPatternOperator OpNode> {
6011  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
6012                                asm, ".8b", ".8b",
6013                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6014  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
6015                                asm, ".16b", ".16b",
6016                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6017
6018}
6019
6020// Supports only B and H element sizes.
6021multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
6022                                SDPatternOperator OpNode> {
6023  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6024                                asm, ".8b", ".8b",
6025                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
6026  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6027                                asm, ".16b", ".16b",
6028                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
6029  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6030                                asm, ".4h", ".4h",
6031                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
6032  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6033                                asm, ".8h", ".8h",
6034                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
6035}
6036
6037// Supports H, S and D element sizes, uses high bit of the size field
6038// as an extra opcode bit.
6039multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
6040                           SDPatternOperator OpNode,
6041                           int fpexceptions = 1> {
6042  let mayRaiseFPException = fpexceptions in {
6043  let Predicates = [HasNEON, HasFullFP16] in {
6044  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6045                                asm, ".4h", ".4h",
6046                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6047  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6048                                asm, ".8h", ".8h",
6049                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6050  } // Predicates = [HasNEON, HasFullFP16]
6051  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6052                                asm, ".2s", ".2s",
6053                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6054  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6055                                asm, ".4s", ".4s",
6056                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6057  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6058                                asm, ".2d", ".2d",
6059                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6060  }
6061}
6062
6063multiclass SIMDTwoVectorFPNoException<bit U, bit S, bits<5> opc, string asm,
6064                                      SDPatternOperator OpNode>
6065    : SIMDTwoVectorFP<U, S, opc, asm, OpNode, 0>;
6066
6067// Supports only S and D element sizes
6068let mayRaiseFPException = 1 in
6069multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6070                           SDPatternOperator OpNode = null_frag> {
6071
6072  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6073                                asm, ".2s", ".2s",
6074                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6075  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6076                                asm, ".4s", ".4s",
6077                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6078  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6079                                asm, ".2d", ".2d",
6080                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6081}
6082
6083multiclass FRIntNNTVector<bit U, bit op, string asm,
6084                          SDPatternOperator OpNode = null_frag> :
6085           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6086
6087// Supports only S element size.
6088multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6089                           SDPatternOperator OpNode> {
6090  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6091                                asm, ".2s", ".2s",
6092                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6093  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6094                                asm, ".4s", ".4s",
6095                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6096}
6097
6098let mayRaiseFPException = 1 in
6099multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6100                           SDPatternOperator OpNode> {
6101  let Predicates = [HasNEON, HasFullFP16] in {
6102  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6103                                asm, ".4h", ".4h",
6104                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6105  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6106                                asm, ".8h", ".8h",
6107                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6108  } // Predicates = [HasNEON, HasFullFP16]
6109  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6110                                asm, ".2s", ".2s",
6111                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6112  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6113                                asm, ".4s", ".4s",
6114                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6115  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6116                                asm, ".2d", ".2d",
6117                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6118}
6119
6120let mayRaiseFPException = 1 in
6121multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6122                           SDPatternOperator OpNode> {
6123  let Predicates = [HasNEON, HasFullFP16] in {
6124  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6125                                asm, ".4h", ".4h",
6126                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6127  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6128                                asm, ".8h", ".8h",
6129                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6130  } // Predicates = [HasNEON, HasFullFP16]
6131  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6132                                asm, ".2s", ".2s",
6133                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6134  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6135                                asm, ".4s", ".4s",
6136                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6137  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6138                                asm, ".2d", ".2d",
6139                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6140}
6141
6142let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6143class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6144                           RegisterOperand inreg, RegisterOperand outreg,
6145                           string asm, string outkind, string inkind,
6146                           list<dag> pattern>
6147  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6148      "{\t$Rd" # outkind # ", $Rn" # inkind #
6149      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6150    Sched<[WriteVq]> {
6151  bits<5> Rd;
6152  bits<5> Rn;
6153  let Inst{31}    = 0;
6154  let Inst{30}    = Q;
6155  let Inst{29}    = U;
6156  let Inst{28-24} = 0b01110;
6157  let Inst{23-22} = size;
6158  let Inst{21-17} = 0b10000;
6159  let Inst{16-12} = opcode;
6160  let Inst{11-10} = 0b10;
6161  let Inst{9-5}   = Rn;
6162  let Inst{4-0}   = Rd;
6163}
6164
6165let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6166class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6167                           RegisterOperand inreg, RegisterOperand outreg,
6168                           string asm, string outkind, string inkind,
6169                           list<dag> pattern>
6170  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6171      "{\t$Rd" # outkind # ", $Rn" # inkind #
6172      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6173    Sched<[WriteVq]> {
6174  bits<5> Rd;
6175  bits<5> Rn;
6176  let Inst{31}    = 0;
6177  let Inst{30}    = Q;
6178  let Inst{29}    = U;
6179  let Inst{28-24} = 0b01110;
6180  let Inst{23-22} = size;
6181  let Inst{21-17} = 0b10000;
6182  let Inst{16-12} = opcode;
6183  let Inst{11-10} = 0b10;
6184  let Inst{9-5}   = Rn;
6185  let Inst{4-0}   = Rd;
6186}
6187
6188multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6189                              SDPatternOperator OpNode> {
6190  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6191                                      asm, ".8b", ".8h",
6192        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6193  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6194                                      asm#"2", ".16b", ".8h", []>;
6195  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6196                                      asm, ".4h", ".4s",
6197        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6198  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6199                                      asm#"2", ".8h", ".4s", []>;
6200  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6201                                      asm, ".2s", ".2d",
6202        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6203  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6204                                      asm#"2", ".4s", ".2d", []>;
6205
6206  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6207            (!cast<Instruction>(NAME # "v16i8")
6208                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6209  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6210            (!cast<Instruction>(NAME # "v8i16")
6211                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6212  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6213            (!cast<Instruction>(NAME # "v4i32")
6214                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6215}
6216
6217class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6218                           bits<5> opcode, RegisterOperand regtype, string asm,
6219                           string kind, string zero, ValueType dty,
6220                           ValueType sty, SDNode OpNode>
6221  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6222      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6223      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6224      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6225    Sched<[!if(Q, WriteVq, WriteVd)]> {
6226  bits<5> Rd;
6227  bits<5> Rn;
6228  let Inst{31}    = 0;
6229  let Inst{30}    = Q;
6230  let Inst{29}    = U;
6231  let Inst{28-24} = 0b01110;
6232  let Inst{23-22} = size;
6233  let Inst{21} = 0b1;
6234  let Inst{20-19} = size2;
6235  let Inst{18-17} = 0b00;
6236  let Inst{16-12} = opcode;
6237  let Inst{11-10} = 0b10;
6238  let Inst{9-5}   = Rn;
6239  let Inst{4-0}   = Rd;
6240}
6241
6242// Comparisons support all element sizes, except 1xD.
6243multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6244                            SDNode OpNode> {
6245  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6246                                     asm, ".8b", "0",
6247                                     v8i8, v8i8, OpNode>;
6248  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6249                                     asm, ".16b", "0",
6250                                     v16i8, v16i8, OpNode>;
6251  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6252                                     asm, ".4h", "0",
6253                                     v4i16, v4i16, OpNode>;
6254  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6255                                     asm, ".8h", "0",
6256                                     v8i16, v8i16, OpNode>;
6257  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6258                                     asm, ".2s", "0",
6259                                     v2i32, v2i32, OpNode>;
6260  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6261                                     asm, ".4s", "0",
6262                                     v4i32, v4i32, OpNode>;
6263  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6264                                     asm, ".2d", "0",
6265                                     v2i64, v2i64, OpNode>;
6266}
6267
6268// FP Comparisons support only S and D element sizes (and H for v8.2a).
6269multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6270                              string asm, SDNode OpNode> {
6271
6272  let mayRaiseFPException = 1 in {
6273  let Predicates = [HasNEON, HasFullFP16] in {
6274  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6275                                     asm, ".4h", "0.0",
6276                                     v4i16, v4f16, OpNode>;
6277  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6278                                     asm, ".8h", "0.0",
6279                                     v8i16, v8f16, OpNode>;
6280  } // Predicates = [HasNEON, HasFullFP16]
6281  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6282                                     asm, ".2s", "0.0",
6283                                     v2i32, v2f32, OpNode>;
6284  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6285                                     asm, ".4s", "0.0",
6286                                     v4i32, v4f32, OpNode>;
6287  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6288                                     asm, ".2d", "0.0",
6289                                     v2i64, v2f64, OpNode>;
6290  }
6291
6292  let Predicates = [HasNEON, HasFullFP16] in {
6293  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6294                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6295  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6296                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6297  }
6298  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6299                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6300  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6301                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6302  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6303                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6304  let Predicates = [HasNEON, HasFullFP16] in {
6305  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6306                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6307  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6308                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6309  }
6310  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6311                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6312  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6313                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6314  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6315                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6316}
6317
6318let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
6319class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6320                             RegisterOperand outtype, RegisterOperand intype,
6321                             string asm, string VdTy, string VnTy,
6322                             list<dag> pattern>
6323  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6324      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6325    Sched<[WriteVq]> {
6326  bits<5> Rd;
6327  bits<5> Rn;
6328  let Inst{31}    = 0;
6329  let Inst{30}    = Q;
6330  let Inst{29}    = U;
6331  let Inst{28-24} = 0b01110;
6332  let Inst{23-22} = size;
6333  let Inst{21-17} = 0b10000;
6334  let Inst{16-12} = opcode;
6335  let Inst{11-10} = 0b10;
6336  let Inst{9-5}   = Rn;
6337  let Inst{4-0}   = Rd;
6338}
6339
6340let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
6341class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6342                             RegisterOperand outtype, RegisterOperand intype,
6343                             string asm, string VdTy, string VnTy,
6344                             list<dag> pattern>
6345  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6346      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6347    Sched<[WriteVq]> {
6348  bits<5> Rd;
6349  bits<5> Rn;
6350  let Inst{31}    = 0;
6351  let Inst{30}    = Q;
6352  let Inst{29}    = U;
6353  let Inst{28-24} = 0b01110;
6354  let Inst{23-22} = size;
6355  let Inst{21-17} = 0b10000;
6356  let Inst{16-12} = opcode;
6357  let Inst{11-10} = 0b10;
6358  let Inst{9-5}   = Rn;
6359  let Inst{4-0}   = Rd;
6360}
6361
6362multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6363  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6364                                    asm, ".4s", ".4h", []>;
6365  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6366                                    asm#"2", ".4s", ".8h", []>;
6367  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6368                                    asm, ".2d", ".2s", []>;
6369  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6370                                    asm#"2", ".2d", ".4s", []>;
6371}
6372
6373multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6374  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6375                                    asm, ".4h", ".4s", []>;
6376  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6377                                    asm#"2", ".8h", ".4s", []>;
6378  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6379                                    asm, ".2s", ".2d", []>;
6380  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6381                                    asm#"2", ".4s", ".2d", []>;
6382}
6383
6384multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6385                                     Intrinsic OpNode> {
6386  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6387                                     asm, ".2s", ".2d",
6388                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6389  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6390                                    asm#"2", ".4s", ".2d", []>;
6391
6392  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6393            (!cast<Instruction>(NAME # "v4f32")
6394                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6395}
6396
6397//----------------------------------------------------------------------------
6398// AdvSIMD three register different-size vector instructions.
6399//----------------------------------------------------------------------------
6400
6401let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6402class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6403                      RegisterOperand outtype, RegisterOperand intype1,
6404                      RegisterOperand intype2, string asm,
6405                      string outkind, string inkind1, string inkind2,
6406                      list<dag> pattern>
6407  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6408      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6409      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6410    Sched<[WriteVq]> {
6411  bits<5> Rd;
6412  bits<5> Rn;
6413  bits<5> Rm;
6414  let Inst{31}    = 0;
6415  let Inst{30}    = size{0};
6416  let Inst{29}    = U;
6417  let Inst{28-24} = 0b01110;
6418  let Inst{23-22} = size{2-1};
6419  let Inst{21}    = 1;
6420  let Inst{20-16} = Rm;
6421  let Inst{15-12} = opcode;
6422  let Inst{11-10} = 0b00;
6423  let Inst{9-5}   = Rn;
6424  let Inst{4-0}   = Rd;
6425}
6426
6427let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6428class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6429                      RegisterOperand outtype, RegisterOperand intype1,
6430                      RegisterOperand intype2, string asm,
6431                      string outkind, string inkind1, string inkind2,
6432                      list<dag> pattern>
6433  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6434      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6435      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6436    Sched<[WriteVq]> {
6437  bits<5> Rd;
6438  bits<5> Rn;
6439  bits<5> Rm;
6440  let Inst{31}    = 0;
6441  let Inst{30}    = size{0};
6442  let Inst{29}    = U;
6443  let Inst{28-24} = 0b01110;
6444  let Inst{23-22} = size{2-1};
6445  let Inst{21}    = 1;
6446  let Inst{20-16} = Rm;
6447  let Inst{15-12} = opcode;
6448  let Inst{11-10} = 0b00;
6449  let Inst{9-5}   = Rn;
6450  let Inst{4-0}   = Rd;
6451}
6452
6453// FIXME: TableGen doesn't know how to deal with expanded types that also
6454//        change the element count (in this case, placing the results in
6455//        the high elements of the result register rather than the low
6456//        elements). Until that's fixed, we can't code-gen those.
6457multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6458                                    Intrinsic IntOp> {
6459  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6460                                                  V64, V128, V128,
6461                                                  asm, ".8b", ".8h", ".8h",
6462     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6463  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6464                                                  V128, V128, V128,
6465                                                  asm#"2", ".16b", ".8h", ".8h",
6466     []>;
6467  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6468                                                  V64, V128, V128,
6469                                                  asm, ".4h", ".4s", ".4s",
6470     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6471  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6472                                                  V128, V128, V128,
6473                                                  asm#"2", ".8h", ".4s", ".4s",
6474     []>;
6475  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6476                                                  V64, V128, V128,
6477                                                  asm, ".2s", ".2d", ".2d",
6478     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6479  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6480                                                  V128, V128, V128,
6481                                                  asm#"2", ".4s", ".2d", ".2d",
6482     []>;
6483
6484
6485  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6486  // a version attached to an instruction.
6487  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6488                                                   (v8i16 V128:$Rm))),
6489            (!cast<Instruction>(NAME # "v8i16_v16i8")
6490                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6491                V128:$Rn, V128:$Rm)>;
6492  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6493                                                    (v4i32 V128:$Rm))),
6494            (!cast<Instruction>(NAME # "v4i32_v8i16")
6495                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6496                V128:$Rn, V128:$Rm)>;
6497  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6498                                                    (v2i64 V128:$Rm))),
6499            (!cast<Instruction>(NAME # "v2i64_v4i32")
6500                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6501                V128:$Rn, V128:$Rm)>;
6502}
6503
6504multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6505                                      Intrinsic IntOp> {
6506  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6507                                            V128, V64, V64,
6508                                            asm, ".8h", ".8b", ".8b",
6509      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6510  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6511                                            V128, V128, V128,
6512                                            asm#"2", ".8h", ".16b", ".16b", []>;
6513  let Predicates = [HasAES] in {
6514    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6515                                              V128, V64, V64,
6516                                              asm, ".1q", ".1d", ".1d", []>;
6517    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6518                                              V128, V128, V128,
6519                                              asm#"2", ".1q", ".2d", ".2d", []>;
6520  }
6521
6522  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 (v16i8 V128:$Rn))),
6523                          (v8i8 (extract_high_v16i8 (v16i8 V128:$Rm))))),
6524      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6525}
6526
6527multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6528                                 SDPatternOperator OpNode> {
6529  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6530                                                  V128, V64, V64,
6531                                                  asm, ".4s", ".4h", ".4h",
6532      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6533  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6534                                                  V128, V128, V128,
6535                                                  asm#"2", ".4s", ".8h", ".8h",
6536      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6537                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6538  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6539                                                  V128, V64, V64,
6540                                                  asm, ".2d", ".2s", ".2s",
6541      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6542  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6543                                                  V128, V128, V128,
6544                                                  asm#"2", ".2d", ".4s", ".4s",
6545      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6546                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6547}
6548
6549multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6550                                  SDPatternOperator OpNode = null_frag> {
6551  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6552                                                  V128, V64, V64,
6553                                                  asm, ".8h", ".8b", ".8b",
6554      [(set (v8i16 V128:$Rd),
6555            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6556  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6557                                                 V128, V128, V128,
6558                                                 asm#"2", ".8h", ".16b", ".16b",
6559      [(set (v8i16 V128:$Rd),
6560            (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6561                                (extract_high_v16i8 (v16i8 V128:$Rm))))))]>;
6562  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6563                                                  V128, V64, V64,
6564                                                  asm, ".4s", ".4h", ".4h",
6565      [(set (v4i32 V128:$Rd),
6566            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6567  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6568                                                  V128, V128, V128,
6569                                                  asm#"2", ".4s", ".8h", ".8h",
6570      [(set (v4i32 V128:$Rd),
6571            (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6572                                  (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6573  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6574                                                  V128, V64, V64,
6575                                                  asm, ".2d", ".2s", ".2s",
6576      [(set (v2i64 V128:$Rd),
6577            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6578  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6579                                                  V128, V128, V128,
6580                                                  asm#"2", ".2d", ".4s", ".4s",
6581      [(set (v2i64 V128:$Rd),
6582            (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6583                                 (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6584}
6585
6586multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6587                                          string asm,
6588                                          SDPatternOperator OpNode> {
6589  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6590                                                  V128, V64, V64,
6591                                                  asm, ".8h", ".8b", ".8b",
6592    [(set (v8i16 V128:$dst),
6593          (add (v8i16 V128:$Rd),
6594               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6595  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6596                                                 V128, V128, V128,
6597                                                 asm#"2", ".8h", ".16b", ".16b",
6598    [(set (v8i16 V128:$dst),
6599          (add (v8i16 V128:$Rd),
6600               (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6601                                   (extract_high_v16i8 (v16i8 V128:$Rm)))))))]>;
6602  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6603                                                  V128, V64, V64,
6604                                                  asm, ".4s", ".4h", ".4h",
6605    [(set (v4i32 V128:$dst),
6606          (add (v4i32 V128:$Rd),
6607               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6608  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6609                                                  V128, V128, V128,
6610                                                  asm#"2", ".4s", ".8h", ".8h",
6611    [(set (v4i32 V128:$dst),
6612          (add (v4i32 V128:$Rd),
6613               (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6614                                    (extract_high_v8i16 (v8i16 V128:$Rm)))))))]>;
6615  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6616                                                  V128, V64, V64,
6617                                                  asm, ".2d", ".2s", ".2s",
6618    [(set (v2i64 V128:$dst),
6619          (add (v2i64 V128:$Rd),
6620               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6621  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6622                                                  V128, V128, V128,
6623                                                  asm#"2", ".2d", ".4s", ".4s",
6624    [(set (v2i64 V128:$dst),
6625          (add (v2i64 V128:$Rd),
6626               (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6627                                    (extract_high_v4i32 (v4i32 V128:$Rm)))))))]>;
6628}
6629
6630multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6631                                  SDPatternOperator OpNode = null_frag> {
6632  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6633                                                  V128, V64, V64,
6634                                                  asm, ".8h", ".8b", ".8b",
6635      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6636  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6637                                                 V128, V128, V128,
6638                                                 asm#"2", ".8h", ".16b", ".16b",
6639      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6640                                      (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6641  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6642                                                  V128, V64, V64,
6643                                                  asm, ".4s", ".4h", ".4h",
6644      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6645  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6646                                                  V128, V128, V128,
6647                                                  asm#"2", ".4s", ".8h", ".8h",
6648      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6649                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6650  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6651                                                  V128, V64, V64,
6652                                                  asm, ".2d", ".2s", ".2s",
6653      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6654  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6655                                                  V128, V128, V128,
6656                                                  asm#"2", ".2d", ".4s", ".4s",
6657      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6658                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6659}
6660
6661multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6662                                      string asm,
6663                                      SDPatternOperator OpNode> {
6664  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6665                                                  V128, V64, V64,
6666                                                  asm, ".8h", ".8b", ".8b",
6667    [(set (v8i16 V128:$dst),
6668          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6669  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6670                                                 V128, V128, V128,
6671                                                 asm#"2", ".8h", ".16b", ".16b",
6672    [(set (v8i16 V128:$dst),
6673          (OpNode (v8i16 V128:$Rd),
6674                  (extract_high_v16i8 (v16i8 V128:$Rn)),
6675                  (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6676  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6677                                                  V128, V64, V64,
6678                                                  asm, ".4s", ".4h", ".4h",
6679    [(set (v4i32 V128:$dst),
6680          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6681  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6682                                                  V128, V128, V128,
6683                                                  asm#"2", ".4s", ".8h", ".8h",
6684    [(set (v4i32 V128:$dst),
6685          (OpNode (v4i32 V128:$Rd),
6686                  (extract_high_v8i16 (v8i16 V128:$Rn)),
6687                  (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6688  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6689                                                  V128, V64, V64,
6690                                                  asm, ".2d", ".2s", ".2s",
6691    [(set (v2i64 V128:$dst),
6692          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6693  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6694                                                  V128, V128, V128,
6695                                                  asm#"2", ".2d", ".4s", ".4s",
6696    [(set (v2i64 V128:$dst),
6697          (OpNode (v2i64 V128:$Rd),
6698                  (extract_high_v4i32 (v4i32 V128:$Rn)),
6699                  (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6700}
6701
6702multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6703                                           SDPatternOperator Accum> {
6704  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6705                                                  V128, V64, V64,
6706                                                  asm, ".4s", ".4h", ".4h",
6707    [(set (v4i32 V128:$dst),
6708          (Accum (v4i32 V128:$Rd),
6709                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6710                                                (v4i16 V64:$Rm)))))]>;
6711  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6712                                                  V128, V128, V128,
6713                                                  asm#"2", ".4s", ".8h", ".8h",
6714    [(set (v4i32 V128:$dst),
6715          (Accum (v4i32 V128:$Rd),
6716                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 (v8i16 V128:$Rn)),
6717                                            (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6718  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6719                                                  V128, V64, V64,
6720                                                  asm, ".2d", ".2s", ".2s",
6721    [(set (v2i64 V128:$dst),
6722          (Accum (v2i64 V128:$Rd),
6723                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6724                                                (v2i32 V64:$Rm)))))]>;
6725  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6726                                                  V128, V128, V128,
6727                                                  asm#"2", ".2d", ".4s", ".4s",
6728    [(set (v2i64 V128:$dst),
6729          (Accum (v2i64 V128:$Rd),
6730                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 (v4i32 V128:$Rn)),
6731                                            (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6732}
6733
6734multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6735                                  SDPatternOperator OpNode> {
6736  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6737                                                  V128, V128, V64,
6738                                                  asm, ".8h", ".8h", ".8b",
6739       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6740  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6741                                                  V128, V128, V128,
6742                                                  asm#"2", ".8h", ".8h", ".16b",
6743       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6744                                       (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6745  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6746                                                  V128, V128, V64,
6747                                                  asm, ".4s", ".4s", ".4h",
6748       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6749  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6750                                                  V128, V128, V128,
6751                                                  asm#"2", ".4s", ".4s", ".8h",
6752       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6753                                       (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6754  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6755                                                  V128, V128, V64,
6756                                                  asm, ".2d", ".2d", ".2s",
6757       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6758  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6759                                                  V128, V128, V128,
6760                                                  asm#"2", ".2d", ".2d", ".4s",
6761       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6762                                       (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6763}
6764
6765//----------------------------------------------------------------------------
6766// AdvSIMD bitwise extract from vector
6767//----------------------------------------------------------------------------
6768
6769class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6770                             string asm, string kind>
6771  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6772      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6773      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6774      [(set (vty regtype:$Rd),
6775            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6776    Sched<[!if(size, WriteVq, WriteVd)]> {
6777  bits<5> Rd;
6778  bits<5> Rn;
6779  bits<5> Rm;
6780  bits<4> imm;
6781  let Inst{31}    = 0;
6782  let Inst{30}    = size;
6783  let Inst{29-21} = 0b101110000;
6784  let Inst{20-16} = Rm;
6785  let Inst{15}    = 0;
6786  let Inst{14-11} = imm;
6787  let Inst{10}    = 0;
6788  let Inst{9-5}   = Rn;
6789  let Inst{4-0}   = Rd;
6790}
6791
6792
6793multiclass SIMDBitwiseExtract<string asm> {
6794  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6795    let imm{3} = 0;
6796  }
6797  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6798}
6799
6800//----------------------------------------------------------------------------
6801// AdvSIMD zip vector
6802//----------------------------------------------------------------------------
6803
6804class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6805                        string asm, string kind, SDNode OpNode, ValueType valty>
6806  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6807      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6808      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6809      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6810    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
6811  bits<5> Rd;
6812  bits<5> Rn;
6813  bits<5> Rm;
6814  let Inst{31}    = 0;
6815  let Inst{30}    = size{0};
6816  let Inst{29-24} = 0b001110;
6817  let Inst{23-22} = size{2-1};
6818  let Inst{21}    = 0;
6819  let Inst{20-16} = Rm;
6820  let Inst{15}    = 0;
6821  let Inst{14-12} = opc;
6822  let Inst{11-10} = 0b10;
6823  let Inst{9-5}   = Rn;
6824  let Inst{4-0}   = Rd;
6825}
6826
6827multiclass SIMDZipVector<bits<3>opc, string asm,
6828                         SDNode OpNode> {
6829  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6830      asm, ".8b", OpNode, v8i8>;
6831  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6832      asm, ".16b", OpNode, v16i8>;
6833  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6834      asm, ".4h", OpNode, v4i16>;
6835  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6836      asm, ".8h", OpNode, v8i16>;
6837  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6838      asm, ".2s", OpNode, v2i32>;
6839  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6840      asm, ".4s", OpNode, v4i32>;
6841  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6842      asm, ".2d", OpNode, v2i64>;
6843
6844  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6845        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6846  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6847        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6848  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6849        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6850  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6851        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6852  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6853        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6854}
6855
6856//----------------------------------------------------------------------------
6857// AdvSIMD three register scalar instructions
6858//----------------------------------------------------------------------------
6859
6860let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6861class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6862                        RegisterClass regtype, string asm,
6863                        list<dag> pattern>
6864  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6865      "\t$Rd, $Rn, $Rm", "", pattern>,
6866    Sched<[WriteVd]> {
6867  bits<5> Rd;
6868  bits<5> Rn;
6869  bits<5> Rm;
6870  let Inst{31-30} = 0b01;
6871  let Inst{29}    = U;
6872  let Inst{28-24} = 0b11110;
6873  let Inst{23-21} = size;
6874  let Inst{20-16} = Rm;
6875  let Inst{15-11} = opcode;
6876  let Inst{10}    = 1;
6877  let Inst{9-5}   = Rn;
6878  let Inst{4-0}   = Rd;
6879}
6880
6881let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6882class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6883                        dag oops, dag iops, string asm,
6884            list<dag> pattern>
6885  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6886    Sched<[WriteVd]> {
6887  bits<5> Rd;
6888  bits<5> Rn;
6889  bits<5> Rm;
6890  let Inst{31-30} = 0b01;
6891  let Inst{29}    = U;
6892  let Inst{28-24} = 0b11110;
6893  let Inst{23-22} = size;
6894  let Inst{21}    = R;
6895  let Inst{20-16} = Rm;
6896  let Inst{15-11} = opcode;
6897  let Inst{10}    = 1;
6898  let Inst{9-5}   = Rn;
6899  let Inst{4-0}   = Rd;
6900}
6901
6902multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6903                            SDPatternOperator OpNode> {
6904  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6905    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6906}
6907
6908multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6909                               SDPatternOperator OpNode> {
6910  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6911    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6912  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6913  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6914  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6915
6916  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6917            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6918  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6919            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6920}
6921
6922multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6923                             SDPatternOperator OpNode> {
6924  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6925                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6926  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6927}
6928
6929multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
6930  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6931                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6932                                     asm, []>;
6933  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6934                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6935                                     asm, []>;
6936}
6937
6938multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6939                             SDPatternOperator OpNode = null_frag,
6940                             Predicate pred = HasNEON> {
6941  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in {
6942    let Predicates = [pred] in {
6943    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6944      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6945    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6946      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6947    }
6948    let Predicates = [pred, HasFullFP16] in {
6949    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6950      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
6951    }
6952  }
6953
6954  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6955            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6956}
6957
6958multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6959                                SDPatternOperator OpNode = null_frag> {
6960  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in {
6961    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6962      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6963    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6964      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6965    let Predicates = [HasNEON, HasFullFP16] in {
6966    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6967      []>;
6968    } // Predicates = [HasNEON, HasFullFP16]
6969  }
6970
6971  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6972            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6973}
6974
6975class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6976              dag oops, dag iops, string asm, string cstr, list<dag> pat>
6977  : I<oops, iops, asm,
6978      "\t$Rd, $Rn, $Rm", cstr, pat>,
6979    Sched<[WriteVd]> {
6980  bits<5> Rd;
6981  bits<5> Rn;
6982  bits<5> Rm;
6983  let Inst{31-30} = 0b01;
6984  let Inst{29}    = U;
6985  let Inst{28-24} = 0b11110;
6986  let Inst{23-22} = size;
6987  let Inst{21}    = 1;
6988  let Inst{20-16} = Rm;
6989  let Inst{15-11} = opcode;
6990  let Inst{10}    = 0;
6991  let Inst{9-5}   = Rn;
6992  let Inst{4-0}   = Rd;
6993}
6994
6995let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6996multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6997                                  SDPatternOperator OpNode = null_frag> {
6998  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6999                                      (outs FPR32:$Rd),
7000                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
7001  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7002                                      (outs FPR64:$Rd),
7003                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
7004            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7005}
7006
7007let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7008multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
7009                                  SDPatternOperator OpNode = null_frag> {
7010  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7011                                      (outs FPR32:$dst),
7012                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
7013                                      asm, "$Rd = $dst", []>;
7014  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7015                                      (outs FPR64:$dst),
7016                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
7017                                      asm, "$Rd = $dst",
7018            [(set (i64 FPR64:$dst),
7019                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7020}
7021
7022//----------------------------------------------------------------------------
7023// AdvSIMD two register scalar instructions
7024//----------------------------------------------------------------------------
7025
7026let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7027class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7028                        RegisterClass regtype, RegisterClass regtype2,
7029                        string asm, list<dag> pat>
7030  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
7031      "\t$Rd, $Rn", "", pat>,
7032    Sched<[WriteVd]> {
7033  bits<5> Rd;
7034  bits<5> Rn;
7035  let Inst{31-30} = 0b01;
7036  let Inst{29}    = U;
7037  let Inst{28-24} = 0b11110;
7038  let Inst{23-22} = size;
7039  let Inst{21} = 0b1;
7040  let Inst{20-19} = size2;
7041  let Inst{18-17} = 0b00;
7042  let Inst{16-12} = opcode;
7043  let Inst{11-10} = 0b10;
7044  let Inst{9-5}   = Rn;
7045  let Inst{4-0}   = Rd;
7046}
7047
7048let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7049class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
7050                        RegisterClass regtype, RegisterClass regtype2,
7051                        string asm, list<dag> pat>
7052  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
7053      "\t$Rd, $Rn", "$Rd = $dst", pat>,
7054    Sched<[WriteVd]> {
7055  bits<5> Rd;
7056  bits<5> Rn;
7057  let Inst{31-30} = 0b01;
7058  let Inst{29}    = U;
7059  let Inst{28-24} = 0b11110;
7060  let Inst{23-22} = size;
7061  let Inst{21-17} = 0b10000;
7062  let Inst{16-12} = opcode;
7063  let Inst{11-10} = 0b10;
7064  let Inst{9-5}   = Rn;
7065  let Inst{4-0}   = Rd;
7066}
7067
7068
7069let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7070class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7071                        RegisterClass regtype, string asm, string zero>
7072  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7073      "\t$Rd, $Rn, #" # zero, "", []>,
7074    Sched<[WriteVd]> {
7075  bits<5> Rd;
7076  bits<5> Rn;
7077  let Inst{31-30} = 0b01;
7078  let Inst{29}    = U;
7079  let Inst{28-24} = 0b11110;
7080  let Inst{23-22} = size;
7081  let Inst{21} = 0b1;
7082  let Inst{20-19} = size2;
7083  let Inst{18-17} = 0b00;
7084  let Inst{16-12} = opcode;
7085  let Inst{11-10} = 0b10;
7086  let Inst{9-5}   = Rn;
7087  let Inst{4-0}   = Rd;
7088}
7089
7090let mayRaiseFPException = 1 in
7091class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7092  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7093     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
7094    Sched<[WriteVd]> {
7095  bits<5> Rd;
7096  bits<5> Rn;
7097  let Inst{31-17} = 0b011111100110000;
7098  let Inst{16-12} = opcode;
7099  let Inst{11-10} = 0b10;
7100  let Inst{9-5}   = Rn;
7101  let Inst{4-0}   = Rd;
7102}
7103
7104multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7105                             SDPatternOperator OpNode> {
7106  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7107
7108  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7109            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7110}
7111
7112multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7113                              SDPatternOperator OpNode> {
7114  let mayRaiseFPException = 1 in {
7115  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7116  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7117  let Predicates = [HasNEON, HasFullFP16] in {
7118  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7119  }
7120  }
7121
7122  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7123                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7124  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7125                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7126  let Predicates = [HasNEON, HasFullFP16] in {
7127  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7128                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7129  }
7130
7131  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7132            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7133}
7134
7135multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7136                          SDPatternOperator OpNode = null_frag> {
7137  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7138    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7139
7140  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7141            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7142}
7143
7144let mayRaiseFPException = 1 in
7145multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm,
7146                           Predicate pred = HasNEON> {
7147  let Predicates = [pred] in {
7148  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7149  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7150  }
7151  let Predicates = [pred, HasFullFP16] in {
7152  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7153  }
7154}
7155
7156let mayRaiseFPException = 1 in
7157multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7158                              SDPatternOperator OpNode> {
7159  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7160                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7161  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7162                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7163  let Predicates = [HasNEON, HasFullFP16] in {
7164  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7165                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7166  }
7167}
7168
7169multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7170                             SDPatternOperator OpNode = null_frag> {
7171  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7172    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7173           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7174    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7175           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7176    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7177    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7178  }
7179
7180  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7181            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7182}
7183
7184multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7185                                 Intrinsic OpNode> {
7186  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7187    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7188        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7189    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7190        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7191    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7192    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7193  }
7194
7195  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7196            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7197}
7198
7199
7200
7201let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7202multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7203                                 SDPatternOperator OpNode = null_frag> {
7204  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7205        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7206  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7207  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7208}
7209
7210//----------------------------------------------------------------------------
7211// AdvSIMD scalar pairwise instructions
7212//----------------------------------------------------------------------------
7213
7214let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7215class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7216                        RegisterOperand regtype, RegisterOperand vectype,
7217                        string asm, string kind>
7218  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7219      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7220    Sched<[WriteVd]> {
7221  bits<5> Rd;
7222  bits<5> Rn;
7223  let Inst{31-30} = 0b01;
7224  let Inst{29}    = U;
7225  let Inst{28-24} = 0b11110;
7226  let Inst{23-22} = size;
7227  let Inst{21-17} = 0b11000;
7228  let Inst{16-12} = opcode;
7229  let Inst{11-10} = 0b10;
7230  let Inst{9-5}   = Rn;
7231  let Inst{4-0}   = Rd;
7232}
7233
7234multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7235  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7236                                      asm, ".2d">;
7237}
7238
7239let mayRaiseFPException = 1 in
7240multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7241  let Predicates = [HasNEON, HasFullFP16] in {
7242  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7243                                      asm, ".2h">;
7244  }
7245  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7246                                      asm, ".2s">;
7247  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7248                                      asm, ".2d">;
7249}
7250
7251//----------------------------------------------------------------------------
7252// AdvSIMD across lanes instructions
7253//----------------------------------------------------------------------------
7254
7255let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7256class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7257                          RegisterClass regtype, RegisterOperand vectype,
7258                          string asm, string kind, list<dag> pattern>
7259  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7260      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7261    Sched<[!if(Q, WriteVq, WriteVd)]> {
7262  bits<5> Rd;
7263  bits<5> Rn;
7264  let Inst{31}    = 0;
7265  let Inst{30}    = Q;
7266  let Inst{29}    = U;
7267  let Inst{28-24} = 0b01110;
7268  let Inst{23-22} = size;
7269  let Inst{21-17} = 0b11000;
7270  let Inst{16-12} = opcode;
7271  let Inst{11-10} = 0b10;
7272  let Inst{9-5}   = Rn;
7273  let Inst{4-0}   = Rd;
7274}
7275
7276multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7277                              string asm> {
7278  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7279                                   asm, ".8b", []>;
7280  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7281                                   asm, ".16b", []>;
7282  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7283                                   asm, ".4h", []>;
7284  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7285                                   asm, ".8h", []>;
7286  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7287                                   asm, ".4s", []>;
7288}
7289
7290multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7291  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7292                                   asm, ".8b", []>;
7293  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7294                                   asm, ".16b", []>;
7295  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7296                                   asm, ".4h", []>;
7297  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7298                                   asm, ".8h", []>;
7299  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7300                                   asm, ".4s", []>;
7301}
7302
7303let mayRaiseFPException = 1 in
7304multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7305                            Intrinsic intOp> {
7306  let Predicates = [HasNEON, HasFullFP16] in {
7307  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7308                                   asm, ".4h",
7309        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7310  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7311                                   asm, ".8h",
7312        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7313  } // Predicates = [HasNEON, HasFullFP16]
7314  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7315                                   asm, ".4s",
7316        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7317}
7318
7319//----------------------------------------------------------------------------
7320// AdvSIMD INS/DUP instructions
7321//----------------------------------------------------------------------------
7322
7323// FIXME: There has got to be a better way to factor these. ugh.
7324
7325class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7326                     string operands, string constraints, list<dag> pattern>
7327  : I<outs, ins, asm, operands, constraints, pattern>,
7328    Sched<[!if(Q, WriteVq, WriteVd)]> {
7329  bits<5> Rd;
7330  bits<5> Rn;
7331  let Inst{31} = 0;
7332  let Inst{30} = Q;
7333  let Inst{29} = op;
7334  let Inst{28-21} = 0b01110000;
7335  let Inst{15} = 0;
7336  let Inst{10} = 1;
7337  let Inst{9-5} = Rn;
7338  let Inst{4-0} = Rd;
7339}
7340
7341class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7342                      RegisterOperand vecreg, RegisterClass regtype>
7343  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7344                   "{\t$Rd" # size # ", $Rn" #
7345                   "|" # size # "\t$Rd, $Rn}", "",
7346                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7347  let Inst{20-16} = imm5;
7348  let Inst{14-11} = 0b0001;
7349}
7350
7351class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7352                         ValueType vectype, ValueType insreg,
7353                         RegisterOperand vecreg, Operand idxtype,
7354                         SDNode OpNode>
7355  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7356                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7357                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7358                 [(set (vectype vecreg:$Rd),
7359                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7360  let Inst{14-11} = 0b0000;
7361}
7362
7363class SIMDDup64FromElement
7364  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7365                       VectorIndexD, AArch64duplane64> {
7366  bits<1> idx;
7367  let Inst{20} = idx;
7368  let Inst{19-16} = 0b1000;
7369}
7370
7371class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7372                           RegisterOperand vecreg>
7373  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7374                       VectorIndexS, AArch64duplane32> {
7375  bits<2> idx;
7376  let Inst{20-19} = idx;
7377  let Inst{18-16} = 0b100;
7378}
7379
7380class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7381                           RegisterOperand vecreg>
7382  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7383                       VectorIndexH, AArch64duplane16> {
7384  bits<3> idx;
7385  let Inst{20-18} = idx;
7386  let Inst{17-16} = 0b10;
7387}
7388
7389class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7390                          RegisterOperand vecreg>
7391  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7392                       VectorIndexB, AArch64duplane8> {
7393  bits<4> idx;
7394  let Inst{20-17} = idx;
7395  let Inst{16} = 1;
7396}
7397
7398class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7399                  Operand idxtype, string asm, list<dag> pattern>
7400  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7401                   "{\t$Rd, $Rn" # size # "$idx" #
7402                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7403  let Inst{14-11} = imm4;
7404}
7405
7406class SIMDSMov<bit Q, string size, RegisterClass regtype,
7407               Operand idxtype>
7408  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7409class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7410               Operand idxtype>
7411  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7412      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7413
7414class SIMDMovAlias<string asm, string size, Instruction inst,
7415                   RegisterClass regtype, Operand idxtype>
7416    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7417                    "|" # size # "\t$dst, $src$idx}",
7418                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7419
7420multiclass SMov {
7421  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7422  // streaming mode.
7423  let Predicates = [HasNEONorSME] in {
7424    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
7425      let Inst{20-16} = 0b00001;
7426    }
7427    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
7428      let Inst{20-16} = 0b00001;
7429    }
7430    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
7431      let Inst{20-16} = 0b00010;
7432    }
7433    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
7434      let Inst{20-16} = 0b00010;
7435    }
7436    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
7437      let Inst{20-16} = 0b00100;
7438    }
7439  }
7440  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7441    bits<4> idx;
7442    let Inst{20-17} = idx;
7443    let Inst{16} = 1;
7444  }
7445  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7446    bits<4> idx;
7447    let Inst{20-17} = idx;
7448    let Inst{16} = 1;
7449  }
7450  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7451    bits<3> idx;
7452    let Inst{20-18} = idx;
7453    let Inst{17-16} = 0b10;
7454  }
7455  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7456    bits<3> idx;
7457    let Inst{20-18} = idx;
7458    let Inst{17-16} = 0b10;
7459  }
7460  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7461    bits<2> idx;
7462    let Inst{20-19} = idx;
7463    let Inst{18-16} = 0b100;
7464  }
7465}
7466
7467multiclass UMov {
7468  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7469  // streaming mode.
7470  let Predicates = [HasNEONorSME] in {
7471    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
7472      let Inst{20-16} = 0b00001;
7473    }
7474    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
7475      let Inst{20-16} = 0b00010;
7476    }
7477    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
7478      let Inst{20-16} = 0b00100;
7479    }
7480    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
7481      let Inst{20-16} = 0b01000;
7482    }
7483    def : SIMDMovAlias<"mov", ".s",
7484                       !cast<Instruction>(NAME # vi32_idx0),
7485                       GPR32, VectorIndex0>;
7486    def : SIMDMovAlias<"mov", ".d",
7487                       !cast<Instruction>(NAME # vi64_idx0),
7488                       GPR64, VectorIndex0>;
7489  }
7490  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7491    bits<4> idx;
7492    let Inst{20-17} = idx;
7493    let Inst{16} = 1;
7494  }
7495  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7496    bits<3> idx;
7497    let Inst{20-18} = idx;
7498    let Inst{17-16} = 0b10;
7499  }
7500  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7501    bits<2> idx;
7502    let Inst{20-19} = idx;
7503    let Inst{18-16} = 0b100;
7504  }
7505  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7506    bits<1> idx;
7507    let Inst{20} = idx;
7508    let Inst{19-16} = 0b1000;
7509  }
7510  def : SIMDMovAlias<"mov", ".s",
7511                     !cast<Instruction>(NAME#"vi32"),
7512                     GPR32, VectorIndexS>;
7513  def : SIMDMovAlias<"mov", ".d",
7514                     !cast<Instruction>(NAME#"vi64"),
7515                     GPR64, VectorIndexD>;
7516}
7517
7518class SIMDInsFromMain<string size, ValueType vectype,
7519                      RegisterClass regtype, Operand idxtype>
7520  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7521                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7522                   "{\t$Rd" # size # "$idx, $Rn" #
7523                   "|" # size # "\t$Rd$idx, $Rn}",
7524                   "$Rd = $dst",
7525            [(set V128:$dst,
7526              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7527  let Inst{14-11} = 0b0011;
7528}
7529
7530class SIMDInsFromElement<string size, ValueType vectype,
7531                         ValueType elttype, Operand idxtype>
7532  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7533                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7534                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7535                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7536                   "$Rd = $dst",
7537         [(set V128:$dst,
7538               (vector_insert
7539                 (vectype V128:$Rd),
7540                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7541                 idxtype:$idx))]>;
7542
7543class SIMDInsMainMovAlias<string size, Instruction inst,
7544                          RegisterClass regtype, Operand idxtype>
7545    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7546                        "|" # size #"\t$dst$idx, $src}",
7547                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7548class SIMDInsElementMovAlias<string size, Instruction inst,
7549                             Operand idxtype>
7550    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7551                      # "|" # size #"\t$dst$idx, $src$idx2}",
7552                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7553
7554
7555multiclass SIMDIns {
7556  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7557    bits<4> idx;
7558    let Inst{20-17} = idx;
7559    let Inst{16} = 1;
7560  }
7561  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7562    bits<3> idx;
7563    let Inst{20-18} = idx;
7564    let Inst{17-16} = 0b10;
7565  }
7566  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7567    bits<2> idx;
7568    let Inst{20-19} = idx;
7569    let Inst{18-16} = 0b100;
7570  }
7571  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7572    bits<1> idx;
7573    let Inst{20} = idx;
7574    let Inst{19-16} = 0b1000;
7575  }
7576
7577  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7578    bits<4> idx;
7579    bits<4> idx2;
7580    let Inst{20-17} = idx;
7581    let Inst{16} = 1;
7582    let Inst{14-11} = idx2;
7583  }
7584  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7585    bits<3> idx;
7586    bits<3> idx2;
7587    let Inst{20-18} = idx;
7588    let Inst{17-16} = 0b10;
7589    let Inst{14-12} = idx2;
7590    let Inst{11} = {?};
7591  }
7592  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7593    bits<2> idx;
7594    bits<2> idx2;
7595    let Inst{20-19} = idx;
7596    let Inst{18-16} = 0b100;
7597    let Inst{14-13} = idx2;
7598    let Inst{12-11} = {?,?};
7599  }
7600  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7601    bits<1> idx;
7602    bits<1> idx2;
7603    let Inst{20} = idx;
7604    let Inst{19-16} = 0b1000;
7605    let Inst{14} = idx2;
7606    let Inst{13-11} = {?,?,?};
7607  }
7608
7609  // For all forms of the INS instruction, the "mov" mnemonic is the
7610  // preferred alias. Why they didn't just call the instruction "mov" in
7611  // the first place is a very good question indeed...
7612  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7613                         GPR32, VectorIndexB>;
7614  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7615                         GPR32, VectorIndexH>;
7616  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7617                         GPR32, VectorIndexS>;
7618  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7619                         GPR64, VectorIndexD>;
7620
7621  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7622                         VectorIndexB>;
7623  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7624                         VectorIndexH>;
7625  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7626                         VectorIndexS>;
7627  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7628                         VectorIndexD>;
7629}
7630
7631//----------------------------------------------------------------------------
7632// AdvSIMD TBL/TBX
7633//----------------------------------------------------------------------------
7634
7635let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7636class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7637                          RegisterOperand listtype, string asm, string kind>
7638  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7639       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7640    Sched<[!if(Q, WriteVq, WriteVd)]> {
7641  bits<5> Vd;
7642  bits<5> Vn;
7643  bits<5> Vm;
7644  let Inst{31}    = 0;
7645  let Inst{30}    = Q;
7646  let Inst{29-21} = 0b001110000;
7647  let Inst{20-16} = Vm;
7648  let Inst{15}    = 0;
7649  let Inst{14-13} = len;
7650  let Inst{12}    = op;
7651  let Inst{11-10} = 0b00;
7652  let Inst{9-5}   = Vn;
7653  let Inst{4-0}   = Vd;
7654}
7655
7656let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7657class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7658                          RegisterOperand listtype, string asm, string kind>
7659  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7660       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7661    Sched<[!if(Q, WriteVq, WriteVd)]> {
7662  bits<5> Vd;
7663  bits<5> Vn;
7664  bits<5> Vm;
7665  let Inst{31}    = 0;
7666  let Inst{30}    = Q;
7667  let Inst{29-21} = 0b001110000;
7668  let Inst{20-16} = Vm;
7669  let Inst{15}    = 0;
7670  let Inst{14-13} = len;
7671  let Inst{12}    = op;
7672  let Inst{11-10} = 0b00;
7673  let Inst{9-5}   = Vn;
7674  let Inst{4-0}   = Vd;
7675}
7676
7677class SIMDTableLookupAlias<string asm, Instruction inst,
7678                          RegisterOperand vectype, RegisterOperand listtype>
7679    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7680                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7681
7682multiclass SIMDTableLookup<bit op, string asm> {
7683  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7684                                      asm, ".8b">;
7685  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7686                                      asm, ".8b">;
7687  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7688                                      asm, ".8b">;
7689  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7690                                      asm, ".8b">;
7691  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7692                                      asm, ".16b">;
7693  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7694                                      asm, ".16b">;
7695  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7696                                      asm, ".16b">;
7697  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7698                                      asm, ".16b">;
7699
7700  def : SIMDTableLookupAlias<asm # ".8b",
7701                         !cast<Instruction>(NAME#"v8i8One"),
7702                         V64, VecListOne128>;
7703  def : SIMDTableLookupAlias<asm # ".8b",
7704                         !cast<Instruction>(NAME#"v8i8Two"),
7705                         V64, VecListTwo128>;
7706  def : SIMDTableLookupAlias<asm # ".8b",
7707                         !cast<Instruction>(NAME#"v8i8Three"),
7708                         V64, VecListThree128>;
7709  def : SIMDTableLookupAlias<asm # ".8b",
7710                         !cast<Instruction>(NAME#"v8i8Four"),
7711                         V64, VecListFour128>;
7712  def : SIMDTableLookupAlias<asm # ".16b",
7713                         !cast<Instruction>(NAME#"v16i8One"),
7714                         V128, VecListOne128>;
7715  def : SIMDTableLookupAlias<asm # ".16b",
7716                         !cast<Instruction>(NAME#"v16i8Two"),
7717                         V128, VecListTwo128>;
7718  def : SIMDTableLookupAlias<asm # ".16b",
7719                         !cast<Instruction>(NAME#"v16i8Three"),
7720                         V128, VecListThree128>;
7721  def : SIMDTableLookupAlias<asm # ".16b",
7722                         !cast<Instruction>(NAME#"v16i8Four"),
7723                         V128, VecListFour128>;
7724}
7725
7726multiclass SIMDTableLookupTied<bit op, string asm> {
7727  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7728                                      asm, ".8b">;
7729  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7730                                      asm, ".8b">;
7731  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7732                                      asm, ".8b">;
7733  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7734                                      asm, ".8b">;
7735  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7736                                      asm, ".16b">;
7737  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7738                                      asm, ".16b">;
7739  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7740                                      asm, ".16b">;
7741  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7742                                      asm, ".16b">;
7743
7744  def : SIMDTableLookupAlias<asm # ".8b",
7745                         !cast<Instruction>(NAME#"v8i8One"),
7746                         V64, VecListOne128>;
7747  def : SIMDTableLookupAlias<asm # ".8b",
7748                         !cast<Instruction>(NAME#"v8i8Two"),
7749                         V64, VecListTwo128>;
7750  def : SIMDTableLookupAlias<asm # ".8b",
7751                         !cast<Instruction>(NAME#"v8i8Three"),
7752                         V64, VecListThree128>;
7753  def : SIMDTableLookupAlias<asm # ".8b",
7754                         !cast<Instruction>(NAME#"v8i8Four"),
7755                         V64, VecListFour128>;
7756  def : SIMDTableLookupAlias<asm # ".16b",
7757                         !cast<Instruction>(NAME#"v16i8One"),
7758                         V128, VecListOne128>;
7759  def : SIMDTableLookupAlias<asm # ".16b",
7760                         !cast<Instruction>(NAME#"v16i8Two"),
7761                         V128, VecListTwo128>;
7762  def : SIMDTableLookupAlias<asm # ".16b",
7763                         !cast<Instruction>(NAME#"v16i8Three"),
7764                         V128, VecListThree128>;
7765  def : SIMDTableLookupAlias<asm # ".16b",
7766                         !cast<Instruction>(NAME#"v16i8Four"),
7767                         V128, VecListFour128>;
7768}
7769
7770
7771//----------------------------------------------------------------------------
7772// AdvSIMD scalar DUP
7773//----------------------------------------------------------------------------
7774let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7775class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
7776                        string asm, string kind, Operand idxtype>
7777  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
7778       "{\t$dst, $src" # kind # "$idx" #
7779       "|\t$dst, $src$idx}", "", []>,
7780    Sched<[WriteVd]> {
7781  bits<5> dst;
7782  bits<5> src;
7783  let Inst{31-21} = 0b01011110000;
7784  let Inst{15-10} = 0b000001;
7785  let Inst{9-5}   = src;
7786  let Inst{4-0}   = dst;
7787}
7788
7789class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
7790      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7791    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7792                    # "|\t$dst, $src$index}",
7793                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7794
7795
7796multiclass SIMDScalarDUP<string asm> {
7797  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
7798    bits<4> idx;
7799    let Inst{20-17} = idx;
7800    let Inst{16} = 1;
7801  }
7802  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
7803    bits<3> idx;
7804    let Inst{20-18} = idx;
7805    let Inst{17-16} = 0b10;
7806  }
7807  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
7808    bits<2> idx;
7809    let Inst{20-19} = idx;
7810    let Inst{18-16} = 0b100;
7811  }
7812  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
7813    bits<1> idx;
7814    let Inst{20} = idx;
7815    let Inst{19-16} = 0b1000;
7816  }
7817
7818  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7819                                                          VectorIndexD:$idx)))),
7820            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7821
7822  // 'DUP' mnemonic aliases.
7823  def : SIMDScalarDUPAlias<"dup", ".b",
7824                           !cast<Instruction>(NAME#"i8"),
7825                           FPR8, V128, VectorIndexB>;
7826  def : SIMDScalarDUPAlias<"dup", ".h",
7827                           !cast<Instruction>(NAME#"i16"),
7828                           FPR16, V128, VectorIndexH>;
7829  def : SIMDScalarDUPAlias<"dup", ".s",
7830                           !cast<Instruction>(NAME#"i32"),
7831                           FPR32, V128, VectorIndexS>;
7832  def : SIMDScalarDUPAlias<"dup", ".d",
7833                           !cast<Instruction>(NAME#"i64"),
7834                           FPR64, V128, VectorIndexD>;
7835}
7836
7837//----------------------------------------------------------------------------
7838// AdvSIMD modified immediate instructions
7839//----------------------------------------------------------------------------
7840
7841class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7842                          string asm, string op_string,
7843                          string cstr, list<dag> pattern>
7844  : I<oops, iops, asm, op_string, cstr, pattern>,
7845    Sched<[!if(Q, WriteVq, WriteVd)]> {
7846  bits<5> Rd;
7847  bits<8> imm8;
7848  let Inst{31}    = 0;
7849  let Inst{30}    = Q;
7850  let Inst{29}    = op;
7851  let Inst{28-19} = 0b0111100000;
7852  let Inst{18-16} = imm8{7-5};
7853  let Inst{11} = op2;
7854  let Inst{10} = 1;
7855  let Inst{9-5}   = imm8{4-0};
7856  let Inst{4-0}   = Rd;
7857}
7858
7859class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7860                                Operand immtype, dag opt_shift_iop,
7861                                string opt_shift, string asm, string kind,
7862                                list<dag> pattern>
7863  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7864                        !con((ins immtype:$imm8), opt_shift_iop), asm,
7865                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
7866                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7867                        "", pattern> {
7868  let DecoderMethod = "DecodeModImmInstruction";
7869}
7870
7871class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7872                                Operand immtype, dag opt_shift_iop,
7873                                string opt_shift, string asm, string kind,
7874                                list<dag> pattern>
7875  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7876                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7877                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7878                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7879                        "$Rd = $dst", pattern> {
7880  let DecoderMethod = "DecodeModImmTiedInstruction";
7881}
7882
7883class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7884                                     RegisterOperand vectype, string asm,
7885                                     string kind, list<dag> pattern>
7886  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7887                              (ins logical_vec_shift:$shift),
7888                              "$shift", asm, kind, pattern> {
7889  bits<2> shift;
7890  let Inst{15}    = b15_b12{1};
7891  let Inst{14-13} = shift;
7892  let Inst{12}    = b15_b12{0};
7893}
7894
7895class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7896                                     RegisterOperand vectype, string asm,
7897                                     string kind, list<dag> pattern>
7898  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7899                              (ins logical_vec_shift:$shift),
7900                              "$shift", asm, kind, pattern> {
7901  bits<2> shift;
7902  let Inst{15}    = b15_b12{1};
7903  let Inst{14-13} = shift;
7904  let Inst{12}    = b15_b12{0};
7905}
7906
7907
7908class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7909                                         RegisterOperand vectype, string asm,
7910                                         string kind, list<dag> pattern>
7911  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7912                              (ins logical_vec_hw_shift:$shift),
7913                              "$shift", asm, kind, pattern> {
7914  bits<2> shift;
7915  let Inst{15} = b15_b12{1};
7916  let Inst{14} = 0;
7917  let Inst{13} = shift{0};
7918  let Inst{12} = b15_b12{0};
7919}
7920
7921class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7922                                         RegisterOperand vectype, string asm,
7923                                         string kind, list<dag> pattern>
7924  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7925                              (ins logical_vec_hw_shift:$shift),
7926                              "$shift", asm, kind, pattern> {
7927  bits<2> shift;
7928  let Inst{15} = b15_b12{1};
7929  let Inst{14} = 0;
7930  let Inst{13} = shift{0};
7931  let Inst{12} = b15_b12{0};
7932}
7933
7934multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7935                                      string asm> {
7936  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7937                                                 asm, ".4h", []>;
7938  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7939                                                 asm, ".8h", []>;
7940
7941  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7942                                             asm, ".2s", []>;
7943  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7944                                             asm, ".4s", []>;
7945}
7946
7947multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7948                                      bits<2> w_cmode, string asm,
7949                                      SDNode OpNode> {
7950  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7951                                                 asm, ".4h",
7952             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7953                                             imm0_255:$imm8,
7954                                             (i32 imm:$shift)))]>;
7955  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7956                                                 asm, ".8h",
7957             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7958                                              imm0_255:$imm8,
7959                                              (i32 imm:$shift)))]>;
7960
7961  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7962                                             asm, ".2s",
7963             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7964                                             imm0_255:$imm8,
7965                                             (i32 imm:$shift)))]>;
7966  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7967                                             asm, ".4s",
7968             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7969                                              imm0_255:$imm8,
7970                                              (i32 imm:$shift)))]>;
7971}
7972
7973class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7974                             RegisterOperand vectype, string asm,
7975                             string kind, list<dag> pattern>
7976  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7977                              (ins move_vec_shift:$shift),
7978                              "$shift", asm, kind, pattern> {
7979  bits<1> shift;
7980  let Inst{15-13} = cmode{3-1};
7981  let Inst{12}    = shift;
7982}
7983
7984class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7985                                   RegisterOperand vectype,
7986                                   Operand imm_type, string asm,
7987                                   string kind, list<dag> pattern>
7988  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7989                              asm, kind, pattern> {
7990  let Inst{15-12} = cmode;
7991}
7992
7993class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7994                                   list<dag> pattern>
7995  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7996                        "\t$Rd, $imm8", "", pattern> {
7997  let Inst{15-12} = cmode;
7998  let DecoderMethod = "DecodeModImmInstruction";
7999}
8000
8001//----------------------------------------------------------------------------
8002// AdvSIMD indexed element
8003//----------------------------------------------------------------------------
8004
8005let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8006class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8007                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8008                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8009                      string apple_kind, string dst_kind, string lhs_kind,
8010                      string rhs_kind, list<dag> pattern>
8011  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
8012      asm,
8013      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8014      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
8015    Sched<[WriteVd]> {
8016  bits<5> Rd;
8017  bits<5> Rn;
8018  bits<5> Rm;
8019
8020  let Inst{31}    = 0;
8021  let Inst{30}    = Q;
8022  let Inst{29}    = U;
8023  let Inst{28}    = Scalar;
8024  let Inst{27-24} = 0b1111;
8025  let Inst{23-22} = size;
8026  // Bit 21 must be set by the derived class.
8027  let Inst{20-16} = Rm;
8028  let Inst{15-12} = opc;
8029  // Bit 11 must be set by the derived class.
8030  let Inst{10}    = 0;
8031  let Inst{9-5}   = Rn;
8032  let Inst{4-0}   = Rd;
8033}
8034
8035let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8036class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8037                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8038                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8039                      string apple_kind, string dst_kind, string lhs_kind,
8040                      string rhs_kind, list<dag> pattern>
8041  : I<(outs dst_reg:$dst),
8042      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
8043      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8044      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
8045    Sched<[WriteVd]> {
8046  bits<5> Rd;
8047  bits<5> Rn;
8048  bits<5> Rm;
8049
8050  let Inst{31}    = 0;
8051  let Inst{30}    = Q;
8052  let Inst{29}    = U;
8053  let Inst{28}    = Scalar;
8054  let Inst{27-24} = 0b1111;
8055  let Inst{23-22} = size;
8056  // Bit 21 must be set by the derived class.
8057  let Inst{20-16} = Rm;
8058  let Inst{15-12} = opc;
8059  // Bit 11 must be set by the derived class.
8060  let Inst{10}    = 0;
8061  let Inst{9-5}   = Rn;
8062  let Inst{4-0}   = Rd;
8063}
8064
8065
8066//----------------------------------------------------------------------------
8067// Armv8.6 BFloat16 Extension
8068//----------------------------------------------------------------------------
8069let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8070
8071class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8072                                   string kind2, RegisterOperand RegType,
8073                                   ValueType AccumType, ValueType InputType>
8074  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8075                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8076                                            (InputType RegType:$Rn),
8077                                            (InputType RegType:$Rm)))]> {
8078  let AsmString = !strconcat(asm,
8079                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8080                               ", $Rm" # kind2 # "}");
8081}
8082
8083multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8084  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8085                                           v2f32, v4bf16>;
8086  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8087                                           v4f32, v8bf16>;
8088}
8089
8090class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
8091                                      string dst_kind, string lhs_kind,
8092                                      string rhs_kind,
8093                                      RegisterOperand RegType,
8094                                      ValueType AccumType,
8095                                      ValueType InputType>
8096  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
8097                        RegType, RegType, V128, VectorIndexS,
8098                        asm, "", dst_kind, lhs_kind, rhs_kind,
8099        [(set (AccumType RegType:$dst),
8100              (AccumType (int_aarch64_neon_bfdot
8101                                 (AccumType RegType:$Rd),
8102                                 (InputType RegType:$Rn),
8103                                 (InputType (bitconvert (AccumType
8104                                    (AArch64duplane32 (v4f32 V128:$Rm),
8105                                        VectorIndexS:$idx)))))))]> {
8106
8107  bits<2> idx;
8108  let Inst{21}    = idx{0};  // L
8109  let Inst{11}    = idx{1};  // H
8110}
8111
8112multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
8113
8114  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
8115                                               ".2h", V64, v2f32, v4bf16>;
8116  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
8117                                              ".2h", V128, v4f32, v8bf16>;
8118}
8119
8120let mayRaiseFPException = 1 in
8121class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
8122  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
8123              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
8124                                               (v8bf16 V128:$Rn),
8125                                               (v8bf16 V128:$Rm)))]> {
8126  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
8127}
8128
8129let mayRaiseFPException = 1 in
8130class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
8131  : I<(outs V128:$dst),
8132      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
8133      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
8134          [(set (v4f32 V128:$dst),
8135                (v4f32 (OpNode (v4f32 V128:$Rd),
8136                               (v8bf16 V128:$Rn),
8137                               (v8bf16
8138                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
8139                                      VectorIndexH:$idx)))))]>,
8140    Sched<[WriteVq]> {
8141  bits<5> Rd;
8142  bits<5> Rn;
8143  bits<4> Rm;
8144  bits<3> idx;
8145
8146  let Inst{31}    = 0;
8147  let Inst{30}    = Q;
8148  let Inst{29-22} = 0b00111111;
8149  let Inst{21-20} = idx{1-0};
8150  let Inst{19-16} = Rm;
8151  let Inst{15-12} = 0b1111;
8152  let Inst{11}    = idx{2};   // H
8153  let Inst{10}    = 0;
8154  let Inst{9-5}   = Rn;
8155  let Inst{4-0}   = Rd;
8156}
8157
8158class SIMDThreeSameVectorBF16MatrixMul<string asm>
8159  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
8160                                V128, asm, ".4s",
8161                          [(set (v4f32 V128:$dst),
8162                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
8163                                                         (v8bf16 V128:$Rn),
8164                                                         (v8bf16 V128:$Rm)))]> {
8165  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8166                                    ", $Rm", ".8h", "}");
8167}
8168
8169let mayRaiseFPException = 1 in
8170class SIMD_BFCVTN
8171  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8172                           "bfcvtn", ".4h", ".4s",
8173    [(set (v8bf16 V128:$Rd),
8174          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8175
8176let mayRaiseFPException = 1 in
8177class SIMD_BFCVTN2
8178  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8179                           "bfcvtn2", ".8h", ".4s",
8180    [(set (v8bf16 V128:$dst),
8181          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8182
8183let mayRaiseFPException = 1 in
8184class BF16ToSinglePrecision<string asm>
8185  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8186    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8187    Sched<[WriteFCvt]> {
8188  bits<5> Rd;
8189  bits<5> Rn;
8190  let Inst{31-10} = 0b0001111001100011010000;
8191  let Inst{9-5}   = Rn;
8192  let Inst{4-0}   = Rd;
8193}
8194} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8195
8196//----------------------------------------------------------------------------
8197// Armv8.6 Matrix Multiply Extension
8198//----------------------------------------------------------------------------
8199
8200class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8201  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8202              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8203                                               (v16i8 V128:$Rn),
8204                                               (v16i8 V128:$Rm)))]> {
8205  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8206}
8207
8208//----------------------------------------------------------------------------
8209// ARMv8.2-A Dot Product Instructions (Indexed)
8210class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
8211                                      string dst_kind, string lhs_kind, string rhs_kind,
8212                                      RegisterOperand RegType,
8213                                      ValueType AccumType, ValueType InputType,
8214                                      SDPatternOperator OpNode> :
8215        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
8216                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8217        [(set (AccumType RegType:$dst),
8218              (AccumType (OpNode (AccumType RegType:$Rd),
8219                                 (InputType RegType:$Rn),
8220                                 (InputType (bitconvert (AccumType
8221                                    (AArch64duplane32 (v4i32 V128:$Rm),
8222                                        VectorIndexS:$idx)))))))]> {
8223  bits<2> idx;
8224  let Inst{21}    = idx{0};  // L
8225  let Inst{11}    = idx{1};  // H
8226}
8227
8228multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8229                                       SDPatternOperator OpNode> {
8230  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
8231                                              V64, v2i32, v8i8, OpNode>;
8232  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
8233                                              V128, v4i32, v16i8, OpNode>;
8234}
8235
8236// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8237let mayRaiseFPException = 1 in
8238class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
8239                                      string dst_kind, string lhs_kind,
8240                                      string rhs_kind, RegisterOperand RegType,
8241                                      ValueType AccumType, ValueType InputType,
8242                                      SDPatternOperator OpNode> :
8243        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
8244                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8245          [(set (AccumType RegType:$dst),
8246                (AccumType (OpNode (AccumType RegType:$Rd),
8247                                   (InputType RegType:$Rn),
8248                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
8249                                                VectorIndexH:$idx)))))]> {
8250  // idx = H:L:M
8251  bits<3> idx;
8252  let Inst{11} = idx{2}; // H
8253  let Inst{21} = idx{1}; // L
8254  let Inst{20} = idx{0}; // M
8255}
8256
8257multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8258                                       SDPatternOperator OpNode> {
8259  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8260                                              V64, v2f32, v4f16, OpNode>;
8261  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8262                                              V128, v4f32, v8f16, OpNode>;
8263}
8264
8265let mayRaiseFPException = 1 in
8266multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8267                         SDPatternOperator OpNode> {
8268  let Predicates = [HasNEON, HasFullFP16] in {
8269  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8270                                      V64, V64,
8271                                      V128_lo, VectorIndexH,
8272                                      asm, ".4h", ".4h", ".4h", ".h",
8273    [(set (v4f16 V64:$Rd),
8274        (OpNode (v4f16 V64:$Rn),
8275         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8276    bits<3> idx;
8277    let Inst{11} = idx{2};
8278    let Inst{21} = idx{1};
8279    let Inst{20} = idx{0};
8280  }
8281
8282  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8283                                      V128, V128,
8284                                      V128_lo, VectorIndexH,
8285                                      asm, ".8h", ".8h", ".8h", ".h",
8286    [(set (v8f16 V128:$Rd),
8287        (OpNode (v8f16 V128:$Rn),
8288         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8289    bits<3> idx;
8290    let Inst{11} = idx{2};
8291    let Inst{21} = idx{1};
8292    let Inst{20} = idx{0};
8293  }
8294  } // Predicates = [HasNEON, HasFullFP16]
8295
8296  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8297                                      V64, V64,
8298                                      V128, VectorIndexS,
8299                                      asm, ".2s", ".2s", ".2s", ".s",
8300    [(set (v2f32 V64:$Rd),
8301        (OpNode (v2f32 V64:$Rn),
8302         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8303    bits<2> idx;
8304    let Inst{11} = idx{1};
8305    let Inst{21} = idx{0};
8306  }
8307
8308  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8309                                      V128, V128,
8310                                      V128, VectorIndexS,
8311                                      asm, ".4s", ".4s", ".4s", ".s",
8312    [(set (v4f32 V128:$Rd),
8313        (OpNode (v4f32 V128:$Rn),
8314         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8315    bits<2> idx;
8316    let Inst{11} = idx{1};
8317    let Inst{21} = idx{0};
8318  }
8319
8320  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8321                                      V128, V128,
8322                                      V128, VectorIndexD,
8323                                      asm, ".2d", ".2d", ".2d", ".d",
8324    [(set (v2f64 V128:$Rd),
8325        (OpNode (v2f64 V128:$Rn),
8326         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8327    bits<1> idx;
8328    let Inst{11} = idx{0};
8329    let Inst{21} = 0;
8330  }
8331
8332  let Predicates = [HasNEON, HasFullFP16] in {
8333  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8334                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8335                                      asm, ".h", "", "", ".h",
8336    [(set (f16 FPR16Op:$Rd),
8337          (OpNode (f16 FPR16Op:$Rn),
8338                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8339                                       VectorIndexH:$idx))))]> {
8340    bits<3> idx;
8341    let Inst{11} = idx{2};
8342    let Inst{21} = idx{1};
8343    let Inst{20} = idx{0};
8344  }
8345  } // Predicates = [HasNEON, HasFullFP16]
8346
8347  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8348                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8349                                      asm, ".s", "", "", ".s",
8350    [(set (f32 FPR32Op:$Rd),
8351          (OpNode (f32 FPR32Op:$Rn),
8352                  (f32 (vector_extract (v4f32 V128:$Rm),
8353                                       VectorIndexS:$idx))))]> {
8354    bits<2> idx;
8355    let Inst{11} = idx{1};
8356    let Inst{21} = idx{0};
8357  }
8358
8359  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8360                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8361                                      asm, ".d", "", "", ".d",
8362    [(set (f64 FPR64Op:$Rd),
8363          (OpNode (f64 FPR64Op:$Rn),
8364                  (f64 (vector_extract (v2f64 V128:$Rm),
8365                                       VectorIndexD:$idx))))]> {
8366    bits<1> idx;
8367    let Inst{11} = idx{0};
8368    let Inst{21} = 0;
8369  }
8370}
8371
8372multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8373  let Predicates = [HasNEON, HasFullFP16] in {
8374  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8375  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8376                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8377                                           VectorIndexH:$idx))),
8378            (!cast<Instruction>(INST # "v8i16_indexed")
8379                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8380  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8381                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8382            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8383                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8384
8385  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8386                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8387                                           VectorIndexH:$idx))),
8388            (!cast<Instruction>(INST # "v4i16_indexed")
8389                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8390  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8391                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8392            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8393                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8394
8395  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8396                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8397            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8398                V128_lo:$Rm, VectorIndexH:$idx)>;
8399  } // Predicates = [HasNEON, HasFullFP16]
8400
8401  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8402  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8403                           (AArch64duplane32 (v4f32 V128:$Rm),
8404                                           VectorIndexS:$idx))),
8405            (!cast<Instruction>(INST # v2i32_indexed)
8406                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8407  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8408                           (AArch64dup (f32 FPR32Op:$Rm)))),
8409            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8410                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8411
8412
8413  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8414  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8415                           (AArch64duplane32 (v4f32 V128:$Rm),
8416                                           VectorIndexS:$idx))),
8417            (!cast<Instruction>(INST # "v4i32_indexed")
8418                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8419  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8420                           (AArch64dup (f32 FPR32Op:$Rm)))),
8421            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8422                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8423
8424  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8425  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8426                           (AArch64duplane64 (v2f64 V128:$Rm),
8427                                           VectorIndexD:$idx))),
8428            (!cast<Instruction>(INST # "v2i64_indexed")
8429                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8430  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8431                           (AArch64dup (f64 FPR64Op:$Rm)))),
8432            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8433                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8434
8435  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8436  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8437                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8438            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8439                V128:$Rm, VectorIndexS:$idx)>;
8440
8441  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8442  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8443                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8444            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8445                V128:$Rm, VectorIndexD:$idx)>;
8446}
8447
8448let mayRaiseFPException = 1 in
8449multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8450  let Predicates = [HasNEON, HasFullFP16] in {
8451  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8452                                          V128_lo, VectorIndexH,
8453                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8454    bits<3> idx;
8455    let Inst{11} = idx{2};
8456    let Inst{21} = idx{1};
8457    let Inst{20} = idx{0};
8458  }
8459
8460  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8461                                          V128, V128,
8462                                          V128_lo, VectorIndexH,
8463                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8464    bits<3> idx;
8465    let Inst{11} = idx{2};
8466    let Inst{21} = idx{1};
8467    let Inst{20} = idx{0};
8468  }
8469  } // Predicates = [HasNEON, HasFullFP16]
8470
8471  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8472                                          V128, VectorIndexS,
8473                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8474    bits<2> idx;
8475    let Inst{11} = idx{1};
8476    let Inst{21} = idx{0};
8477  }
8478
8479  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8480                                      V128, V128,
8481                                      V128, VectorIndexS,
8482                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8483    bits<2> idx;
8484    let Inst{11} = idx{1};
8485    let Inst{21} = idx{0};
8486  }
8487
8488  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8489                                      V128, V128,
8490                                      V128, VectorIndexD,
8491                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8492    bits<1> idx;
8493    let Inst{11} = idx{0};
8494    let Inst{21} = 0;
8495  }
8496
8497  let Predicates = [HasNEON, HasFullFP16] in {
8498  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8499                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8500                                      asm, ".h", "", "", ".h", []> {
8501    bits<3> idx;
8502    let Inst{11} = idx{2};
8503    let Inst{21} = idx{1};
8504    let Inst{20} = idx{0};
8505  }
8506  } // Predicates = [HasNEON, HasFullFP16]
8507
8508  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8509                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8510                                      asm, ".s", "", "", ".s", []> {
8511    bits<2> idx;
8512    let Inst{11} = idx{1};
8513    let Inst{21} = idx{0};
8514  }
8515
8516  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8517                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8518                                      asm, ".d", "", "", ".d", []> {
8519    bits<1> idx;
8520    let Inst{11} = idx{0};
8521    let Inst{21} = 0;
8522  }
8523}
8524
8525multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8526                                 SDPatternOperator OpNodeLaneQ> {
8527
8528  def : Pat<(v4i16 (OpNodeLane
8529                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8530                     VectorIndexS32b:$idx)),
8531            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8532              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8533              (UImmS1XForm $idx))>;
8534
8535  def : Pat<(v4i16 (OpNodeLaneQ
8536                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8537                     VectorIndexH32b:$idx)),
8538            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8539              (UImmS1XForm $idx))>;
8540
8541  def : Pat<(v8i16 (OpNodeLane
8542                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8543                     VectorIndexS32b:$idx)),
8544            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8545              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8546              (UImmS1XForm $idx))>;
8547
8548  def : Pat<(v8i16 (OpNodeLaneQ
8549                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8550                     VectorIndexH32b:$idx)),
8551            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8552              (UImmS1XForm $idx))>;
8553
8554  def : Pat<(v2i32 (OpNodeLane
8555                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8556                     VectorIndexD32b:$idx)),
8557            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8558              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8559              (UImmS1XForm $idx))>;
8560
8561  def : Pat<(v2i32 (OpNodeLaneQ
8562                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8563                     VectorIndexS32b:$idx)),
8564            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8565              (UImmS1XForm $idx))>;
8566
8567  def : Pat<(v4i32 (OpNodeLane
8568                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8569                     VectorIndexD32b:$idx)),
8570            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8571              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8572              (UImmS1XForm $idx))>;
8573
8574  def : Pat<(v4i32 (OpNodeLaneQ
8575                     (v4i32 V128:$Rn),
8576                     (v4i32 V128:$Rm),
8577                     VectorIndexS32b:$idx)),
8578            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8579              (UImmS1XForm $idx))>;
8580
8581}
8582
8583multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8584                         SDPatternOperator OpNode> {
8585  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8586                                      V128_lo, VectorIndexH,
8587                                      asm, ".4h", ".4h", ".4h", ".h",
8588    [(set (v4i16 V64:$Rd),
8589        (OpNode (v4i16 V64:$Rn),
8590         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8591    bits<3> idx;
8592    let Inst{11} = idx{2};
8593    let Inst{21} = idx{1};
8594    let Inst{20} = idx{0};
8595  }
8596
8597  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8598                                      V128, V128,
8599                                      V128_lo, VectorIndexH,
8600                                      asm, ".8h", ".8h", ".8h", ".h",
8601    [(set (v8i16 V128:$Rd),
8602       (OpNode (v8i16 V128:$Rn),
8603         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8604    bits<3> idx;
8605    let Inst{11} = idx{2};
8606    let Inst{21} = idx{1};
8607    let Inst{20} = idx{0};
8608  }
8609
8610  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8611                                      V64, V64,
8612                                      V128, VectorIndexS,
8613                                      asm, ".2s", ".2s", ".2s",  ".s",
8614    [(set (v2i32 V64:$Rd),
8615       (OpNode (v2i32 V64:$Rn),
8616          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8617    bits<2> idx;
8618    let Inst{11} = idx{1};
8619    let Inst{21} = idx{0};
8620  }
8621
8622  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8623                                      V128, V128,
8624                                      V128, VectorIndexS,
8625                                      asm, ".4s", ".4s", ".4s", ".s",
8626    [(set (v4i32 V128:$Rd),
8627       (OpNode (v4i32 V128:$Rn),
8628          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8629    bits<2> idx;
8630    let Inst{11} = idx{1};
8631    let Inst{21} = idx{0};
8632  }
8633
8634  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8635                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8636                                      asm, ".h", "", "", ".h", []> {
8637    bits<3> idx;
8638    let Inst{11} = idx{2};
8639    let Inst{21} = idx{1};
8640    let Inst{20} = idx{0};
8641  }
8642
8643  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8644                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8645                                      asm, ".s", "", "", ".s",
8646      [(set (i32 FPR32Op:$Rd),
8647            (OpNode FPR32Op:$Rn,
8648                    (i32 (vector_extract (v4i32 V128:$Rm),
8649                                         VectorIndexS:$idx))))]> {
8650    bits<2> idx;
8651    let Inst{11} = idx{1};
8652    let Inst{21} = idx{0};
8653  }
8654}
8655
8656multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8657                               SDPatternOperator OpNode> {
8658  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8659                                      V64, V64,
8660                                      V128_lo, VectorIndexH,
8661                                      asm, ".4h", ".4h", ".4h", ".h",
8662    [(set (v4i16 V64:$Rd),
8663        (OpNode (v4i16 V64:$Rn),
8664         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8665    bits<3> idx;
8666    let Inst{11} = idx{2};
8667    let Inst{21} = idx{1};
8668    let Inst{20} = idx{0};
8669  }
8670
8671  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8672                                      V128, V128,
8673                                      V128_lo, VectorIndexH,
8674                                      asm, ".8h", ".8h", ".8h", ".h",
8675    [(set (v8i16 V128:$Rd),
8676       (OpNode (v8i16 V128:$Rn),
8677         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8678    bits<3> idx;
8679    let Inst{11} = idx{2};
8680    let Inst{21} = idx{1};
8681    let Inst{20} = idx{0};
8682  }
8683
8684  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8685                                      V64, V64,
8686                                      V128, VectorIndexS,
8687                                      asm, ".2s", ".2s", ".2s", ".s",
8688    [(set (v2i32 V64:$Rd),
8689       (OpNode (v2i32 V64:$Rn),
8690          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8691    bits<2> idx;
8692    let Inst{11} = idx{1};
8693    let Inst{21} = idx{0};
8694  }
8695
8696  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8697                                      V128, V128,
8698                                      V128, VectorIndexS,
8699                                      asm, ".4s", ".4s", ".4s", ".s",
8700    [(set (v4i32 V128:$Rd),
8701       (OpNode (v4i32 V128:$Rn),
8702          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8703    bits<2> idx;
8704    let Inst{11} = idx{1};
8705    let Inst{21} = idx{0};
8706  }
8707}
8708
8709multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8710                                   SDPatternOperator OpNode> {
8711  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8712                                          V128_lo, VectorIndexH,
8713                                          asm, ".4h", ".4h", ".4h", ".h",
8714    [(set (v4i16 V64:$dst),
8715        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8716         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8717    bits<3> idx;
8718    let Inst{11} = idx{2};
8719    let Inst{21} = idx{1};
8720    let Inst{20} = idx{0};
8721  }
8722
8723  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8724                                      V128, V128,
8725                                      V128_lo, VectorIndexH,
8726                                      asm, ".8h", ".8h", ".8h", ".h",
8727    [(set (v8i16 V128:$dst),
8728       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8729         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8730    bits<3> idx;
8731    let Inst{11} = idx{2};
8732    let Inst{21} = idx{1};
8733    let Inst{20} = idx{0};
8734  }
8735
8736  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8737                                      V64, V64,
8738                                      V128, VectorIndexS,
8739                                      asm, ".2s", ".2s", ".2s", ".s",
8740    [(set (v2i32 V64:$dst),
8741       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8742          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8743    bits<2> idx;
8744    let Inst{11} = idx{1};
8745    let Inst{21} = idx{0};
8746  }
8747
8748  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8749                                      V128, V128,
8750                                      V128, VectorIndexS,
8751                                      asm, ".4s", ".4s", ".4s", ".s",
8752    [(set (v4i32 V128:$dst),
8753       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8754          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8755    bits<2> idx;
8756    let Inst{11} = idx{1};
8757    let Inst{21} = idx{0};
8758  }
8759}
8760
8761multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8762                             SDPatternOperator OpNode> {
8763  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8764                                      V128, V64,
8765                                      V128_lo, VectorIndexH,
8766                                      asm, ".4s", ".4s", ".4h", ".h",
8767    [(set (v4i32 V128:$Rd),
8768        (OpNode (v4i16 V64:$Rn),
8769         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8770    bits<3> idx;
8771    let Inst{11} = idx{2};
8772    let Inst{21} = idx{1};
8773    let Inst{20} = idx{0};
8774  }
8775
8776  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8777                                      V128, V128,
8778                                      V128_lo, VectorIndexH,
8779                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8780    [(set (v4i32 V128:$Rd),
8781          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
8782                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8783
8784    bits<3> idx;
8785    let Inst{11} = idx{2};
8786    let Inst{21} = idx{1};
8787    let Inst{20} = idx{0};
8788  }
8789
8790  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8791                                      V128, V64,
8792                                      V128, VectorIndexS,
8793                                      asm, ".2d", ".2d", ".2s", ".s",
8794    [(set (v2i64 V128:$Rd),
8795        (OpNode (v2i32 V64:$Rn),
8796         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8797    bits<2> idx;
8798    let Inst{11} = idx{1};
8799    let Inst{21} = idx{0};
8800  }
8801
8802  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8803                                      V128, V128,
8804                                      V128, VectorIndexS,
8805                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8806    [(set (v2i64 V128:$Rd),
8807          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
8808                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8809    bits<2> idx;
8810    let Inst{11} = idx{1};
8811    let Inst{21} = idx{0};
8812  }
8813
8814  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8815                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8816                                      asm, ".h", "", "", ".h", []> {
8817    bits<3> idx;
8818    let Inst{11} = idx{2};
8819    let Inst{21} = idx{1};
8820    let Inst{20} = idx{0};
8821  }
8822
8823  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8824                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8825                                      asm, ".s", "", "", ".s", []> {
8826    bits<2> idx;
8827    let Inst{11} = idx{1};
8828    let Inst{21} = idx{0};
8829  }
8830}
8831
8832multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8833                                       SDPatternOperator Accum> {
8834  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8835                                      V128, V64,
8836                                      V128_lo, VectorIndexH,
8837                                      asm, ".4s", ".4s", ".4h", ".h",
8838    [(set (v4i32 V128:$dst),
8839          (Accum (v4i32 V128:$Rd),
8840                 (v4i32 (int_aarch64_neon_sqdmull
8841                             (v4i16 V64:$Rn),
8842                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8843                                                    VectorIndexH:$idx))))))]> {
8844    bits<3> idx;
8845    let Inst{11} = idx{2};
8846    let Inst{21} = idx{1};
8847    let Inst{20} = idx{0};
8848  }
8849
8850  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8851  // intermediate EXTRACT_SUBREG would be untyped.
8852  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8853                (i32 (vector_extract (v4i32
8854                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8855                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8856                                                    VectorIndexH:$idx)))),
8857                         (i64 0))))),
8858            (EXTRACT_SUBREG
8859                (!cast<Instruction>(NAME # v4i16_indexed)
8860                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8861                    V128_lo:$Rm, VectorIndexH:$idx),
8862                ssub)>;
8863
8864  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8865                                      V128, V128,
8866                                      V128_lo, VectorIndexH,
8867                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8868    [(set (v4i32 V128:$dst),
8869          (Accum (v4i32 V128:$Rd),
8870                 (v4i32 (int_aarch64_neon_sqdmull
8871                            (extract_high_v8i16 (v8i16 V128:$Rn)),
8872                            (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))))]> {
8873    bits<3> idx;
8874    let Inst{11} = idx{2};
8875    let Inst{21} = idx{1};
8876    let Inst{20} = idx{0};
8877  }
8878
8879  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8880                                      V128, V64,
8881                                      V128, VectorIndexS,
8882                                      asm, ".2d", ".2d", ".2s", ".s",
8883    [(set (v2i64 V128:$dst),
8884        (Accum (v2i64 V128:$Rd),
8885               (v2i64 (int_aarch64_neon_sqdmull
8886                          (v2i32 V64:$Rn),
8887                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8888                                                 VectorIndexS:$idx))))))]> {
8889    bits<2> idx;
8890    let Inst{11} = idx{1};
8891    let Inst{21} = idx{0};
8892  }
8893
8894  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8895                                      V128, V128,
8896                                      V128, VectorIndexS,
8897                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8898    [(set (v2i64 V128:$dst),
8899          (Accum (v2i64 V128:$Rd),
8900                 (v2i64 (int_aarch64_neon_sqdmull
8901                            (extract_high_v4i32 (v4i32 V128:$Rn)),
8902                            (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
8903    bits<2> idx;
8904    let Inst{11} = idx{1};
8905    let Inst{21} = idx{0};
8906  }
8907
8908  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8909                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8910                                      asm, ".h", "", "", ".h", []> {
8911    bits<3> idx;
8912    let Inst{11} = idx{2};
8913    let Inst{21} = idx{1};
8914    let Inst{20} = idx{0};
8915  }
8916
8917
8918  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8919                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8920                                      asm, ".s", "", "", ".s",
8921    [(set (i64 FPR64Op:$dst),
8922          (Accum (i64 FPR64Op:$Rd),
8923                 (i64 (int_aarch64_neon_sqdmulls_scalar
8924                            (i32 FPR32Op:$Rn),
8925                            (i32 (vector_extract (v4i32 V128:$Rm),
8926                                                 VectorIndexS:$idx))))))]> {
8927
8928    bits<2> idx;
8929    let Inst{11} = idx{1};
8930    let Inst{21} = idx{0};
8931  }
8932}
8933
8934multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8935                                   SDPatternOperator OpNode> {
8936  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8937  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8938                                      V128, V64,
8939                                      V128_lo, VectorIndexH,
8940                                      asm, ".4s", ".4s", ".4h", ".h",
8941    [(set (v4i32 V128:$Rd),
8942        (OpNode (v4i16 V64:$Rn),
8943         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8944    bits<3> idx;
8945    let Inst{11} = idx{2};
8946    let Inst{21} = idx{1};
8947    let Inst{20} = idx{0};
8948  }
8949
8950  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8951                                      V128, V128,
8952                                      V128_lo, VectorIndexH,
8953                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8954    [(set (v4i32 V128:$Rd),
8955          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
8956                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8957
8958    bits<3> idx;
8959    let Inst{11} = idx{2};
8960    let Inst{21} = idx{1};
8961    let Inst{20} = idx{0};
8962  }
8963
8964  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8965                                      V128, V64,
8966                                      V128, VectorIndexS,
8967                                      asm, ".2d", ".2d", ".2s", ".s",
8968    [(set (v2i64 V128:$Rd),
8969        (OpNode (v2i32 V64:$Rn),
8970         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8971    bits<2> idx;
8972    let Inst{11} = idx{1};
8973    let Inst{21} = idx{0};
8974  }
8975
8976  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8977                                      V128, V128,
8978                                      V128, VectorIndexS,
8979                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8980    [(set (v2i64 V128:$Rd),
8981          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
8982                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8983    bits<2> idx;
8984    let Inst{11} = idx{1};
8985    let Inst{21} = idx{0};
8986  }
8987  }
8988}
8989
8990multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8991                                       SDPatternOperator OpNode> {
8992  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8993  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8994                                      V128, V64,
8995                                      V128_lo, VectorIndexH,
8996                                      asm, ".4s", ".4s", ".4h", ".h",
8997    [(set (v4i32 V128:$dst),
8998        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8999         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9000    bits<3> idx;
9001    let Inst{11} = idx{2};
9002    let Inst{21} = idx{1};
9003    let Inst{20} = idx{0};
9004  }
9005
9006  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9007                                      V128, V128,
9008                                      V128_lo, VectorIndexH,
9009                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9010    [(set (v4i32 V128:$dst),
9011          (OpNode (v4i32 V128:$Rd),
9012                  (extract_high_v8i16 (v8i16 V128:$Rn)),
9013                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9014    bits<3> idx;
9015    let Inst{11} = idx{2};
9016    let Inst{21} = idx{1};
9017    let Inst{20} = idx{0};
9018  }
9019
9020  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9021                                      V128, V64,
9022                                      V128, VectorIndexS,
9023                                      asm, ".2d", ".2d", ".2s", ".s",
9024    [(set (v2i64 V128:$dst),
9025        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
9026         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9027    bits<2> idx;
9028    let Inst{11} = idx{1};
9029    let Inst{21} = idx{0};
9030  }
9031
9032  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9033                                      V128, V128,
9034                                      V128, VectorIndexS,
9035                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9036    [(set (v2i64 V128:$dst),
9037          (OpNode (v2i64 V128:$Rd),
9038                  (extract_high_v4i32 (v4i32 V128:$Rn)),
9039                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9040    bits<2> idx;
9041    let Inst{11} = idx{1};
9042    let Inst{21} = idx{0};
9043  }
9044  }
9045}
9046
9047//----------------------------------------------------------------------------
9048// AdvSIMD scalar shift by immediate
9049//----------------------------------------------------------------------------
9050
9051let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9052class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
9053                     RegisterClass regtype1, RegisterClass regtype2,
9054                     Operand immtype, string asm, list<dag> pattern>
9055  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
9056      asm, "\t$Rd, $Rn, $imm", "", pattern>,
9057    Sched<[WriteVd]> {
9058  bits<5> Rd;
9059  bits<5> Rn;
9060  bits<7> imm;
9061  let Inst{31-30} = 0b01;
9062  let Inst{29}    = U;
9063  let Inst{28-23} = 0b111110;
9064  let Inst{22-16} = fixed_imm;
9065  let Inst{15-11} = opc;
9066  let Inst{10}    = 1;
9067  let Inst{9-5} = Rn;
9068  let Inst{4-0} = Rd;
9069}
9070
9071let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9072class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
9073                     RegisterClass regtype1, RegisterClass regtype2,
9074                     Operand immtype, string asm, list<dag> pattern>
9075  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
9076      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
9077    Sched<[WriteVd]> {
9078  bits<5> Rd;
9079  bits<5> Rn;
9080  bits<7> imm;
9081  let Inst{31-30} = 0b01;
9082  let Inst{29}    = U;
9083  let Inst{28-23} = 0b111110;
9084  let Inst{22-16} = fixed_imm;
9085  let Inst{15-11} = opc;
9086  let Inst{10}    = 1;
9087  let Inst{9-5} = Rn;
9088  let Inst{4-0} = Rd;
9089}
9090
9091
9092multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
9093  let Predicates = [HasNEON, HasFullFP16] in {
9094  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9095                              FPR16, FPR16, vecshiftR16, asm, []> {
9096    let Inst{19-16} = imm{3-0};
9097  }
9098  } // Predicates = [HasNEON, HasFullFP16]
9099  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9100                              FPR32, FPR32, vecshiftR32, asm, []> {
9101    let Inst{20-16} = imm{4-0};
9102  }
9103  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9104                              FPR64, FPR64, vecshiftR64, asm, []> {
9105    let Inst{21-16} = imm{5-0};
9106  }
9107}
9108
9109multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
9110                             SDPatternOperator OpNode> {
9111  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9112                              FPR64, FPR64, vecshiftR64, asm,
9113  [(set (i64 FPR64:$Rd),
9114     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
9115    let Inst{21-16} = imm{5-0};
9116  }
9117
9118  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
9119            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
9120}
9121
9122multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
9123                                 SDPatternOperator OpNode = null_frag> {
9124  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9125                              FPR64, FPR64, vecshiftR64, asm,
9126  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
9127                                                   (i32 vecshiftR64:$imm)))]> {
9128    let Inst{21-16} = imm{5-0};
9129  }
9130
9131  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
9132                           (i32 vecshiftR64:$imm))),
9133            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
9134                                            vecshiftR64:$imm)>;
9135}
9136
9137multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
9138                             SDPatternOperator OpNode> {
9139  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9140                              FPR64, FPR64, vecshiftL64, asm,
9141    [(set (i64 FPR64:$Rd),
9142       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9143    let Inst{21-16} = imm{5-0};
9144  }
9145
9146  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9147            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9148}
9149
9150let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9151multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
9152  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9153                              FPR64, FPR64, vecshiftL64, asm, []> {
9154    let Inst{21-16} = imm{5-0};
9155  }
9156}
9157
9158let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9159multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
9160                               SDPatternOperator OpNode = null_frag> {
9161  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9162                              FPR8, FPR16, vecshiftR8, asm, []> {
9163    let Inst{18-16} = imm{2-0};
9164  }
9165
9166  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9167                              FPR16, FPR32, vecshiftR16, asm, []> {
9168    let Inst{19-16} = imm{3-0};
9169  }
9170
9171  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9172                              FPR32, FPR64, vecshiftR32, asm,
9173    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9174    let Inst{20-16} = imm{4-0};
9175  }
9176}
9177
9178multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9179                                SDPatternOperator OpNode> {
9180  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9181                              FPR8, FPR8, vecshiftL8, asm, []> {
9182    let Inst{18-16} = imm{2-0};
9183  }
9184
9185  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9186                              FPR16, FPR16, vecshiftL16, asm, []> {
9187    let Inst{19-16} = imm{3-0};
9188  }
9189
9190  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9191                              FPR32, FPR32, vecshiftL32, asm,
9192    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9193    let Inst{20-16} = imm{4-0};
9194  }
9195
9196  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9197                              FPR64, FPR64, vecshiftL64, asm,
9198    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9199    let Inst{21-16} = imm{5-0};
9200  }
9201
9202  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9203            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9204}
9205
9206multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9207  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9208                              FPR8, FPR8, vecshiftR8, asm, []> {
9209    let Inst{18-16} = imm{2-0};
9210  }
9211
9212  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9213                              FPR16, FPR16, vecshiftR16, asm, []> {
9214    let Inst{19-16} = imm{3-0};
9215  }
9216
9217  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9218                              FPR32, FPR32, vecshiftR32, asm, []> {
9219    let Inst{20-16} = imm{4-0};
9220  }
9221
9222  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9223                              FPR64, FPR64, vecshiftR64, asm, []> {
9224    let Inst{21-16} = imm{5-0};
9225  }
9226}
9227
9228//----------------------------------------------------------------------------
9229// AdvSIMD vector x indexed element
9230//----------------------------------------------------------------------------
9231
9232let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9233class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9234                     RegisterOperand dst_reg, RegisterOperand src_reg,
9235                     Operand immtype,
9236                     string asm, string dst_kind, string src_kind,
9237                     list<dag> pattern>
9238  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9239      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9240           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9241    Sched<[!if(Q, WriteVq, WriteVd)]> {
9242  bits<5> Rd;
9243  bits<5> Rn;
9244  let Inst{31}    = 0;
9245  let Inst{30}    = Q;
9246  let Inst{29}    = U;
9247  let Inst{28-23} = 0b011110;
9248  let Inst{22-16} = fixed_imm;
9249  let Inst{15-11} = opc;
9250  let Inst{10}    = 1;
9251  let Inst{9-5}   = Rn;
9252  let Inst{4-0}   = Rd;
9253}
9254
9255let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9256class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9257                     RegisterOperand vectype1, RegisterOperand vectype2,
9258                     Operand immtype,
9259                     string asm, string dst_kind, string src_kind,
9260                     list<dag> pattern>
9261  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9262      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9263           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9264    Sched<[!if(Q, WriteVq, WriteVd)]> {
9265  bits<5> Rd;
9266  bits<5> Rn;
9267  let Inst{31}    = 0;
9268  let Inst{30}    = Q;
9269  let Inst{29}    = U;
9270  let Inst{28-23} = 0b011110;
9271  let Inst{22-16} = fixed_imm;
9272  let Inst{15-11} = opc;
9273  let Inst{10}    = 1;
9274  let Inst{9-5}   = Rn;
9275  let Inst{4-0}   = Rd;
9276}
9277
9278multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9279                              Intrinsic OpNode> {
9280  let Predicates = [HasNEON, HasFullFP16] in {
9281  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9282                                  V64, V64, vecshiftR16,
9283                                  asm, ".4h", ".4h",
9284      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9285    bits<4> imm;
9286    let Inst{19-16} = imm;
9287  }
9288
9289  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9290                                  V128, V128, vecshiftR16,
9291                                  asm, ".8h", ".8h",
9292      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9293    bits<4> imm;
9294    let Inst{19-16} = imm;
9295  }
9296  } // Predicates = [HasNEON, HasFullFP16]
9297  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9298                                  V64, V64, vecshiftR32,
9299                                  asm, ".2s", ".2s",
9300      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9301    bits<5> imm;
9302    let Inst{20-16} = imm;
9303  }
9304
9305  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9306                                  V128, V128, vecshiftR32,
9307                                  asm, ".4s", ".4s",
9308      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9309    bits<5> imm;
9310    let Inst{20-16} = imm;
9311  }
9312
9313  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9314                                  V128, V128, vecshiftR64,
9315                                  asm, ".2d", ".2d",
9316      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9317    bits<6> imm;
9318    let Inst{21-16} = imm;
9319  }
9320}
9321
9322multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9323                                  Intrinsic OpNode> {
9324  let Predicates = [HasNEON, HasFullFP16] in {
9325  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9326                                  V64, V64, vecshiftR16,
9327                                  asm, ".4h", ".4h",
9328      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9329    bits<4> imm;
9330    let Inst{19-16} = imm;
9331  }
9332
9333  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9334                                  V128, V128, vecshiftR16,
9335                                  asm, ".8h", ".8h",
9336      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9337    bits<4> imm;
9338    let Inst{19-16} = imm;
9339  }
9340  } // Predicates = [HasNEON, HasFullFP16]
9341
9342  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9343                                  V64, V64, vecshiftR32,
9344                                  asm, ".2s", ".2s",
9345      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9346    bits<5> imm;
9347    let Inst{20-16} = imm;
9348  }
9349
9350  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9351                                  V128, V128, vecshiftR32,
9352                                  asm, ".4s", ".4s",
9353      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9354    bits<5> imm;
9355    let Inst{20-16} = imm;
9356  }
9357
9358  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9359                                  V128, V128, vecshiftR64,
9360                                  asm, ".2d", ".2d",
9361      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9362    bits<6> imm;
9363    let Inst{21-16} = imm;
9364  }
9365}
9366
9367multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9368                                     SDPatternOperator OpNode> {
9369  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9370                                  V64, V128, vecshiftR16Narrow,
9371                                  asm, ".8b", ".8h",
9372      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9373    bits<3> imm;
9374    let Inst{18-16} = imm;
9375  }
9376
9377  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9378                                  V128, V128, vecshiftR16Narrow,
9379                                  asm#"2", ".16b", ".8h", []> {
9380    bits<3> imm;
9381    let Inst{18-16} = imm;
9382    let hasSideEffects = 0;
9383  }
9384
9385  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9386                                  V64, V128, vecshiftR32Narrow,
9387                                  asm, ".4h", ".4s",
9388      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9389    bits<4> imm;
9390    let Inst{19-16} = imm;
9391  }
9392
9393  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9394                                  V128, V128, vecshiftR32Narrow,
9395                                  asm#"2", ".8h", ".4s", []> {
9396    bits<4> imm;
9397    let Inst{19-16} = imm;
9398    let hasSideEffects = 0;
9399  }
9400
9401  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9402                                  V64, V128, vecshiftR64Narrow,
9403                                  asm, ".2s", ".2d",
9404      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9405    bits<5> imm;
9406    let Inst{20-16} = imm;
9407  }
9408
9409  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9410                                  V128, V128, vecshiftR64Narrow,
9411                                  asm#"2", ".4s", ".2d", []> {
9412    bits<5> imm;
9413    let Inst{20-16} = imm;
9414    let hasSideEffects = 0;
9415  }
9416
9417  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9418  // themselves, so put them here instead.
9419
9420  // Patterns involving what's effectively an insert high and a normal
9421  // intrinsic, represented by CONCAT_VECTORS.
9422  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9423                                                   vecshiftR16Narrow:$imm)),
9424            (!cast<Instruction>(NAME # "v16i8_shift")
9425                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9426                V128:$Rn, vecshiftR16Narrow:$imm)>;
9427  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9428                                                     vecshiftR32Narrow:$imm)),
9429            (!cast<Instruction>(NAME # "v8i16_shift")
9430                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9431                V128:$Rn, vecshiftR32Narrow:$imm)>;
9432  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9433                                                     vecshiftR64Narrow:$imm)),
9434            (!cast<Instruction>(NAME # "v4i32_shift")
9435                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9436                V128:$Rn, vecshiftR64Narrow:$imm)>;
9437}
9438
9439multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9440                                SDPatternOperator OpNode> {
9441  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9442                                  V64, V64, vecshiftL8,
9443                                  asm, ".8b", ".8b",
9444                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9445                       (i32 vecshiftL8:$imm)))]> {
9446    bits<3> imm;
9447    let Inst{18-16} = imm;
9448  }
9449
9450  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9451                                  V128, V128, vecshiftL8,
9452                                  asm, ".16b", ".16b",
9453             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9454                   (i32 vecshiftL8:$imm)))]> {
9455    bits<3> imm;
9456    let Inst{18-16} = imm;
9457  }
9458
9459  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9460                                  V64, V64, vecshiftL16,
9461                                  asm, ".4h", ".4h",
9462              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9463                    (i32 vecshiftL16:$imm)))]> {
9464    bits<4> imm;
9465    let Inst{19-16} = imm;
9466  }
9467
9468  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9469                                  V128, V128, vecshiftL16,
9470                                  asm, ".8h", ".8h",
9471            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9472                  (i32 vecshiftL16:$imm)))]> {
9473    bits<4> imm;
9474    let Inst{19-16} = imm;
9475  }
9476
9477  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9478                                  V64, V64, vecshiftL32,
9479                                  asm, ".2s", ".2s",
9480              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9481                    (i32 vecshiftL32:$imm)))]> {
9482    bits<5> imm;
9483    let Inst{20-16} = imm;
9484  }
9485
9486  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9487                                  V128, V128, vecshiftL32,
9488                                  asm, ".4s", ".4s",
9489            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9490                  (i32 vecshiftL32:$imm)))]> {
9491    bits<5> imm;
9492    let Inst{20-16} = imm;
9493  }
9494
9495  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9496                                  V128, V128, vecshiftL64,
9497                                  asm, ".2d", ".2d",
9498            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9499                  (i32 vecshiftL64:$imm)))]> {
9500    bits<6> imm;
9501    let Inst{21-16} = imm;
9502  }
9503}
9504
9505multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9506                                SDPatternOperator OpNode> {
9507  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9508                                  V64, V64, vecshiftR8,
9509                                  asm, ".8b", ".8b",
9510                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9511                       (i32 vecshiftR8:$imm)))]> {
9512    bits<3> imm;
9513    let Inst{18-16} = imm;
9514  }
9515
9516  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9517                                  V128, V128, vecshiftR8,
9518                                  asm, ".16b", ".16b",
9519             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9520                   (i32 vecshiftR8:$imm)))]> {
9521    bits<3> imm;
9522    let Inst{18-16} = imm;
9523  }
9524
9525  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9526                                  V64, V64, vecshiftR16,
9527                                  asm, ".4h", ".4h",
9528              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9529                    (i32 vecshiftR16:$imm)))]> {
9530    bits<4> imm;
9531    let Inst{19-16} = imm;
9532  }
9533
9534  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9535                                  V128, V128, vecshiftR16,
9536                                  asm, ".8h", ".8h",
9537            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9538                  (i32 vecshiftR16:$imm)))]> {
9539    bits<4> imm;
9540    let Inst{19-16} = imm;
9541  }
9542
9543  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9544                                  V64, V64, vecshiftR32,
9545                                  asm, ".2s", ".2s",
9546              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9547                    (i32 vecshiftR32:$imm)))]> {
9548    bits<5> imm;
9549    let Inst{20-16} = imm;
9550  }
9551
9552  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9553                                  V128, V128, vecshiftR32,
9554                                  asm, ".4s", ".4s",
9555            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9556                  (i32 vecshiftR32:$imm)))]> {
9557    bits<5> imm;
9558    let Inst{20-16} = imm;
9559  }
9560
9561  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9562                                  V128, V128, vecshiftR64,
9563                                  asm, ".2d", ".2d",
9564            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9565                  (i32 vecshiftR64:$imm)))]> {
9566    bits<6> imm;
9567    let Inst{21-16} = imm;
9568  }
9569}
9570
9571let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9572multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9573                                    SDPatternOperator OpNode = null_frag> {
9574  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9575                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9576                 [(set (v8i8 V64:$dst),
9577                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9578                           (i32 vecshiftR8:$imm)))]> {
9579    bits<3> imm;
9580    let Inst{18-16} = imm;
9581  }
9582
9583  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9584                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9585             [(set (v16i8 V128:$dst),
9586               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9587                       (i32 vecshiftR8:$imm)))]> {
9588    bits<3> imm;
9589    let Inst{18-16} = imm;
9590  }
9591
9592  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9593                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9594              [(set (v4i16 V64:$dst),
9595                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9596                        (i32 vecshiftR16:$imm)))]> {
9597    bits<4> imm;
9598    let Inst{19-16} = imm;
9599  }
9600
9601  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9602                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9603            [(set (v8i16 V128:$dst),
9604              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9605                      (i32 vecshiftR16:$imm)))]> {
9606    bits<4> imm;
9607    let Inst{19-16} = imm;
9608  }
9609
9610  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9611                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9612              [(set (v2i32 V64:$dst),
9613                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9614                        (i32 vecshiftR32:$imm)))]> {
9615    bits<5> imm;
9616    let Inst{20-16} = imm;
9617  }
9618
9619  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9620                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9621            [(set (v4i32 V128:$dst),
9622              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9623                      (i32 vecshiftR32:$imm)))]> {
9624    bits<5> imm;
9625    let Inst{20-16} = imm;
9626  }
9627
9628  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9629                                  V128, V128, vecshiftR64,
9630                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9631              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9632                      (i32 vecshiftR64:$imm)))]> {
9633    bits<6> imm;
9634    let Inst{21-16} = imm;
9635  }
9636}
9637
9638multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9639                                    SDPatternOperator OpNode = null_frag> {
9640  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9641                                  V64, V64, vecshiftL8,
9642                                  asm, ".8b", ".8b",
9643                    [(set (v8i8 V64:$dst),
9644                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9645                                  (i32 vecshiftL8:$imm)))]> {
9646    bits<3> imm;
9647    let Inst{18-16} = imm;
9648  }
9649
9650  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9651                                  V128, V128, vecshiftL8,
9652                                  asm, ".16b", ".16b",
9653                    [(set (v16i8 V128:$dst),
9654                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9655                                  (i32 vecshiftL8:$imm)))]> {
9656    bits<3> imm;
9657    let Inst{18-16} = imm;
9658  }
9659
9660  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9661                                  V64, V64, vecshiftL16,
9662                                  asm, ".4h", ".4h",
9663                    [(set (v4i16 V64:$dst),
9664                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9665                                   (i32 vecshiftL16:$imm)))]> {
9666    bits<4> imm;
9667    let Inst{19-16} = imm;
9668  }
9669
9670  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9671                                  V128, V128, vecshiftL16,
9672                                  asm, ".8h", ".8h",
9673                    [(set (v8i16 V128:$dst),
9674                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9675                                  (i32 vecshiftL16:$imm)))]> {
9676    bits<4> imm;
9677    let Inst{19-16} = imm;
9678  }
9679
9680  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9681                                  V64, V64, vecshiftL32,
9682                                  asm, ".2s", ".2s",
9683                    [(set (v2i32 V64:$dst),
9684                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9685                                  (i32 vecshiftL32:$imm)))]> {
9686    bits<5> imm;
9687    let Inst{20-16} = imm;
9688  }
9689
9690  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9691                                  V128, V128, vecshiftL32,
9692                                  asm, ".4s", ".4s",
9693                    [(set (v4i32 V128:$dst),
9694                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9695                                  (i32 vecshiftL32:$imm)))]> {
9696    bits<5> imm;
9697    let Inst{20-16} = imm;
9698  }
9699
9700  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9701                                  V128, V128, vecshiftL64,
9702                                  asm, ".2d", ".2d",
9703                    [(set (v2i64 V128:$dst),
9704                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9705                                  (i32 vecshiftL64:$imm)))]> {
9706    bits<6> imm;
9707    let Inst{21-16} = imm;
9708  }
9709}
9710
9711multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9712                                   SDPatternOperator OpNode> {
9713  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9714                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9715      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9716    bits<3> imm;
9717    let Inst{18-16} = imm;
9718  }
9719
9720  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9721                                  V128, V128, vecshiftL8,
9722                                  asm#"2", ".8h", ".16b",
9723      [(set (v8i16 V128:$Rd),
9724            (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)), vecshiftL8:$imm))]> {
9725    bits<3> imm;
9726    let Inst{18-16} = imm;
9727  }
9728
9729  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9730                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9731      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9732    bits<4> imm;
9733    let Inst{19-16} = imm;
9734  }
9735
9736  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9737                                  V128, V128, vecshiftL16,
9738                                  asm#"2", ".4s", ".8h",
9739      [(set (v4i32 V128:$Rd),
9740            (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)), vecshiftL16:$imm))]> {
9741
9742    bits<4> imm;
9743    let Inst{19-16} = imm;
9744  }
9745
9746  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9747                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9748      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9749    bits<5> imm;
9750    let Inst{20-16} = imm;
9751  }
9752
9753  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9754                                  V128, V128, vecshiftL32,
9755                                  asm#"2", ".2d", ".4s",
9756      [(set (v2i64 V128:$Rd),
9757            (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)), vecshiftL32:$imm))]> {
9758    bits<5> imm;
9759    let Inst{20-16} = imm;
9760  }
9761}
9762
9763
9764//---
9765// Vector load/store
9766//---
9767// SIMD ldX/stX no-index memory references don't allow the optional
9768// ", #0" constant and handle post-indexing explicitly, so we use
9769// a more specialized parse method for them. Otherwise, it's the same as
9770// the general GPR64sp handling.
9771
9772class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9773                   string asm, dag oops, dag iops, list<dag> pattern>
9774  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9775  bits<5> Vt;
9776  bits<5> Rn;
9777  let Inst{31} = 0;
9778  let Inst{30} = Q;
9779  let Inst{29-23} = 0b0011000;
9780  let Inst{22} = L;
9781  let Inst{21-16} = 0b000000;
9782  let Inst{15-12} = opcode;
9783  let Inst{11-10} = size;
9784  let Inst{9-5} = Rn;
9785  let Inst{4-0} = Vt;
9786}
9787
9788class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9789                       string asm, dag oops, dag iops>
9790  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9791  bits<5> Vt;
9792  bits<5> Rn;
9793  bits<5> Xm;
9794  let Inst{31} = 0;
9795  let Inst{30} = Q;
9796  let Inst{29-23} = 0b0011001;
9797  let Inst{22} = L;
9798  let Inst{21} = 0;
9799  let Inst{20-16} = Xm;
9800  let Inst{15-12} = opcode;
9801  let Inst{11-10} = size;
9802  let Inst{9-5} = Rn;
9803  let Inst{4-0} = Vt;
9804}
9805
9806// The immediate form of AdvSIMD post-indexed addressing is encoded with
9807// register post-index addressing from the zero register.
9808multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9809                           int Offset, int Size> {
9810  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9811  //      "ld1\t$Vt, [$Rn], #16"
9812  // may get mapped to
9813  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9814  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9815                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9816                      GPR64sp:$Rn,
9817                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9818                      XZR), 1>;
9819
9820  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9821  //      "ld1.8b\t$Vt, [$Rn], #16"
9822  // may get mapped to
9823  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9824  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9825                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9826                      GPR64sp:$Rn,
9827                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9828                      XZR), 0>;
9829
9830  // E.g. "ld1.8b { v0, v1 }, [x1]"
9831  //      "ld1\t$Vt, [$Rn]"
9832  // may get mapped to
9833  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9834  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9835                  (!cast<Instruction>(BaseName # Count # "v" # layout)
9836                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9837                      GPR64sp:$Rn), 0>;
9838
9839  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9840  //      "ld1\t$Vt, [$Rn], $Xm"
9841  // may get mapped to
9842  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9843  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9844                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9845                      GPR64sp:$Rn,
9846                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9847                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9848}
9849
9850multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9851                       int Offset128, int Offset64, bits<4> opcode> {
9852  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9853    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9854                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9855                           (ins GPR64sp:$Rn), []>;
9856    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9857                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9858                           (ins GPR64sp:$Rn), []>;
9859    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9860                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9861                           (ins GPR64sp:$Rn), []>;
9862    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9863                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9864                           (ins GPR64sp:$Rn), []>;
9865    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9866                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9867                           (ins GPR64sp:$Rn), []>;
9868    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9869                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9870                           (ins GPR64sp:$Rn), []>;
9871    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9872                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9873                           (ins GPR64sp:$Rn), []>;
9874
9875
9876    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9877                       (outs GPR64sp:$wback,
9878                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
9879                       (ins GPR64sp:$Rn,
9880                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9881    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9882                       (outs GPR64sp:$wback,
9883                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
9884                       (ins GPR64sp:$Rn,
9885                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9886    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9887                       (outs GPR64sp:$wback,
9888                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
9889                       (ins GPR64sp:$Rn,
9890                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9891    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9892                       (outs GPR64sp:$wback,
9893                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
9894                       (ins GPR64sp:$Rn,
9895                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9896    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9897                       (outs GPR64sp:$wback,
9898                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
9899                       (ins GPR64sp:$Rn,
9900                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9901    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9902                       (outs GPR64sp:$wback,
9903                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
9904                       (ins GPR64sp:$Rn,
9905                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9906    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9907                       (outs GPR64sp:$wback,
9908                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
9909                       (ins GPR64sp:$Rn,
9910                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9911  }
9912
9913  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9914  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9915  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9916  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9917  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9918  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9919  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9920}
9921
9922// Only ld1/st1 has a v1d version.
9923multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9924                       int Offset128, int Offset64, bits<4> opcode> {
9925  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9926    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9927                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9928                                 GPR64sp:$Rn), []>;
9929    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9930                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9931                                GPR64sp:$Rn), []>;
9932    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9933                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9934                                GPR64sp:$Rn), []>;
9935    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9936                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9937                                GPR64sp:$Rn), []>;
9938    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9939                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9940                                GPR64sp:$Rn), []>;
9941    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9942                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9943                                GPR64sp:$Rn), []>;
9944    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9945                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9946                                GPR64sp:$Rn), []>;
9947
9948    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9949                       (outs GPR64sp:$wback),
9950                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9951                            GPR64sp:$Rn,
9952                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9953    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9954                       (outs GPR64sp:$wback),
9955                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9956                            GPR64sp:$Rn,
9957                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9958    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9959                       (outs GPR64sp:$wback),
9960                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9961                            GPR64sp:$Rn,
9962                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9963    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9964                       (outs GPR64sp:$wback),
9965                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9966                            GPR64sp:$Rn,
9967                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9968    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9969                       (outs GPR64sp:$wback),
9970                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9971                            GPR64sp:$Rn,
9972                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9973    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9974                       (outs GPR64sp:$wback),
9975                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9976                            GPR64sp:$Rn,
9977                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9978    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9979                       (outs GPR64sp:$wback),
9980                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9981                            GPR64sp:$Rn,
9982                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9983  }
9984
9985  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9986  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9987  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9988  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9989  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9990  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9991  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9992}
9993
9994multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9995                       int Offset128, int Offset64, bits<4> opcode>
9996  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9997
9998  // LD1 instructions have extra "1d" variants.
9999  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10000    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
10001                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
10002                           (ins GPR64sp:$Rn), []>;
10003
10004    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
10005                       (outs GPR64sp:$wback,
10006                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
10007                       (ins GPR64sp:$Rn,
10008                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10009  }
10010
10011  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10012}
10013
10014multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
10015                       int Offset128, int Offset64, bits<4> opcode>
10016  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10017
10018  // ST1 instructions have extra "1d" variants.
10019  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
10020    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
10021                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10022                                GPR64sp:$Rn), []>;
10023
10024    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
10025                       (outs GPR64sp:$wback),
10026                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10027                            GPR64sp:$Rn,
10028                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10029  }
10030
10031  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10032}
10033
10034multiclass SIMDLd1Multiple<string asm> {
10035  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10036  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10037  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10038  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10039}
10040
10041multiclass SIMDSt1Multiple<string asm> {
10042  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10043  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10044  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10045  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10046}
10047
10048multiclass SIMDLd2Multiple<string asm> {
10049  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10050}
10051
10052multiclass SIMDSt2Multiple<string asm> {
10053  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10054}
10055
10056multiclass SIMDLd3Multiple<string asm> {
10057  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10058}
10059
10060multiclass SIMDSt3Multiple<string asm> {
10061  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10062}
10063
10064multiclass SIMDLd4Multiple<string asm> {
10065  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10066}
10067
10068multiclass SIMDSt4Multiple<string asm> {
10069  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10070}
10071
10072//---
10073// AdvSIMD Load/store single-element
10074//---
10075
10076class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
10077                         string asm, string operands, string cst,
10078                         dag oops, dag iops, list<dag> pattern>
10079  : I<oops, iops, asm, operands, cst, pattern> {
10080  bits<5> Vt;
10081  bits<5> Rn;
10082  let Inst{31} = 0;
10083  let Inst{29-24} = 0b001101;
10084  let Inst{22} = L;
10085  let Inst{21} = R;
10086  let Inst{15-13} = opcode;
10087  let Inst{9-5} = Rn;
10088  let Inst{4-0} = Vt;
10089}
10090
10091class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
10092                         string asm, string operands, string cst,
10093                         dag oops, dag iops, list<dag> pattern>
10094  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
10095  bits<5> Vt;
10096  bits<5> Rn;
10097  let Inst{31} = 0;
10098  let Inst{29-24} = 0b001101;
10099  let Inst{22} = L;
10100  let Inst{21} = R;
10101  let Inst{15-13} = opcode;
10102  let Inst{9-5} = Rn;
10103  let Inst{4-0} = Vt;
10104}
10105
10106
10107let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10108class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
10109                  DAGOperand listtype>
10110  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
10111                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
10112                       []> {
10113  let Inst{30} = Q;
10114  let Inst{23} = 0;
10115  let Inst{20-16} = 0b00000;
10116  let Inst{12} = S;
10117  let Inst{11-10} = size;
10118}
10119let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10120class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
10121                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
10122  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
10123                       "$Rn = $wback",
10124                       (outs GPR64sp:$wback, listtype:$Vt),
10125                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
10126  bits<5> Xm;
10127  let Inst{30} = Q;
10128  let Inst{23} = 1;
10129  let Inst{20-16} = Xm;
10130  let Inst{12} = S;
10131  let Inst{11-10} = size;
10132}
10133
10134multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
10135                          int Offset, int Size> {
10136  // E.g. "ld1r { v0.8b }, [x1], #1"
10137  //      "ld1r.8b\t$Vt, [$Rn], #1"
10138  // may get mapped to
10139  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10140  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10141                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10142                      GPR64sp:$Rn,
10143                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10144                      XZR), 1>;
10145
10146  // E.g. "ld1r.8b { v0 }, [x1], #1"
10147  //      "ld1r.8b\t$Vt, [$Rn], #1"
10148  // may get mapped to
10149  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10150  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10151                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10152                      GPR64sp:$Rn,
10153                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10154                      XZR), 0>;
10155
10156  // E.g. "ld1r.8b { v0 }, [x1]"
10157  //      "ld1r.8b\t$Vt, [$Rn]"
10158  // may get mapped to
10159  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10160  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10161                  (!cast<Instruction>(BaseName # "v" # layout)
10162                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10163                      GPR64sp:$Rn), 0>;
10164
10165  // E.g. "ld1r.8b { v0 }, [x1], x2"
10166  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10167  // may get mapped to
10168  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10169  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10170                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10171                      GPR64sp:$Rn,
10172                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10173                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10174}
10175
10176multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10177  int Offset1, int Offset2, int Offset4, int Offset8> {
10178  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10179                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10180  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10181                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10182  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10183                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10184  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10185                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10186  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10187                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10188  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10189                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10190  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10191                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10192  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10193                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10194
10195  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10196                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10197                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10198  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10199                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10200                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10201  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10202                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10203                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10204  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10205                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10206                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10207  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10208                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10209                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10210  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10211                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10212                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10213  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10214                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10215                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10216  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10217                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10218                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10219
10220  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10221  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10222  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10223  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10224  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10225  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10226  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10227  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10228}
10229
10230class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10231                      dag oops, dag iops, list<dag> pattern>
10232  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10233                       pattern> {
10234  // idx encoded in Q:S:size fields.
10235  bits<4> idx;
10236  let Inst{30} = idx{3};
10237  let Inst{23} = 0;
10238  let Inst{20-16} = 0b00000;
10239  let Inst{12} = idx{2};
10240  let Inst{11-10} = idx{1-0};
10241}
10242class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10243                      dag oops, dag iops, list<dag> pattern>
10244  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10245                           oops, iops, pattern> {
10246  // idx encoded in Q:S:size fields.
10247  bits<4> idx;
10248  let Inst{30} = idx{3};
10249  let Inst{23} = 0;
10250  let Inst{20-16} = 0b00000;
10251  let Inst{12} = idx{2};
10252  let Inst{11-10} = idx{1-0};
10253}
10254class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10255                          dag oops, dag iops>
10256  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10257                       "$Rn = $wback", oops, iops, []> {
10258  // idx encoded in Q:S:size fields.
10259  bits<4> idx;
10260  bits<5> Xm;
10261  let Inst{30} = idx{3};
10262  let Inst{23} = 1;
10263  let Inst{20-16} = Xm;
10264  let Inst{12} = idx{2};
10265  let Inst{11-10} = idx{1-0};
10266}
10267class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10268                          dag oops, dag iops>
10269  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10270                           "$Rn = $wback", oops, iops, []> {
10271  // idx encoded in Q:S:size fields.
10272  bits<4> idx;
10273  bits<5> Xm;
10274  let Inst{30} = idx{3};
10275  let Inst{23} = 1;
10276  let Inst{20-16} = Xm;
10277  let Inst{12} = idx{2};
10278  let Inst{11-10} = idx{1-0};
10279}
10280
10281class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10282                      dag oops, dag iops, list<dag> pattern>
10283  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10284                       pattern> {
10285  // idx encoded in Q:S:size<1> fields.
10286  bits<3> idx;
10287  let Inst{30} = idx{2};
10288  let Inst{23} = 0;
10289  let Inst{20-16} = 0b00000;
10290  let Inst{12} = idx{1};
10291  let Inst{11} = idx{0};
10292  let Inst{10} = size;
10293}
10294class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10295                      dag oops, dag iops, list<dag> pattern>
10296  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10297                           oops, iops, pattern> {
10298  // idx encoded in Q:S:size<1> fields.
10299  bits<3> idx;
10300  let Inst{30} = idx{2};
10301  let Inst{23} = 0;
10302  let Inst{20-16} = 0b00000;
10303  let Inst{12} = idx{1};
10304  let Inst{11} = idx{0};
10305  let Inst{10} = size;
10306}
10307
10308class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10309                          dag oops, dag iops>
10310  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10311                       "$Rn = $wback", oops, iops, []> {
10312  // idx encoded in Q:S:size<1> fields.
10313  bits<3> idx;
10314  bits<5> Xm;
10315  let Inst{30} = idx{2};
10316  let Inst{23} = 1;
10317  let Inst{20-16} = Xm;
10318  let Inst{12} = idx{1};
10319  let Inst{11} = idx{0};
10320  let Inst{10} = size;
10321}
10322class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10323                          dag oops, dag iops>
10324  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10325                           "$Rn = $wback", oops, iops, []> {
10326  // idx encoded in Q:S:size<1> fields.
10327  bits<3> idx;
10328  bits<5> Xm;
10329  let Inst{30} = idx{2};
10330  let Inst{23} = 1;
10331  let Inst{20-16} = Xm;
10332  let Inst{12} = idx{1};
10333  let Inst{11} = idx{0};
10334  let Inst{10} = size;
10335}
10336class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10337                      dag oops, dag iops, list<dag> pattern>
10338  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10339                       pattern> {
10340  // idx encoded in Q:S fields.
10341  bits<2> idx;
10342  let Inst{30} = idx{1};
10343  let Inst{23} = 0;
10344  let Inst{20-16} = 0b00000;
10345  let Inst{12} = idx{0};
10346  let Inst{11-10} = size;
10347}
10348class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10349                      dag oops, dag iops, list<dag> pattern>
10350  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10351                           oops, iops, pattern> {
10352  // idx encoded in Q:S fields.
10353  bits<2> idx;
10354  let Inst{30} = idx{1};
10355  let Inst{23} = 0;
10356  let Inst{20-16} = 0b00000;
10357  let Inst{12} = idx{0};
10358  let Inst{11-10} = size;
10359}
10360class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10361                          string asm, dag oops, dag iops>
10362  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10363                       "$Rn = $wback", oops, iops, []> {
10364  // idx encoded in Q:S fields.
10365  bits<2> idx;
10366  bits<5> Xm;
10367  let Inst{30} = idx{1};
10368  let Inst{23} = 1;
10369  let Inst{20-16} = Xm;
10370  let Inst{12} = idx{0};
10371  let Inst{11-10} = size;
10372}
10373class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10374                          string asm, dag oops, dag iops>
10375  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10376                           "$Rn = $wback", oops, iops, []> {
10377  // idx encoded in Q:S fields.
10378  bits<2> idx;
10379  bits<5> Xm;
10380  let Inst{30} = idx{1};
10381  let Inst{23} = 1;
10382  let Inst{20-16} = Xm;
10383  let Inst{12} = idx{0};
10384  let Inst{11-10} = size;
10385}
10386class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10387                      dag oops, dag iops, list<dag> pattern>
10388  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10389                       pattern> {
10390  // idx encoded in Q field.
10391  bits<1> idx;
10392  let Inst{30} = idx;
10393  let Inst{23} = 0;
10394  let Inst{20-16} = 0b00000;
10395  let Inst{12} = 0;
10396  let Inst{11-10} = size;
10397}
10398class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10399                      dag oops, dag iops, list<dag> pattern>
10400  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10401                           oops, iops, pattern> {
10402  // idx encoded in Q field.
10403  bits<1> idx;
10404  let Inst{30} = idx;
10405  let Inst{23} = 0;
10406  let Inst{20-16} = 0b00000;
10407  let Inst{12} = 0;
10408  let Inst{11-10} = size;
10409}
10410class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10411                          string asm, dag oops, dag iops>
10412  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10413                       "$Rn = $wback", oops, iops, []> {
10414  // idx encoded in Q field.
10415  bits<1> idx;
10416  bits<5> Xm;
10417  let Inst{30} = idx;
10418  let Inst{23} = 1;
10419  let Inst{20-16} = Xm;
10420  let Inst{12} = 0;
10421  let Inst{11-10} = size;
10422}
10423class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10424                          string asm, dag oops, dag iops>
10425  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10426                           "$Rn = $wback", oops, iops, []> {
10427  // idx encoded in Q field.
10428  bits<1> idx;
10429  bits<5> Xm;
10430  let Inst{30} = idx;
10431  let Inst{23} = 1;
10432  let Inst{20-16} = Xm;
10433  let Inst{12} = 0;
10434  let Inst{11-10} = size;
10435}
10436
10437let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10438multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10439                         RegisterOperand listtype,
10440                         RegisterOperand GPR64pi> {
10441  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10442                           (outs listtype:$dst),
10443                           (ins listtype:$Vt, VectorIndexB:$idx,
10444                                GPR64sp:$Rn), []>;
10445
10446  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10447                            (outs GPR64sp:$wback, listtype:$dst),
10448                            (ins listtype:$Vt, VectorIndexB:$idx,
10449                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10450}
10451let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10452multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10453                         RegisterOperand listtype,
10454                         RegisterOperand GPR64pi> {
10455  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10456                            (outs listtype:$dst),
10457                            (ins listtype:$Vt, VectorIndexH:$idx,
10458                                 GPR64sp:$Rn), []>;
10459
10460  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10461                            (outs GPR64sp:$wback, listtype:$dst),
10462                            (ins listtype:$Vt, VectorIndexH:$idx,
10463                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10464}
10465let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10466multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10467                         RegisterOperand listtype,
10468                         RegisterOperand GPR64pi> {
10469  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10470                            (outs listtype:$dst),
10471                            (ins listtype:$Vt, VectorIndexS:$idx,
10472                                 GPR64sp:$Rn), []>;
10473
10474  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10475                            (outs GPR64sp:$wback, listtype:$dst),
10476                            (ins listtype:$Vt, VectorIndexS:$idx,
10477                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10478}
10479let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10480multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10481                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10482  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10483                            (outs listtype:$dst),
10484                            (ins listtype:$Vt, VectorIndexD:$idx,
10485                                 GPR64sp:$Rn), []>;
10486
10487  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10488                            (outs GPR64sp:$wback, listtype:$dst),
10489                            (ins listtype:$Vt, VectorIndexD:$idx,
10490                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10491}
10492let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10493multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10494                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10495  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10496                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10497                                        GPR64sp:$Rn), []>;
10498
10499  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10500                                    (outs GPR64sp:$wback),
10501                                    (ins listtype:$Vt, VectorIndexB:$idx,
10502                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10503}
10504let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10505multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10506                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10507  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10508                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10509                                         GPR64sp:$Rn), []>;
10510
10511  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10512                            (outs GPR64sp:$wback),
10513                            (ins listtype:$Vt, VectorIndexH:$idx,
10514                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10515}
10516let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10517multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10518                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10519  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10520                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10521                                         GPR64sp:$Rn), []>;
10522
10523  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10524                            (outs GPR64sp:$wback),
10525                            (ins listtype:$Vt, VectorIndexS:$idx,
10526                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10527}
10528let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10529multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10530                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10531  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10532                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10533                                         GPR64sp:$Rn), []>;
10534
10535  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10536                            (outs GPR64sp:$wback),
10537                            (ins listtype:$Vt, VectorIndexD:$idx,
10538                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10539}
10540
10541multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10542                                 string Count, int Offset, Operand idxtype> {
10543  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10544  //      "ld1\t$Vt, [$Rn], #1"
10545  // may get mapped to
10546  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10547  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10548                  (!cast<Instruction>(NAME # Type  # "_POST")
10549                      GPR64sp:$Rn,
10550                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10551                      idxtype:$idx, XZR), 1>;
10552
10553  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10554  //      "ld1.8b\t$Vt, [$Rn], #1"
10555  // may get mapped to
10556  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10557  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10558                  (!cast<Instruction>(NAME # Type # "_POST")
10559                      GPR64sp:$Rn,
10560                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10561                      idxtype:$idx, XZR), 0>;
10562
10563  // E.g. "ld1.8b { v0 }[0], [x1]"
10564  //      "ld1.8b\t$Vt, [$Rn]"
10565  // may get mapped to
10566  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10567  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10568                      (!cast<Instruction>(NAME # Type)
10569                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10570                         idxtype:$idx, GPR64sp:$Rn), 0>;
10571
10572  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10573  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10574  // may get mapped to
10575  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10576  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10577                      (!cast<Instruction>(NAME # Type # "_POST")
10578                         GPR64sp:$Rn,
10579                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10580                         idxtype:$idx,
10581                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10582}
10583
10584multiclass SIMDLdSt1SingleAliases<string asm> {
10585  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10586  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10587  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10588  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10589}
10590
10591multiclass SIMDLdSt2SingleAliases<string asm> {
10592  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10593  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10594  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10595  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10596}
10597
10598multiclass SIMDLdSt3SingleAliases<string asm> {
10599  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10600  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10601  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10602  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10603}
10604
10605multiclass SIMDLdSt4SingleAliases<string asm> {
10606  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10607  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10608  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10609  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10610}
10611} // end of 'let Predicates = [HasNEON]'
10612
10613//----------------------------------------------------------------------------
10614// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10615//----------------------------------------------------------------------------
10616
10617let Predicates = [HasNEON, HasRDM] in {
10618
10619class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10620                                    RegisterOperand regtype, string asm,
10621                                    string kind, list<dag> pattern>
10622  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10623                                pattern> {
10624}
10625multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10626                                             SDPatternOperator op> {
10627  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10628    [(set (v4i16 V64:$dst),
10629          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
10630  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10631    [(set (v8i16 V128:$dst),
10632          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
10633  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10634    [(set (v2i32 V64:$dst),
10635          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
10636  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10637    [(set (v4i32 V128:$dst),
10638          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
10639}
10640
10641multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10642                                     SDPatternOperator op> {
10643  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10644                                          V64, V64, V128_lo, VectorIndexH,
10645                                          asm, ".4h", ".4h", ".4h", ".h",
10646    [(set (v4i16 V64:$dst),
10647          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10648                     (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10649                                              VectorIndexH:$idx)))))]> {
10650    bits<3> idx;
10651    let Inst{11} = idx{2};
10652    let Inst{21} = idx{1};
10653    let Inst{20} = idx{0};
10654  }
10655
10656  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10657                                          V128, V128, V128_lo, VectorIndexH,
10658                                          asm, ".8h", ".8h", ".8h", ".h",
10659    [(set (v8i16 V128:$dst),
10660          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10661                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10662                                              VectorIndexH:$idx)))))]> {
10663    bits<3> idx;
10664    let Inst{11} = idx{2};
10665    let Inst{21} = idx{1};
10666    let Inst{20} = idx{0};
10667  }
10668
10669  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10670                                          V64, V64, V128, VectorIndexS,
10671                                          asm, ".2s", ".2s", ".2s", ".s",
10672    [(set (v2i32 V64:$dst),
10673          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10674                     (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10675                                              VectorIndexS:$idx)))))]> {
10676    bits<2> idx;
10677    let Inst{11} = idx{1};
10678    let Inst{21} = idx{0};
10679  }
10680
10681  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10682                                          V128, V128, V128, VectorIndexS,
10683                                          asm, ".4s", ".4s", ".4s", ".s",
10684    [(set (v4i32 V128:$dst),
10685          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10686                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10687                                              VectorIndexS:$idx)))))]> {
10688    bits<2> idx;
10689    let Inst{11} = idx{1};
10690    let Inst{21} = idx{0};
10691  }
10692
10693  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10694                                        FPR16Op, FPR16Op, V128_lo,
10695                                        VectorIndexH, asm, ".h", "", "", ".h",
10696                                        []> {
10697    bits<3> idx;
10698    let Inst{11} = idx{2};
10699    let Inst{21} = idx{1};
10700    let Inst{20} = idx{0};
10701  }
10702
10703  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10704                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10705                                        asm, ".s", "", "", ".s",
10706    [(set (i32 FPR32Op:$dst),
10707          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
10708                   (i32 (vector_extract (v4i32 V128:$Rm),
10709                                        VectorIndexS:$idx)))))]> {
10710    bits<2> idx;
10711    let Inst{11} = idx{1};
10712    let Inst{21} = idx{0};
10713  }
10714}
10715} // let Predicates = [HasNeon, HasRDM]
10716
10717//----------------------------------------------------------------------------
10718// ARMv8.3 Complex ADD/MLA instructions
10719//----------------------------------------------------------------------------
10720
10721class ComplexRotationOperand<int Angle, int Remainder, string Type>
10722  : AsmOperandClass {
10723  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10724  let DiagnosticType = "InvalidComplexRotation" # Type;
10725  let Name = "ComplexRotation" # Type;
10726}
10727def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10728                                                  SDNodeXForm<imm, [{
10729  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10730}]>> {
10731  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10732  let PrintMethod = "printComplexRotationOp<90, 0>";
10733}
10734def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10735                                                  SDNodeXForm<imm, [{
10736  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10737}]>> {
10738  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10739  let PrintMethod = "printComplexRotationOp<180, 90>";
10740}
10741let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
10742class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10743                                     RegisterOperand regtype, Operand rottype,
10744                                     string asm, string kind, list<dag> pattern>
10745  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10746      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10747      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10748    Sched<[!if(Q, WriteVq, WriteVd)]> {
10749  bits<5> Rd;
10750  bits<5> Rn;
10751  bits<5> Rm;
10752  bits<1> rot;
10753  let Inst{31}    = 0;
10754  let Inst{30}    = Q;
10755  let Inst{29}    = U;
10756  let Inst{28-24} = 0b01110;
10757  let Inst{23-22} = size;
10758  let Inst{21}    = 0;
10759  let Inst{20-16} = Rm;
10760  let Inst{15-13} = opcode;
10761  // Non-tied version (FCADD) only has one rotation bit
10762  let Inst{12}    = rot;
10763  let Inst{11}    = 0;
10764  let Inst{10}    = 1;
10765  let Inst{9-5}   = Rn;
10766  let Inst{4-0}   = Rd;
10767}
10768
10769//8.3 CompNum - Floating-point complex number support
10770multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10771                                          string asm, SDPatternOperator OpNode>{
10772  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10773  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10774              asm, ".4h",
10775              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10776                                              (v4f16 V64:$Rn),
10777                                              (v4f16 V64:$Rm),
10778                                              (i32 rottype:$rot)))]>;
10779
10780  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10781              asm, ".8h",
10782              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10783                                               (v8f16 V128:$Rn),
10784                                               (v8f16 V128:$Rm),
10785                                               (i32 rottype:$rot)))]>;
10786  }
10787
10788  let Predicates = [HasComplxNum, HasNEON] in {
10789  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10790              asm, ".2s",
10791              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10792                                              (v2f32 V64:$Rn),
10793                                              (v2f32 V64:$Rm),
10794                                              (i32 rottype:$rot)))]>;
10795
10796  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10797              asm, ".4s",
10798              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10799                                               (v4f32 V128:$Rn),
10800                                               (v4f32 V128:$Rm),
10801                                               (i32 rottype:$rot)))]>;
10802
10803  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10804              asm, ".2d",
10805              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10806                                               (v2f64 V128:$Rn),
10807                                               (v2f64 V128:$Rm),
10808                                               (i32 rottype:$rot)))]>;
10809  }
10810}
10811
10812let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
10813class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10814                                         bits<3> opcode,
10815                                         RegisterOperand regtype,
10816                                         Operand rottype, string asm,
10817                                         string kind, list<dag> pattern>
10818  : I<(outs regtype:$dst),
10819      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10820      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10821      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10822    Sched<[!if(Q, WriteVq, WriteVd)]> {
10823  bits<5> Rd;
10824  bits<5> Rn;
10825  bits<5> Rm;
10826  bits<2> rot;
10827  let Inst{31}    = 0;
10828  let Inst{30}    = Q;
10829  let Inst{29}    = U;
10830  let Inst{28-24} = 0b01110;
10831  let Inst{23-22} = size;
10832  let Inst{21}    = 0;
10833  let Inst{20-16} = Rm;
10834  let Inst{15-13} = opcode;
10835  let Inst{12-11} = rot;
10836  let Inst{10}    = 1;
10837  let Inst{9-5}   = Rn;
10838  let Inst{4-0}   = Rd;
10839}
10840
10841multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10842                                             Operand rottype, string asm,
10843                                             SDPatternOperator OpNode> {
10844  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10845  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10846              rottype, asm, ".4h",
10847              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10848                                              (v4f16 V64:$Rn),
10849                                              (v4f16 V64:$Rm),
10850                                              (i32 rottype:$rot)))]>;
10851
10852  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10853              rottype, asm, ".8h",
10854              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10855                                               (v8f16 V128:$Rn),
10856                                               (v8f16 V128:$Rm),
10857                                               (i32 rottype:$rot)))]>;
10858  }
10859
10860  let Predicates = [HasComplxNum, HasNEON] in {
10861  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10862              rottype, asm, ".2s",
10863              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10864                                              (v2f32 V64:$Rn),
10865                                              (v2f32 V64:$Rm),
10866                                              (i32 rottype:$rot)))]>;
10867
10868  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10869              rottype, asm, ".4s",
10870              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10871                                               (v4f32 V128:$Rn),
10872                                               (v4f32 V128:$Rm),
10873                                               (i32 rottype:$rot)))]>;
10874
10875  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10876              rottype, asm, ".2d",
10877              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10878                                               (v2f64 V128:$Rn),
10879                                               (v2f64 V128:$Rm),
10880                                               (i32 rottype:$rot)))]>;
10881  }
10882}
10883
10884let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
10885class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10886                                 bit opc1, bit opc2, RegisterOperand dst_reg,
10887                                 RegisterOperand lhs_reg,
10888                                 RegisterOperand rhs_reg, Operand vec_idx,
10889                                 Operand rottype, string asm, string apple_kind,
10890                                 string dst_kind, string lhs_kind,
10891                                 string rhs_kind, list<dag> pattern>
10892  : I<(outs dst_reg:$dst),
10893      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10894      asm,
10895      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10896      "$idx, $rot" # "|" # apple_kind #
10897      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10898    Sched<[!if(Q, WriteVq, WriteVd)]> {
10899  bits<5> Rd;
10900  bits<5> Rn;
10901  bits<5> Rm;
10902  bits<2> rot;
10903
10904  let Inst{31}    = 0;
10905  let Inst{30}    = Q;
10906  let Inst{29}    = U;
10907  let Inst{28}    = Scalar;
10908  let Inst{27-24} = 0b1111;
10909  let Inst{23-22} = size;
10910  // Bit 21 must be set by the derived class.
10911  let Inst{20-16} = Rm;
10912  let Inst{15}    = opc1;
10913  let Inst{14-13} = rot;
10914  let Inst{12}    = opc2;
10915  // Bit 11 must be set by the derived class.
10916  let Inst{10}    = 0;
10917  let Inst{9-5}   = Rn;
10918  let Inst{4-0}   = Rd;
10919}
10920
10921// The complex instructions index by pairs of elements, so the VectorIndexes
10922// don't match the lane types, and the index bits are different to the other
10923// classes.
10924multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
10925                                     string asm> {
10926  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10927  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10928                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10929                      ".4h", ".h", []> {
10930    bits<1> idx;
10931    let Inst{11} = 0;
10932    let Inst{21} = idx{0};
10933  }
10934
10935  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10936                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10937                      ".8h", ".8h", ".h", []> {
10938    bits<2> idx;
10939    let Inst{11} = idx{1};
10940    let Inst{21} = idx{0};
10941  }
10942  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10943
10944  let Predicates = [HasComplxNum, HasNEON] in {
10945  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10946                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10947                      ".4s", ".4s", ".s", []> {
10948    bits<1> idx;
10949    let Inst{11} = idx{0};
10950    let Inst{21} = 0;
10951  }
10952  } // Predicates = [HasComplxNum, HasNEON]
10953}
10954
10955//----------------------------------------------------------------------------
10956// Crypto extensions
10957//----------------------------------------------------------------------------
10958
10959let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10960class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10961              list<dag> pat>
10962  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10963    Sched<[WriteVq]>{
10964  bits<5> Rd;
10965  bits<5> Rn;
10966  let Inst{31-16} = 0b0100111000101000;
10967  let Inst{15-12} = opc;
10968  let Inst{11-10} = 0b10;
10969  let Inst{9-5}   = Rn;
10970  let Inst{4-0}   = Rd;
10971}
10972
10973class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10974  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10975            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10976
10977class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10978  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10979            "$Rd = $dst",
10980            [(set (v16i8 V128:$dst),
10981                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10982
10983let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10984class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10985                     dag oops, dag iops, list<dag> pat>
10986  : I<oops, iops, asm,
10987      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10988      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10989    Sched<[WriteVq]>{
10990  bits<5> Rd;
10991  bits<5> Rn;
10992  bits<5> Rm;
10993  let Inst{31-21} = 0b01011110000;
10994  let Inst{20-16} = Rm;
10995  let Inst{15}    = 0;
10996  let Inst{14-12} = opc;
10997  let Inst{11-10} = 0b00;
10998  let Inst{9-5}   = Rn;
10999  let Inst{4-0}   = Rd;
11000}
11001
11002class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
11003  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11004                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
11005                   [(set (v4i32 FPR128:$dst),
11006                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
11007                                 (v4i32 V128:$Rm)))]>;
11008
11009class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
11010  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
11011                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
11012                   [(set (v4i32 V128:$dst),
11013                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11014                                 (v4i32 V128:$Rm)))]>;
11015
11016class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
11017  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11018                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
11019                   [(set (v4i32 FPR128:$dst),
11020                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
11021                                 (v4i32 V128:$Rm)))]>;
11022
11023let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11024class SHA2OpInst<bits<4> opc, string asm, string kind,
11025                 string cstr, dag oops, dag iops,
11026                 list<dag> pat>
11027  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
11028                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
11029    Sched<[WriteVq]>{
11030  bits<5> Rd;
11031  bits<5> Rn;
11032  let Inst{31-16} = 0b0101111000101000;
11033  let Inst{15-12} = opc;
11034  let Inst{11-10} = 0b10;
11035  let Inst{9-5}   = Rn;
11036  let Inst{4-0}   = Rd;
11037}
11038
11039class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
11040  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
11041               (ins V128:$Rd, V128:$Rn),
11042               [(set (v4i32 V128:$dst),
11043                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
11044
11045class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
11046  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
11047               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
11048
11049// Armv8.2-A Crypto extensions
11050class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
11051                    list<dag> pattern>
11052  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
11053  bits<5> Vd;
11054  bits<5> Vn;
11055  let Inst{31-25} = 0b1100111;
11056  let Inst{9-5}   = Vn;
11057  let Inst{4-0}   = Vd;
11058}
11059
11060class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
11061  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
11062                  "$Vd = $Vdst", []> {
11063  let Inst{31-25} = 0b1100111;
11064  let Inst{24-21} = 0b0110;
11065  let Inst{20-15} = 0b000001;
11066  let Inst{14}    = op0;
11067  let Inst{13-12} = 0b00;
11068  let Inst{11-10} = op1;
11069}
11070class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
11071  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
11072class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
11073  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
11074
11075class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
11076                string asmops, string cst>
11077  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
11078  bits<5> Vm;
11079  let Inst{24-21} = 0b0011;
11080  let Inst{20-16} = Vm;
11081  let Inst{15}    = 0b1;
11082  let Inst{14}    = op0;
11083  let Inst{13-12} = 0b00;
11084  let Inst{11-10} = op1;
11085}
11086class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
11087  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11088              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
11089class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
11090  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11091              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11092class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
11093  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11094              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
11095class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
11096  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11097              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11098class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11099  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11100              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11101
11102class CryptoRRRR<bits<2>op0, string asm, string asmops>
11103  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11104                  asmops, "", []> {
11105  bits<5> Vm;
11106  bits<5> Va;
11107  let Inst{24-23} = 0b00;
11108  let Inst{22-21} = op0;
11109  let Inst{20-16} = Vm;
11110  let Inst{15}    = 0b0;
11111  let Inst{14-10} = Va;
11112}
11113class CryptoRRRR_16B<bits<2>op0, string asm>
11114 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11115                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11116}
11117class CryptoRRRR_4S<bits<2>op0, string asm>
11118 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11119                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11120}
11121
11122class CryptoRRRi6<string asm>
11123  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11124                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11125                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11126  bits<6> imm;
11127  bits<5> Vm;
11128  let Inst{24-21} = 0b0100;
11129  let Inst{20-16} = Vm;
11130  let Inst{15-10} = imm;
11131  let Inst{9-5}   = Vn;
11132  let Inst{4-0}   = Vd;
11133}
11134
11135class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11136  : BaseCryptoV82<(outs V128:$Vdst),
11137                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11138                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11139                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11140  bits<2> imm;
11141  bits<5> Vm;
11142  let Inst{24-21} = 0b0010;
11143  let Inst{20-16} = Vm;
11144  let Inst{15}    = 0b1;
11145  let Inst{14}    = op0;
11146  let Inst{13-12} = imm;
11147  let Inst{11-10} = op1;
11148}
11149
11150//----------------------------------------------------------------------------
11151// v8.1 atomic instructions extension:
11152// * CAS
11153// * CASP
11154// * SWP
11155// * LDOPregister<OP>, and aliases STOPregister<OP>
11156
11157// Instruction encodings:
11158//
11159//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11160// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11161// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11162// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11163// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11164// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11165
11166// Instruction syntax:
11167//
11168// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11169// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11170// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11171// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11172// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11173// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11174// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11175// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11176// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11177// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11178
11179let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11180class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11181                      string cstr, list<dag> pattern>
11182      : I<oops, iops, asm, operands, cstr, pattern> {
11183  bits<2> Sz;
11184  bit NP;
11185  bit Acq;
11186  bit Rel;
11187  bits<5> Rs;
11188  bits<5> Rn;
11189  bits<5> Rt;
11190  let Inst{31-30} = Sz;
11191  let Inst{29-24} = 0b001000;
11192  let Inst{23} = NP;
11193  let Inst{22} = Acq;
11194  let Inst{21} = 0b1;
11195  let Inst{20-16} = Rs;
11196  let Inst{15} = Rel;
11197  let Inst{14-10} = 0b11111;
11198  let Inst{9-5} = Rn;
11199  let Inst{4-0} = Rt;
11200  let Predicates = [HasLSE];
11201}
11202
11203class BaseCAS<string order, string size, RegisterClass RC>
11204      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11205                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11206                        "$out = $Rs",[]>,
11207        Sched<[WriteAtomic]> {
11208  let NP = 1;
11209}
11210
11211multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11212  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11213  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11214  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11215  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11216}
11217
11218class BaseCASP<string order, string size, RegisterOperand RC>
11219      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11220                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11221                        "$out = $Rs",[]>,
11222        Sched<[WriteAtomic]> {
11223  let NP = 0;
11224}
11225
11226multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11227  let Sz = 0b00, Acq = Acq, Rel = Rel in
11228    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11229  let Sz = 0b01, Acq = Acq, Rel = Rel in
11230    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11231}
11232
11233let Predicates = [HasLSE] in
11234class BaseSWP<string order, string size, RegisterClass RC>
11235      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11236          "\t$Rs, $Rt, [$Rn]","",[]>,
11237        Sched<[WriteAtomic]> {
11238  bits<2> Sz;
11239  bit Acq;
11240  bit Rel;
11241  bits<5> Rs;
11242  bits<3> opc = 0b000;
11243  bits<5> Rn;
11244  bits<5> Rt;
11245  let Inst{31-30} = Sz;
11246  let Inst{29-24} = 0b111000;
11247  let Inst{23} = Acq;
11248  let Inst{22} = Rel;
11249  let Inst{21} = 0b1;
11250  let Inst{20-16} = Rs;
11251  let Inst{15} = 0b1;
11252  let Inst{14-12} = opc;
11253  let Inst{11-10} = 0b00;
11254  let Inst{9-5} = Rn;
11255  let Inst{4-0} = Rt;
11256  let Predicates = [HasLSE];
11257}
11258
11259multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11260  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11261  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11262  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11263  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11264}
11265
11266let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11267class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11268      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11269          "\t$Rs, $Rt, [$Rn]","",[]>,
11270        Sched<[WriteAtomic]> {
11271  bits<2> Sz;
11272  bit Acq;
11273  bit Rel;
11274  bits<5> Rs;
11275  bits<3> opc;
11276  bits<5> Rn;
11277  bits<5> Rt;
11278  let Inst{31-30} = Sz;
11279  let Inst{29-24} = 0b111000;
11280  let Inst{23} = Acq;
11281  let Inst{22} = Rel;
11282  let Inst{21} = 0b1;
11283  let Inst{20-16} = Rs;
11284  let Inst{15} = 0b0;
11285  let Inst{14-12} = opc;
11286  let Inst{11-10} = 0b00;
11287  let Inst{9-5} = Rn;
11288  let Inst{4-0} = Rt;
11289  let Predicates = [HasLSE];
11290}
11291
11292multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11293                        string order> {
11294  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11295    def B : BaseLDOPregister<op, order, "b", GPR32>;
11296  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11297    def H : BaseLDOPregister<op, order, "h", GPR32>;
11298  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11299    def W : BaseLDOPregister<op, order, "", GPR32>;
11300  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11301    def X : BaseLDOPregister<op, order, "", GPR64>;
11302}
11303
11304// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11305// complex DAG for DstRHS.
11306let Predicates = [HasLSE] in
11307multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11308                                         string size, dag SrcRHS, dag DstRHS> {
11309  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11310            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11311  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11312            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11313  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11314            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11315  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11316            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11317  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11318            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11319}
11320
11321multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11322                                     string size, dag RHS> {
11323  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11324}
11325
11326multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11327                                         string size, dag LHS, dag RHS> {
11328  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11329}
11330
11331multiclass LDOPregister_patterns<string inst, string op> {
11332  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11333  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11334  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11335  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11336}
11337
11338multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11339  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11340                        (i64 GPR64:$Rm),
11341                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11342  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11343                        (i32 GPR32:$Rm),
11344                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11345  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11346                        (i32 GPR32:$Rm),
11347                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11348  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11349                        (i32 GPR32:$Rm),
11350                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11351}
11352
11353let Predicates = [HasLSE] in
11354multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11355                                        string size, dag OLD, dag NEW> {
11356  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11357            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11358  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11359            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11360  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11361            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11362  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11363            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11364  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11365            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11366}
11367
11368multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11369                                    string size, dag OLD, dag NEW> {
11370  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11371}
11372
11373multiclass CASregister_patterns<string inst, string op> {
11374  defm : CASregister_patterns_ord<inst, "X", op, "64",
11375                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11376  defm : CASregister_patterns_ord<inst, "W", op, "32",
11377                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11378  defm : CASregister_patterns_ord<inst, "H", op, "16",
11379                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11380  defm : CASregister_patterns_ord<inst, "B", op, "8",
11381                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11382}
11383
11384let Predicates = [HasLSE] in
11385class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11386                        Instruction inst> :
11387      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11388
11389multiclass STOPregister<string asm, string instr> {
11390  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11391                    !cast<Instruction>(instr # "LB")>;
11392  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11393                    !cast<Instruction>(instr # "LH")>;
11394  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11395                    !cast<Instruction>(instr # "LW")>;
11396  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11397                    !cast<Instruction>(instr # "LX")>;
11398  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11399                    !cast<Instruction>(instr # "B")>;
11400  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11401                    !cast<Instruction>(instr # "H")>;
11402  def : BaseSTOPregister<asm,        GPR32, WZR,
11403                    !cast<Instruction>(instr # "W")>;
11404  def : BaseSTOPregister<asm,        GPR64, XZR,
11405                    !cast<Instruction>(instr # "X")>;
11406}
11407
11408class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11409                        dag iops, dag oops, list<dag> pat>
11410    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11411      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11412  bits<5> Rt;
11413  bits<5> Rn;
11414  let Inst{31-21} = 0b11111000001;
11415  let Inst{15}    = 1;
11416  let Inst{14-12} = opc;
11417  let Inst{11-10} = 0b00;
11418  let Inst{9-5}   = Rn;
11419  let Inst{4-0}   = Rt;
11420
11421  let Predicates = [HasV8_7a];
11422}
11423
11424class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11425                      list<dag> pat = []>
11426    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11427  let Inst{20-16} = 0b11111;
11428}
11429
11430class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11431    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11432                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11433  bits<5> Rs;
11434  let Inst{20-16} = Rs;
11435}
11436
11437class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
11438                             bits<2> op2, string asm>
11439  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
11440      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
11441      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
11442      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
11443    Sched<[]> {
11444  bits<5> Rd;
11445  bits<5> Rs;
11446  bits<5> Rn;
11447  let Inst{31-27} = 0b00011;
11448  let Inst{26} = isMove;
11449  let Inst{25-24} = 0b01;
11450  let Inst{23-22} = opcode;
11451  let Inst{21} = 0b0;
11452  let Inst{20-16} = Rs;
11453  let Inst{15-14} = op2;
11454  let Inst{13-12} = op1;
11455  let Inst{11-10} = 0b01;
11456  let Inst{9-5} = Rn;
11457  let Inst{4-0} = Rd;
11458
11459  let DecoderMethod = "DecodeCPYMemOpInstruction";
11460  let mayLoad = 1;
11461  let mayStore = 1;
11462}
11463
11464class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11465  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
11466
11467class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11468  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
11469
11470class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
11471                        string asm>
11472  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
11473      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
11474      asm, "\t[$Rd]!, $Rn!, $Rm",
11475      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
11476    Sched<[]> {
11477  bits<5> Rd;
11478  bits<5> Rn;
11479  bits<5> Rm;
11480  let Inst{31-27} = 0b00011;
11481  let Inst{26} = isTagging;
11482  let Inst{25-21} = 0b01110;
11483  let Inst{20-16} = Rm;
11484  let Inst{15-14} = opcode;
11485  let Inst{13} = op2;
11486  let Inst{12} = op1;
11487  let Inst{11-10} = 0b01;
11488  let Inst{9-5} = Rn;
11489  let Inst{4-0} = Rd;
11490
11491  let DecoderMethod = "DecodeSETMemOpInstruction";
11492  let mayLoad = 0;
11493  let mayStore = 1;
11494}
11495
11496class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
11497  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
11498
11499class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
11500  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
11501
11502multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
11503  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
11504  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
11505  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
11506  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
11507  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
11508  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
11509  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
11510  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
11511  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
11512  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
11513  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
11514  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
11515  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
11516  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
11517  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
11518  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
11519}
11520
11521multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
11522  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
11523  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
11524  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
11525  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
11526  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
11527  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
11528  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
11529  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
11530  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
11531  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
11532  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
11533  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
11534  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
11535  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
11536  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
11537  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
11538}
11539
11540multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
11541  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
11542  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
11543  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
11544  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
11545}
11546
11547multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
11548  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
11549  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
11550  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
11551  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
11552}
11553
11554//----------------------------------------------------------------------------
11555// Allow the size specifier tokens to be upper case, not just lower.
11556def : TokenAlias<".4B", ".4b">;  // Add dot product
11557def : TokenAlias<".8B", ".8b">;
11558def : TokenAlias<".4H", ".4h">;
11559def : TokenAlias<".2S", ".2s">;
11560def : TokenAlias<".1D", ".1d">;
11561def : TokenAlias<".16B", ".16b">;
11562def : TokenAlias<".8H", ".8h">;
11563def : TokenAlias<".4S", ".4s">;
11564def : TokenAlias<".2D", ".2d">;
11565def : TokenAlias<".1Q", ".1q">;
11566def : TokenAlias<".2H", ".2h">;
11567def : TokenAlias<".B", ".b">;
11568def : TokenAlias<".H", ".h">;
11569def : TokenAlias<".S", ".s">;
11570def : TokenAlias<".D", ".d">;
11571def : TokenAlias<".Q", ".q">;
11572