1//===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9//===----------------------------------------------------------------------===//
10//  Describe AArch64 instructions format here
11//
12
13// Format specifies the encoding used by the instruction.  This is part of the
14// ad-hoc solution used to emit machine instruction encodings by our machine
15// code emitter.
16class Format<bits<2> val> {
17  bits<2> Value = val;
18}
19
20def PseudoFrm   : Format<0>;
21def NormalFrm   : Format<1>; // Do we need any others?
22
23// Enum describing whether an instruction is
24// destructive in its first source operand.
25class DestructiveInstTypeEnum<bits<4> val> {
26  bits<4> Value = val;
27}
28def NotDestructive                : DestructiveInstTypeEnum<0>;
29// Destructive in its first operand and can be MOVPRFX'd, but has no other
30// special properties.
31def DestructiveOther              : DestructiveInstTypeEnum<1>;
32def DestructiveUnary              : DestructiveInstTypeEnum<2>;
33def DestructiveBinaryImm          : DestructiveInstTypeEnum<3>;
34def DestructiveBinaryShImmUnpred  : DestructiveInstTypeEnum<4>;
35def DestructiveBinary             : DestructiveInstTypeEnum<5>;
36def DestructiveBinaryComm         : DestructiveInstTypeEnum<6>;
37def DestructiveBinaryCommWithRev  : DestructiveInstTypeEnum<7>;
38def DestructiveTernaryCommWithRev : DestructiveInstTypeEnum<8>;
39def DestructiveUnaryPassthru      : DestructiveInstTypeEnum<9>;
40
41class FalseLanesEnum<bits<2> val> {
42  bits<2> Value = val;
43}
44def FalseLanesNone  : FalseLanesEnum<0>;
45def FalseLanesZero  : FalseLanesEnum<1>;
46def FalseLanesUndef : FalseLanesEnum<2>;
47
48// AArch64 Instruction Format
49class AArch64Inst<Format f, string cstr> : Instruction {
50  field bits<32> Inst; // Instruction encoding.
51  // Mask of bits that cause an encoding to be UNPREDICTABLE.
52  // If a bit is set, then if the corresponding bit in the
53  // target encoding differs from its value in the "Inst" field,
54  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
55  field bits<32> Unpredictable = 0;
56  // SoftFail is the generic name for this field, but we alias it so
57  // as to make it more obvious what it means in ARM-land.
58  field bits<32> SoftFail = Unpredictable;
59  let Namespace   = "AArch64";
60  Format F        = f;
61  bits<2> Form    = F.Value;
62
63  // Defaults
64  bit isWhile = 0;
65  bit isPTestLike = 0;
66  FalseLanesEnum FalseLanes = FalseLanesNone;
67  DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
68  ElementSizeEnum ElementSize = ElementSizeNone;
69
70  let TSFlags{10}  = isPTestLike;
71  let TSFlags{9}   = isWhile;
72  let TSFlags{8-7} = FalseLanes.Value;
73  let TSFlags{6-3} = DestructiveInstType.Value;
74  let TSFlags{2-0} = ElementSize.Value;
75
76  let Pattern     = [];
77  let Constraints = cstr;
78}
79
80class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
81  : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
82
83// Pseudo instructions (don't have encoding information)
84class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
85    : AArch64Inst<PseudoFrm, cstr> {
86  dag OutOperandList = oops;
87  dag InOperandList  = iops;
88  let Pattern        = pattern;
89  let isCodeGenOnly  = 1;
90  let isPseudo       = 1;
91}
92
93// Real instructions (have encoding information)
94class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
95  let Pattern = pattern;
96  let Size = 4;
97}
98
99// Normal instructions
100class I<dag oops, dag iops, string asm, string operands, string cstr,
101        list<dag> pattern>
102    : EncodedI<cstr, pattern> {
103  dag OutOperandList = oops;
104  dag InOperandList  = iops;
105  let AsmString      = !strconcat(asm, operands);
106}
107
108class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
109class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
110class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
111
112// Helper fragment for an extract of the high portion of a 128-bit vector. The
113// ComplexPattern match both extract_subvector and bitcast(extract_subvector(..)).
114def extract_high_v16i8 :
115    ComplexPattern<v8i8, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
116def extract_high_v8i16 :
117    ComplexPattern<v4i16, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
118def extract_high_v4i32 :
119    ComplexPattern<v2i32, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
120
121def extract_high_dup_v8i16 :
122   BinOpFrag<(extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 4))>;
123def extract_high_dup_v4i32 :
124   BinOpFrag<(extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 2))>;
125
126//===----------------------------------------------------------------------===//
127// Asm Operand Classes.
128//
129
130// Shifter operand for arithmetic shifted encodings.
131def ShifterOperand : AsmOperandClass {
132  let Name = "Shifter";
133}
134
135// Shifter operand for mov immediate encodings.
136def MovImm32ShifterOperand : AsmOperandClass {
137  let SuperClasses = [ShifterOperand];
138  let Name = "MovImm32Shifter";
139  let RenderMethod = "addShifterOperands";
140  let DiagnosticType = "InvalidMovImm32Shift";
141}
142def MovImm64ShifterOperand : AsmOperandClass {
143  let SuperClasses = [ShifterOperand];
144  let Name = "MovImm64Shifter";
145  let RenderMethod = "addShifterOperands";
146  let DiagnosticType = "InvalidMovImm64Shift";
147}
148
149// Shifter operand for arithmetic register shifted encodings.
150class ArithmeticShifterOperand<int width> : AsmOperandClass {
151  let SuperClasses = [ShifterOperand];
152  let Name = "ArithmeticShifter" # width;
153  let PredicateMethod = "isArithmeticShifter<" # width # ">";
154  let RenderMethod = "addShifterOperands";
155  let DiagnosticType = "AddSubRegShift" # width;
156}
157
158def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
159def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
160
161// Shifter operand for logical register shifted encodings.
162class LogicalShifterOperand<int width> : AsmOperandClass {
163  let SuperClasses = [ShifterOperand];
164  let Name = "LogicalShifter" # width;
165  let PredicateMethod = "isLogicalShifter<" # width # ">";
166  let RenderMethod = "addShifterOperands";
167  let DiagnosticType = "AddSubRegShift" # width;
168}
169
170def LogicalShifterOperand32 : LogicalShifterOperand<32>;
171def LogicalShifterOperand64 : LogicalShifterOperand<64>;
172
173// Shifter operand for logical vector 128/64-bit shifted encodings.
174def LogicalVecShifterOperand : AsmOperandClass {
175  let SuperClasses = [ShifterOperand];
176  let Name = "LogicalVecShifter";
177  let RenderMethod = "addShifterOperands";
178}
179def LogicalVecHalfWordShifterOperand : AsmOperandClass {
180  let SuperClasses = [LogicalVecShifterOperand];
181  let Name = "LogicalVecHalfWordShifter";
182  let RenderMethod = "addShifterOperands";
183}
184
185// The "MSL" shifter on the vector MOVI instruction.
186def MoveVecShifterOperand : AsmOperandClass {
187  let SuperClasses = [ShifterOperand];
188  let Name = "MoveVecShifter";
189  let RenderMethod = "addShifterOperands";
190}
191
192// Extend operand for arithmetic encodings.
193def ExtendOperand : AsmOperandClass {
194  let Name = "Extend";
195  let DiagnosticType = "AddSubRegExtendLarge";
196}
197def ExtendOperand64 : AsmOperandClass {
198  let SuperClasses = [ExtendOperand];
199  let Name = "Extend64";
200  let DiagnosticType = "AddSubRegExtendSmall";
201}
202// 'extend' that's a lsl of a 64-bit register.
203def ExtendOperandLSL64 : AsmOperandClass {
204  let SuperClasses = [ExtendOperand];
205  let Name = "ExtendLSL64";
206  let RenderMethod = "addExtend64Operands";
207  let DiagnosticType = "AddSubRegExtendLarge";
208}
209
210// 8-bit floating-point immediate encodings.
211def FPImmOperand : AsmOperandClass {
212  let Name = "FPImm";
213  let ParserMethod = "tryParseFPImm<true>";
214  let DiagnosticType = "InvalidFPImm";
215}
216
217def CondCode : AsmOperandClass {
218  let Name = "CondCode";
219  let DiagnosticType = "InvalidCondCode";
220}
221
222// A 32-bit register pasrsed as 64-bit
223def GPR32as64Operand : AsmOperandClass {
224  let Name = "GPR32as64";
225  let ParserMethod =
226      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
227}
228def GPR32as64 : RegisterOperand<GPR32> {
229  let ParserMatchClass = GPR32as64Operand;
230}
231
232// A 64-bit register pasrsed as 32-bit
233def GPR64as32Operand : AsmOperandClass {
234  let Name = "GPR64as32";
235  let ParserMethod =
236      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
237}
238def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
239  let ParserMatchClass = GPR64as32Operand;
240}
241
242// 8-bit immediate for AdvSIMD where 64-bit values of the form:
243// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
244// are encoded as the eight bit value 'abcdefgh'.
245def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
246
247class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
248  let Name = "UImm" # Width # "s" # Scale;
249  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
250  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
251  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
252}
253
254class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
255  let Name = "SImm" # Width # "s" # Scale;
256  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
257  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
258  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
259}
260
261//===----------------------------------------------------------------------===//
262// Operand Definitions.
263//
264
265// ADR[P] instruction labels.
266def AdrpOperand : AsmOperandClass {
267  let Name = "AdrpLabel";
268  let ParserMethod = "tryParseAdrpLabel";
269  let DiagnosticType = "InvalidLabel";
270}
271def adrplabel : Operand<i64> {
272  let EncoderMethod = "getAdrLabelOpValue";
273  let PrintMethod = "printAdrpLabel";
274  let ParserMatchClass = AdrpOperand;
275  let OperandType = "OPERAND_PCREL";
276}
277
278def AdrOperand : AsmOperandClass {
279  let Name = "AdrLabel";
280  let ParserMethod = "tryParseAdrLabel";
281  let DiagnosticType = "InvalidLabel";
282}
283def adrlabel : Operand<i64> {
284  let EncoderMethod = "getAdrLabelOpValue";
285  let ParserMatchClass = AdrOperand;
286}
287
288class SImmOperand<int width> : AsmOperandClass {
289  let Name = "SImm" # width;
290  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
291  let RenderMethod = "addImmOperands";
292  let PredicateMethod = "isSImm<" # width # ">";
293}
294
295
296class AsmImmRange<int Low, int High> : AsmOperandClass {
297  let Name = "Imm" # Low # "_" # High;
298  let DiagnosticType = "InvalidImm" # Low # "_" # High;
299  let RenderMethod = "addImmOperands";
300  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
301}
302
303// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
304def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
305def simm10Scaled : Operand<i64> {
306  let ParserMatchClass = SImm10s8Operand;
307  let DecoderMethod = "DecodeSImm<10>";
308  let PrintMethod = "printImmScale<8>";
309}
310
311def simm9s16 : Operand<i64> {
312  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
313  let DecoderMethod = "DecodeSImm<9>";
314  let PrintMethod = "printImmScale<16>";
315}
316
317// uimm6 predicate - True if the immediate is in the range [0, 63].
318def UImm6Operand : AsmOperandClass {
319  let Name = "UImm6";
320  let DiagnosticType = "InvalidImm0_63";
321}
322
323def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
324  let ParserMatchClass = UImm6Operand;
325}
326
327def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
328  let ParserMatchClass = AsmImmRange<0, 65535>;
329}
330
331def SImm9Operand : SImmOperand<9>;
332def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
333  let ParserMatchClass = SImm9Operand;
334  let DecoderMethod = "DecodeSImm<9>";
335}
336
337def SImm8Operand : SImmOperand<8>;
338def simm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
339  let ParserMatchClass = SImm8Operand;
340  let DecoderMethod = "DecodeSImm<8>";
341}
342
343def SImm6Operand : SImmOperand<6>;
344def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
345  let ParserMatchClass = SImm6Operand;
346  let DecoderMethod = "DecodeSImm<6>";
347}
348
349def SImm5Operand : SImmOperand<5>;
350def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
351  let ParserMatchClass = SImm5Operand;
352  let DecoderMethod = "DecodeSImm<5>";
353}
354
355def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
356  let ParserMatchClass = SImm5Operand;
357  let DecoderMethod = "DecodeSImm<5>";
358}
359
360def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
361  let ParserMatchClass = SImm5Operand;
362  let DecoderMethod = "DecodeSImm<5>";
363  let PrintMethod = "printSImm<8>";
364}
365
366def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
367  let ParserMatchClass = SImm5Operand;
368  let DecoderMethod = "DecodeSImm<5>";
369  let PrintMethod = "printSImm<16>";
370}
371
372// simm7sN predicate - True if the immediate is a multiple of N in the range
373// [-64 * N, 63 * N].
374
375def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
376def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
377def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
378
379def simm7s4 : Operand<i32> {
380  let ParserMatchClass = SImm7s4Operand;
381  let PrintMethod = "printImmScale<4>";
382}
383
384def simm7s8 : Operand<i32> {
385  let ParserMatchClass = SImm7s8Operand;
386  let PrintMethod = "printImmScale<8>";
387}
388
389def simm7s16 : Operand<i32> {
390  let ParserMatchClass = SImm7s16Operand;
391  let PrintMethod = "printImmScale<16>";
392}
393
394def am_sve_fi : ComplexPattern<iPTR, 2, "SelectAddrModeFrameIndexSVE", []>;
395
396def am_indexed7s8   : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S8", []>;
397def am_indexed7s16  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S16", []>;
398def am_indexed7s32  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S32", []>;
399def am_indexed7s64  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S64", []>;
400def am_indexed7s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S128", []>;
401
402def am_indexedu6s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedU6S128", []>;
403def am_indexeds9s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedS9S128", []>;
404
405def UImmS1XForm : SDNodeXForm<imm, [{
406  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
407}]>;
408def UImmS2XForm : SDNodeXForm<imm, [{
409  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
410}]>;
411def UImmS4XForm : SDNodeXForm<imm, [{
412  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
413}]>;
414def UImmS8XForm : SDNodeXForm<imm, [{
415  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
416}]>;
417
418// uimm5sN predicate - True if the immediate is a multiple of N in the range
419// [0 * N, 32 * N].
420def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
421def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
422def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
423
424def uimm5s2 : Operand<i64>, ImmLeaf<i64,
425                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
426                UImmS2XForm> {
427  let ParserMatchClass = UImm5s2Operand;
428  let PrintMethod = "printImmScale<2>";
429}
430def uimm5s4 : Operand<i64>, ImmLeaf<i64,
431                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
432                UImmS4XForm> {
433  let ParserMatchClass = UImm5s4Operand;
434  let PrintMethod = "printImmScale<4>";
435}
436def uimm5s8 : Operand<i64>, ImmLeaf<i64,
437                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
438                UImmS8XForm> {
439  let ParserMatchClass = UImm5s8Operand;
440  let PrintMethod = "printImmScale<8>";
441}
442
443// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
444// instead of ImmLeaf (Constant)
445def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
446                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
447                UImmS2XForm> {
448  let ParserMatchClass = UImm5s2Operand;
449  let PrintMethod = "printImmScale<2>";
450}
451def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
452                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
453                UImmS4XForm> {
454  let ParserMatchClass = UImm5s4Operand;
455  let PrintMethod = "printImmScale<4>";
456}
457def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
458                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
459                UImmS8XForm> {
460  let ParserMatchClass = UImm5s8Operand;
461  let PrintMethod = "printImmScale<8>";
462}
463
464// uimm6sN predicate - True if the immediate is a multiple of N in the range
465// [0 * N, 64 * N].
466def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
467def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
468def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
469def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
470def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
471
472def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
473  let ParserMatchClass = UImm6s1Operand;
474}
475def uimm6s2 : Operand<i64>, ImmLeaf<i64,
476[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
477  let PrintMethod = "printImmScale<2>";
478  let ParserMatchClass = UImm6s2Operand;
479}
480def uimm6s4 : Operand<i64>, ImmLeaf<i64,
481[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
482  let PrintMethod = "printImmScale<4>";
483  let ParserMatchClass = UImm6s4Operand;
484}
485def uimm6s8 : Operand<i64>, ImmLeaf<i64,
486[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
487  let PrintMethod = "printImmScale<8>";
488  let ParserMatchClass = UImm6s8Operand;
489}
490def uimm6s16 : Operand<i64>, ImmLeaf<i64,
491[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
492  let PrintMethod = "printImmScale<16>";
493  let ParserMatchClass = UImm6s16Operand;
494}
495
496def SImmS2XForm : SDNodeXForm<imm, [{
497  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
498}]>;
499def SImmS3XForm : SDNodeXForm<imm, [{
500  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
501}]>;
502def SImmS4XForm : SDNodeXForm<imm, [{
503  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
504}]>;
505def SImmS16XForm : SDNodeXForm<imm, [{
506  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
507}]>;
508def SImmS32XForm : SDNodeXForm<imm, [{
509  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
510}]>;
511
512// simm6sN predicate - True if the immediate is a multiple of N in the range
513// [-32 * N, 31 * N].
514def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
515def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
516  let ParserMatchClass = SImm6s1Operand;
517  let DecoderMethod = "DecodeSImm<6>";
518}
519
520// simm4sN predicate - True if the immediate is a multiple of N in the range
521// [ -8* N, 7 * N].
522def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
523def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
524def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
525def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
526def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
527def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
528
529def simm4s1 : Operand<i64>, ImmLeaf<i64,
530[{ return Imm >=-8  && Imm <= 7; }]> {
531  let ParserMatchClass = SImm4s1Operand;
532  let DecoderMethod = "DecodeSImm<4>";
533}
534
535def simm4s2 : Operand<i64>, ImmLeaf<i64,
536[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
537  let PrintMethod = "printImmScale<2>";
538  let ParserMatchClass = SImm4s2Operand;
539  let DecoderMethod = "DecodeSImm<4>";
540}
541
542def simm4s3 : Operand<i64>, ImmLeaf<i64,
543[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
544  let PrintMethod = "printImmScale<3>";
545  let ParserMatchClass = SImm4s3Operand;
546  let DecoderMethod = "DecodeSImm<4>";
547}
548
549def simm4s4 : Operand<i64>, ImmLeaf<i64,
550[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
551  let PrintMethod = "printImmScale<4>";
552  let ParserMatchClass = SImm4s4Operand;
553  let DecoderMethod = "DecodeSImm<4>";
554}
555def simm4s16 : Operand<i64>, ImmLeaf<i64,
556[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
557  let PrintMethod = "printImmScale<16>";
558  let ParserMatchClass = SImm4s16Operand;
559  let DecoderMethod = "DecodeSImm<4>";
560}
561def simm4s32 : Operand<i64>, ImmLeaf<i64,
562[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
563  let PrintMethod = "printImmScale<32>";
564  let ParserMatchClass = SImm4s32Operand;
565  let DecoderMethod = "DecodeSImm<4>";
566}
567
568def Imm1_8Operand : AsmImmRange<1, 8>;
569def Imm1_16Operand : AsmImmRange<1, 16>;
570def Imm1_32Operand : AsmImmRange<1, 32>;
571def Imm1_64Operand : AsmImmRange<1, 64>;
572
573class BranchTarget<int N> : AsmOperandClass {
574  let Name = "BranchTarget" # N;
575  let DiagnosticType = "InvalidLabel";
576  let PredicateMethod = "isBranchTarget<" # N # ">";
577}
578
579class PCRelLabel<int N> : BranchTarget<N> {
580  let Name = "PCRelLabel" # N;
581}
582
583def BranchTarget14Operand : BranchTarget<14>;
584def BranchTarget26Operand : BranchTarget<26>;
585def PCRelLabel19Operand   : PCRelLabel<19>;
586
587def MovWSymbolG3AsmOperand : AsmOperandClass {
588  let Name = "MovWSymbolG3";
589  let RenderMethod = "addImmOperands";
590}
591
592def movw_symbol_g3 : Operand<i32> {
593  let ParserMatchClass = MovWSymbolG3AsmOperand;
594}
595
596def MovWSymbolG2AsmOperand : AsmOperandClass {
597  let Name = "MovWSymbolG2";
598  let RenderMethod = "addImmOperands";
599}
600
601def movw_symbol_g2 : Operand<i32> {
602  let ParserMatchClass = MovWSymbolG2AsmOperand;
603}
604
605def MovWSymbolG1AsmOperand : AsmOperandClass {
606  let Name = "MovWSymbolG1";
607  let RenderMethod = "addImmOperands";
608}
609
610def movw_symbol_g1 : Operand<i32> {
611  let ParserMatchClass = MovWSymbolG1AsmOperand;
612}
613
614def MovWSymbolG0AsmOperand : AsmOperandClass {
615  let Name = "MovWSymbolG0";
616  let RenderMethod = "addImmOperands";
617}
618
619def movw_symbol_g0 : Operand<i32> {
620  let ParserMatchClass = MovWSymbolG0AsmOperand;
621}
622
623class fixedpoint_i32<ValueType FloatVT>
624  : Operand<FloatVT>,
625    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
626  let EncoderMethod = "getFixedPointScaleOpValue";
627  let DecoderMethod = "DecodeFixedPointScaleImm32";
628  let ParserMatchClass = Imm1_32Operand;
629}
630
631class fixedpoint_i64<ValueType FloatVT>
632  : Operand<FloatVT>,
633    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
634  let EncoderMethod = "getFixedPointScaleOpValue";
635  let DecoderMethod = "DecodeFixedPointScaleImm64";
636  let ParserMatchClass = Imm1_64Operand;
637}
638
639def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
640def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
641def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
642
643def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
644def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
645def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
646
647def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
648  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
649}]> {
650  let EncoderMethod = "getVecShiftR8OpValue";
651  let DecoderMethod = "DecodeVecShiftR8Imm";
652  let ParserMatchClass = Imm1_8Operand;
653}
654def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
655  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
656}]> {
657  let EncoderMethod = "getVecShiftR16OpValue";
658  let DecoderMethod = "DecodeVecShiftR16Imm";
659  let ParserMatchClass = Imm1_16Operand;
660}
661def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
662  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
663}]> {
664  let EncoderMethod = "getVecShiftR16OpValue";
665  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
666  let ParserMatchClass = Imm1_8Operand;
667}
668def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
669  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
670}]> {
671  let EncoderMethod = "getVecShiftR32OpValue";
672  let DecoderMethod = "DecodeVecShiftR32Imm";
673  let ParserMatchClass = Imm1_32Operand;
674}
675def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
676  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
677}]> {
678  let EncoderMethod = "getVecShiftR32OpValue";
679  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
680  let ParserMatchClass = Imm1_16Operand;
681}
682def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
683  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
684}]> {
685  let EncoderMethod = "getVecShiftR64OpValue";
686  let DecoderMethod = "DecodeVecShiftR64Imm";
687  let ParserMatchClass = Imm1_64Operand;
688}
689def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
690  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
691}]> {
692  let EncoderMethod = "getVecShiftR64OpValue";
693  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
694  let ParserMatchClass = Imm1_32Operand;
695}
696
697// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
698// (ImmLeaf)
699def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
700  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
701}]> {
702  let EncoderMethod = "getVecShiftR8OpValue";
703  let DecoderMethod = "DecodeVecShiftR8Imm";
704  let ParserMatchClass = Imm1_8Operand;
705}
706def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
707  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
708}]> {
709  let EncoderMethod = "getVecShiftR16OpValue";
710  let DecoderMethod = "DecodeVecShiftR16Imm";
711  let ParserMatchClass = Imm1_16Operand;
712}
713def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
714  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
715}]> {
716  let EncoderMethod = "getVecShiftR32OpValue";
717  let DecoderMethod = "DecodeVecShiftR32Imm";
718  let ParserMatchClass = Imm1_32Operand;
719}
720def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
721  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
722}]> {
723  let EncoderMethod = "getVecShiftR64OpValue";
724  let DecoderMethod = "DecodeVecShiftR64Imm";
725  let ParserMatchClass = Imm1_64Operand;
726}
727
728def Imm0_0Operand : AsmImmRange<0, 0>;
729def Imm0_1Operand : AsmImmRange<0, 1>;
730def Imm0_3Operand : AsmImmRange<0, 3>;
731def Imm0_7Operand : AsmImmRange<0, 7>;
732def Imm0_15Operand : AsmImmRange<0, 15>;
733def Imm0_31Operand : AsmImmRange<0, 31>;
734def Imm0_63Operand : AsmImmRange<0, 63>;
735
736def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
737  return (((uint32_t)Imm) < 8);
738}]> {
739  let EncoderMethod = "getVecShiftL8OpValue";
740  let DecoderMethod = "DecodeVecShiftL8Imm";
741  let ParserMatchClass = Imm0_7Operand;
742}
743def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
744  return (((uint32_t)Imm) < 16);
745}]> {
746  let EncoderMethod = "getVecShiftL16OpValue";
747  let DecoderMethod = "DecodeVecShiftL16Imm";
748  let ParserMatchClass = Imm0_15Operand;
749}
750def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
751  return (((uint32_t)Imm) < 32);
752}]> {
753  let EncoderMethod = "getVecShiftL32OpValue";
754  let DecoderMethod = "DecodeVecShiftL32Imm";
755  let ParserMatchClass = Imm0_31Operand;
756}
757def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
758  return (((uint32_t)Imm) < 64);
759}]> {
760  let EncoderMethod = "getVecShiftL64OpValue";
761  let DecoderMethod = "DecodeVecShiftL64Imm";
762  let ParserMatchClass = Imm0_63Operand;
763}
764
765// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
766// (ImmLeaf)
767def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
768  return (((uint32_t)Imm) < 8);
769}]> {
770  let EncoderMethod = "getVecShiftL8OpValue";
771  let DecoderMethod = "DecodeVecShiftL8Imm";
772  let ParserMatchClass = Imm0_7Operand;
773}
774def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
775  return (((uint32_t)Imm) < 16);
776}]> {
777  let EncoderMethod = "getVecShiftL16OpValue";
778  let DecoderMethod = "DecodeVecShiftL16Imm";
779  let ParserMatchClass = Imm0_15Operand;
780}
781def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
782  return (((uint32_t)Imm) < 32);
783}]> {
784  let EncoderMethod = "getVecShiftL32OpValue";
785  let DecoderMethod = "DecodeVecShiftL32Imm";
786  let ParserMatchClass = Imm0_31Operand;
787}
788def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
789  return (((uint32_t)Imm) < 64);
790}]> {
791  let EncoderMethod = "getVecShiftL64OpValue";
792  let DecoderMethod = "DecodeVecShiftL64Imm";
793  let ParserMatchClass = Imm0_63Operand;
794}
795
796// Crazy immediate formats used by 32-bit and 64-bit logical immediate
797// instructions for splatting repeating bit patterns across the immediate.
798def logical_imm32_XFORM : SDNodeXForm<imm, [{
799  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
800  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
801}]>;
802def logical_imm64_XFORM : SDNodeXForm<imm, [{
803  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
804  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
805}]>;
806
807def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
808  GISDNodeXFormEquiv<logical_imm32_XFORM>;
809def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
810  GISDNodeXFormEquiv<logical_imm64_XFORM>;
811
812let DiagnosticType = "LogicalSecondSource" in {
813  def LogicalImm32Operand : AsmOperandClass {
814    let Name = "LogicalImm32";
815    let PredicateMethod = "isLogicalImm<int32_t>";
816    let RenderMethod = "addLogicalImmOperands<int32_t>";
817  }
818  def LogicalImm64Operand : AsmOperandClass {
819    let Name = "LogicalImm64";
820    let PredicateMethod = "isLogicalImm<int64_t>";
821    let RenderMethod = "addLogicalImmOperands<int64_t>";
822  }
823  def LogicalImm32NotOperand : AsmOperandClass {
824    let Name = "LogicalImm32Not";
825    let PredicateMethod = "isLogicalImm<int32_t>";
826    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
827  }
828  def LogicalImm64NotOperand : AsmOperandClass {
829    let Name = "LogicalImm64Not";
830    let PredicateMethod = "isLogicalImm<int64_t>";
831    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
832  }
833}
834def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
835  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
836}], logical_imm32_XFORM> {
837  let PrintMethod = "printLogicalImm<int32_t>";
838  let ParserMatchClass = LogicalImm32Operand;
839}
840def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
841  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
842}], logical_imm64_XFORM> {
843  let PrintMethod = "printLogicalImm<int64_t>";
844  let ParserMatchClass = LogicalImm64Operand;
845}
846def logical_imm32_not : Operand<i32> {
847  let ParserMatchClass = LogicalImm32NotOperand;
848}
849def logical_imm64_not : Operand<i64> {
850  let ParserMatchClass = LogicalImm64NotOperand;
851}
852
853// immXX_0_65535 predicates - True if the immediate is in the range [0,65535].
854let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
855def timm32_0_65535 : Operand<i32>, TImmLeaf<i32, [{
856  return ((uint32_t)Imm) < 65536;
857}]>;
858
859def timm64_0_65535 : Operand<i64>, TImmLeaf<i64, [{
860  return ((uint64_t)Imm) < 65536;
861}]>;
862}
863
864// imm0_255 predicate - True if the immediate is in the range [0,255].
865def Imm0_255Operand : AsmImmRange<0,255>;
866
867def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
868  return ((uint32_t)Imm) < 256;
869}]> {
870  let ParserMatchClass = Imm0_255Operand;
871  let PrintMethod = "printImm";
872}
873
874// imm0_127 predicate - True if the immediate is in the range [0,127]
875def Imm0_127Operand : AsmImmRange<0, 127>;
876def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
877  return ((uint32_t)Imm) < 128;
878}]> {
879  let ParserMatchClass = Imm0_127Operand;
880  let PrintMethod = "printImm";
881}
882
883def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
884  return ((uint64_t)Imm) < 128;
885}]> {
886  let ParserMatchClass = Imm0_127Operand;
887  let PrintMethod = "printImm";
888}
889
890// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
891// for all shift-amounts.
892
893// imm0_63 predicate - True if the immediate is in the range [0,63]
894def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
895  return ((uint64_t)Imm) < 64;
896}]> {
897  let ParserMatchClass = Imm0_63Operand;
898}
899
900def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
901  return ((uint64_t)Imm) < 64;
902}]> {
903  let ParserMatchClass = Imm0_63Operand;
904}
905
906// imm0_31 predicate - True if the immediate is in the range [0,31]
907def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
908  return ((uint64_t)Imm) < 32;
909}]> {
910  let ParserMatchClass = Imm0_31Operand;
911}
912
913// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
914// instead of Constant (ImmLeaf)
915def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
916  return ((uint64_t)Imm) < 32;
917}]> {
918  let ParserMatchClass = Imm0_31Operand;
919}
920
921// True if the 32-bit immediate is in the range [0,31]
922def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
923  return ((uint64_t)Imm) < 32;
924}]> {
925  let ParserMatchClass = Imm0_31Operand;
926}
927
928// imm0_1 predicate - True if the immediate is in the range [0,1]
929def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
930  return ((uint64_t)Imm) < 2;
931}]> {
932  let ParserMatchClass = Imm0_1Operand;
933}
934
935// timm0_1 - as above, but use TargetConstant (TImmLeaf)
936def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
937  return ((uint64_t)Imm) < 2;
938}]> {
939  let ParserMatchClass = Imm0_1Operand;
940}
941
942// imm0_15 predicate - True if the immediate is in the range [0,15]
943def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
944  return ((uint64_t)Imm) < 16;
945}]> {
946  let ParserMatchClass = Imm0_15Operand;
947}
948
949// imm0_7 predicate - True if the immediate is in the range [0,7]
950def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
951  return ((uint64_t)Imm) < 8;
952}]> {
953  let ParserMatchClass = Imm0_7Operand;
954}
955
956// imm0_3 predicate - True if the immediate is in the range [0,3]
957def imm0_3 : Operand<i64>, ImmLeaf<i64, [{
958  return ((uint64_t)Imm) < 4;
959}]> {
960  let ParserMatchClass = Imm0_3Operand;
961}
962
963// timm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
964def timm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
965  return ((uint32_t)Imm) < 8;
966}]> {
967  let ParserMatchClass = Imm0_7Operand;
968}
969
970// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
971def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
972  return ((uint32_t)Imm) < 16;
973}]> {
974  let ParserMatchClass = Imm0_15Operand;
975}
976
977// An arithmetic shifter operand:
978//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
979//  {5-0} - imm6
980class arith_shift<ValueType Ty, int width> : Operand<Ty> {
981  let PrintMethod = "printShifter";
982  let ParserMatchClass = !cast<AsmOperandClass>(
983                         "ArithmeticShifterOperand" # width);
984}
985
986def arith_shift32 : arith_shift<i32, 32>;
987def arith_shift64 : arith_shift<i64, 64>;
988
989class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
990    : Operand<Ty>,
991      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
992  let PrintMethod = "printShiftedRegister";
993  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
994}
995
996def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
997def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
998
999def gi_arith_shifted_reg32 :
1000  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
1001  GIComplexPatternEquiv<arith_shifted_reg32>;
1002
1003def gi_arith_shifted_reg64 :
1004  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
1005  GIComplexPatternEquiv<arith_shifted_reg64>;
1006
1007// An arithmetic shifter operand:
1008//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
1009//  {5-0} - imm6
1010class logical_shift<int width> : Operand<i32> {
1011  let PrintMethod = "printShifter";
1012  let ParserMatchClass = !cast<AsmOperandClass>(
1013                         "LogicalShifterOperand" # width);
1014}
1015
1016def logical_shift32 : logical_shift<32>;
1017def logical_shift64 : logical_shift<64>;
1018
1019class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1020    : Operand<Ty>,
1021      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1022  let PrintMethod = "printShiftedRegister";
1023  let MIOperandInfo = (ops regclass, shiftop);
1024}
1025
1026def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1027def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1028
1029def gi_logical_shifted_reg32 :
1030  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1031  GIComplexPatternEquiv<logical_shifted_reg32>;
1032
1033def gi_logical_shifted_reg64 :
1034  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1035  GIComplexPatternEquiv<logical_shifted_reg64>;
1036
1037// A logical vector shifter operand:
1038//  {7-6} - shift type: 00 = lsl
1039//  {5-0} - imm6: #0, #8, #16, or #24
1040def logical_vec_shift : Operand<i32> {
1041  let PrintMethod = "printShifter";
1042  let EncoderMethod = "getVecShifterOpValue";
1043  let ParserMatchClass = LogicalVecShifterOperand;
1044}
1045
1046// A logical vector half-word shifter operand:
1047//  {7-6} - shift type: 00 = lsl
1048//  {5-0} - imm6: #0 or #8
1049def logical_vec_hw_shift : Operand<i32> {
1050  let PrintMethod = "printShifter";
1051  let EncoderMethod = "getVecShifterOpValue";
1052  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1053}
1054
1055// A vector move shifter operand:
1056//  {0} - imm1: #8 or #16
1057def move_vec_shift : Operand<i32> {
1058  let PrintMethod = "printShifter";
1059  let EncoderMethod = "getMoveVecShifterOpValue";
1060  let ParserMatchClass = MoveVecShifterOperand;
1061}
1062
1063let DiagnosticType = "AddSubSecondSource" in {
1064  def AddSubImmOperand : AsmOperandClass {
1065    let Name = "AddSubImm";
1066    let ParserMethod = "tryParseImmWithOptionalShift";
1067    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1068  }
1069  def AddSubImmNegOperand : AsmOperandClass {
1070    let Name = "AddSubImmNeg";
1071    let ParserMethod = "tryParseImmWithOptionalShift";
1072    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1073  }
1074}
1075// An ADD/SUB immediate shifter operand:
1076//  second operand:
1077//  {7-6} - shift type: 00 = lsl
1078//  {5-0} - imm6: #0 or #12
1079class addsub_shifted_imm<ValueType Ty>
1080    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1081  let PrintMethod = "printAddSubImm";
1082  let EncoderMethod = "getAddSubImmOpValue";
1083  let ParserMatchClass = AddSubImmOperand;
1084  let MIOperandInfo = (ops i32imm, i32imm);
1085}
1086
1087class addsub_shifted_imm_neg<ValueType Ty>
1088    : Operand<Ty> {
1089  let EncoderMethod = "getAddSubImmOpValue";
1090  let ParserMatchClass = AddSubImmNegOperand;
1091  let MIOperandInfo = (ops i32imm, i32imm);
1092}
1093
1094def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1095def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1096def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1097def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1098
1099def gi_addsub_shifted_imm32 :
1100    GIComplexOperandMatcher<s32, "selectArithImmed">,
1101    GIComplexPatternEquiv<addsub_shifted_imm32>;
1102
1103def gi_addsub_shifted_imm64 :
1104    GIComplexOperandMatcher<s64, "selectArithImmed">,
1105    GIComplexPatternEquiv<addsub_shifted_imm64>;
1106
1107class neg_addsub_shifted_imm<ValueType Ty>
1108    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1109  let PrintMethod = "printAddSubImm";
1110  let EncoderMethod = "getAddSubImmOpValue";
1111  let ParserMatchClass = AddSubImmOperand;
1112  let MIOperandInfo = (ops i32imm, i32imm);
1113}
1114
1115def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1116def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1117
1118def gi_neg_addsub_shifted_imm32 :
1119    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1120    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1121
1122def gi_neg_addsub_shifted_imm64 :
1123    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1124    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1125
1126// An extend operand:
1127//  {5-3} - extend type
1128//  {2-0} - imm3
1129def arith_extend : Operand<i32> {
1130  let PrintMethod = "printArithExtend";
1131  let ParserMatchClass = ExtendOperand;
1132}
1133def arith_extend64 : Operand<i32> {
1134  let PrintMethod = "printArithExtend";
1135  let ParserMatchClass = ExtendOperand64;
1136}
1137
1138// 'extend' that's a lsl of a 64-bit register.
1139def arith_extendlsl64 : Operand<i32> {
1140  let PrintMethod = "printArithExtend";
1141  let ParserMatchClass = ExtendOperandLSL64;
1142}
1143
1144class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1145                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1146  let PrintMethod = "printExtendedRegister";
1147  let MIOperandInfo = (ops GPR32, arith_extend);
1148}
1149
1150class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1151                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1152  let PrintMethod = "printExtendedRegister";
1153  let MIOperandInfo = (ops GPR32, arith_extend64);
1154}
1155
1156def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1157def gi_arith_extended_reg32_i32 :
1158    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1159    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1160
1161def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1162def gi_arith_extended_reg32_i64 :
1163    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1164    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1165
1166def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1167def gi_arith_extended_reg32to64_i64 :
1168    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1169    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1170
1171// Floating-point immediate.
1172
1173def fpimm16XForm : SDNodeXForm<fpimm, [{
1174      APFloat InVal = N->getValueAPF();
1175      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1176      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1177    }]>;
1178
1179def fpimm32XForm : SDNodeXForm<fpimm, [{
1180      APFloat InVal = N->getValueAPF();
1181      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1182      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1183    }]>;
1184
1185def fpimm32SIMDModImmType4XForm : SDNodeXForm<fpimm, [{
1186      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType4(N->getValueAPF()
1187                                                          .bitcastToAPInt()
1188                                                          .getZExtValue());
1189      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1190    }]>;
1191
1192def fpimm64XForm : SDNodeXForm<fpimm, [{
1193      APFloat InVal = N->getValueAPF();
1194      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1195      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1196    }]>;
1197
1198def fpimm16 : Operand<f16>,
1199              FPImmLeaf<f16, [{
1200      return AArch64_AM::getFP16Imm(Imm) != -1;
1201    }], fpimm16XForm> {
1202  let ParserMatchClass = FPImmOperand;
1203  let PrintMethod = "printFPImmOperand";
1204}
1205
1206def fpimm32 : Operand<f32>,
1207              FPImmLeaf<f32, [{
1208      return AArch64_AM::getFP32Imm(Imm) != -1;
1209    }], fpimm32XForm> {
1210  let ParserMatchClass = FPImmOperand;
1211  let PrintMethod = "printFPImmOperand";
1212}
1213
1214def fpimm32SIMDModImmType4 : FPImmLeaf<f32, [{
1215      uint64_t Enc = Imm.bitcastToAPInt().getZExtValue();
1216      return Enc != 0 && AArch64_AM::isAdvSIMDModImmType4(Enc << 32 | Enc);
1217    }], fpimm32SIMDModImmType4XForm> {
1218}
1219
1220def fpimm64 : Operand<f64>,
1221              FPImmLeaf<f64, [{
1222      return AArch64_AM::getFP64Imm(Imm) != -1;
1223    }], fpimm64XForm> {
1224  let ParserMatchClass = FPImmOperand;
1225  let PrintMethod = "printFPImmOperand";
1226}
1227
1228def fpimm8 : Operand<i32> {
1229  let ParserMatchClass = FPImmOperand;
1230  let PrintMethod = "printFPImmOperand";
1231}
1232
1233def fpimm0 : FPImmLeaf<fAny, [{
1234  return Imm.isExactlyValue(+0.0);
1235}]>;
1236
1237def fpimm_half : FPImmLeaf<fAny, [{
1238  return Imm.isExactlyValue(+0.5);
1239}]>;
1240
1241def fpimm_one : FPImmLeaf<fAny, [{
1242  return Imm.isExactlyValue(+1.0);
1243}]>;
1244
1245def fpimm_two : FPImmLeaf<fAny, [{
1246  return Imm.isExactlyValue(+2.0);
1247}]>;
1248
1249def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1250  GISDNodeXFormEquiv<fpimm16XForm>;
1251def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1252  GISDNodeXFormEquiv<fpimm32XForm>;
1253def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1254  GISDNodeXFormEquiv<fpimm64XForm>;
1255def gi_fpimm32SIMDModImmType4 :
1256    GICustomOperandRenderer<"renderFPImm32SIMDModImmType4">,
1257  GISDNodeXFormEquiv<fpimm32SIMDModImmType4XForm>;
1258
1259// Vector lane operands
1260class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1261  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1262  let DiagnosticType = "Invalid" # Name;
1263  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1264  let RenderMethod = "addVectorIndexOperands";
1265}
1266
1267class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1268    : Operand<ty> {
1269  let ParserMatchClass = mc;
1270  let PrintMethod = "printVectorIndex";
1271}
1272
1273multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1274  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1275  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1276}
1277
1278def VectorIndex0Operand : AsmVectorIndex<0, 0>;
1279def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1280def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1281def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1282def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1283def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1284
1285let OperandNamespace = "AArch64" in {
1286  let OperandType = "OPERAND_IMPLICIT_IMM_0" in {
1287    defm VectorIndex0 : VectorIndex<i64, VectorIndex0Operand,
1288                                [{ return ((uint64_t)Imm) == 0; }]>;
1289  }
1290}
1291defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1292                                [{ return ((uint64_t)Imm) == 1; }]>;
1293defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1294                                [{ return ((uint64_t)Imm) < 16; }]>;
1295defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1296                                [{ return ((uint64_t)Imm) < 8; }]>;
1297defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1298                                [{ return ((uint64_t)Imm) < 4; }]>;
1299defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1300                                [{ return ((uint64_t)Imm) < 2; }]>;
1301
1302defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1303                                   [{ return ((uint64_t)Imm) == 1; }]>;
1304defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1305                                   [{ return ((uint64_t)Imm) < 16; }]>;
1306defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1307                                   [{ return ((uint64_t)Imm) < 8; }]>;
1308defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1309                                   [{ return ((uint64_t)Imm) < 4; }]>;
1310defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1311                                   [{ return ((uint64_t)Imm) < 2; }]>;
1312
1313def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1314def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1315def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1316def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1317def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1318
1319defm sve_elm_idx_extdup_b
1320  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1321                [{ return ((uint64_t)Imm) < 64; }]>;
1322defm sve_elm_idx_extdup_h
1323  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1324                [{ return ((uint64_t)Imm) < 32; }]>;
1325defm sve_elm_idx_extdup_s
1326  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1327                [{ return ((uint64_t)Imm) < 16; }]>;
1328defm sve_elm_idx_extdup_d
1329  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1330                [{ return ((uint64_t)Imm) < 8; }]>;
1331defm sve_elm_idx_extdup_q
1332  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1333                [{ return ((uint64_t)Imm) < 4; }]>;
1334
1335def sme_elm_idx0_0 : Operand<i64>, ImmLeaf<i64, [{
1336  return ((uint64_t)Imm) == 0;
1337}]> {
1338  let ParserMatchClass = Imm0_0Operand;
1339  let PrintMethod = "printMatrixIndex";
1340  let OperandNamespace = "AArch64";
1341  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1342}
1343def sme_elm_idx0_1 : Operand<i64>, ImmLeaf<i64, [{
1344  return ((uint64_t)Imm) <= 1;
1345}]> {
1346  let ParserMatchClass = Imm0_1Operand;
1347  let PrintMethod = "printMatrixIndex";
1348}
1349def sme_elm_idx0_3 : Operand<i64>, ImmLeaf<i64, [{
1350  return ((uint64_t)Imm) <= 3;
1351}]> {
1352  let ParserMatchClass = Imm0_3Operand;
1353  let PrintMethod = "printMatrixIndex";
1354}
1355def sme_elm_idx0_7 : Operand<i64>, ImmLeaf<i64, [{
1356  return ((uint64_t)Imm) <= 7;
1357}]> {
1358  let ParserMatchClass = Imm0_7Operand;
1359  let PrintMethod = "printMatrixIndex";
1360}
1361def sme_elm_idx0_15 : Operand<i64>, ImmLeaf<i64, [{
1362  return ((uint64_t)Imm) <= 15;
1363}]> {
1364  let ParserMatchClass = Imm0_15Operand;
1365  let PrintMethod = "printMatrixIndex";
1366}
1367
1368// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1369// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1370// are encoded as the eight bit value 'abcdefgh'.
1371def simdimmtype10 : Operand<i32>,
1372                    FPImmLeaf<f64, [{
1373      return AArch64_AM::isAdvSIMDModImmType10(
1374                 Imm.bitcastToAPInt().getZExtValue());
1375    }], SDNodeXForm<fpimm, [{
1376      APFloat InVal = N->getValueAPF();
1377      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1378                                                           .bitcastToAPInt()
1379                                                           .getZExtValue());
1380      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1381    }]>> {
1382  let ParserMatchClass = SIMDImmType10Operand;
1383  let PrintMethod = "printSIMDType10Operand";
1384}
1385
1386
1387//---
1388// System management
1389//---
1390
1391// Base encoding for system instruction operands.
1392let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1393class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1394                  list<dag> pattern = []>
1395    : I<oops, iops, asm, operands, "", pattern> {
1396  let Inst{31-22} = 0b1101010100;
1397  let Inst{21}    = L;
1398}
1399
1400// System instructions which do not have an Rt register.
1401class SimpleSystemI<bit L, dag iops, string asm, string operands,
1402                    list<dag> pattern = []>
1403    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1404  let Inst{4-0} = 0b11111;
1405}
1406
1407// System instructions which have an Rt register.
1408class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1409                list<dag> pattern = []>
1410    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1411      Sched<[WriteSys]> {
1412  bits<5> Rt;
1413  let Inst{4-0} = Rt;
1414}
1415
1416// System instructions for transactional memory extension
1417class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1418                    string asm, string operands, list<dag> pattern>
1419    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1420      Sched<[WriteSys]> {
1421  let Inst{20-12} = 0b000110011;
1422  let Inst{11-8} = CRm;
1423  let Inst{7-5} = op2;
1424  let DecoderMethod = "";
1425
1426  let mayLoad = 1;
1427  let mayStore = 1;
1428}
1429
1430// System instructions for transactional memory - single input operand
1431class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1432    : TMBaseSystemI<0b1, CRm, 0b011,
1433                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1434  bits<5> Rt;
1435  let Inst{4-0} = Rt;
1436}
1437
1438// System instructions that pass a register argument
1439// This class assumes the register is for input rather than output.
1440class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1441                      list<dag> pattern = []>
1442    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1443  let Inst{20-12} = 0b000110001;
1444  let Inst{11-8} = CRm;
1445  let Inst{7-5} = Op2;
1446}
1447
1448// System instructions for transactional memory - no operand
1449class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1450    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1451  let Inst{4-0} = 0b11111;
1452}
1453
1454// System instructions for exit from transactions
1455class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1456    : I<(outs), (ins timm64_0_65535:$imm), asm, "\t$imm", "", pattern>,
1457      Sched<[WriteSys]> {
1458  bits<16> imm;
1459  let Inst{31-24} = 0b11010100;
1460  let Inst{23-21} = op1;
1461  let Inst{20-5}  = imm;
1462  let Inst{4-0}   = 0b00000;
1463}
1464
1465// Hint instructions that take both a CRm and a 3-bit immediate.
1466// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1467// model patterns with sufficiently fine granularity
1468let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1469  class HintI<string mnemonic>
1470      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1471                      [(int_aarch64_hint imm0_127:$imm)]>,
1472        Sched<[WriteHint]> {
1473    bits <7> imm;
1474    let Inst{20-12} = 0b000110010;
1475    let Inst{11-5} = imm;
1476  }
1477
1478// System instructions taking a single literal operand which encodes into
1479// CRm. op2 differentiates the opcodes.
1480def BarrierAsmOperand : AsmOperandClass {
1481  let Name = "Barrier";
1482  let ParserMethod = "tryParseBarrierOperand";
1483}
1484def barrier_op : Operand<i32> {
1485  let PrintMethod = "printBarrierOption";
1486  let ParserMatchClass = BarrierAsmOperand;
1487}
1488def BarriernXSAsmOperand : AsmOperandClass {
1489  let Name = "BarriernXS";
1490  let ParserMethod = "tryParseBarriernXSOperand";
1491}
1492def barrier_nxs_op : Operand<i32> {
1493  let PrintMethod = "printBarriernXSOption";
1494  let ParserMatchClass = BarriernXSAsmOperand;
1495}
1496class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1497                 list<dag> pattern = []>
1498    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1499      Sched<[WriteBarrier]> {
1500  bits<4> CRm;
1501  let Inst{20-12} = 0b000110011;
1502  let Inst{11-8} = CRm;
1503  let Inst{7-5} = opc;
1504}
1505
1506class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1507    : SimpleSystemI<0, (ins), asm, "", pattern>,
1508      Sched<[]> {
1509  bits<4> CRm;
1510  let CRm = 0b0011;
1511  let Inst{31-12} = 0b11010101000000110010;
1512  let Inst{11-8} = CRm;
1513  let Inst{7-5} = op2;
1514  let Inst{4-0} = 0b11111;
1515}
1516
1517// MRS/MSR system instructions. These have different operand classes because
1518// a different subset of registers can be accessed through each instruction.
1519def MRSSystemRegisterOperand : AsmOperandClass {
1520  let Name = "MRSSystemRegister";
1521  let ParserMethod = "tryParseSysReg";
1522  let DiagnosticType = "MRS";
1523}
1524// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1525def mrs_sysreg_op : Operand<i32> {
1526  let ParserMatchClass = MRSSystemRegisterOperand;
1527  let DecoderMethod = "DecodeMRSSystemRegister";
1528  let PrintMethod = "printMRSSystemRegister";
1529}
1530
1531def MSRSystemRegisterOperand : AsmOperandClass {
1532  let Name = "MSRSystemRegister";
1533  let ParserMethod = "tryParseSysReg";
1534  let DiagnosticType = "MSR";
1535}
1536def msr_sysreg_op : Operand<i32> {
1537  let ParserMatchClass = MSRSystemRegisterOperand;
1538  let DecoderMethod = "DecodeMSRSystemRegister";
1539  let PrintMethod = "printMSRSystemRegister";
1540}
1541
1542def PSBHintOperand : AsmOperandClass {
1543  let Name = "PSBHint";
1544  let ParserMethod = "tryParsePSBHint";
1545}
1546def psbhint_op : Operand<i32> {
1547  let ParserMatchClass = PSBHintOperand;
1548  let PrintMethod = "printPSBHintOp";
1549  let MCOperandPredicate = [{
1550    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1551    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1552    if (!MCOp.isImm())
1553      return false;
1554    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1555  }];
1556}
1557
1558def BTIHintOperand : AsmOperandClass {
1559  let Name = "BTIHint";
1560  let ParserMethod = "tryParseBTIHint";
1561}
1562def btihint_op : Operand<i32> {
1563  let ParserMatchClass = BTIHintOperand;
1564  let PrintMethod = "printBTIHintOp";
1565  let MCOperandPredicate = [{
1566    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1567    if (!MCOp.isImm())
1568      return false;
1569    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1570  }];
1571}
1572
1573class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1574                       "mrs", "\t$Rt, $systemreg"> {
1575  bits<16> systemreg;
1576  let Inst{20-5} = systemreg;
1577  let DecoderNamespace = "Fallback";
1578  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1579  // require doing this. The alternative was to explicitly model each one, but
1580  // it feels like it is unnecessary because it seems there are no negative
1581  // consequences setting these flags for all.
1582  let Defs = [NZCV];
1583}
1584
1585// FIXME: Some of these def NZCV, others don't. Best way to model that?
1586// Explicitly modeling each of the system register as a register class
1587// would do it, but feels like overkill at this point.
1588class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1589                       "msr", "\t$systemreg, $Rt"> {
1590  bits<16> systemreg;
1591  let Inst{20-5} = systemreg;
1592  let DecoderNamespace = "Fallback";
1593}
1594
1595def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1596  let Name = "SystemPStateFieldWithImm0_15";
1597  let ParserMethod = "tryParseSysReg";
1598}
1599def pstatefield4_op : Operand<i32> {
1600  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1601  let PrintMethod = "printSystemPStateField";
1602}
1603
1604// Instructions to modify PSTATE, no input reg
1605let Defs = [NZCV] in
1606class PstateWriteSimple<dag iops, string asm, string operands>
1607  : SimpleSystemI<0, iops, asm, operands> {
1608
1609  let Inst{20-19} = 0b00;
1610  let Inst{15-12} = 0b0100;
1611}
1612
1613class MSRpstateImm0_15
1614  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1615                  "\t$pstatefield, $imm">,
1616    Sched<[WriteSys]> {
1617
1618  bits<6> pstatefield;
1619  bits<4> imm;
1620  let Inst{18-16} = pstatefield{5-3};
1621  let Inst{11-8} = imm;
1622  let Inst{7-5} = pstatefield{2-0};
1623
1624  let DecoderMethod = "DecodeSystemPStateInstruction";
1625  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1626  // Fail the decoder should attempt to decode the instruction as MSRI.
1627  let hasCompleteDecoder = 0;
1628}
1629
1630def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1631  let Name = "SystemPStateFieldWithImm0_1";
1632  let ParserMethod = "tryParseSysReg";
1633}
1634def pstatefield1_op : Operand<i32> {
1635  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1636  let PrintMethod = "printSystemPStateField";
1637}
1638
1639class MSRpstateImm0_1
1640  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1641                 "\t$pstatefield, $imm">,
1642    Sched<[WriteSys]> {
1643
1644  bits<6> pstatefield;
1645  bit imm;
1646  let Inst{18-16} = pstatefield{5-3};
1647  let Inst{11-9} = 0b000;
1648  let Inst{8} = imm;
1649  let Inst{7-5} = pstatefield{2-0};
1650
1651  let DecoderMethod = "DecodeSystemPStateInstruction";
1652  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1653  // Fail the decoder should attempt to decode the instruction as MSRI.
1654  let hasCompleteDecoder = 0;
1655}
1656
1657// SYS and SYSL generic system instructions.
1658def SysCRAsmOperand : AsmOperandClass {
1659  let Name = "SysCR";
1660  let ParserMethod = "tryParseSysCROperand";
1661}
1662
1663def sys_cr_op : Operand<i32> {
1664  let PrintMethod = "printSysCROperand";
1665  let ParserMatchClass = SysCRAsmOperand;
1666}
1667
1668class SystemXtI<bit L, string asm>
1669  : RtSystemI<L, (outs),
1670       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1671       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1672  bits<3> op1;
1673  bits<4> Cn;
1674  bits<4> Cm;
1675  bits<3> op2;
1676  let Inst{20-19} = 0b01;
1677  let Inst{18-16} = op1;
1678  let Inst{15-12} = Cn;
1679  let Inst{11-8}  = Cm;
1680  let Inst{7-5}   = op2;
1681}
1682
1683class SystemLXtI<bit L, string asm>
1684  : RtSystemI<L, (outs),
1685       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1686       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1687  bits<3> op1;
1688  bits<4> Cn;
1689  bits<4> Cm;
1690  bits<3> op2;
1691  let Inst{20-19} = 0b01;
1692  let Inst{18-16} = op1;
1693  let Inst{15-12} = Cn;
1694  let Inst{11-8}  = Cm;
1695  let Inst{7-5}   = op2;
1696}
1697
1698
1699// Branch (register) instructions:
1700//
1701//  case opc of
1702//    0001 blr
1703//    0000 br
1704//    0101 dret
1705//    0100 eret
1706//    0010 ret
1707//    otherwise UNDEFINED
1708class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1709                    string operands, list<dag> pattern>
1710    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1711  let Inst{31-25} = 0b1101011;
1712  let Inst{24-21} = opc;
1713  let Inst{20-16} = 0b11111;
1714  let Inst{15-10} = 0b000000;
1715  let Inst{4-0}   = 0b00000;
1716}
1717
1718class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1719    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1720  bits<5> Rn;
1721  let Inst{9-5} = Rn;
1722}
1723
1724let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1725class SpecialReturn<bits<4> opc, string asm>
1726    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1727  let Inst{9-5} = 0b11111;
1728}
1729
1730let mayLoad = 1 in
1731class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1732  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1733  Sched<[]> {
1734  bits<5> Rn;
1735  bits<5> Rt;
1736  let Inst{31-30} = sz;
1737  let Inst{29-10} = 0b11100010111111110000;
1738  let Inst{9-5} = Rn;
1739  let Inst{4-0} = Rt;
1740}
1741
1742class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1743               list<dag> pattern>
1744  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1745  let isAuthenticated = 1;
1746  let Inst{31-25} = 0b1101011;
1747  let Inst{20-11} = 0b1111100001;
1748  let Inst{10} = M;
1749  let Inst{4-0} = 0b11111;
1750}
1751
1752class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1753  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1754  bits<5> Rn;
1755  bits<5> Rm;
1756  let Inst{24-22} = 0b100;
1757  let Inst{21} = op;
1758  let Inst{9-5} = Rn;
1759  let Inst{4-0} = Rm;
1760}
1761
1762class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1763  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1764  bits<5> Rn;
1765  let Inst{24} = 0;
1766  let Inst{23-21} = opc;
1767  let Inst{9-5} = Rn;
1768}
1769
1770let Uses = [LR,SP] in
1771class AuthReturn<bits<3> op, bits<1> M, string asm>
1772  : AuthBase<M, (outs), (ins), asm, "", []> {
1773  let Inst{24} = 0;
1774  let Inst{23-21} = op;
1775  let Inst{9-0} = 0b1111111111;
1776}
1777
1778let mayLoad = 1 in
1779class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1780                   string operands, string cstr>
1781  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1782  bits<10> offset;
1783  bits<5> Rn;
1784  bits<5> Rt;
1785  let isAuthenticated = 1;
1786  let Inst{31-24} = 0b11111000;
1787  let Inst{23} = M;
1788  let Inst{22} = offset{9};
1789  let Inst{21} = 1;
1790  let Inst{20-12} = offset{8-0};
1791  let Inst{11} = W;
1792  let Inst{10} = 1;
1793  let Inst{9-5} = Rn;
1794  let Inst{4-0} = Rt;
1795
1796  let DecoderMethod = "DecodeAuthLoadInstruction";
1797}
1798
1799multiclass AuthLoad<bit M, string asm, Operand opr> {
1800  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1801                               (ins GPR64sp:$Rn, opr:$offset),
1802                               asm, "\t$Rt, [$Rn, $offset]", "">;
1803  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1804                               (ins GPR64sp:$Rn, opr:$offset),
1805                               asm, "\t$Rt, [$Rn, $offset]!",
1806                               "$Rn = $wback,@earlyclobber $wback">;
1807
1808  def : InstAlias<asm # "\t$Rt, [$Rn]",
1809                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1810
1811  def : InstAlias<asm # "\t$Rt, [$wback]!",
1812                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1813}
1814
1815//---
1816// Conditional branch instruction.
1817//---
1818
1819// Condition code.
1820// 4-bit immediate. Pretty-printed as <cc>
1821def ccode : Operand<i32> {
1822  let PrintMethod = "printCondCode";
1823  let ParserMatchClass = CondCode;
1824}
1825def inv_ccode : Operand<i32> {
1826  // AL and NV are invalid in the aliases which use inv_ccode
1827  let PrintMethod = "printInverseCondCode";
1828  let ParserMatchClass = CondCode;
1829  let MCOperandPredicate = [{
1830    return MCOp.isImm() &&
1831           MCOp.getImm() != AArch64CC::AL &&
1832           MCOp.getImm() != AArch64CC::NV;
1833  }];
1834}
1835
1836// Conditional branch target. 19-bit immediate. The low two bits of the target
1837// offset are implied zero and so are not part of the immediate.
1838def am_brcond : Operand<OtherVT> {
1839  let EncoderMethod = "getCondBranchTargetOpValue";
1840  let DecoderMethod = "DecodePCRelLabel19";
1841  let PrintMethod = "printAlignedLabel";
1842  let ParserMatchClass = PCRelLabel19Operand;
1843  let OperandType = "OPERAND_PCREL";
1844}
1845
1846class BranchCond<bit bit4, string mnemonic>
1847   : I<(outs), (ins ccode:$cond, am_brcond:$target),
1848       mnemonic, ".$cond\t$target", "",
1849       [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> {
1850  let isBranch = 1;
1851  let isTerminator = 1;
1852  let Uses = [NZCV];
1853
1854  bits<4> cond;
1855  bits<19> target;
1856  let Inst{31-24} = 0b01010100;
1857  let Inst{23-5} = target;
1858  let Inst{4} = bit4;
1859  let Inst{3-0} = cond;
1860}
1861
1862//---
1863// Compare-and-branch instructions.
1864//---
1865class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1866    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1867         asm, "\t$Rt, $target", "",
1868         [(node regtype:$Rt, bb:$target)]>,
1869      Sched<[WriteBr]> {
1870  let isBranch = 1;
1871  let isTerminator = 1;
1872
1873  bits<5> Rt;
1874  bits<19> target;
1875  let Inst{30-25} = 0b011010;
1876  let Inst{24}    = op;
1877  let Inst{23-5}  = target;
1878  let Inst{4-0}   = Rt;
1879}
1880
1881multiclass CmpBranch<bit op, string asm, SDNode node> {
1882  def W : BaseCmpBranch<GPR32, op, asm, node> {
1883    let Inst{31} = 0;
1884  }
1885  def X : BaseCmpBranch<GPR64, op, asm, node> {
1886    let Inst{31} = 1;
1887  }
1888}
1889
1890//---
1891// Test-bit-and-branch instructions.
1892//---
1893// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1894// the target offset are implied zero and so are not part of the immediate.
1895def am_tbrcond : Operand<OtherVT> {
1896  let EncoderMethod = "getTestBranchTargetOpValue";
1897  let PrintMethod = "printAlignedLabel";
1898  let ParserMatchClass = BranchTarget14Operand;
1899  let OperandType = "OPERAND_PCREL";
1900}
1901
1902// AsmOperand classes to emit (or not) special diagnostics
1903def TBZImm0_31Operand : AsmOperandClass {
1904  let Name = "TBZImm0_31";
1905  let PredicateMethod = "isImmInRange<0,31>";
1906  let RenderMethod = "addImmOperands";
1907}
1908def TBZImm32_63Operand : AsmOperandClass {
1909  let Name = "Imm32_63";
1910  let PredicateMethod = "isImmInRange<32,63>";
1911  let DiagnosticType = "InvalidImm0_63";
1912  let RenderMethod = "addImmOperands";
1913}
1914
1915class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1916  return (((uint32_t)Imm) < 32);
1917}]> {
1918  let ParserMatchClass = matcher;
1919}
1920
1921def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1922def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1923
1924def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1925  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1926}]> {
1927  let ParserMatchClass = TBZImm32_63Operand;
1928}
1929
1930class BaseTestBranch<RegisterClass regtype, Operand immtype,
1931                     bit op, string asm, SDNode node>
1932    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1933       asm, "\t$Rt, $bit_off, $target", "",
1934       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1935      Sched<[WriteBr]> {
1936  let isBranch = 1;
1937  let isTerminator = 1;
1938
1939  bits<5> Rt;
1940  bits<6> bit_off;
1941  bits<14> target;
1942
1943  let Inst{30-25} = 0b011011;
1944  let Inst{24}    = op;
1945  let Inst{23-19} = bit_off{4-0};
1946  let Inst{18-5}  = target;
1947  let Inst{4-0}   = Rt;
1948
1949  let DecoderMethod = "DecodeTestAndBranch";
1950}
1951
1952multiclass TestBranch<bit op, string asm, SDNode node> {
1953  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1954    let Inst{31} = 0;
1955  }
1956
1957  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1958    let Inst{31} = 1;
1959  }
1960
1961  // Alias X-reg with 0-31 imm to W-Reg.
1962  def : InstAlias<asm # "\t$Rd, $imm, $target",
1963                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1964                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1965  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1966            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1967            tbz_imm0_31_diag:$imm, bb:$target)>;
1968}
1969
1970//---
1971// Unconditional branch (immediate) instructions.
1972//---
1973def am_b_target : Operand<OtherVT> {
1974  let EncoderMethod = "getBranchTargetOpValue";
1975  let PrintMethod = "printAlignedLabel";
1976  let ParserMatchClass = BranchTarget26Operand;
1977  let OperandType = "OPERAND_PCREL";
1978}
1979def am_bl_target : Operand<i64> {
1980  let EncoderMethod = "getBranchTargetOpValue";
1981  let PrintMethod = "printAlignedLabel";
1982  let ParserMatchClass = BranchTarget26Operand;
1983  let OperandType = "OPERAND_PCREL";
1984}
1985
1986class BImm<bit op, dag iops, string asm, list<dag> pattern>
1987    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1988  bits<26> addr;
1989  let Inst{31}    = op;
1990  let Inst{30-26} = 0b00101;
1991  let Inst{25-0}  = addr;
1992
1993  let DecoderMethod = "DecodeUnconditionalBranch";
1994}
1995
1996class BranchImm<bit op, string asm, list<dag> pattern>
1997    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1998class CallImm<bit op, string asm, list<dag> pattern>
1999    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
2000
2001//---
2002// Basic one-operand data processing instructions.
2003//---
2004
2005let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2006class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
2007                         SDPatternOperator node>
2008  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
2009      [(set regtype:$Rd, (node regtype:$Rn))]>,
2010    Sched<[WriteI, ReadI]> {
2011  bits<5> Rd;
2012  bits<5> Rn;
2013
2014  let Inst{30-13} = 0b101101011000000000;
2015  let Inst{12-10} = opc;
2016  let Inst{9-5}   = Rn;
2017  let Inst{4-0}   = Rd;
2018}
2019
2020let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2021multiclass OneOperandData<bits<3> opc, string asm,
2022                          SDPatternOperator node = null_frag> {
2023  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
2024    let Inst{31} = 0;
2025  }
2026
2027  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
2028    let Inst{31} = 1;
2029  }
2030}
2031
2032class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
2033    : BaseOneOperandData<opc, GPR32, asm, node> {
2034  let Inst{31} = 0;
2035}
2036
2037class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
2038    : BaseOneOperandData<opc, GPR64, asm, node> {
2039  let Inst{31} = 1;
2040}
2041
2042class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm,
2043                      SDPatternOperator op>
2044  : I<(outs GPR64:$dst), (ins GPR64:$Rd, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
2045      "$dst = $Rd", [(set GPR64:$dst, (op GPR64:$Rd, opcode, GPR64sp:$Rn))]>,
2046    Sched<[WriteI, ReadI]> {
2047  bits<5> Rd;
2048  bits<5> Rn;
2049  let Inst{31-15} = 0b11011010110000010;
2050  let Inst{14-12} = opcode_prefix;
2051  let Inst{11-10} = opcode;
2052  let Inst{9-5} = Rn;
2053  let Inst{4-0} = Rd;
2054}
2055
2056class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm,
2057                   SDPatternOperator op>
2058  : I<(outs GPR64:$dst), (ins GPR64:$Rd), asm, "\t$Rd", "$dst = $Rd",
2059      [(set GPR64:$dst, (op GPR64:$Rd, opcode, (i64 0)))]>,
2060    Sched<[]> {
2061  bits<5> Rd;
2062  let Inst{31-15} = 0b11011010110000010;
2063  let Inst{14-12} = opcode_prefix;
2064  let Inst{11-10} = opcode;
2065  let Inst{9-5} = 0b11111;
2066  let Inst{4-0} = Rd;
2067}
2068
2069class SignAuthTwoOperand<bits<4> opc, string asm,
2070                         SDPatternOperator OpNode>
2071  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
2072      asm, "\t$Rd, $Rn, $Rm", "",
2073      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
2074    Sched<[WriteI, ReadI, ReadI]> {
2075  bits<5> Rd;
2076  bits<5> Rn;
2077  bits<5> Rm;
2078  let Inst{31-21} = 0b10011010110;
2079  let Inst{20-16} = Rm;
2080  let Inst{15-14} = 0b00;
2081  let Inst{13-10} = opc;
2082  let Inst{9-5}   = Rn;
2083  let Inst{4-0}   = Rd;
2084}
2085
2086class ClearAuth<bits<1> data, string asm>
2087  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2088  bits<5> Rd;
2089  let Inst{31-11} = 0b110110101100000101000;
2090  let Inst{10} = data;
2091  let Inst{9-5} = 0b11111;
2092  let Inst{4-0} = Rd;
2093}
2094
2095// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2096class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2097    : I<(outs), iops, asm, ops, "", []>,
2098      Sched<[WriteI, ReadI, ReadI]> {
2099  let Uses = [NZCV];
2100  let Defs = [NZCV];
2101  bits<5> Rn;
2102  let Inst{31}    = sf;
2103  let Inst{30-15} = 0b0111010000000000;
2104  let Inst{14}    = sz;
2105  let Inst{13-10} = 0b0010;
2106  let Inst{9-5}   = Rn;
2107  let Inst{4-0}   = 0b01101;
2108}
2109
2110class FlagRotate<dag iops, string asm, string ops>
2111    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2112  bits<6> imm;
2113  bits<4> mask;
2114  let Inst{20-15} = imm;
2115  let Inst{13-10} = 0b0001;
2116  let Inst{4}     = 0b0;
2117  let Inst{3-0}   = mask;
2118}
2119
2120//---
2121// Basic two-operand data processing instructions.
2122//---
2123class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2124                          list<dag> pattern>
2125    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2126        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2127      Sched<[WriteI, ReadI, ReadI]> {
2128  let Uses = [NZCV];
2129  bits<5> Rd;
2130  bits<5> Rn;
2131  bits<5> Rm;
2132  let Inst{30}    = isSub;
2133  let Inst{28-21} = 0b11010000;
2134  let Inst{20-16} = Rm;
2135  let Inst{15-10} = 0;
2136  let Inst{9-5}   = Rn;
2137  let Inst{4-0}   = Rd;
2138}
2139
2140class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2141                      SDNode OpNode>
2142    : BaseBaseAddSubCarry<isSub, regtype, asm,
2143        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2144
2145class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2146                              SDNode OpNode>
2147    : BaseBaseAddSubCarry<isSub, regtype, asm,
2148        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2149         (implicit NZCV)]> {
2150  let Defs = [NZCV];
2151}
2152
2153multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2154                       SDNode OpNode, SDNode OpNode_setflags> {
2155  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2156    let Inst{31} = 0;
2157    let Inst{29} = 0;
2158  }
2159  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2160    let Inst{31} = 1;
2161    let Inst{29} = 0;
2162  }
2163
2164  // Sets flags.
2165  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2166                                    OpNode_setflags> {
2167    let Inst{31} = 0;
2168    let Inst{29} = 1;
2169  }
2170  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2171                                    OpNode_setflags> {
2172    let Inst{31} = 1;
2173    let Inst{29} = 1;
2174  }
2175}
2176
2177class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
2178                     SDPatternOperator OpNode,
2179                     RegisterClass in1regtype = regtype,
2180                     RegisterClass in2regtype = regtype>
2181  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2182      asm, "\t$Rd, $Rn, $Rm", "",
2183      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2184  bits<5> Rd;
2185  bits<5> Rn;
2186  bits<5> Rm;
2187  let Inst{30-21} = 0b0011010110;
2188  let Inst{20-16} = Rm;
2189  let Inst{15-14} = 0b00;
2190  let Inst{13-10} = opc;
2191  let Inst{9-5}   = Rn;
2192  let Inst{4-0}   = Rd;
2193}
2194
2195class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
2196              SDPatternOperator OpNode>
2197    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
2198  let Inst{10}    = isSigned;
2199}
2200
2201multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2202  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
2203           Sched<[WriteID32, ReadID, ReadID]> {
2204    let Inst{31} = 0;
2205  }
2206  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
2207           Sched<[WriteID64, ReadID, ReadID]> {
2208    let Inst{31} = 1;
2209  }
2210}
2211
2212class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
2213                SDPatternOperator OpNode = null_frag>
2214  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
2215    Sched<[WriteIS, ReadI]> {
2216  let Inst{11-10} = shift_type;
2217}
2218
2219multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2220  def Wr : BaseShift<shift_type, GPR32, asm> {
2221    let Inst{31} = 0;
2222  }
2223
2224  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
2225    let Inst{31} = 1;
2226  }
2227
2228  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2229            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2230                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2231
2232  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2233            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2234
2235  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2236            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2237
2238  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2239            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2240
2241  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2242            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2243                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2244
2245  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2246            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2247                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2248}
2249
2250class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2251    : InstAlias<asm#"\t$dst, $src1, $src2",
2252                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2253
2254class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2255                       RegisterClass addtype, string asm,
2256                       list<dag> pattern>
2257  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2258      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2259  bits<5> Rd;
2260  bits<5> Rn;
2261  bits<5> Rm;
2262  bits<5> Ra;
2263  let Inst{30-24} = 0b0011011;
2264  let Inst{23-21} = opc;
2265  let Inst{20-16} = Rm;
2266  let Inst{15}    = isSub;
2267  let Inst{14-10} = Ra;
2268  let Inst{9-5}   = Rn;
2269  let Inst{4-0}   = Rd;
2270}
2271
2272multiclass MulAccum<bit isSub, string asm> {
2273  // MADD/MSUB generation is decided by MachineCombiner.cpp
2274  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, []>,
2275      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2276    let Inst{31} = 0;
2277  }
2278
2279  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, []>,
2280      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2281    let Inst{31} = 1;
2282  }
2283}
2284
2285class WideMulAccum<bit isSub, bits<3> opc, string asm,
2286                   SDNode AccNode, SDNode ExtNode>
2287  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2288    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2289                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2290    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2291  let Inst{31} = 1;
2292}
2293
2294class MulHi<bits<3> opc, string asm, SDNode OpNode>
2295  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2296      asm, "\t$Rd, $Rn, $Rm", "",
2297      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2298    Sched<[WriteIM64, ReadIM, ReadIM]> {
2299  bits<5> Rd;
2300  bits<5> Rn;
2301  bits<5> Rm;
2302  let Inst{31-24} = 0b10011011;
2303  let Inst{23-21} = opc;
2304  let Inst{20-16} = Rm;
2305  let Inst{15}    = 0;
2306  let Inst{9-5}   = Rn;
2307  let Inst{4-0}   = Rd;
2308
2309  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2310  // (i.e. all bits 1) but is ignored by the processor.
2311  let PostEncoderMethod = "fixMulHigh";
2312}
2313
2314class MulAccumWAlias<string asm, Instruction inst>
2315    : InstAlias<asm#"\t$dst, $src1, $src2",
2316                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2317class MulAccumXAlias<string asm, Instruction inst>
2318    : InstAlias<asm#"\t$dst, $src1, $src2",
2319                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2320class WideMulAccumAlias<string asm, Instruction inst>
2321    : InstAlias<asm#"\t$dst, $src1, $src2",
2322                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2323
2324class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2325              SDPatternOperator OpNode, string asm>
2326  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2327      asm, "\t$Rd, $Rn, $Rm", "",
2328      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2329    Sched<[WriteISReg, ReadI, ReadISReg]> {
2330  bits<5> Rd;
2331  bits<5> Rn;
2332  bits<5> Rm;
2333
2334  let Inst{31} = sf;
2335  let Inst{30-21} = 0b0011010110;
2336  let Inst{20-16} = Rm;
2337  let Inst{15-13} = 0b010;
2338  let Inst{12} = C;
2339  let Inst{11-10} = sz;
2340  let Inst{9-5} = Rn;
2341  let Inst{4-0} = Rd;
2342  let Predicates = [HasCRC];
2343}
2344
2345//---
2346// Address generation.
2347//---
2348
2349class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2350    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2351        pattern>,
2352      Sched<[WriteI]> {
2353  bits<5>  Xd;
2354  bits<21> label;
2355  let Inst{31}    = page;
2356  let Inst{30-29} = label{1-0};
2357  let Inst{28-24} = 0b10000;
2358  let Inst{23-5}  = label{20-2};
2359  let Inst{4-0}   = Xd;
2360
2361  let DecoderMethod = "DecodeAdrInstruction";
2362}
2363
2364//---
2365// Move immediate.
2366//---
2367
2368def movimm32_imm : Operand<i32> {
2369  let ParserMatchClass = AsmImmRange<0, 65535>;
2370  let EncoderMethod = "getMoveWideImmOpValue";
2371  let PrintMethod = "printImm";
2372}
2373def movimm32_shift : Operand<i32> {
2374  let PrintMethod = "printShifter";
2375  let ParserMatchClass = MovImm32ShifterOperand;
2376}
2377def movimm64_shift : Operand<i32> {
2378  let PrintMethod = "printShifter";
2379  let ParserMatchClass = MovImm64ShifterOperand;
2380}
2381
2382let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2383class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2384                        string asm>
2385  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2386       asm, "\t$Rd, $imm$shift", "", []>,
2387    Sched<[WriteImm]> {
2388  bits<5> Rd;
2389  bits<16> imm;
2390  bits<6> shift;
2391  let Inst{30-29} = opc;
2392  let Inst{28-23} = 0b100101;
2393  let Inst{22-21} = shift{5-4};
2394  let Inst{20-5}  = imm;
2395  let Inst{4-0}   = Rd;
2396
2397  let DecoderMethod = "DecodeMoveImmInstruction";
2398}
2399
2400multiclass MoveImmediate<bits<2> opc, string asm> {
2401  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2402    let Inst{31} = 0;
2403  }
2404
2405  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2406    let Inst{31} = 1;
2407  }
2408}
2409
2410let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2411class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2412                          string asm>
2413  : I<(outs regtype:$Rd),
2414      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2415       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2416    Sched<[WriteI, ReadI]> {
2417  bits<5> Rd;
2418  bits<16> imm;
2419  bits<6> shift;
2420  let Inst{30-29} = opc;
2421  let Inst{28-23} = 0b100101;
2422  let Inst{22-21} = shift{5-4};
2423  let Inst{20-5}  = imm;
2424  let Inst{4-0}   = Rd;
2425
2426  let DecoderMethod = "DecodeMoveImmInstruction";
2427}
2428
2429multiclass InsertImmediate<bits<2> opc, string asm> {
2430  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2431    let Inst{31} = 0;
2432  }
2433
2434  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2435    let Inst{31} = 1;
2436  }
2437}
2438
2439//---
2440// Add/Subtract
2441//---
2442
2443class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2444                    string asm_inst, string asm_ops,
2445                    dag inputs, dag pattern>
2446    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2447      Sched<[WriteI, ReadI]> {
2448  bits<5>  Rd;
2449  bits<5>  Rn;
2450  let Inst{30}    = isSub;
2451  let Inst{29}    = setFlags;
2452  let Inst{28-24} = 0b10001;
2453  let Inst{9-5}   = Rn;
2454  let Inst{4-0}   = Rd;
2455}
2456
2457class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2458                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2459                     string asm_inst, SDPatternOperator OpNode>
2460    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2461                    (ins srcRegtype:$Rn, immtype:$imm),
2462                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2463  bits<14> imm;
2464  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2465  let Inst{21-10} = imm{11-0};
2466  let DecoderMethod = "DecodeAddSubImmShift";
2467}
2468
2469class BaseAddSubRegPseudo<RegisterClass regtype,
2470                          SDPatternOperator OpNode>
2471    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2472             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2473      Sched<[WriteI, ReadI, ReadI]>;
2474
2475class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2476                     arith_shifted_reg shifted_regtype, string asm,
2477                     SDPatternOperator OpNode>
2478    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2479        asm, "\t$Rd, $Rn, $Rm", "",
2480        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2481      Sched<[WriteISReg, ReadI, ReadISReg]> {
2482  // The operands are in order to match the 'addr' MI operands, so we
2483  // don't need an encoder method and by-name matching. Just use the default
2484  // in-order handling. Since we're using by-order, make sure the names
2485  // do not match.
2486  bits<5> dst;
2487  bits<5> src1;
2488  bits<5> src2;
2489  bits<8> shift;
2490  let Inst{30}    = isSub;
2491  let Inst{29}    = setFlags;
2492  let Inst{28-24} = 0b01011;
2493  let Inst{23-22} = shift{7-6};
2494  let Inst{21}    = 0;
2495  let Inst{20-16} = src2;
2496  let Inst{15-10} = shift{5-0};
2497  let Inst{9-5}   = src1;
2498  let Inst{4-0}   = dst;
2499
2500  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2501}
2502
2503class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2504                     RegisterClass src1Regtype, Operand src2Regtype,
2505                     string asm, SDPatternOperator OpNode>
2506    : I<(outs dstRegtype:$R1),
2507        (ins src1Regtype:$R2, src2Regtype:$R3),
2508        asm, "\t$R1, $R2, $R3", "",
2509        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2510      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2511  bits<5> Rd;
2512  bits<5> Rn;
2513  bits<5> Rm;
2514  bits<6> ext;
2515  let Inst{30}    = isSub;
2516  let Inst{29}    = setFlags;
2517  let Inst{28-24} = 0b01011;
2518  let Inst{23-21} = 0b001;
2519  let Inst{20-16} = Rm;
2520  let Inst{15-13} = ext{5-3};
2521  let Inst{12-10} = ext{2-0};
2522  let Inst{9-5}   = Rn;
2523  let Inst{4-0}   = Rd;
2524
2525  let DecoderMethod = "DecodeAddSubERegInstruction";
2526}
2527
2528let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2529class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2530                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2531                       Operand ext_op, string asm>
2532    : I<(outs dstRegtype:$Rd),
2533        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2534        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2535      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2536  bits<5> Rd;
2537  bits<5> Rn;
2538  bits<5> Rm;
2539  bits<6> ext;
2540  let Inst{30}    = isSub;
2541  let Inst{29}    = setFlags;
2542  let Inst{28-24} = 0b01011;
2543  let Inst{23-21} = 0b001;
2544  let Inst{20-16} = Rm;
2545  let Inst{15}    = ext{5};
2546  let Inst{12-10} = ext{2-0};
2547  let Inst{9-5}   = Rn;
2548  let Inst{4-0}   = Rd;
2549
2550  let DecoderMethod = "DecodeAddSubERegInstruction";
2551}
2552
2553// Aliases for register+register add/subtract.
2554class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2555                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2556                     int shiftExt>
2557    : InstAlias<asm#"\t$dst, $src1, $src2",
2558                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2559                      shiftExt)>;
2560
2561multiclass AddSub<bit isSub, string mnemonic, string alias,
2562                  SDPatternOperator OpNode = null_frag> {
2563  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2564  // Add/Subtract immediate
2565  // Increase the weight of the immediate variant to try to match it before
2566  // the extended register variant.
2567  // We used to match the register variant before the immediate when the
2568  // register argument could be implicitly zero-extended.
2569  let AddedComplexity = 6 in
2570  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2571                           mnemonic, OpNode> {
2572    let Inst{31} = 0;
2573  }
2574  let AddedComplexity = 6 in
2575  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2576                           mnemonic, OpNode> {
2577    let Inst{31} = 1;
2578  }
2579
2580  // Add/Subtract register - Only used for CodeGen
2581  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2582  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2583
2584  // Add/Subtract shifted register
2585  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2586                           OpNode> {
2587    let Inst{31} = 0;
2588  }
2589  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2590                           OpNode> {
2591    let Inst{31} = 1;
2592  }
2593  }
2594
2595  // Add/Subtract extended register
2596  let AddedComplexity = 1, hasSideEffects = 0 in {
2597  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2598                           arith_extended_reg32_i32, mnemonic, OpNode> {
2599    let Inst{31} = 0;
2600  }
2601  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2602                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2603    let Inst{31} = 1;
2604  }
2605  }
2606
2607  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2608                               arith_extendlsl64, mnemonic> {
2609    // UXTX and SXTX only.
2610    let Inst{14-13} = 0b11;
2611    let Inst{31} = 1;
2612  }
2613
2614  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2615  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2616                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2617                      addsub_shifted_imm32_neg:$imm), 0>;
2618  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2619                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2620                       addsub_shifted_imm64_neg:$imm), 0>;
2621
2622  // Register/register aliases with no shift when SP is not used.
2623  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2624                       GPR32, GPR32, GPR32, 0>;
2625  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2626                       GPR64, GPR64, GPR64, 0>;
2627
2628  // Register/register aliases with no shift when either the destination or
2629  // first source register is SP.
2630  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2631                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2632  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2633                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2634  def : AddSubRegAlias<mnemonic,
2635                       !cast<Instruction>(NAME#"Xrx64"),
2636                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2637  def : AddSubRegAlias<mnemonic,
2638                       !cast<Instruction>(NAME#"Xrx64"),
2639                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2640}
2641
2642multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2643                   string alias, string cmpAlias> {
2644  let isCompare = 1, Defs = [NZCV] in {
2645  // Add/Subtract immediate
2646  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2647                           mnemonic, OpNode> {
2648    let Inst{31} = 0;
2649  }
2650  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2651                           mnemonic, OpNode> {
2652    let Inst{31} = 1;
2653  }
2654
2655  // Add/Subtract register
2656  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2657  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2658
2659  // Add/Subtract shifted register
2660  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2661                           OpNode> {
2662    let Inst{31} = 0;
2663  }
2664  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2665                           OpNode> {
2666    let Inst{31} = 1;
2667  }
2668
2669  // Add/Subtract extended register
2670  let AddedComplexity = 1 in {
2671  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2672                           arith_extended_reg32_i32, mnemonic, OpNode> {
2673    let Inst{31} = 0;
2674  }
2675  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2676                           arith_extended_reg32_i64, mnemonic, OpNode> {
2677    let Inst{31} = 1;
2678  }
2679  }
2680
2681  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2682                               arith_extendlsl64, mnemonic> {
2683    // UXTX and SXTX only.
2684    let Inst{14-13} = 0b11;
2685    let Inst{31} = 1;
2686  }
2687  } // Defs = [NZCV]
2688
2689  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2690  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2691                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2692                      addsub_shifted_imm32_neg:$imm), 0>;
2693  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2694                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2695                       addsub_shifted_imm64_neg:$imm), 0>;
2696
2697  // Compare aliases
2698  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2699                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2700  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2701                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2702  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2703                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2704  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2705                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2706  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2707                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2708  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2709                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2710  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2711                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2712
2713  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2714  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2715                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2716  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2717                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2718
2719  // Compare shorthands
2720  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2721                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2722  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2723                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2724  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2725                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2726  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2727                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2728
2729  // Register/register aliases with no shift when SP is not used.
2730  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2731                       GPR32, GPR32, GPR32, 0>;
2732  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2733                       GPR64, GPR64, GPR64, 0>;
2734
2735  // Register/register aliases with no shift when the first source register
2736  // is SP.
2737  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2738                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2739  def : AddSubRegAlias<mnemonic,
2740                       !cast<Instruction>(NAME#"Xrx64"),
2741                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2742}
2743
2744class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2745      : BaseAddSubImm<
2746          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2747          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2748          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2749  bits<6> imm6;
2750  bits<4> imm4;
2751  let Inst{31} = 1;
2752  let Inst{23-22} = 0b10;
2753  let Inst{21-16} = imm6;
2754  let Inst{15-14} = 0b00;
2755  let Inst{13-10} = imm4;
2756  let Unpredictable{15-14} = 0b11;
2757}
2758
2759class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2760      : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2761  let Inst{31} = 1;
2762  let Inst{29} = setsFlags;
2763}
2764
2765//---
2766// Extract
2767//---
2768def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2769                                      SDTCisPtrTy<3>]>;
2770def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2771
2772class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2773                     list<dag> patterns>
2774    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2775         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2776      Sched<[WriteExtr, ReadExtrHi]> {
2777  bits<5> Rd;
2778  bits<5> Rn;
2779  bits<5> Rm;
2780  bits<6> imm;
2781
2782  let Inst{30-23} = 0b00100111;
2783  let Inst{21}    = 0;
2784  let Inst{20-16} = Rm;
2785  let Inst{15-10} = imm;
2786  let Inst{9-5}   = Rn;
2787  let Inst{4-0}   = Rd;
2788}
2789
2790multiclass ExtractImm<string asm> {
2791  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2792                      [(set GPR32:$Rd,
2793                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2794    let Inst{31} = 0;
2795    let Inst{22} = 0;
2796    // imm<5> must be zero.
2797    let imm{5}   = 0;
2798  }
2799  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2800                      [(set GPR64:$Rd,
2801                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2802
2803    let Inst{31} = 1;
2804    let Inst{22} = 1;
2805  }
2806}
2807
2808//---
2809// Bitfield
2810//---
2811
2812let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2813class BaseBitfieldImm<bits<2> opc,
2814                      RegisterClass regtype, Operand imm_type, string asm>
2815    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2816         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2817      Sched<[WriteIS, ReadI]> {
2818  bits<5> Rd;
2819  bits<5> Rn;
2820  bits<6> immr;
2821  bits<6> imms;
2822
2823  let Inst{30-29} = opc;
2824  let Inst{28-23} = 0b100110;
2825  let Inst{21-16} = immr;
2826  let Inst{15-10} = imms;
2827  let Inst{9-5}   = Rn;
2828  let Inst{4-0}   = Rd;
2829}
2830
2831multiclass BitfieldImm<bits<2> opc, string asm> {
2832  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2833    let Inst{31} = 0;
2834    let Inst{22} = 0;
2835    // imms<5> and immr<5> must be zero, else ReservedValue().
2836    let Inst{21} = 0;
2837    let Inst{15} = 0;
2838  }
2839  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2840    let Inst{31} = 1;
2841    let Inst{22} = 1;
2842  }
2843}
2844
2845let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2846class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2847                      RegisterClass regtype, Operand imm_type, string asm>
2848    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2849                             imm_type:$imms),
2850         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2851      Sched<[WriteIS, ReadI]> {
2852  bits<5> Rd;
2853  bits<5> Rn;
2854  bits<6> immr;
2855  bits<6> imms;
2856
2857  let Inst{30-29} = opc;
2858  let Inst{28-23} = 0b100110;
2859  let Inst{21-16} = immr;
2860  let Inst{15-10} = imms;
2861  let Inst{9-5}   = Rn;
2862  let Inst{4-0}   = Rd;
2863}
2864
2865multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2866  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2867    let Inst{31} = 0;
2868    let Inst{22} = 0;
2869    // imms<5> and immr<5> must be zero, else ReservedValue().
2870    let Inst{21} = 0;
2871    let Inst{15} = 0;
2872  }
2873  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2874    let Inst{31} = 1;
2875    let Inst{22} = 1;
2876  }
2877}
2878
2879//---
2880// Logical
2881//---
2882
2883// Logical (immediate)
2884class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2885                     RegisterClass sregtype, Operand imm_type, string asm,
2886                     list<dag> pattern>
2887    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2888         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2889      Sched<[WriteI, ReadI]> {
2890  bits<5>  Rd;
2891  bits<5>  Rn;
2892  bits<13> imm;
2893  let Inst{30-29} = opc;
2894  let Inst{28-23} = 0b100100;
2895  let Inst{22}    = imm{12};
2896  let Inst{21-16} = imm{11-6};
2897  let Inst{15-10} = imm{5-0};
2898  let Inst{9-5}   = Rn;
2899  let Inst{4-0}   = Rd;
2900
2901  let DecoderMethod = "DecodeLogicalImmInstruction";
2902}
2903
2904// Logical (shifted register)
2905class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2906                      logical_shifted_reg shifted_regtype, string asm,
2907                      list<dag> pattern>
2908    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2909        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2910      Sched<[WriteISReg, ReadI, ReadISReg]> {
2911  // The operands are in order to match the 'addr' MI operands, so we
2912  // don't need an encoder method and by-name matching. Just use the default
2913  // in-order handling. Since we're using by-order, make sure the names
2914  // do not match.
2915  bits<5> dst;
2916  bits<5> src1;
2917  bits<5> src2;
2918  bits<8> shift;
2919  let Inst{30-29} = opc;
2920  let Inst{28-24} = 0b01010;
2921  let Inst{23-22} = shift{7-6};
2922  let Inst{21}    = N;
2923  let Inst{20-16} = src2;
2924  let Inst{15-10} = shift{5-0};
2925  let Inst{9-5}   = src1;
2926  let Inst{4-0}   = dst;
2927
2928  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2929}
2930
2931// Aliases for register+register logical instructions.
2932class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2933    : InstAlias<asm#"\t$dst, $src1, $src2",
2934                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2935
2936multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2937                      string Alias> {
2938  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2939  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2940                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2941                                               logical_imm32:$imm))]> {
2942    let Inst{31} = 0;
2943    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2944  }
2945  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2946  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2947                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2948                                               logical_imm64:$imm))]> {
2949    let Inst{31} = 1;
2950  }
2951
2952  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2953                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2954                      logical_imm32_not:$imm), 0>;
2955  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2956                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2957                       logical_imm64_not:$imm), 0>;
2958}
2959
2960multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2961                       string Alias> {
2962  let isCompare = 1, Defs = [NZCV] in {
2963  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2964      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2965    let Inst{31} = 0;
2966    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2967  }
2968  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2969      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2970    let Inst{31} = 1;
2971  }
2972  } // end Defs = [NZCV]
2973
2974  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2975                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2976                      logical_imm32_not:$imm), 0>;
2977  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2978                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2979                       logical_imm64_not:$imm), 0>;
2980}
2981
2982class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2983    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2984             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2985      Sched<[WriteI, ReadI, ReadI]>;
2986
2987// Split from LogicalImm as not all instructions have both.
2988multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2989                      SDPatternOperator OpNode> {
2990  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2991  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2992  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2993  }
2994
2995  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2996                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2997                                                 logical_shifted_reg32:$Rm))]> {
2998    let Inst{31} = 0;
2999  }
3000  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3001                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
3002                                                 logical_shifted_reg64:$Rm))]> {
3003    let Inst{31} = 1;
3004  }
3005
3006  def : LogicalRegAlias<mnemonic,
3007                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3008  def : LogicalRegAlias<mnemonic,
3009                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3010}
3011
3012// Split from LogicalReg to allow setting NZCV Defs
3013multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
3014                       SDPatternOperator OpNode = null_frag> {
3015  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
3016  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3017  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3018
3019  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3020            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
3021    let Inst{31} = 0;
3022  }
3023  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3024            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
3025    let Inst{31} = 1;
3026  }
3027  } // Defs = [NZCV]
3028
3029  def : LogicalRegAlias<mnemonic,
3030                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3031  def : LogicalRegAlias<mnemonic,
3032                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3033}
3034
3035//---
3036// Conditionally set flags
3037//---
3038
3039let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3040class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3041                            string mnemonic, SDNode OpNode>
3042    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3043         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3044         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3045                             (i32 imm:$cond), NZCV))]>,
3046      Sched<[WriteI, ReadI]> {
3047  let Uses = [NZCV];
3048  let Defs = [NZCV];
3049
3050  bits<5> Rn;
3051  bits<5> imm;
3052  bits<4> nzcv;
3053  bits<4> cond;
3054
3055  let Inst{30}    = op;
3056  let Inst{29-21} = 0b111010010;
3057  let Inst{20-16} = imm;
3058  let Inst{15-12} = cond;
3059  let Inst{11-10} = 0b10;
3060  let Inst{9-5}   = Rn;
3061  let Inst{4}     = 0b0;
3062  let Inst{3-0}   = nzcv;
3063}
3064
3065let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3066class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3067                            SDNode OpNode>
3068    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3069         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3070         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3071                             (i32 imm:$cond), NZCV))]>,
3072      Sched<[WriteI, ReadI, ReadI]> {
3073  let Uses = [NZCV];
3074  let Defs = [NZCV];
3075
3076  bits<5> Rn;
3077  bits<5> Rm;
3078  bits<4> nzcv;
3079  bits<4> cond;
3080
3081  let Inst{30}    = op;
3082  let Inst{29-21} = 0b111010010;
3083  let Inst{20-16} = Rm;
3084  let Inst{15-12} = cond;
3085  let Inst{11-10} = 0b00;
3086  let Inst{9-5}   = Rn;
3087  let Inst{4}     = 0b0;
3088  let Inst{3-0}   = nzcv;
3089}
3090
3091multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3092  // immediate operand variants
3093  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3094    let Inst{31} = 0;
3095  }
3096  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3097    let Inst{31} = 1;
3098  }
3099  // register operand variants
3100  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3101    let Inst{31} = 0;
3102  }
3103  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3104    let Inst{31} = 1;
3105  }
3106}
3107
3108//---
3109// Conditional select
3110//---
3111
3112class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3113    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3114         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3115         [(set regtype:$Rd,
3116               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3117      Sched<[WriteI, ReadI, ReadI]> {
3118  let Uses = [NZCV];
3119
3120  bits<5> Rd;
3121  bits<5> Rn;
3122  bits<5> Rm;
3123  bits<4> cond;
3124
3125  let Inst{30}    = op;
3126  let Inst{29-21} = 0b011010100;
3127  let Inst{20-16} = Rm;
3128  let Inst{15-12} = cond;
3129  let Inst{11-10} = op2;
3130  let Inst{9-5}   = Rn;
3131  let Inst{4-0}   = Rd;
3132}
3133
3134multiclass CondSelect<bit op, bits<2> op2, string asm> {
3135  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3136    let Inst{31} = 0;
3137  }
3138  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3139    let Inst{31} = 1;
3140  }
3141}
3142
3143class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3144                       PatFrag frag>
3145    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3146         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3147         [(set regtype:$Rd,
3148               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3149               (i32 imm:$cond), NZCV))]>,
3150      Sched<[WriteI, ReadI, ReadI]> {
3151  let Uses = [NZCV];
3152
3153  bits<5> Rd;
3154  bits<5> Rn;
3155  bits<5> Rm;
3156  bits<4> cond;
3157
3158  let Inst{30}    = op;
3159  let Inst{29-21} = 0b011010100;
3160  let Inst{20-16} = Rm;
3161  let Inst{15-12} = cond;
3162  let Inst{11-10} = op2;
3163  let Inst{9-5}   = Rn;
3164  let Inst{4-0}   = Rd;
3165}
3166
3167def inv_cond_XFORM : SDNodeXForm<imm, [{
3168  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3169  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3170                                   MVT::i32);
3171}]>;
3172
3173multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3174  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3175    let Inst{31} = 0;
3176  }
3177  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3178    let Inst{31} = 1;
3179  }
3180
3181  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3182            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3183                                           (inv_cond_XFORM imm:$cond))>;
3184
3185  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3186            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3187                                           (inv_cond_XFORM imm:$cond))>;
3188}
3189
3190//---
3191// Special Mask Value
3192//---
3193def maski8_or_more : Operand<i32>,
3194  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3195}
3196def maski16_or_more : Operand<i32>,
3197  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3198}
3199
3200
3201//---
3202// Load/store
3203//---
3204
3205// (unsigned immediate)
3206// Indexed for 8-bit registers. offset is in range [0,4095].
3207def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3208def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3209def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3210def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3211def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3212
3213// (unsigned immediate)
3214// Indexed for 8-bit registers. offset is in range [0,63].
3215def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3216def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3217def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3218def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3219
3220def gi_am_indexed8 :
3221    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3222    GIComplexPatternEquiv<am_indexed8>;
3223def gi_am_indexed16 :
3224    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3225    GIComplexPatternEquiv<am_indexed16>;
3226def gi_am_indexed32 :
3227    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3228    GIComplexPatternEquiv<am_indexed32>;
3229def gi_am_indexed64 :
3230    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3231    GIComplexPatternEquiv<am_indexed64>;
3232def gi_am_indexed128 :
3233    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3234    GIComplexPatternEquiv<am_indexed128>;
3235
3236class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3237  let Name = "UImm12Offset" # Scale;
3238  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3239  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3240  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3241}
3242
3243def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3244def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3245def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3246def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3247def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3248
3249class uimm12_scaled<int Scale> : Operand<i64> {
3250  let ParserMatchClass
3251   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3252  let EncoderMethod
3253   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3254  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3255}
3256
3257def uimm12s1 : uimm12_scaled<1>;
3258def uimm12s2 : uimm12_scaled<2>;
3259def uimm12s4 : uimm12_scaled<4>;
3260def uimm12s8 : uimm12_scaled<8>;
3261def uimm12s16 : uimm12_scaled<16>;
3262
3263class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3264                      string asm, list<dag> pattern>
3265    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3266  bits<5> Rt;
3267
3268  bits<5> Rn;
3269  bits<12> offset;
3270
3271  let Inst{31-30} = sz;
3272  let Inst{29-27} = 0b111;
3273  let Inst{26}    = V;
3274  let Inst{25-24} = 0b01;
3275  let Inst{23-22} = opc;
3276  let Inst{21-10} = offset;
3277  let Inst{9-5}   = Rn;
3278  let Inst{4-0}   = Rt;
3279
3280  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3281}
3282
3283multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3284                  Operand indextype, string asm, list<dag> pattern> {
3285  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3286  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3287                           (ins GPR64sp:$Rn, indextype:$offset),
3288                           asm, pattern>,
3289           Sched<[WriteLD]>;
3290
3291  def : InstAlias<asm # "\t$Rt, [$Rn]",
3292                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3293}
3294
3295multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3296             Operand indextype, string asm, list<dag> pattern> {
3297  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3298  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3299                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3300                           asm, pattern>,
3301           Sched<[WriteST]>;
3302
3303  def : InstAlias<asm # "\t$Rt, [$Rn]",
3304                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3305}
3306
3307// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3308// substitute zero-registers automatically.
3309//
3310// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3311//       into StoreUI.
3312multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3313             Operand indextype, string asm, list<dag> pattern> {
3314  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3315  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3316                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3317                           asm, pattern>,
3318           Sched<[WriteST]>;
3319
3320  def : InstAlias<asm # "\t$Rt, [$Rn]",
3321                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3322}
3323
3324def PrefetchOperand : AsmOperandClass {
3325  let Name = "Prefetch";
3326  let ParserMethod = "tryParsePrefetch";
3327}
3328def prfop : Operand<i32> {
3329  let PrintMethod = "printPrefetchOp";
3330  let ParserMatchClass = PrefetchOperand;
3331}
3332
3333let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3334class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3335    : BaseLoadStoreUI<sz, V, opc,
3336                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3337                      asm, pat>,
3338      Sched<[WriteLD]>;
3339
3340//---
3341// Load literal
3342//---
3343
3344// Load literal address: 19-bit immediate. The low two bits of the target
3345// offset are implied zero and so are not part of the immediate.
3346def am_ldrlit : Operand<iPTR> {
3347  let EncoderMethod = "getLoadLiteralOpValue";
3348  let DecoderMethod = "DecodePCRelLabel19";
3349  let PrintMethod = "printAlignedLabel";
3350  let ParserMatchClass = PCRelLabel19Operand;
3351  let OperandType = "OPERAND_PCREL";
3352}
3353
3354let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3355class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3356    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3357        asm, "\t$Rt, $label", "", pat>,
3358      Sched<[WriteLD]> {
3359  bits<5> Rt;
3360  bits<19> label;
3361  let Inst{31-30} = opc;
3362  let Inst{29-27} = 0b011;
3363  let Inst{26}    = V;
3364  let Inst{25-24} = 0b00;
3365  let Inst{23-5}  = label;
3366  let Inst{4-0}   = Rt;
3367}
3368
3369let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3370class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3371    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3372        asm, "\t$Rt, $label", "", pat>,
3373      Sched<[WriteLD]> {
3374  bits<5> Rt;
3375  bits<19> label;
3376  let Inst{31-30} = opc;
3377  let Inst{29-27} = 0b011;
3378  let Inst{26}    = V;
3379  let Inst{25-24} = 0b00;
3380  let Inst{23-5}  = label;
3381  let Inst{4-0}   = Rt;
3382}
3383
3384//---
3385// Load/store register offset
3386//---
3387
3388def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3389def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3390def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3391def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3392def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3393
3394def gi_ro_Xindexed8 :
3395    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3396    GIComplexPatternEquiv<ro_Xindexed8>;
3397def gi_ro_Xindexed16 :
3398    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3399    GIComplexPatternEquiv<ro_Xindexed16>;
3400def gi_ro_Xindexed32 :
3401    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3402    GIComplexPatternEquiv<ro_Xindexed32>;
3403def gi_ro_Xindexed64 :
3404    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3405    GIComplexPatternEquiv<ro_Xindexed64>;
3406def gi_ro_Xindexed128 :
3407    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3408    GIComplexPatternEquiv<ro_Xindexed128>;
3409
3410def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3411def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3412def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3413def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3414def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3415
3416def gi_ro_Windexed8 :
3417    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3418    GIComplexPatternEquiv<ro_Windexed8>;
3419def gi_ro_Windexed16 :
3420    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3421    GIComplexPatternEquiv<ro_Windexed16>;
3422def gi_ro_Windexed32 :
3423    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3424    GIComplexPatternEquiv<ro_Windexed32>;
3425def gi_ro_Windexed64 :
3426    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3427    GIComplexPatternEquiv<ro_Windexed64>;
3428def gi_ro_Windexed128 :
3429    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3430    GIComplexPatternEquiv<ro_Windexed128>;
3431
3432class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3433  let Name = "Mem" # Reg # "Extend" # Width;
3434  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3435  let RenderMethod = "addMemExtendOperands";
3436  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3437}
3438
3439def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3440  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3441  // the trivial shift.
3442  let RenderMethod = "addMemExtend8Operands";
3443}
3444def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3445def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3446def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3447def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3448
3449def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3450  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3451  // the trivial shift.
3452  let RenderMethod = "addMemExtend8Operands";
3453}
3454def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3455def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3456def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3457def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3458
3459class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3460        : Operand<i32> {
3461  let ParserMatchClass = ParserClass;
3462  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3463  let DecoderMethod = "DecodeMemExtend";
3464  let EncoderMethod = "getMemExtendOpValue";
3465  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3466}
3467
3468def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3469def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3470def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3471def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3472def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3473
3474def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3475def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3476def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3477def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3478def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3479
3480class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3481                  Operand wextend, Operand xextend>  {
3482  // CodeGen-level pattern covering the entire addressing mode.
3483  ComplexPattern Wpat = windex;
3484  ComplexPattern Xpat = xindex;
3485
3486  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3487  Operand Wext = wextend;
3488  Operand Xext = xextend;
3489}
3490
3491def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3492def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3493def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3494def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3495def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3496                       ro_Xextend128>;
3497
3498class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3499                   dag outs, list<dag> pat>
3500    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3501  bits<5> Rt;
3502  bits<5> Rn;
3503  bits<5> Rm;
3504  bits<2> extend;
3505  let Inst{31-30} = sz;
3506  let Inst{29-27} = 0b111;
3507  let Inst{26}    = V;
3508  let Inst{25-24} = 0b00;
3509  let Inst{23-22} = opc;
3510  let Inst{21}    = 1;
3511  let Inst{20-16} = Rm;
3512  let Inst{15}    = extend{1}; // sign extend Rm?
3513  let Inst{14}    = 1;
3514  let Inst{12}    = extend{0}; // do shift?
3515  let Inst{11-10} = 0b10;
3516  let Inst{9-5}   = Rn;
3517  let Inst{4-0}   = Rt;
3518}
3519
3520class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3521  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3522              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3523
3524multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3525                   string asm, ValueType Ty, SDPatternOperator loadop> {
3526  let AddedComplexity = 10 in
3527  def roW : LoadStore8RO<sz, V, opc, asm,
3528                 (outs regtype:$Rt),
3529                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3530                 [(set (Ty regtype:$Rt),
3531                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3532                                             ro_Wextend8:$extend)))]>,
3533           Sched<[WriteLDIdx, ReadAdrBase]> {
3534    let Inst{13} = 0b0;
3535  }
3536
3537  let AddedComplexity = 10 in
3538  def roX : LoadStore8RO<sz, V, opc, asm,
3539                 (outs regtype:$Rt),
3540                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3541                 [(set (Ty regtype:$Rt),
3542                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3543                                             ro_Xextend8:$extend)))]>,
3544           Sched<[WriteLDIdx, ReadAdrBase]> {
3545    let Inst{13} = 0b1;
3546  }
3547
3548  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3549}
3550
3551multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3552                    string asm, ValueType Ty, SDPatternOperator storeop> {
3553  let AddedComplexity = 10 in
3554  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
3555                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3556                 [(storeop (Ty regtype:$Rt),
3557                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3558                                         ro_Wextend8:$extend))]>,
3559            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3560    let Inst{13} = 0b0;
3561  }
3562
3563  let AddedComplexity = 10 in
3564  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
3565                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3566                 [(storeop (Ty regtype:$Rt),
3567                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3568                                         ro_Xextend8:$extend))]>,
3569            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3570    let Inst{13} = 0b1;
3571  }
3572
3573  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3574}
3575
3576class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3577                    dag outs, list<dag> pat>
3578    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3579  bits<5> Rt;
3580  bits<5> Rn;
3581  bits<5> Rm;
3582  bits<2> extend;
3583  let Inst{31-30} = sz;
3584  let Inst{29-27} = 0b111;
3585  let Inst{26}    = V;
3586  let Inst{25-24} = 0b00;
3587  let Inst{23-22} = opc;
3588  let Inst{21}    = 1;
3589  let Inst{20-16} = Rm;
3590  let Inst{15}    = extend{1}; // sign extend Rm?
3591  let Inst{14}    = 1;
3592  let Inst{12}    = extend{0}; // do shift?
3593  let Inst{11-10} = 0b10;
3594  let Inst{9-5}   = Rn;
3595  let Inst{4-0}   = Rt;
3596}
3597
3598multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3599                    string asm, ValueType Ty, SDPatternOperator loadop> {
3600  let AddedComplexity = 10 in
3601  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3602                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3603                 [(set (Ty regtype:$Rt),
3604                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3605                                              ro_Wextend16:$extend)))]>,
3606            Sched<[WriteLDIdx, ReadAdrBase]> {
3607    let Inst{13} = 0b0;
3608  }
3609
3610  let AddedComplexity = 10 in
3611  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3612                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3613                 [(set (Ty regtype:$Rt),
3614                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3615                                             ro_Xextend16:$extend)))]>,
3616            Sched<[WriteLDIdx, ReadAdrBase]> {
3617    let Inst{13} = 0b1;
3618  }
3619
3620  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3621}
3622
3623multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3624                     string asm, ValueType Ty, SDPatternOperator storeop> {
3625  let AddedComplexity = 10 in
3626  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
3627                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3628                [(storeop (Ty regtype:$Rt),
3629                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3630                                         ro_Wextend16:$extend))]>,
3631           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3632    let Inst{13} = 0b0;
3633  }
3634
3635  let AddedComplexity = 10 in
3636  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
3637                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3638                [(storeop (Ty regtype:$Rt),
3639                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3640                                         ro_Xextend16:$extend))]>,
3641           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3642    let Inst{13} = 0b1;
3643  }
3644
3645  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3646}
3647
3648class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3649                    dag outs, list<dag> pat>
3650    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3651  bits<5> Rt;
3652  bits<5> Rn;
3653  bits<5> Rm;
3654  bits<2> extend;
3655  let Inst{31-30} = sz;
3656  let Inst{29-27} = 0b111;
3657  let Inst{26}    = V;
3658  let Inst{25-24} = 0b00;
3659  let Inst{23-22} = opc;
3660  let Inst{21}    = 1;
3661  let Inst{20-16} = Rm;
3662  let Inst{15}    = extend{1}; // sign extend Rm?
3663  let Inst{14}    = 1;
3664  let Inst{12}    = extend{0}; // do shift?
3665  let Inst{11-10} = 0b10;
3666  let Inst{9-5}   = Rn;
3667  let Inst{4-0}   = Rt;
3668}
3669
3670multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3671                    string asm, ValueType Ty, SDPatternOperator loadop> {
3672  let AddedComplexity = 10 in
3673  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3674                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3675                 [(set (Ty regtype:$Rt),
3676                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3677                                              ro_Wextend32:$extend)))]>,
3678           Sched<[WriteLDIdx, ReadAdrBase]> {
3679    let Inst{13} = 0b0;
3680  }
3681
3682  let AddedComplexity = 10 in
3683  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
3684                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3685                 [(set (Ty regtype:$Rt),
3686                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3687                                              ro_Xextend32:$extend)))]>,
3688           Sched<[WriteLDIdx, ReadAdrBase]> {
3689    let Inst{13} = 0b1;
3690  }
3691
3692  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3693}
3694
3695multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3696                     string asm, ValueType Ty, SDPatternOperator storeop> {
3697  let AddedComplexity = 10 in
3698  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
3699                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3700                [(storeop (Ty regtype:$Rt),
3701                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3702                                         ro_Wextend32:$extend))]>,
3703            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3704    let Inst{13} = 0b0;
3705  }
3706
3707  let AddedComplexity = 10 in
3708  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
3709                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3710                [(storeop (Ty regtype:$Rt),
3711                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3712                                        ro_Xextend32:$extend))]>,
3713            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3714    let Inst{13} = 0b1;
3715  }
3716
3717  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3718}
3719
3720class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3721                    dag outs, list<dag> pat>
3722    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3723  bits<5> Rt;
3724  bits<5> Rn;
3725  bits<5> Rm;
3726  bits<2> extend;
3727  let Inst{31-30} = sz;
3728  let Inst{29-27} = 0b111;
3729  let Inst{26}    = V;
3730  let Inst{25-24} = 0b00;
3731  let Inst{23-22} = opc;
3732  let Inst{21}    = 1;
3733  let Inst{20-16} = Rm;
3734  let Inst{15}    = extend{1}; // sign extend Rm?
3735  let Inst{14}    = 1;
3736  let Inst{12}    = extend{0}; // do shift?
3737  let Inst{11-10} = 0b10;
3738  let Inst{9-5}   = Rn;
3739  let Inst{4-0}   = Rt;
3740}
3741
3742multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3743                    string asm, ValueType Ty, SDPatternOperator loadop> {
3744  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3745  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3746                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3747                [(set (Ty regtype:$Rt),
3748                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3749                                             ro_Wextend64:$extend)))]>,
3750           Sched<[WriteLDIdx, ReadAdrBase]> {
3751    let Inst{13} = 0b0;
3752  }
3753
3754  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3755  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
3756                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3757                 [(set (Ty regtype:$Rt),
3758                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3759                                              ro_Xextend64:$extend)))]>,
3760           Sched<[WriteLDIdx, ReadAdrBase]> {
3761    let Inst{13} = 0b1;
3762  }
3763
3764  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3765}
3766
3767multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3768                     string asm, ValueType Ty, SDPatternOperator storeop> {
3769  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3770  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
3771                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3772                [(storeop (Ty regtype:$Rt),
3773                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3774                                         ro_Wextend64:$extend))]>,
3775            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3776    let Inst{13} = 0b0;
3777  }
3778
3779  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3780  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
3781                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3782                [(storeop (Ty regtype:$Rt),
3783                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3784                                         ro_Xextend64:$extend))]>,
3785            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3786    let Inst{13} = 0b1;
3787  }
3788
3789  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3790}
3791
3792class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3793                     dag outs, list<dag> pat>
3794    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3795  bits<5> Rt;
3796  bits<5> Rn;
3797  bits<5> Rm;
3798  bits<2> extend;
3799  let Inst{31-30} = sz;
3800  let Inst{29-27} = 0b111;
3801  let Inst{26}    = V;
3802  let Inst{25-24} = 0b00;
3803  let Inst{23-22} = opc;
3804  let Inst{21}    = 1;
3805  let Inst{20-16} = Rm;
3806  let Inst{15}    = extend{1}; // sign extend Rm?
3807  let Inst{14}    = 1;
3808  let Inst{12}    = extend{0}; // do shift?
3809  let Inst{11-10} = 0b10;
3810  let Inst{9-5}   = Rn;
3811  let Inst{4-0}   = Rt;
3812}
3813
3814multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3815                     string asm, ValueType Ty, SDPatternOperator loadop> {
3816  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3817  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3818                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3819                 [(set (Ty regtype:$Rt),
3820                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3821                                               ro_Wextend128:$extend)))]>,
3822            Sched<[WriteLDIdx, ReadAdrBase]> {
3823    let Inst{13} = 0b0;
3824  }
3825
3826  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3827  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
3828                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3829                 [(set (Ty regtype:$Rt),
3830                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3831                                               ro_Xextend128:$extend)))]>,
3832            Sched<[WriteLDIdx, ReadAdrBase]> {
3833    let Inst{13} = 0b1;
3834  }
3835
3836  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3837}
3838
3839multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3840                      string asm> {
3841  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3842  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
3843               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3844                []>,
3845            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3846    let Inst{13} = 0b0;
3847  }
3848
3849  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3850  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
3851               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3852                []>,
3853            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3854    let Inst{13} = 0b1;
3855  }
3856
3857  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3858}
3859
3860let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3861class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3862                     string asm, list<dag> pat>
3863    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3864      Sched<[WriteLD]> {
3865  bits<5> Rt;
3866  bits<5> Rn;
3867  bits<5> Rm;
3868  bits<2> extend;
3869  let Inst{31-30} = sz;
3870  let Inst{29-27} = 0b111;
3871  let Inst{26}    = V;
3872  let Inst{25-24} = 0b00;
3873  let Inst{23-22} = opc;
3874  let Inst{21}    = 1;
3875  let Inst{20-16} = Rm;
3876  let Inst{15}    = extend{1}; // sign extend Rm?
3877  let Inst{14}    = 1;
3878  let Inst{12}    = extend{0}; // do shift?
3879  let Inst{11-10} = 0b10;
3880  let Inst{9-5}   = Rn;
3881  let Inst{4-0}   = Rt;
3882}
3883
3884multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3885  def roW : BasePrefetchRO<sz, V, opc, (outs),
3886                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3887                asm, [(AArch64Prefetch imm:$Rt,
3888                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3889                                                    ro_Wextend64:$extend))]> {
3890    let Inst{13} = 0b0;
3891  }
3892
3893  def roX : BasePrefetchRO<sz, V, opc, (outs),
3894                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3895                asm,  [(AArch64Prefetch imm:$Rt,
3896                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3897                                                     ro_Xextend64:$extend))]> {
3898    let Inst{13} = 0b1;
3899  }
3900
3901  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3902               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3903                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3904}
3905
3906//---
3907// Load/store unscaled immediate
3908//---
3909
3910def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
3911def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
3912def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
3913def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
3914def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
3915
3916def gi_am_unscaled8 :
3917    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3918    GIComplexPatternEquiv<am_unscaled8>;
3919def gi_am_unscaled16 :
3920    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3921    GIComplexPatternEquiv<am_unscaled16>;
3922def gi_am_unscaled32 :
3923    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3924    GIComplexPatternEquiv<am_unscaled32>;
3925def gi_am_unscaled64 :
3926    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3927    GIComplexPatternEquiv<am_unscaled64>;
3928def gi_am_unscaled128 :
3929    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3930    GIComplexPatternEquiv<am_unscaled128>;
3931
3932
3933class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3934                           string asm, list<dag> pattern>
3935    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3936  bits<5> Rt;
3937  bits<5> Rn;
3938  bits<9> offset;
3939  let Inst{31-30} = sz;
3940  let Inst{29-27} = 0b111;
3941  let Inst{26}    = V;
3942  let Inst{25-24} = 0b00;
3943  let Inst{23-22} = opc;
3944  let Inst{21}    = 0;
3945  let Inst{20-12} = offset;
3946  let Inst{11-10} = 0b00;
3947  let Inst{9-5}   = Rn;
3948  let Inst{4-0}   = Rt;
3949
3950  let DecoderMethod = "DecodeSignedLdStInstruction";
3951}
3952
3953// Armv8.4 LDAPR & STLR with Immediate Offset instruction
3954multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3955                              DAGOperand regtype > {
3956  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3957                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3958          Sched<[WriteST]> {
3959    let Inst{29} = 0;
3960    let Inst{24} = 1;
3961  }
3962  def : InstAlias<asm # "\t$Rt, [$Rn]",
3963                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3964}
3965
3966multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3967                               DAGOperand regtype > {
3968  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3969                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3970                               asm, []>,
3971          Sched<[WriteST]> {
3972    let Inst{29} = 0;
3973    let Inst{24} = 1;
3974  }
3975  def : InstAlias<asm # "\t$Rt, [$Rn]",
3976                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3977}
3978
3979multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3980                   string asm, list<dag> pattern> {
3981  let AddedComplexity = 1 in // try this before LoadUI
3982  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3983                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3984          Sched<[WriteLD]>;
3985
3986  def : InstAlias<asm # "\t$Rt, [$Rn]",
3987                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3988}
3989
3990multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3991                         string asm, list<dag> pattern> {
3992  let AddedComplexity = 1 in // try this before StoreUI
3993  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3994                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3995                               asm, pattern>,
3996          Sched<[WriteST]>;
3997
3998  def : InstAlias<asm # "\t$Rt, [$Rn]",
3999                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4000}
4001
4002multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
4003                            list<dag> pat> {
4004  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4005  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4006                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
4007                               asm, pat>,
4008          Sched<[WriteLD]>;
4009
4010  def : InstAlias<asm # "\t$Rt, [$Rn]",
4011                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
4012}
4013
4014//---
4015// Load/store unscaled immediate, unprivileged
4016//---
4017
4018class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4019                                dag oops, dag iops, string asm>
4020    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
4021  bits<5> Rt;
4022  bits<5> Rn;
4023  bits<9> offset;
4024  let Inst{31-30} = sz;
4025  let Inst{29-27} = 0b111;
4026  let Inst{26}    = V;
4027  let Inst{25-24} = 0b00;
4028  let Inst{23-22} = opc;
4029  let Inst{21}    = 0;
4030  let Inst{20-12} = offset;
4031  let Inst{11-10} = 0b10;
4032  let Inst{9-5}   = Rn;
4033  let Inst{4-0}   = Rt;
4034
4035  let DecoderMethod = "DecodeSignedLdStInstruction";
4036}
4037
4038multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4039                            RegisterClass regtype, string asm> {
4040  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4041  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4042                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4043          Sched<[WriteLD]>;
4044
4045  def : InstAlias<asm # "\t$Rt, [$Rn]",
4046                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4047}
4048
4049multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4050                             RegisterClass regtype, string asm> {
4051  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4052  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4053                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4054                                 asm>,
4055          Sched<[WriteST]>;
4056
4057  def : InstAlias<asm # "\t$Rt, [$Rn]",
4058                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4059}
4060
4061//---
4062// Load/store pre-indexed
4063//---
4064
4065class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4066                          string asm, string cstr, list<dag> pat>
4067    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4068  bits<5> Rt;
4069  bits<5> Rn;
4070  bits<9> offset;
4071  let Inst{31-30} = sz;
4072  let Inst{29-27} = 0b111;
4073  let Inst{26}    = V;
4074  let Inst{25-24} = 0;
4075  let Inst{23-22} = opc;
4076  let Inst{21}    = 0;
4077  let Inst{20-12} = offset;
4078  let Inst{11-10} = 0b11;
4079  let Inst{9-5}   = Rn;
4080  let Inst{4-0}   = Rt;
4081
4082  let DecoderMethod = "DecodeSignedLdStInstruction";
4083}
4084
4085let hasSideEffects = 0 in {
4086let mayStore = 0, mayLoad = 1 in
4087class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4088             string asm>
4089    : BaseLoadStorePreIdx<sz, V, opc,
4090                     (outs GPR64sp:$wback, regtype:$Rt),
4091                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4092                     "$Rn = $wback,@earlyclobber $wback", []>,
4093      Sched<[WriteAdr, WriteLD]>;
4094
4095let mayStore = 1, mayLoad = 0 in
4096class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4097                  string asm, SDPatternOperator storeop, ValueType Ty>
4098    : BaseLoadStorePreIdx<sz, V, opc,
4099                      (outs GPR64sp:$wback),
4100                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4101                      asm, "$Rn = $wback,@earlyclobber $wback",
4102      [(set GPR64sp:$wback,
4103            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4104      Sched<[WriteAdr, WriteST]>;
4105} // hasSideEffects = 0
4106
4107//---
4108// Load/store post-indexed
4109//---
4110
4111class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4112                          string asm, string cstr, list<dag> pat>
4113    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4114  bits<5> Rt;
4115  bits<5> Rn;
4116  bits<9> offset;
4117  let Inst{31-30} = sz;
4118  let Inst{29-27} = 0b111;
4119  let Inst{26}    = V;
4120  let Inst{25-24} = 0b00;
4121  let Inst{23-22} = opc;
4122  let Inst{21}    = 0b0;
4123  let Inst{20-12} = offset;
4124  let Inst{11-10} = 0b01;
4125  let Inst{9-5}   = Rn;
4126  let Inst{4-0}   = Rt;
4127
4128  let DecoderMethod = "DecodeSignedLdStInstruction";
4129}
4130
4131let hasSideEffects = 0 in {
4132let mayStore = 0, mayLoad = 1 in
4133class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4134             string asm>
4135    : BaseLoadStorePostIdx<sz, V, opc,
4136                      (outs GPR64sp:$wback, regtype:$Rt),
4137                      (ins GPR64sp:$Rn, simm9:$offset),
4138                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4139      Sched<[WriteAdr, WriteLD]>;
4140
4141let mayStore = 1, mayLoad = 0 in
4142class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4143                   string asm, SDPatternOperator storeop, ValueType Ty>
4144    : BaseLoadStorePostIdx<sz, V, opc,
4145                      (outs GPR64sp:$wback),
4146                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4147                       asm, "$Rn = $wback,@earlyclobber $wback",
4148      [(set GPR64sp:$wback,
4149            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4150    Sched<[WriteAdr, WriteST]>;
4151} // hasSideEffects = 0
4152
4153
4154//---
4155// Load/store pair
4156//---
4157
4158// (indexed, offset)
4159
4160class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4161                              string asm>
4162    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4163  bits<5> Rt;
4164  bits<5> Rt2;
4165  bits<5> Rn;
4166  bits<7> offset;
4167  let Inst{31-30} = opc;
4168  let Inst{29-27} = 0b101;
4169  let Inst{26}    = V;
4170  let Inst{25-23} = 0b010;
4171  let Inst{22}    = L;
4172  let Inst{21-15} = offset;
4173  let Inst{14-10} = Rt2;
4174  let Inst{9-5}   = Rn;
4175  let Inst{4-0}   = Rt;
4176
4177  let DecoderMethod = "DecodePairLdStInstruction";
4178}
4179
4180multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4181                          Operand indextype, string asm> {
4182  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4183  def i : BaseLoadStorePairOffset<opc, V, 1,
4184                                  (outs regtype:$Rt, regtype:$Rt2),
4185                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4186          Sched<[WriteLD, WriteLDHi]>;
4187
4188  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4189                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4190                                                  GPR64sp:$Rn, 0)>;
4191}
4192
4193
4194multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4195                           Operand indextype, string asm> {
4196  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4197  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4198                                  (ins regtype:$Rt, regtype:$Rt2,
4199                                       GPR64sp:$Rn, indextype:$offset),
4200                                  asm>,
4201          Sched<[WriteSTP]>;
4202
4203  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4204                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4205                                                  GPR64sp:$Rn, 0)>;
4206}
4207
4208// (pre-indexed)
4209class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4210                              string asm>
4211    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4212  bits<5> Rt;
4213  bits<5> Rt2;
4214  bits<5> Rn;
4215  bits<7> offset;
4216  let Inst{31-30} = opc;
4217  let Inst{29-27} = 0b101;
4218  let Inst{26}    = V;
4219  let Inst{25-23} = 0b011;
4220  let Inst{22}    = L;
4221  let Inst{21-15} = offset;
4222  let Inst{14-10} = Rt2;
4223  let Inst{9-5}   = Rn;
4224  let Inst{4-0}   = Rt;
4225
4226  let DecoderMethod = "DecodePairLdStInstruction";
4227}
4228
4229let hasSideEffects = 0 in {
4230let mayStore = 0, mayLoad = 1 in
4231class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4232                     Operand indextype, string asm>
4233    : BaseLoadStorePairPreIdx<opc, V, 1,
4234                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4235                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4236      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4237
4238let mayStore = 1, mayLoad = 0 in
4239class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4240                      Operand indextype, string asm>
4241    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4242                             (ins regtype:$Rt, regtype:$Rt2,
4243                                  GPR64sp:$Rn, indextype:$offset),
4244                             asm>,
4245      Sched<[WriteAdr, WriteSTP]>;
4246} // hasSideEffects = 0
4247
4248// (post-indexed)
4249
4250class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4251                              string asm>
4252    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4253  bits<5> Rt;
4254  bits<5> Rt2;
4255  bits<5> Rn;
4256  bits<7> offset;
4257  let Inst{31-30} = opc;
4258  let Inst{29-27} = 0b101;
4259  let Inst{26}    = V;
4260  let Inst{25-23} = 0b001;
4261  let Inst{22}    = L;
4262  let Inst{21-15} = offset;
4263  let Inst{14-10} = Rt2;
4264  let Inst{9-5}   = Rn;
4265  let Inst{4-0}   = Rt;
4266
4267  let DecoderMethod = "DecodePairLdStInstruction";
4268}
4269
4270let hasSideEffects = 0 in {
4271let mayStore = 0, mayLoad = 1 in
4272class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4273                      Operand idxtype, string asm>
4274    : BaseLoadStorePairPostIdx<opc, V, 1,
4275                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4276                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4277      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4278
4279let mayStore = 1, mayLoad = 0 in
4280class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4281                       Operand idxtype, string asm>
4282    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4283                             (ins regtype:$Rt, regtype:$Rt2,
4284                                  GPR64sp:$Rn, idxtype:$offset),
4285                             asm>,
4286      Sched<[WriteAdr, WriteSTP]>;
4287} // hasSideEffects = 0
4288
4289//  (no-allocate)
4290
4291class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4292                              string asm>
4293    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4294  bits<5> Rt;
4295  bits<5> Rt2;
4296  bits<5> Rn;
4297  bits<7> offset;
4298  let Inst{31-30} = opc;
4299  let Inst{29-27} = 0b101;
4300  let Inst{26}    = V;
4301  let Inst{25-23} = 0b000;
4302  let Inst{22}    = L;
4303  let Inst{21-15} = offset;
4304  let Inst{14-10} = Rt2;
4305  let Inst{9-5}   = Rn;
4306  let Inst{4-0}   = Rt;
4307
4308  let DecoderMethod = "DecodePairLdStInstruction";
4309}
4310
4311multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4312                           Operand indextype, string asm> {
4313  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4314  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4315                                   (outs regtype:$Rt, regtype:$Rt2),
4316                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4317          Sched<[WriteLD, WriteLDHi]>;
4318
4319
4320  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4321                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4322                                                  GPR64sp:$Rn, 0)>;
4323}
4324
4325multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4326                      Operand indextype, string asm> {
4327  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4328  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4329                                   (ins regtype:$Rt, regtype:$Rt2,
4330                                        GPR64sp:$Rn, indextype:$offset),
4331                                   asm>,
4332          Sched<[WriteSTP]>;
4333
4334  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4335                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4336                                                  GPR64sp:$Rn, 0)>;
4337}
4338
4339//---
4340// Load/store exclusive
4341//---
4342
4343// True exclusive operations write to and/or read from the system's exclusive
4344// monitors, which as far as a compiler is concerned can be modelled as a
4345// random shared memory address. Hence LoadExclusive mayStore.
4346//
4347// Since these instructions have the undefined register bits set to 1 in
4348// their canonical form, we need a post encoder method to set those bits
4349// to 1 when encoding these instructions. We do this using the
4350// fixLoadStoreExclusive function. This function has template parameters:
4351//
4352// fixLoadStoreExclusive<int hasRs, int hasRt2>
4353//
4354// hasRs indicates that the instruction uses the Rs field, so we won't set
4355// it to 1 (and the same for Rt2). We don't need template parameters for
4356// the other register fields since Rt and Rn are always used.
4357//
4358let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4359class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4360                             dag oops, dag iops, string asm, string operands>
4361    : I<oops, iops, asm, operands, "", []> {
4362  let Inst{31-30} = sz;
4363  let Inst{29-24} = 0b001000;
4364  let Inst{23}    = o2;
4365  let Inst{22}    = L;
4366  let Inst{21}    = o1;
4367  let Inst{15}    = o0;
4368
4369  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4370}
4371
4372// Neither Rs nor Rt2 operands.
4373class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4374                               dag oops, dag iops, string asm, string operands>
4375    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4376  bits<5> Rt;
4377  bits<5> Rn;
4378  let Inst{20-16} = 0b11111;
4379  let Unpredictable{20-16} = 0b11111;
4380  let Inst{14-10} = 0b11111;
4381  let Unpredictable{14-10} = 0b11111;
4382  let Inst{9-5} = Rn;
4383  let Inst{4-0} = Rt;
4384
4385  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4386}
4387
4388// Simple load acquires don't set the exclusive monitor
4389let mayLoad = 1, mayStore = 0 in
4390class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4391                  RegisterClass regtype, string asm>
4392    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4393                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4394      Sched<[WriteLD]>;
4395
4396class LoadExclusive<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 LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4403                       RegisterClass regtype, string asm>
4404    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4405                             (outs regtype:$Rt, regtype:$Rt2),
4406                             (ins GPR64sp0:$Rn), asm,
4407                             "\t$Rt, $Rt2, [$Rn]">,
4408      Sched<[WriteLD, WriteLDHi]> {
4409  bits<5> Rt;
4410  bits<5> Rt2;
4411  bits<5> Rn;
4412  let Inst{14-10} = Rt2;
4413  let Inst{9-5} = Rn;
4414  let Inst{4-0} = Rt;
4415
4416  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4417}
4418
4419// Simple store release operations do not check the exclusive monitor.
4420let mayLoad = 0, mayStore = 1 in
4421class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4422                   RegisterClass regtype, string asm>
4423    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4424                               (ins regtype:$Rt, GPR64sp0:$Rn),
4425                               asm, "\t$Rt, [$Rn]">,
4426      Sched<[WriteST]>;
4427
4428let mayLoad = 1, mayStore = 1 in
4429class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4430                     RegisterClass regtype, string asm>
4431    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4432                             (ins regtype:$Rt, GPR64sp0:$Rn),
4433                             asm, "\t$Ws, $Rt, [$Rn]">,
4434      Sched<[WriteSTX]> {
4435  bits<5> Ws;
4436  bits<5> Rt;
4437  bits<5> Rn;
4438  let Inst{20-16} = Ws;
4439  let Inst{9-5} = Rn;
4440  let Inst{4-0} = Rt;
4441
4442  let Constraints = "@earlyclobber $Ws";
4443  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4444}
4445
4446class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4447                         RegisterClass regtype, string asm>
4448    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4449                             (outs GPR32:$Ws),
4450                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4451                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4452      Sched<[WriteSTX]> {
4453  bits<5> Ws;
4454  bits<5> Rt;
4455  bits<5> Rt2;
4456  bits<5> Rn;
4457  let Inst{20-16} = Ws;
4458  let Inst{14-10} = Rt2;
4459  let Inst{9-5} = Rn;
4460  let Inst{4-0} = Rt;
4461
4462  let Constraints = "@earlyclobber $Ws";
4463}
4464
4465// Armv8.5-A Memory Tagging Extension
4466class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4467                 string asm_opnds, string cstr, dag oops, dag iops>
4468    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4469      Sched<[]> {
4470  bits<5> Rn;
4471
4472  let Inst{31-24} = 0b11011001;
4473  let Inst{23-22} = opc1;
4474  let Inst{21}    = 1;
4475  // Inst{20-12} defined by subclass
4476  let Inst{11-10} = opc2;
4477  let Inst{9-5}   = Rn;
4478  // Inst{4-0} defined by subclass
4479}
4480
4481class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4482                   dag oops, dag iops>
4483    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4484                  "", oops, iops> {
4485  bits<5> Rt;
4486
4487  let Inst{20-12} = 0b000000000;
4488  let Inst{4-0}   = Rt;
4489
4490  let mayLoad = Load;
4491}
4492
4493class MemTagLoad<string asm_insn, string asm_opnds>
4494    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4495                 (outs GPR64:$wback),
4496                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4497  bits<5> Rt;
4498  bits<9> offset;
4499
4500  let Inst{20-12} = offset;
4501  let Inst{4-0}   = Rt;
4502
4503  let mayLoad = 1;
4504}
4505
4506class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4507                     string asm_opnds, string cstr, dag oops, dag iops>
4508    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4509  bits<5> Rt;
4510  bits<9> offset;
4511
4512  let Inst{20-12} = offset;
4513  let Inst{4-0}   = Rt;
4514
4515  let mayStore = 1;
4516}
4517
4518multiclass MemTagStore<bits<2> opc1, string insn> {
4519  def Offset :
4520    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4521                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4522  def PreIndex :
4523    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4524                    "$Rn = $wback",
4525                    (outs GPR64sp:$wback),
4526                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4527  def PostIndex :
4528    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4529                    "$Rn = $wback",
4530                    (outs GPR64sp:$wback),
4531                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4532
4533  def : InstAlias<insn # "\t$Rt, [$Rn]",
4534                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4535}
4536
4537//---
4538// Exception generation
4539//---
4540
4541let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4542class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm,
4543                          list<dag> pattern = []>
4544    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", pattern>,
4545      Sched<[WriteSys]> {
4546  bits<16> imm;
4547  let Inst{31-24} = 0b11010100;
4548  let Inst{23-21} = op1;
4549  let Inst{20-5}  = imm;
4550  let Inst{4-2}   = 0b000;
4551  let Inst{1-0}   = ll;
4552}
4553
4554//---
4555// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4556//--
4557let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4558class UDFType<bits<16> opc, string asm>
4559  : I<(outs), (ins uimm16:$imm),
4560       asm, "\t$imm", "", []>,
4561    Sched<[]> {
4562  bits<16> imm;
4563  let Inst{31-16} = opc;
4564  let Inst{15-0} = imm;
4565}
4566}
4567let Predicates = [HasFPARMv8] in {
4568
4569//---
4570// Floating point to integer conversion
4571//---
4572
4573let mayRaiseFPException = 1 in
4574class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4575                      RegisterClass srcType, RegisterClass dstType,
4576                      string asm, list<dag> pattern>
4577    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4578         asm, "\t$Rd, $Rn", "", pattern>,
4579      Sched<[WriteFCvt]> {
4580  bits<5> Rd;
4581  bits<5> Rn;
4582  let Inst{30-29} = 0b00;
4583  let Inst{28-24} = 0b11110;
4584  let Inst{23-22} = type;
4585  let Inst{21}    = 1;
4586  let Inst{20-19} = rmode;
4587  let Inst{18-16} = opcode;
4588  let Inst{15-10} = 0;
4589  let Inst{9-5}   = Rn;
4590  let Inst{4-0}   = Rd;
4591}
4592
4593let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
4594class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4595                      RegisterClass srcType, RegisterClass dstType,
4596                      Operand immType, string asm, list<dag> pattern>
4597    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4598         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4599      Sched<[WriteFCvt]> {
4600  bits<5> Rd;
4601  bits<5> Rn;
4602  bits<6> scale;
4603  let Inst{30-29} = 0b00;
4604  let Inst{28-24} = 0b11110;
4605  let Inst{23-22} = type;
4606  let Inst{21}    = 0;
4607  let Inst{20-19} = rmode;
4608  let Inst{18-16} = opcode;
4609  let Inst{15-10} = scale;
4610  let Inst{9-5}   = Rn;
4611  let Inst{4-0}   = Rd;
4612}
4613
4614multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4615           SDPatternOperator OpN> {
4616  // Unscaled half-precision to 32-bit
4617  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4618                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4619    let Inst{31} = 0; // 32-bit GPR flag
4620    let Predicates = [HasFullFP16];
4621  }
4622
4623  // Unscaled half-precision to 64-bit
4624  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4625                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4626    let Inst{31} = 1; // 64-bit GPR flag
4627    let Predicates = [HasFullFP16];
4628  }
4629
4630  // Unscaled single-precision to 32-bit
4631  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4632                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4633    let Inst{31} = 0; // 32-bit GPR flag
4634  }
4635
4636  // Unscaled single-precision to 64-bit
4637  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4638                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4639    let Inst{31} = 1; // 64-bit GPR flag
4640  }
4641
4642  // Unscaled double-precision to 32-bit
4643  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4644                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4645    let Inst{31} = 0; // 32-bit GPR flag
4646  }
4647
4648  // Unscaled double-precision to 64-bit
4649  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4650                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4651    let Inst{31} = 1; // 64-bit GPR flag
4652  }
4653}
4654
4655multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4656                             SDPatternOperator OpN> {
4657  // Scaled half-precision to 32-bit
4658  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4659                              fixedpoint_f16_i32, asm,
4660              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4661                                          fixedpoint_f16_i32:$scale)))]> {
4662    let Inst{31} = 0; // 32-bit GPR flag
4663    let scale{5} = 1;
4664    let Predicates = [HasFullFP16];
4665  }
4666
4667  // Scaled half-precision to 64-bit
4668  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4669                              fixedpoint_f16_i64, asm,
4670              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4671                                          fixedpoint_f16_i64:$scale)))]> {
4672    let Inst{31} = 1; // 64-bit GPR flag
4673    let Predicates = [HasFullFP16];
4674  }
4675
4676  // Scaled single-precision to 32-bit
4677  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4678                              fixedpoint_f32_i32, asm,
4679              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4680                                          fixedpoint_f32_i32:$scale)))]> {
4681    let Inst{31} = 0; // 32-bit GPR flag
4682    let scale{5} = 1;
4683  }
4684
4685  // Scaled single-precision to 64-bit
4686  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4687                              fixedpoint_f32_i64, asm,
4688              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4689                                          fixedpoint_f32_i64:$scale)))]> {
4690    let Inst{31} = 1; // 64-bit GPR flag
4691  }
4692
4693  // Scaled double-precision to 32-bit
4694  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4695                              fixedpoint_f64_i32, asm,
4696              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4697                                          fixedpoint_f64_i32:$scale)))]> {
4698    let Inst{31} = 0; // 32-bit GPR flag
4699    let scale{5} = 1;
4700  }
4701
4702  // Scaled double-precision to 64-bit
4703  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4704                              fixedpoint_f64_i64, asm,
4705              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4706                                          fixedpoint_f64_i64:$scale)))]> {
4707    let Inst{31} = 1; // 64-bit GPR flag
4708  }
4709}
4710
4711//---
4712// Integer to floating point conversion
4713//---
4714
4715let mayStore = 0, mayLoad = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
4716class BaseIntegerToFP<bit isUnsigned,
4717                      RegisterClass srcType, RegisterClass dstType,
4718                      Operand immType, string asm, list<dag> pattern>
4719    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4720         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4721      Sched<[WriteFCvt]> {
4722  bits<5> Rd;
4723  bits<5> Rn;
4724  bits<6> scale;
4725  let Inst{30-24} = 0b0011110;
4726  let Inst{21-17} = 0b00001;
4727  let Inst{16}    = isUnsigned;
4728  let Inst{15-10} = scale;
4729  let Inst{9-5}   = Rn;
4730  let Inst{4-0}   = Rd;
4731}
4732
4733let mayRaiseFPException = 1 in
4734class BaseIntegerToFPUnscaled<bit isUnsigned,
4735                      RegisterClass srcType, RegisterClass dstType,
4736                      ValueType dvt, string asm, SDPatternOperator node>
4737    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4738         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4739      Sched<[WriteFCvt]> {
4740  bits<5> Rd;
4741  bits<5> Rn;
4742  bits<6> scale;
4743  let Inst{30-24} = 0b0011110;
4744  let Inst{21-17} = 0b10001;
4745  let Inst{16}    = isUnsigned;
4746  let Inst{15-10} = 0b000000;
4747  let Inst{9-5}   = Rn;
4748  let Inst{4-0}   = Rd;
4749}
4750
4751multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
4752  // Unscaled
4753  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4754    let Inst{31} = 0; // 32-bit GPR flag
4755    let Inst{23-22} = 0b11; // 16-bit FPR flag
4756    let Predicates = [HasFullFP16];
4757  }
4758
4759  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4760    let Inst{31} = 0; // 32-bit GPR flag
4761    let Inst{23-22} = 0b00; // 32-bit FPR flag
4762  }
4763
4764  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4765    let Inst{31} = 0; // 32-bit GPR flag
4766    let Inst{23-22} = 0b01; // 64-bit FPR flag
4767  }
4768
4769  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4770    let Inst{31} = 1; // 64-bit GPR flag
4771    let Inst{23-22} = 0b11; // 16-bit FPR flag
4772    let Predicates = [HasFullFP16];
4773  }
4774
4775  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4776    let Inst{31} = 1; // 64-bit GPR flag
4777    let Inst{23-22} = 0b00; // 32-bit FPR flag
4778  }
4779
4780  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4781    let Inst{31} = 1; // 64-bit GPR flag
4782    let Inst{23-22} = 0b01; // 64-bit FPR flag
4783  }
4784
4785  // Scaled
4786  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4787                             [(set (f16 FPR16:$Rd),
4788                                   (fdiv (node GPR32:$Rn),
4789                                         fixedpoint_f16_i32:$scale))]> {
4790    let Inst{31} = 0; // 32-bit GPR flag
4791    let Inst{23-22} = 0b11; // 16-bit FPR flag
4792    let scale{5} = 1;
4793    let Predicates = [HasFullFP16];
4794  }
4795
4796  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4797                             [(set FPR32:$Rd,
4798                                   (fdiv (node GPR32:$Rn),
4799                                         fixedpoint_f32_i32:$scale))]> {
4800    let Inst{31} = 0; // 32-bit GPR flag
4801    let Inst{23-22} = 0b00; // 32-bit FPR flag
4802    let scale{5} = 1;
4803  }
4804
4805  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4806                             [(set FPR64:$Rd,
4807                                   (fdiv (node GPR32:$Rn),
4808                                         fixedpoint_f64_i32:$scale))]> {
4809    let Inst{31} = 0; // 32-bit GPR flag
4810    let Inst{23-22} = 0b01; // 64-bit FPR flag
4811    let scale{5} = 1;
4812  }
4813
4814  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4815                             [(set (f16 FPR16:$Rd),
4816                                   (fdiv (node GPR64:$Rn),
4817                                         fixedpoint_f16_i64:$scale))]> {
4818    let Inst{31} = 1; // 64-bit GPR flag
4819    let Inst{23-22} = 0b11; // 16-bit FPR flag
4820    let Predicates = [HasFullFP16];
4821  }
4822
4823  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4824                             [(set FPR32:$Rd,
4825                                   (fdiv (node GPR64:$Rn),
4826                                         fixedpoint_f32_i64:$scale))]> {
4827    let Inst{31} = 1; // 64-bit GPR flag
4828    let Inst{23-22} = 0b00; // 32-bit FPR flag
4829  }
4830
4831  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4832                             [(set FPR64:$Rd,
4833                                   (fdiv (node GPR64:$Rn),
4834                                         fixedpoint_f64_i64:$scale))]> {
4835    let Inst{31} = 1; // 64-bit GPR flag
4836    let Inst{23-22} = 0b01; // 64-bit FPR flag
4837  }
4838}
4839
4840//---
4841// Unscaled integer <-> floating point conversion (i.e. FMOV)
4842//---
4843
4844let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4845class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4846                      RegisterClass srcType, RegisterClass dstType,
4847                      string asm>
4848    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4849        // We use COPY_TO_REGCLASS for these bitconvert operations.
4850        // copyPhysReg() expands the resultant COPY instructions after
4851        // regalloc is done. This gives greater freedom for the allocator
4852        // and related passes (coalescing, copy propagation, et. al.) to
4853        // be more effective.
4854        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4855      Sched<[WriteFCopy]> {
4856  bits<5> Rd;
4857  bits<5> Rn;
4858  let Inst{30-24} = 0b0011110;
4859  let Inst{21}    = 1;
4860  let Inst{20-19} = rmode;
4861  let Inst{18-16} = opcode;
4862  let Inst{15-10} = 0b000000;
4863  let Inst{9-5}   = Rn;
4864  let Inst{4-0}   = Rd;
4865}
4866
4867let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4868class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4869                     RegisterClass srcType, RegisterOperand dstType, string asm,
4870                     string kind>
4871    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4872        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4873      Sched<[WriteFCopy]> {
4874  bits<5> Rd;
4875  bits<5> Rn;
4876  let Inst{30-23} = 0b00111101;
4877  let Inst{21}    = 1;
4878  let Inst{20-19} = rmode;
4879  let Inst{18-16} = opcode;
4880  let Inst{15-10} = 0b000000;
4881  let Inst{9-5}   = Rn;
4882  let Inst{4-0}   = Rd;
4883
4884  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4885}
4886
4887let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4888class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4889                     RegisterOperand srcType, RegisterClass dstType, string asm,
4890                     string kind>
4891    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4892        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4893      Sched<[WriteFCopy]> {
4894  bits<5> Rd;
4895  bits<5> Rn;
4896  let Inst{30-23} = 0b00111101;
4897  let Inst{21}    = 1;
4898  let Inst{20-19} = rmode;
4899  let Inst{18-16} = opcode;
4900  let Inst{15-10} = 0b000000;
4901  let Inst{9-5}   = Rn;
4902  let Inst{4-0}   = Rd;
4903
4904  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4905}
4906
4907
4908multiclass UnscaledConversion<string asm> {
4909  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4910    let Inst{31} = 0; // 32-bit GPR flag
4911    let Inst{23-22} = 0b11; // 16-bit FPR flag
4912    let Predicates = [HasFullFP16];
4913  }
4914
4915  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4916    let Inst{31} = 1; // 64-bit GPR flag
4917    let Inst{23-22} = 0b11; // 16-bit FPR flag
4918    let Predicates = [HasFullFP16];
4919  }
4920
4921  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4922    let Inst{31} = 0; // 32-bit GPR flag
4923    let Inst{23-22} = 0b00; // 32-bit FPR flag
4924  }
4925
4926  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4927    let Inst{31} = 1; // 64-bit GPR flag
4928    let Inst{23-22} = 0b01; // 64-bit FPR flag
4929  }
4930
4931  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4932    let Inst{31} = 0; // 32-bit GPR flag
4933    let Inst{23-22} = 0b11; // 16-bit FPR flag
4934    let Predicates = [HasFullFP16];
4935  }
4936
4937  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4938    let Inst{31} = 1; // 64-bit GPR flag
4939    let Inst{23-22} = 0b11; // 16-bit FPR flag
4940    let Predicates = [HasFullFP16];
4941  }
4942
4943  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4944    let Inst{31} = 0; // 32-bit GPR flag
4945    let Inst{23-22} = 0b00; // 32-bit FPR flag
4946  }
4947
4948  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4949    let Inst{31} = 1; // 64-bit GPR flag
4950    let Inst{23-22} = 0b01; // 64-bit FPR flag
4951  }
4952
4953  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4954                                             asm, ".d"> {
4955    let Inst{31} = 1;
4956    let Inst{22} = 0;
4957  }
4958
4959  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4960                                               asm, ".d"> {
4961    let Inst{31} = 1;
4962    let Inst{22} = 0;
4963  }
4964}
4965
4966//---
4967// Floating point conversion
4968//---
4969
4970let mayRaiseFPException = 1 in
4971class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4972                       RegisterClass srcType, string asm, list<dag> pattern>
4973    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4974      Sched<[WriteFCvt]> {
4975  bits<5> Rd;
4976  bits<5> Rn;
4977  let Inst{31-24} = 0b00011110;
4978  let Inst{23-22} = type;
4979  let Inst{21-17} = 0b10001;
4980  let Inst{16-15} = opcode;
4981  let Inst{14-10} = 0b10000;
4982  let Inst{9-5}   = Rn;
4983  let Inst{4-0}   = Rd;
4984}
4985
4986multiclass FPConversion<string asm> {
4987  // Double-precision to Half-precision
4988  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4989                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
4990
4991  // Double-precision to Single-precision
4992  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4993                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
4994
4995  // Half-precision to Double-precision
4996  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4997                             [(set FPR64:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
4998
4999  // Half-precision to Single-precision
5000  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
5001                             [(set FPR32:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5002
5003  // Single-precision to Double-precision
5004  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
5005                             [(set FPR64:$Rd, (any_fpextend FPR32:$Rn))]>;
5006
5007  // Single-precision to Half-precision
5008  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
5009                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
5010}
5011
5012//---
5013// Single operand floating point data processing
5014//---
5015
5016let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5017class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
5018                              ValueType vt, string asm, SDPatternOperator node>
5019    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
5020         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
5021      Sched<[WriteF]> {
5022  bits<5> Rd;
5023  bits<5> Rn;
5024  let Inst{31-24} = 0b00011110;
5025  let Inst{21}    = 0b1;
5026  let Inst{20-15} = opcode;
5027  let Inst{14-10} = 0b10000;
5028  let Inst{9-5}   = Rn;
5029  let Inst{4-0}   = Rd;
5030}
5031
5032multiclass SingleOperandFPData<bits<4> opcode, string asm,
5033                               SDPatternOperator node = null_frag,
5034                               int fpexceptions = 1> {
5035  let mayRaiseFPException = fpexceptions in {
5036  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5037    let Inst{23-22} = 0b11; // 16-bit size flag
5038    let Predicates = [HasFullFP16];
5039  }
5040
5041  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5042    let Inst{23-22} = 0b00; // 32-bit size flag
5043  }
5044
5045  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5046    let Inst{23-22} = 0b01; // 64-bit size flag
5047  }
5048  }
5049}
5050
5051multiclass SingleOperandFPDataNoException<bits<4> opcode, string asm,
5052                                       SDPatternOperator node = null_frag>
5053    : SingleOperandFPData<opcode, asm, node, 0>;
5054
5055let mayRaiseFPException = 1 in
5056multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5057                  SDPatternOperator node = null_frag>{
5058
5059  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5060    let Inst{23-22} = 0b00; // 32-bit registers
5061  }
5062
5063  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5064    let Inst{23-22} = 0b01; // 64-bit registers
5065  }
5066}
5067
5068// FRInt[32|64][Z|N] instructions
5069multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5070      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5071
5072//---
5073// Two operand floating point data processing
5074//---
5075
5076let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5077class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5078                           string asm, list<dag> pat>
5079    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5080         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5081      Sched<[WriteF]> {
5082  bits<5> Rd;
5083  bits<5> Rn;
5084  bits<5> Rm;
5085  let Inst{31-24} = 0b00011110;
5086  let Inst{21}    = 1;
5087  let Inst{20-16} = Rm;
5088  let Inst{15-12} = opcode;
5089  let Inst{11-10} = 0b10;
5090  let Inst{9-5}   = Rn;
5091  let Inst{4-0}   = Rd;
5092}
5093
5094multiclass TwoOperandFPData<bits<4> opcode, string asm,
5095                            SDPatternOperator node = null_frag> {
5096  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5097                         [(set (f16 FPR16:$Rd),
5098                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5099    let Inst{23-22} = 0b11; // 16-bit size flag
5100    let Predicates = [HasFullFP16];
5101  }
5102
5103  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5104                         [(set (f32 FPR32:$Rd),
5105                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5106    let Inst{23-22} = 0b00; // 32-bit size flag
5107  }
5108
5109  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5110                         [(set (f64 FPR64:$Rd),
5111                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5112    let Inst{23-22} = 0b01; // 64-bit size flag
5113  }
5114}
5115
5116multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm,
5117                               SDPatternOperator node> {
5118  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5119                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5120    let Inst{23-22} = 0b11; // 16-bit size flag
5121    let Predicates = [HasFullFP16];
5122  }
5123
5124  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5125                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5126    let Inst{23-22} = 0b00; // 32-bit size flag
5127  }
5128
5129  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5130                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5131    let Inst{23-22} = 0b01; // 64-bit size flag
5132  }
5133}
5134
5135
5136//---
5137// Three operand floating point data processing
5138//---
5139
5140let mayRaiseFPException = 1 in
5141class BaseThreeOperandFPData<bit isNegated, bit isSub,
5142                             RegisterClass regtype, string asm, list<dag> pat>
5143    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5144         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5145      Sched<[WriteFMul]> {
5146  bits<5> Rd;
5147  bits<5> Rn;
5148  bits<5> Rm;
5149  bits<5> Ra;
5150  let Inst{31-24} = 0b00011111;
5151  let Inst{21}    = isNegated;
5152  let Inst{20-16} = Rm;
5153  let Inst{15}    = isSub;
5154  let Inst{14-10} = Ra;
5155  let Inst{9-5}   = Rn;
5156  let Inst{4-0}   = Rd;
5157}
5158
5159multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5160                              SDPatternOperator node> {
5161  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5162            [(set (f16 FPR16:$Rd),
5163                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5164    let Inst{23-22} = 0b11; // 16-bit size flag
5165    let Predicates = [HasFullFP16];
5166  }
5167
5168  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5169            [(set FPR32:$Rd,
5170                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5171    let Inst{23-22} = 0b00; // 32-bit size flag
5172  }
5173
5174  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5175            [(set FPR64:$Rd,
5176                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5177    let Inst{23-22} = 0b01; // 64-bit size flag
5178  }
5179}
5180
5181//---
5182// Floating point data comparisons
5183//---
5184
5185let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5186class BaseOneOperandFPComparison<bit signalAllNans,
5187                                 RegisterClass regtype, string asm,
5188                                 list<dag> pat>
5189    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5190      Sched<[WriteFCmp]> {
5191  bits<5> Rn;
5192  let Inst{31-24} = 0b00011110;
5193  let Inst{21}    = 1;
5194
5195  let Inst{15-10} = 0b001000;
5196  let Inst{9-5}   = Rn;
5197  let Inst{4}     = signalAllNans;
5198  let Inst{3-0}   = 0b1000;
5199
5200  // Rm should be 0b00000 canonically, but we need to accept any value.
5201  let PostEncoderMethod = "fixOneOperandFPComparison";
5202}
5203
5204let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5205class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5206                                string asm, list<dag> pat>
5207    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5208      Sched<[WriteFCmp]> {
5209  bits<5> Rm;
5210  bits<5> Rn;
5211  let Inst{31-24} = 0b00011110;
5212  let Inst{21}    = 1;
5213  let Inst{20-16} = Rm;
5214  let Inst{15-10} = 0b001000;
5215  let Inst{9-5}   = Rn;
5216  let Inst{4}     = signalAllNans;
5217  let Inst{3-0}   = 0b0000;
5218}
5219
5220multiclass FPComparison<bit signalAllNans, string asm,
5221                        SDPatternOperator OpNode = null_frag> {
5222  let Defs = [NZCV] in {
5223  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5224      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5225    let Inst{23-22} = 0b11;
5226    let Predicates = [HasFullFP16];
5227  }
5228
5229  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5230      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5231    let Inst{23-22} = 0b11;
5232    let Predicates = [HasFullFP16];
5233  }
5234
5235  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5236      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5237    let Inst{23-22} = 0b00;
5238  }
5239
5240  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5241      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5242    let Inst{23-22} = 0b00;
5243  }
5244
5245  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5246      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5247    let Inst{23-22} = 0b01;
5248  }
5249
5250  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5251      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5252    let Inst{23-22} = 0b01;
5253  }
5254  } // Defs = [NZCV]
5255}
5256
5257//---
5258// Floating point conditional comparisons
5259//---
5260
5261let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
5262class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5263                           string mnemonic, list<dag> pat>
5264    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5265         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5266      Sched<[WriteFCmp]> {
5267  let Uses = [NZCV];
5268  let Defs = [NZCV];
5269
5270  bits<5> Rn;
5271  bits<5> Rm;
5272  bits<4> nzcv;
5273  bits<4> cond;
5274
5275  let Inst{31-24} = 0b00011110;
5276  let Inst{21}    = 1;
5277  let Inst{20-16} = Rm;
5278  let Inst{15-12} = cond;
5279  let Inst{11-10} = 0b01;
5280  let Inst{9-5}   = Rn;
5281  let Inst{4}     = signalAllNans;
5282  let Inst{3-0}   = nzcv;
5283}
5284
5285multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5286                            SDPatternOperator OpNode = null_frag> {
5287  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5288      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5289                          (i32 imm:$cond), NZCV))]> {
5290    let Inst{23-22} = 0b11;
5291    let Predicates = [HasFullFP16];
5292  }
5293
5294  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5295      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5296                          (i32 imm:$cond), NZCV))]> {
5297    let Inst{23-22} = 0b00;
5298  }
5299
5300  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5301      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5302                          (i32 imm:$cond), NZCV))]> {
5303    let Inst{23-22} = 0b01;
5304  }
5305}
5306
5307//---
5308// Floating point conditional select
5309//---
5310
5311class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5312    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5313         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5314         [(set regtype:$Rd,
5315               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5316                          (i32 imm:$cond), NZCV))]>,
5317      Sched<[WriteF]> {
5318  bits<5> Rd;
5319  bits<5> Rn;
5320  bits<5> Rm;
5321  bits<4> cond;
5322
5323  let Inst{31-24} = 0b00011110;
5324  let Inst{21}    = 1;
5325  let Inst{20-16} = Rm;
5326  let Inst{15-12} = cond;
5327  let Inst{11-10} = 0b11;
5328  let Inst{9-5}   = Rn;
5329  let Inst{4-0}   = Rd;
5330}
5331
5332multiclass FPCondSelect<string asm> {
5333  let Uses = [NZCV] in {
5334  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5335    let Inst{23-22} = 0b11;
5336    let Predicates = [HasFullFP16];
5337  }
5338
5339  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5340    let Inst{23-22} = 0b00;
5341  }
5342
5343  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5344    let Inst{23-22} = 0b01;
5345  }
5346  } // Uses = [NZCV]
5347}
5348
5349//---
5350// Floating move immediate
5351//---
5352
5353class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5354  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5355      [(set regtype:$Rd, fpimmtype:$imm)]>,
5356    Sched<[WriteFImm]> {
5357  bits<5> Rd;
5358  bits<8> imm;
5359  let Inst{31-24} = 0b00011110;
5360  let Inst{21}    = 1;
5361  let Inst{20-13} = imm;
5362  let Inst{12-5}  = 0b10000000;
5363  let Inst{4-0}   = Rd;
5364}
5365
5366multiclass FPMoveImmediate<string asm> {
5367  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5368    let Inst{23-22} = 0b11;
5369    let Predicates = [HasFullFP16];
5370  }
5371
5372  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5373    let Inst{23-22} = 0b00;
5374  }
5375
5376  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5377    let Inst{23-22} = 0b01;
5378  }
5379}
5380} // end of 'let Predicates = [HasFPARMv8]'
5381
5382//----------------------------------------------------------------------------
5383// AdvSIMD
5384//----------------------------------------------------------------------------
5385
5386let Predicates = [HasNEON] in {
5387
5388//----------------------------------------------------------------------------
5389// AdvSIMD three register vector instructions
5390//----------------------------------------------------------------------------
5391
5392let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5393class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5394                        RegisterOperand regtype, string asm, string kind,
5395                        list<dag> pattern>
5396  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5397      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5398      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5399    Sched<[!if(Q, WriteVq, WriteVd)]> {
5400  bits<5> Rd;
5401  bits<5> Rn;
5402  bits<5> Rm;
5403  let Inst{31}    = 0;
5404  let Inst{30}    = Q;
5405  let Inst{29}    = U;
5406  let Inst{28-24} = 0b01110;
5407  let Inst{23-21} = size;
5408  let Inst{20-16} = Rm;
5409  let Inst{15-11} = opcode;
5410  let Inst{10}    = 1;
5411  let Inst{9-5}   = Rn;
5412  let Inst{4-0}   = Rd;
5413}
5414
5415let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5416class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5417                        RegisterOperand regtype, string asm, string kind,
5418                        list<dag> pattern>
5419  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5420      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5421      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5422    Sched<[!if(Q, WriteVq, WriteVd)]> {
5423  bits<5> Rd;
5424  bits<5> Rn;
5425  bits<5> Rm;
5426  let Inst{31}    = 0;
5427  let Inst{30}    = Q;
5428  let Inst{29}    = U;
5429  let Inst{28-24} = 0b01110;
5430  let Inst{23-21} = size;
5431  let Inst{20-16} = Rm;
5432  let Inst{15-11} = opcode;
5433  let Inst{10}    = 1;
5434  let Inst{9-5}   = Rn;
5435  let Inst{4-0}   = Rd;
5436}
5437
5438let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5439class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5440  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5441    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
5442
5443multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5444  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5445             [(set (v8i8 V64:$dst),
5446                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5447  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5448             [(set (v16i8 V128:$dst),
5449                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5450                           (v16i8 V128:$Rm)))]>;
5451
5452  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5453                           (v4i16 V64:$RHS))),
5454          (!cast<Instruction>(NAME#"v8i8")
5455            V64:$LHS, V64:$MHS, V64:$RHS)>;
5456  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5457                           (v2i32 V64:$RHS))),
5458          (!cast<Instruction>(NAME#"v8i8")
5459            V64:$LHS, V64:$MHS, V64:$RHS)>;
5460  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5461                           (v1i64 V64:$RHS))),
5462          (!cast<Instruction>(NAME#"v8i8")
5463            V64:$LHS, V64:$MHS, V64:$RHS)>;
5464
5465  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5466                           (v8i16 V128:$RHS))),
5467      (!cast<Instruction>(NAME#"v16i8")
5468        V128:$LHS, V128:$MHS, V128:$RHS)>;
5469  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5470                           (v4i32 V128:$RHS))),
5471      (!cast<Instruction>(NAME#"v16i8")
5472        V128:$LHS, V128:$MHS, V128:$RHS)>;
5473  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5474                           (v2i64 V128:$RHS))),
5475      (!cast<Instruction>(NAME#"v16i8")
5476        V128:$LHS, V128:$MHS, V128:$RHS)>;
5477}
5478
5479// All operand sizes distinguished in the encoding.
5480multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5481                               SDPatternOperator OpNode> {
5482  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5483                                      asm, ".8b",
5484         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5485  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5486                                      asm, ".16b",
5487         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5488  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5489                                      asm, ".4h",
5490         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5491  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5492                                      asm, ".8h",
5493         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5494  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5495                                      asm, ".2s",
5496         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5497  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5498                                      asm, ".4s",
5499         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5500  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5501                                      asm, ".2d",
5502         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5503}
5504
5505multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5506  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5507          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5508  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5509          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5510  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5511          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5512
5513  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5514          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5515  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5516          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5517  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5518          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5519  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5520          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5521}
5522
5523// As above, but D sized elements unsupported.
5524multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5525                                  SDPatternOperator OpNode> {
5526  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5527                                      asm, ".8b",
5528        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5529  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5530                                      asm, ".16b",
5531        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5532  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5533                                      asm, ".4h",
5534        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5535  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5536                                      asm, ".8h",
5537        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5538  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5539                                      asm, ".2s",
5540        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5541  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5542                                      asm, ".4s",
5543        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5544}
5545
5546multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5547                                  SDPatternOperator OpNode> {
5548  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5549                                      asm, ".8b",
5550      [(set (v8i8 V64:$dst),
5551            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5552  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5553                                      asm, ".16b",
5554      [(set (v16i8 V128:$dst),
5555            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5556  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5557                                      asm, ".4h",
5558      [(set (v4i16 V64:$dst),
5559            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5560  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5561                                      asm, ".8h",
5562      [(set (v8i16 V128:$dst),
5563            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5564  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5565                                      asm, ".2s",
5566      [(set (v2i32 V64:$dst),
5567            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5568  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5569                                      asm, ".4s",
5570      [(set (v4i32 V128:$dst),
5571            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5572}
5573
5574// As above, but only B sized elements supported.
5575multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5576                                SDPatternOperator OpNode> {
5577  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5578                                      asm, ".8b",
5579    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5580  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5581                                      asm, ".16b",
5582    [(set (v16i8 V128:$Rd),
5583          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5584}
5585
5586// As above, but only floating point elements supported.
5587let mayRaiseFPException = 1 in
5588multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5589                                 string asm, SDPatternOperator OpNode> {
5590  let Predicates = [HasNEON, HasFullFP16] in {
5591  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5592                                      asm, ".4h",
5593        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5594  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5595                                      asm, ".8h",
5596        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5597  } // Predicates = [HasNEON, HasFullFP16]
5598  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5599                                      asm, ".2s",
5600        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5601  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5602                                      asm, ".4s",
5603        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5604  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5605                                      asm, ".2d",
5606        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5607}
5608
5609let mayRaiseFPException = 1 in
5610multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5611                                    string asm,
5612                                    SDPatternOperator OpNode> {
5613  let Predicates = [HasNEON, HasFullFP16] in {
5614  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5615                                      asm, ".4h",
5616        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5617  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5618                                      asm, ".8h",
5619        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5620  } // Predicates = [HasNEON, HasFullFP16]
5621  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5622                                      asm, ".2s",
5623        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5624  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5625                                      asm, ".4s",
5626        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5627  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5628                                      asm, ".2d",
5629        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5630}
5631
5632let mayRaiseFPException = 1 in
5633multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5634                                 string asm, SDPatternOperator OpNode> {
5635  let Predicates = [HasNEON, HasFullFP16] in {
5636  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5637                                      asm, ".4h",
5638     [(set (v4f16 V64:$dst),
5639           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5640  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5641                                      asm, ".8h",
5642     [(set (v8f16 V128:$dst),
5643           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5644  } // Predicates = [HasNEON, HasFullFP16]
5645  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5646                                      asm, ".2s",
5647     [(set (v2f32 V64:$dst),
5648           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5649  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5650                                      asm, ".4s",
5651     [(set (v4f32 V128:$dst),
5652           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5653  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5654                                      asm, ".2d",
5655     [(set (v2f64 V128:$dst),
5656           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5657}
5658
5659// As above, but D and B sized elements unsupported.
5660let mayRaiseFPException = 1 in
5661multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5662                                SDPatternOperator OpNode> {
5663  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5664                                      asm, ".4h",
5665        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5666  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5667                                      asm, ".8h",
5668        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5669  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5670                                      asm, ".2s",
5671        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5672  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5673                                      asm, ".4s",
5674        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5675}
5676
5677// Logical three vector ops share opcode bits, and only use B sized elements.
5678multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5679                                  SDPatternOperator OpNode = null_frag> {
5680  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5681                                     asm, ".8b",
5682                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5683  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5684                                     asm, ".16b",
5685                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5686
5687  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5688          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5689  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5690          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5691  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5692          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5693
5694  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5695      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5696  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5697      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5698  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5699      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5700}
5701
5702multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5703                                  string asm, SDPatternOperator OpNode = null_frag> {
5704  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5705                                     asm, ".8b",
5706             [(set (v8i8 V64:$dst),
5707                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5708  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5709                                     asm, ".16b",
5710             [(set (v16i8 V128:$dst),
5711                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5712                           (v16i8 V128:$Rm)))]>;
5713
5714  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5715                           (v4i16 V64:$RHS))),
5716          (!cast<Instruction>(NAME#"v8i8")
5717            V64:$LHS, V64:$MHS, V64:$RHS)>;
5718  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5719                           (v2i32 V64:$RHS))),
5720          (!cast<Instruction>(NAME#"v8i8")
5721            V64:$LHS, V64:$MHS, V64:$RHS)>;
5722  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5723                           (v1i64 V64:$RHS))),
5724          (!cast<Instruction>(NAME#"v8i8")
5725            V64:$LHS, V64:$MHS, V64:$RHS)>;
5726
5727  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5728                           (v8i16 V128:$RHS))),
5729      (!cast<Instruction>(NAME#"v16i8")
5730        V128:$LHS, V128:$MHS, V128:$RHS)>;
5731  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5732                           (v4i32 V128:$RHS))),
5733      (!cast<Instruction>(NAME#"v16i8")
5734        V128:$LHS, V128:$MHS, V128:$RHS)>;
5735  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5736                           (v2i64 V128:$RHS))),
5737      (!cast<Instruction>(NAME#"v16i8")
5738        V128:$LHS, V128:$MHS, V128:$RHS)>;
5739}
5740
5741// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5742// bytes from S-sized elements.
5743class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5744                                 string kind2, RegisterOperand RegType,
5745                                 ValueType AccumType, ValueType InputType,
5746                                 SDPatternOperator OpNode> :
5747        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5748        [(set (AccumType RegType:$dst),
5749              (OpNode (AccumType RegType:$Rd),
5750                      (InputType RegType:$Rn),
5751                      (InputType RegType:$Rm)))]> {
5752  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5753}
5754
5755multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5756  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5757                                         v2i32, v8i8, OpNode>;
5758  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5759                                         v4i32, v16i8, OpNode>;
5760}
5761
5762// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5763// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5764// 8H to 4S, when Q=1).
5765let mayRaiseFPException = 1 in
5766class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5767                                 string kind2, RegisterOperand RegType,
5768                                 ValueType AccumType, ValueType InputType,
5769                                 SDPatternOperator OpNode> :
5770        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5771		[(set (AccumType RegType:$dst),
5772              (OpNode (AccumType RegType:$Rd),
5773                      (InputType RegType:$Rn),
5774                      (InputType RegType:$Rm)))]> {
5775  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5776  let Inst{13} = b13;
5777}
5778
5779multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5780                                  SDPatternOperator OpNode> {
5781  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5782                                         v2f32, v4f16, OpNode>;
5783  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5784                                         v4f32, v8f16, OpNode>;
5785}
5786
5787
5788//----------------------------------------------------------------------------
5789// AdvSIMD two register vector instructions.
5790//----------------------------------------------------------------------------
5791
5792let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5793class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5794                            bits<2> size2, RegisterOperand regtype, string asm,
5795                            string dstkind, string srckind, list<dag> pattern>
5796  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5797      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5798      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5799    Sched<[!if(Q, WriteVq, WriteVd)]> {
5800  bits<5> Rd;
5801  bits<5> Rn;
5802  let Inst{31}    = 0;
5803  let Inst{30}    = Q;
5804  let Inst{29}    = U;
5805  let Inst{28-24} = 0b01110;
5806  let Inst{23-22} = size;
5807  let Inst{21} = 0b1;
5808  let Inst{20-19} = size2;
5809  let Inst{18-17} = 0b00;
5810  let Inst{16-12} = opcode;
5811  let Inst{11-10} = 0b10;
5812  let Inst{9-5}   = Rn;
5813  let Inst{4-0}   = Rd;
5814}
5815
5816let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5817class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5818                                bits<2> size2, RegisterOperand regtype,
5819                                string asm, string dstkind, string srckind,
5820                                list<dag> pattern>
5821  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5822      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5823      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5824    Sched<[!if(Q, WriteVq, WriteVd)]> {
5825  bits<5> Rd;
5826  bits<5> Rn;
5827  let Inst{31}    = 0;
5828  let Inst{30}    = Q;
5829  let Inst{29}    = U;
5830  let Inst{28-24} = 0b01110;
5831  let Inst{23-22} = size;
5832  let Inst{21} = 0b1;
5833  let Inst{20-19} = size2;
5834  let Inst{18-17} = 0b00;
5835  let Inst{16-12} = opcode;
5836  let Inst{11-10} = 0b10;
5837  let Inst{9-5}   = Rn;
5838  let Inst{4-0}   = Rd;
5839}
5840
5841// Supports B, H, and S element sizes.
5842multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5843                            SDPatternOperator OpNode> {
5844  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5845                                      asm, ".8b", ".8b",
5846                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5847  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5848                                      asm, ".16b", ".16b",
5849                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5850  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5851                                      asm, ".4h", ".4h",
5852                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5853  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5854                                      asm, ".8h", ".8h",
5855                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5856  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5857                                      asm, ".2s", ".2s",
5858                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5859  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5860                                      asm, ".4s", ".4s",
5861                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5862}
5863
5864class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5865                            RegisterOperand regtype, string asm, string dstkind,
5866                            string srckind, string amount>
5867  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5868      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5869      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5870    Sched<[WriteVq]> {
5871  bits<5> Rd;
5872  bits<5> Rn;
5873  let Inst{31}    = 0;
5874  let Inst{30}    = Q;
5875  let Inst{29-24} = 0b101110;
5876  let Inst{23-22} = size;
5877  let Inst{21-10} = 0b100001001110;
5878  let Inst{9-5}   = Rn;
5879  let Inst{4-0}   = Rd;
5880}
5881
5882multiclass SIMDVectorLShiftLongBySizeBHS {
5883  let hasSideEffects = 0 in {
5884  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5885                                             "shll", ".8h",  ".8b", "8">;
5886  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5887                                             "shll2", ".8h", ".16b", "8">;
5888  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5889                                             "shll", ".4s",  ".4h", "16">;
5890  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5891                                             "shll2", ".4s", ".8h", "16">;
5892  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5893                                             "shll", ".2d",  ".2s", "32">;
5894  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5895                                             "shll2", ".2d", ".4s", "32">;
5896  }
5897}
5898
5899// Supports all element sizes.
5900multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5901                             SDPatternOperator OpNode> {
5902  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5903                                      asm, ".4h", ".8b",
5904               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5905  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5906                                      asm, ".8h", ".16b",
5907               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5908  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5909                                      asm, ".2s", ".4h",
5910               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5911  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5912                                      asm, ".4s", ".8h",
5913               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5914  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5915                                      asm, ".1d", ".2s",
5916               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5917  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5918                                      asm, ".2d", ".4s",
5919               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5920}
5921
5922multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5923                                 SDPatternOperator OpNode> {
5924  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5925                                          asm, ".4h", ".8b",
5926      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5927                                      (v8i8 V64:$Rn)))]>;
5928  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5929                                          asm, ".8h", ".16b",
5930      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5931                                      (v16i8 V128:$Rn)))]>;
5932  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5933                                          asm, ".2s", ".4h",
5934      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5935                                      (v4i16 V64:$Rn)))]>;
5936  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5937                                          asm, ".4s", ".8h",
5938      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5939                                      (v8i16 V128:$Rn)))]>;
5940  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5941                                          asm, ".1d", ".2s",
5942      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5943                                      (v2i32 V64:$Rn)))]>;
5944  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5945                                          asm, ".2d", ".4s",
5946      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5947                                      (v4i32 V128:$Rn)))]>;
5948}
5949
5950// Supports all element sizes, except 1xD.
5951multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5952                                  SDPatternOperator OpNode> {
5953  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5954                                    asm, ".8b", ".8b",
5955    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5956  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5957                                    asm, ".16b", ".16b",
5958    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5959  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5960                                    asm, ".4h", ".4h",
5961    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5962  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5963                                    asm, ".8h", ".8h",
5964    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5965  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5966                                    asm, ".2s", ".2s",
5967    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5968  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5969                                    asm, ".4s", ".4s",
5970    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5971  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5972                                    asm, ".2d", ".2d",
5973    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5974}
5975
5976multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5977                             SDPatternOperator OpNode = null_frag> {
5978  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5979                                asm, ".8b", ".8b",
5980    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5981  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5982                                asm, ".16b", ".16b",
5983    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5984  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5985                                asm, ".4h", ".4h",
5986    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5987  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5988                                asm, ".8h", ".8h",
5989    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5990  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5991                                asm, ".2s", ".2s",
5992    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5993  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5994                                asm, ".4s", ".4s",
5995    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5996  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5997                                asm, ".2d", ".2d",
5998    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5999}
6000
6001
6002// Supports only B element sizes.
6003multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
6004                          SDPatternOperator OpNode> {
6005  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
6006                                asm, ".8b", ".8b",
6007                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6008  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
6009                                asm, ".16b", ".16b",
6010                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6011
6012}
6013
6014// Supports only B and H element sizes.
6015multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
6016                                SDPatternOperator OpNode> {
6017  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6018                                asm, ".8b", ".8b",
6019                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
6020  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6021                                asm, ".16b", ".16b",
6022                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
6023  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6024                                asm, ".4h", ".4h",
6025                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
6026  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6027                                asm, ".8h", ".8h",
6028                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
6029}
6030
6031// Supports H, S and D element sizes, uses high bit of the size field
6032// as an extra opcode bit.
6033multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
6034                           SDPatternOperator OpNode,
6035                           int fpexceptions = 1> {
6036  let mayRaiseFPException = fpexceptions in {
6037  let Predicates = [HasNEON, HasFullFP16] in {
6038  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6039                                asm, ".4h", ".4h",
6040                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6041  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6042                                asm, ".8h", ".8h",
6043                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6044  } // Predicates = [HasNEON, HasFullFP16]
6045  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6046                                asm, ".2s", ".2s",
6047                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6048  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6049                                asm, ".4s", ".4s",
6050                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6051  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6052                                asm, ".2d", ".2d",
6053                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6054  }
6055}
6056
6057multiclass SIMDTwoVectorFPNoException<bit U, bit S, bits<5> opc, string asm,
6058                                      SDPatternOperator OpNode>
6059    : SIMDTwoVectorFP<U, S, opc, asm, OpNode, 0>;
6060
6061// Supports only S and D element sizes
6062let mayRaiseFPException = 1 in
6063multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6064                           SDPatternOperator OpNode = null_frag> {
6065
6066  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6067                                asm, ".2s", ".2s",
6068                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6069  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6070                                asm, ".4s", ".4s",
6071                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6072  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6073                                asm, ".2d", ".2d",
6074                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6075}
6076
6077multiclass FRIntNNTVector<bit U, bit op, string asm,
6078                          SDPatternOperator OpNode = null_frag> :
6079           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6080
6081// Supports only S element size.
6082multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6083                           SDPatternOperator OpNode> {
6084  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6085                                asm, ".2s", ".2s",
6086                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6087  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6088                                asm, ".4s", ".4s",
6089                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6090}
6091
6092let mayRaiseFPException = 1 in
6093multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6094                           SDPatternOperator OpNode> {
6095  let Predicates = [HasNEON, HasFullFP16] in {
6096  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6097                                asm, ".4h", ".4h",
6098                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6099  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6100                                asm, ".8h", ".8h",
6101                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6102  } // Predicates = [HasNEON, HasFullFP16]
6103  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6104                                asm, ".2s", ".2s",
6105                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6106  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6107                                asm, ".4s", ".4s",
6108                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6109  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6110                                asm, ".2d", ".2d",
6111                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6112}
6113
6114let mayRaiseFPException = 1 in
6115multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6116                           SDPatternOperator OpNode> {
6117  let Predicates = [HasNEON, HasFullFP16] in {
6118  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6119                                asm, ".4h", ".4h",
6120                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6121  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6122                                asm, ".8h", ".8h",
6123                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6124  } // Predicates = [HasNEON, HasFullFP16]
6125  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6126                                asm, ".2s", ".2s",
6127                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6128  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6129                                asm, ".4s", ".4s",
6130                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6131  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6132                                asm, ".2d", ".2d",
6133                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6134}
6135
6136let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6137class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6138                           RegisterOperand inreg, RegisterOperand outreg,
6139                           string asm, string outkind, string inkind,
6140                           list<dag> pattern>
6141  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6142      "{\t$Rd" # outkind # ", $Rn" # inkind #
6143      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6144    Sched<[WriteVq]> {
6145  bits<5> Rd;
6146  bits<5> Rn;
6147  let Inst{31}    = 0;
6148  let Inst{30}    = Q;
6149  let Inst{29}    = U;
6150  let Inst{28-24} = 0b01110;
6151  let Inst{23-22} = size;
6152  let Inst{21-17} = 0b10000;
6153  let Inst{16-12} = opcode;
6154  let Inst{11-10} = 0b10;
6155  let Inst{9-5}   = Rn;
6156  let Inst{4-0}   = Rd;
6157}
6158
6159let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6160class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6161                           RegisterOperand inreg, RegisterOperand outreg,
6162                           string asm, string outkind, string inkind,
6163                           list<dag> pattern>
6164  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6165      "{\t$Rd" # outkind # ", $Rn" # inkind #
6166      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6167    Sched<[WriteVq]> {
6168  bits<5> Rd;
6169  bits<5> Rn;
6170  let Inst{31}    = 0;
6171  let Inst{30}    = Q;
6172  let Inst{29}    = U;
6173  let Inst{28-24} = 0b01110;
6174  let Inst{23-22} = size;
6175  let Inst{21-17} = 0b10000;
6176  let Inst{16-12} = opcode;
6177  let Inst{11-10} = 0b10;
6178  let Inst{9-5}   = Rn;
6179  let Inst{4-0}   = Rd;
6180}
6181
6182multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6183                              SDPatternOperator OpNode> {
6184  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6185                                      asm, ".8b", ".8h",
6186        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6187  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6188                                      asm#"2", ".16b", ".8h", []>;
6189  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6190                                      asm, ".4h", ".4s",
6191        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6192  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6193                                      asm#"2", ".8h", ".4s", []>;
6194  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6195                                      asm, ".2s", ".2d",
6196        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6197  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6198                                      asm#"2", ".4s", ".2d", []>;
6199
6200  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6201            (!cast<Instruction>(NAME # "v16i8")
6202                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6203  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6204            (!cast<Instruction>(NAME # "v8i16")
6205                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6206  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6207            (!cast<Instruction>(NAME # "v4i32")
6208                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6209}
6210
6211class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6212                           bits<5> opcode, RegisterOperand regtype, string asm,
6213                           string kind, string zero, ValueType dty,
6214                           ValueType sty, SDNode OpNode>
6215  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6216      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6217      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6218      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6219    Sched<[!if(Q, WriteVq, WriteVd)]> {
6220  bits<5> Rd;
6221  bits<5> Rn;
6222  let Inst{31}    = 0;
6223  let Inst{30}    = Q;
6224  let Inst{29}    = U;
6225  let Inst{28-24} = 0b01110;
6226  let Inst{23-22} = size;
6227  let Inst{21} = 0b1;
6228  let Inst{20-19} = size2;
6229  let Inst{18-17} = 0b00;
6230  let Inst{16-12} = opcode;
6231  let Inst{11-10} = 0b10;
6232  let Inst{9-5}   = Rn;
6233  let Inst{4-0}   = Rd;
6234}
6235
6236// Comparisons support all element sizes, except 1xD.
6237multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6238                            SDNode OpNode> {
6239  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6240                                     asm, ".8b", "0",
6241                                     v8i8, v8i8, OpNode>;
6242  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6243                                     asm, ".16b", "0",
6244                                     v16i8, v16i8, OpNode>;
6245  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6246                                     asm, ".4h", "0",
6247                                     v4i16, v4i16, OpNode>;
6248  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6249                                     asm, ".8h", "0",
6250                                     v8i16, v8i16, OpNode>;
6251  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6252                                     asm, ".2s", "0",
6253                                     v2i32, v2i32, OpNode>;
6254  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6255                                     asm, ".4s", "0",
6256                                     v4i32, v4i32, OpNode>;
6257  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6258                                     asm, ".2d", "0",
6259                                     v2i64, v2i64, OpNode>;
6260}
6261
6262// FP Comparisons support only S and D element sizes (and H for v8.2a).
6263multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6264                              string asm, SDNode OpNode> {
6265
6266  let mayRaiseFPException = 1 in {
6267  let Predicates = [HasNEON, HasFullFP16] in {
6268  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6269                                     asm, ".4h", "0.0",
6270                                     v4i16, v4f16, OpNode>;
6271  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6272                                     asm, ".8h", "0.0",
6273                                     v8i16, v8f16, OpNode>;
6274  } // Predicates = [HasNEON, HasFullFP16]
6275  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6276                                     asm, ".2s", "0.0",
6277                                     v2i32, v2f32, OpNode>;
6278  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6279                                     asm, ".4s", "0.0",
6280                                     v4i32, v4f32, OpNode>;
6281  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6282                                     asm, ".2d", "0.0",
6283                                     v2i64, v2f64, OpNode>;
6284  }
6285
6286  let Predicates = [HasNEON, HasFullFP16] in {
6287  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6288                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6289  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6290                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6291  }
6292  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6293                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6294  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6295                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6296  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6297                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6298  let Predicates = [HasNEON, HasFullFP16] in {
6299  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6300                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6301  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6302                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6303  }
6304  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6305                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6306  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6307                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6308  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6309                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6310}
6311
6312let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
6313class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6314                             RegisterOperand outtype, RegisterOperand intype,
6315                             string asm, string VdTy, string VnTy,
6316                             list<dag> pattern>
6317  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6318      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6319    Sched<[WriteVq]> {
6320  bits<5> Rd;
6321  bits<5> Rn;
6322  let Inst{31}    = 0;
6323  let Inst{30}    = Q;
6324  let Inst{29}    = U;
6325  let Inst{28-24} = 0b01110;
6326  let Inst{23-22} = size;
6327  let Inst{21-17} = 0b10000;
6328  let Inst{16-12} = opcode;
6329  let Inst{11-10} = 0b10;
6330  let Inst{9-5}   = Rn;
6331  let Inst{4-0}   = Rd;
6332}
6333
6334let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
6335class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6336                             RegisterOperand outtype, RegisterOperand intype,
6337                             string asm, string VdTy, string VnTy,
6338                             list<dag> pattern>
6339  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6340      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6341    Sched<[WriteVq]> {
6342  bits<5> Rd;
6343  bits<5> Rn;
6344  let Inst{31}    = 0;
6345  let Inst{30}    = Q;
6346  let Inst{29}    = U;
6347  let Inst{28-24} = 0b01110;
6348  let Inst{23-22} = size;
6349  let Inst{21-17} = 0b10000;
6350  let Inst{16-12} = opcode;
6351  let Inst{11-10} = 0b10;
6352  let Inst{9-5}   = Rn;
6353  let Inst{4-0}   = Rd;
6354}
6355
6356multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6357  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6358                                    asm, ".4s", ".4h", []>;
6359  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6360                                    asm#"2", ".4s", ".8h", []>;
6361  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6362                                    asm, ".2d", ".2s", []>;
6363  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6364                                    asm#"2", ".2d", ".4s", []>;
6365}
6366
6367multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6368  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6369                                    asm, ".4h", ".4s", []>;
6370  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6371                                    asm#"2", ".8h", ".4s", []>;
6372  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6373                                    asm, ".2s", ".2d", []>;
6374  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6375                                    asm#"2", ".4s", ".2d", []>;
6376}
6377
6378multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6379                                     Intrinsic OpNode> {
6380  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6381                                     asm, ".2s", ".2d",
6382                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6383  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6384                                    asm#"2", ".4s", ".2d", []>;
6385
6386  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6387            (!cast<Instruction>(NAME # "v4f32")
6388                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6389}
6390
6391//----------------------------------------------------------------------------
6392// AdvSIMD three register different-size vector instructions.
6393//----------------------------------------------------------------------------
6394
6395let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6396class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6397                      RegisterOperand outtype, RegisterOperand intype1,
6398                      RegisterOperand intype2, string asm,
6399                      string outkind, string inkind1, string inkind2,
6400                      list<dag> pattern>
6401  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6402      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6403      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6404    Sched<[WriteVq]> {
6405  bits<5> Rd;
6406  bits<5> Rn;
6407  bits<5> Rm;
6408  let Inst{31}    = 0;
6409  let Inst{30}    = size{0};
6410  let Inst{29}    = U;
6411  let Inst{28-24} = 0b01110;
6412  let Inst{23-22} = size{2-1};
6413  let Inst{21}    = 1;
6414  let Inst{20-16} = Rm;
6415  let Inst{15-12} = opcode;
6416  let Inst{11-10} = 0b00;
6417  let Inst{9-5}   = Rn;
6418  let Inst{4-0}   = Rd;
6419}
6420
6421let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6422class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6423                      RegisterOperand outtype, RegisterOperand intype1,
6424                      RegisterOperand intype2, string asm,
6425                      string outkind, string inkind1, string inkind2,
6426                      list<dag> pattern>
6427  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6428      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6429      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6430    Sched<[WriteVq]> {
6431  bits<5> Rd;
6432  bits<5> Rn;
6433  bits<5> Rm;
6434  let Inst{31}    = 0;
6435  let Inst{30}    = size{0};
6436  let Inst{29}    = U;
6437  let Inst{28-24} = 0b01110;
6438  let Inst{23-22} = size{2-1};
6439  let Inst{21}    = 1;
6440  let Inst{20-16} = Rm;
6441  let Inst{15-12} = opcode;
6442  let Inst{11-10} = 0b00;
6443  let Inst{9-5}   = Rn;
6444  let Inst{4-0}   = Rd;
6445}
6446
6447// FIXME: TableGen doesn't know how to deal with expanded types that also
6448//        change the element count (in this case, placing the results in
6449//        the high elements of the result register rather than the low
6450//        elements). Until that's fixed, we can't code-gen those.
6451multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6452                                    Intrinsic IntOp> {
6453  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6454                                                  V64, V128, V128,
6455                                                  asm, ".8b", ".8h", ".8h",
6456     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6457  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6458                                                  V128, V128, V128,
6459                                                  asm#"2", ".16b", ".8h", ".8h",
6460     []>;
6461  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6462                                                  V64, V128, V128,
6463                                                  asm, ".4h", ".4s", ".4s",
6464     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6465  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6466                                                  V128, V128, V128,
6467                                                  asm#"2", ".8h", ".4s", ".4s",
6468     []>;
6469  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6470                                                  V64, V128, V128,
6471                                                  asm, ".2s", ".2d", ".2d",
6472     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6473  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6474                                                  V128, V128, V128,
6475                                                  asm#"2", ".4s", ".2d", ".2d",
6476     []>;
6477
6478
6479  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6480  // a version attached to an instruction.
6481  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6482                                                   (v8i16 V128:$Rm))),
6483            (!cast<Instruction>(NAME # "v8i16_v16i8")
6484                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6485                V128:$Rn, V128:$Rm)>;
6486  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6487                                                    (v4i32 V128:$Rm))),
6488            (!cast<Instruction>(NAME # "v4i32_v8i16")
6489                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6490                V128:$Rn, V128:$Rm)>;
6491  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6492                                                    (v2i64 V128:$Rm))),
6493            (!cast<Instruction>(NAME # "v2i64_v4i32")
6494                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6495                V128:$Rn, V128:$Rm)>;
6496}
6497
6498multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6499                                      Intrinsic IntOp> {
6500  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6501                                            V128, V64, V64,
6502                                            asm, ".8h", ".8b", ".8b",
6503      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6504  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6505                                            V128, V128, V128,
6506                                            asm#"2", ".8h", ".16b", ".16b", []>;
6507  let Predicates = [HasAES] in {
6508    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6509                                              V128, V64, V64,
6510                                              asm, ".1q", ".1d", ".1d", []>;
6511    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6512                                              V128, V128, V128,
6513                                              asm#"2", ".1q", ".2d", ".2d", []>;
6514  }
6515
6516  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 (v16i8 V128:$Rn))),
6517                          (v8i8 (extract_high_v16i8 (v16i8 V128:$Rm))))),
6518      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6519}
6520
6521multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6522                                 SDPatternOperator OpNode> {
6523  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6524                                                  V128, V64, V64,
6525                                                  asm, ".4s", ".4h", ".4h",
6526      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6527  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6528                                                  V128, V128, V128,
6529                                                  asm#"2", ".4s", ".8h", ".8h",
6530      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6531                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6532  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6533                                                  V128, V64, V64,
6534                                                  asm, ".2d", ".2s", ".2s",
6535      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6536  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6537                                                  V128, V128, V128,
6538                                                  asm#"2", ".2d", ".4s", ".4s",
6539      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6540                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6541}
6542
6543multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6544                                  SDPatternOperator OpNode = null_frag> {
6545  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6546                                                  V128, V64, V64,
6547                                                  asm, ".8h", ".8b", ".8b",
6548      [(set (v8i16 V128:$Rd),
6549            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6550  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6551                                                 V128, V128, V128,
6552                                                 asm#"2", ".8h", ".16b", ".16b",
6553      [(set (v8i16 V128:$Rd),
6554            (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6555                                (extract_high_v16i8 (v16i8 V128:$Rm))))))]>;
6556  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6557                                                  V128, V64, V64,
6558                                                  asm, ".4s", ".4h", ".4h",
6559      [(set (v4i32 V128:$Rd),
6560            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6561  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6562                                                  V128, V128, V128,
6563                                                  asm#"2", ".4s", ".8h", ".8h",
6564      [(set (v4i32 V128:$Rd),
6565            (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6566                                  (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6567  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6568                                                  V128, V64, V64,
6569                                                  asm, ".2d", ".2s", ".2s",
6570      [(set (v2i64 V128:$Rd),
6571            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6572  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6573                                                  V128, V128, V128,
6574                                                  asm#"2", ".2d", ".4s", ".4s",
6575      [(set (v2i64 V128:$Rd),
6576            (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6577                                 (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6578}
6579
6580multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6581                                          string asm,
6582                                          SDPatternOperator OpNode> {
6583  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6584                                                  V128, V64, V64,
6585                                                  asm, ".8h", ".8b", ".8b",
6586    [(set (v8i16 V128:$dst),
6587          (add (v8i16 V128:$Rd),
6588               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6589  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6590                                                 V128, V128, V128,
6591                                                 asm#"2", ".8h", ".16b", ".16b",
6592    [(set (v8i16 V128:$dst),
6593          (add (v8i16 V128:$Rd),
6594               (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6595                                   (extract_high_v16i8 (v16i8 V128:$Rm)))))))]>;
6596  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6597                                                  V128, V64, V64,
6598                                                  asm, ".4s", ".4h", ".4h",
6599    [(set (v4i32 V128:$dst),
6600          (add (v4i32 V128:$Rd),
6601               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6602  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6603                                                  V128, V128, V128,
6604                                                  asm#"2", ".4s", ".8h", ".8h",
6605    [(set (v4i32 V128:$dst),
6606          (add (v4i32 V128:$Rd),
6607               (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6608                                    (extract_high_v8i16 (v8i16 V128:$Rm)))))))]>;
6609  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6610                                                  V128, V64, V64,
6611                                                  asm, ".2d", ".2s", ".2s",
6612    [(set (v2i64 V128:$dst),
6613          (add (v2i64 V128:$Rd),
6614               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6615  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6616                                                  V128, V128, V128,
6617                                                  asm#"2", ".2d", ".4s", ".4s",
6618    [(set (v2i64 V128:$dst),
6619          (add (v2i64 V128:$Rd),
6620               (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6621                                    (extract_high_v4i32 (v4i32 V128:$Rm)))))))]>;
6622}
6623
6624multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6625                                  SDPatternOperator OpNode = null_frag> {
6626  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6627                                                  V128, V64, V64,
6628                                                  asm, ".8h", ".8b", ".8b",
6629      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6630  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6631                                                 V128, V128, V128,
6632                                                 asm#"2", ".8h", ".16b", ".16b",
6633      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
6634                                      (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6635  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6636                                                  V128, V64, V64,
6637                                                  asm, ".4s", ".4h", ".4h",
6638      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6639  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6640                                                  V128, V128, V128,
6641                                                  asm#"2", ".4s", ".8h", ".8h",
6642      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6643                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6644  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6645                                                  V128, V64, V64,
6646                                                  asm, ".2d", ".2s", ".2s",
6647      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6648  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6649                                                  V128, V128, V128,
6650                                                  asm#"2", ".2d", ".4s", ".4s",
6651      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6652                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6653}
6654
6655multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6656                                      string asm,
6657                                      SDPatternOperator OpNode> {
6658  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6659                                                  V128, V64, V64,
6660                                                  asm, ".8h", ".8b", ".8b",
6661    [(set (v8i16 V128:$dst),
6662          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6663  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6664                                                 V128, V128, V128,
6665                                                 asm#"2", ".8h", ".16b", ".16b",
6666    [(set (v8i16 V128:$dst),
6667          (OpNode (v8i16 V128:$Rd),
6668                  (extract_high_v16i8 (v16i8 V128:$Rn)),
6669                  (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6670  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6671                                                  V128, V64, V64,
6672                                                  asm, ".4s", ".4h", ".4h",
6673    [(set (v4i32 V128:$dst),
6674          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6675  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6676                                                  V128, V128, V128,
6677                                                  asm#"2", ".4s", ".8h", ".8h",
6678    [(set (v4i32 V128:$dst),
6679          (OpNode (v4i32 V128:$Rd),
6680                  (extract_high_v8i16 (v8i16 V128:$Rn)),
6681                  (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6682  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6683                                                  V128, V64, V64,
6684                                                  asm, ".2d", ".2s", ".2s",
6685    [(set (v2i64 V128:$dst),
6686          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6687  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6688                                                  V128, V128, V128,
6689                                                  asm#"2", ".2d", ".4s", ".4s",
6690    [(set (v2i64 V128:$dst),
6691          (OpNode (v2i64 V128:$Rd),
6692                  (extract_high_v4i32 (v4i32 V128:$Rn)),
6693                  (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6694}
6695
6696multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6697                                           SDPatternOperator Accum> {
6698  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6699                                                  V128, V64, V64,
6700                                                  asm, ".4s", ".4h", ".4h",
6701    [(set (v4i32 V128:$dst),
6702          (Accum (v4i32 V128:$Rd),
6703                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6704                                                (v4i16 V64:$Rm)))))]>;
6705  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6706                                                  V128, V128, V128,
6707                                                  asm#"2", ".4s", ".8h", ".8h",
6708    [(set (v4i32 V128:$dst),
6709          (Accum (v4i32 V128:$Rd),
6710                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 (v8i16 V128:$Rn)),
6711                                            (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
6712  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6713                                                  V128, V64, V64,
6714                                                  asm, ".2d", ".2s", ".2s",
6715    [(set (v2i64 V128:$dst),
6716          (Accum (v2i64 V128:$Rd),
6717                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6718                                                (v2i32 V64:$Rm)))))]>;
6719  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6720                                                  V128, V128, V128,
6721                                                  asm#"2", ".2d", ".4s", ".4s",
6722    [(set (v2i64 V128:$dst),
6723          (Accum (v2i64 V128:$Rd),
6724                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 (v4i32 V128:$Rn)),
6725                                            (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
6726}
6727
6728multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6729                                  SDPatternOperator OpNode> {
6730  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6731                                                  V128, V128, V64,
6732                                                  asm, ".8h", ".8h", ".8b",
6733       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6734  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6735                                                  V128, V128, V128,
6736                                                  asm#"2", ".8h", ".8h", ".16b",
6737       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6738                                       (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
6739  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6740                                                  V128, V128, V64,
6741                                                  asm, ".4s", ".4s", ".4h",
6742       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6743  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6744                                                  V128, V128, V128,
6745                                                  asm#"2", ".4s", ".4s", ".8h",
6746       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6747                                       (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6748  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6749                                                  V128, V128, V64,
6750                                                  asm, ".2d", ".2d", ".2s",
6751       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6752  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6753                                                  V128, V128, V128,
6754                                                  asm#"2", ".2d", ".2d", ".4s",
6755       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6756                                       (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6757}
6758
6759//----------------------------------------------------------------------------
6760// AdvSIMD bitwise extract from vector
6761//----------------------------------------------------------------------------
6762
6763class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6764                             string asm, string kind>
6765  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6766      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6767      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6768      [(set (vty regtype:$Rd),
6769            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6770    Sched<[!if(size, WriteVq, WriteVd)]> {
6771  bits<5> Rd;
6772  bits<5> Rn;
6773  bits<5> Rm;
6774  bits<4> imm;
6775  let Inst{31}    = 0;
6776  let Inst{30}    = size;
6777  let Inst{29-21} = 0b101110000;
6778  let Inst{20-16} = Rm;
6779  let Inst{15}    = 0;
6780  let Inst{14-11} = imm;
6781  let Inst{10}    = 0;
6782  let Inst{9-5}   = Rn;
6783  let Inst{4-0}   = Rd;
6784}
6785
6786
6787multiclass SIMDBitwiseExtract<string asm> {
6788  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6789    let imm{3} = 0;
6790  }
6791  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6792}
6793
6794//----------------------------------------------------------------------------
6795// AdvSIMD zip vector
6796//----------------------------------------------------------------------------
6797
6798class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6799                        string asm, string kind, SDNode OpNode, ValueType valty>
6800  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6801      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6802      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6803      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6804    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
6805  bits<5> Rd;
6806  bits<5> Rn;
6807  bits<5> Rm;
6808  let Inst{31}    = 0;
6809  let Inst{30}    = size{0};
6810  let Inst{29-24} = 0b001110;
6811  let Inst{23-22} = size{2-1};
6812  let Inst{21}    = 0;
6813  let Inst{20-16} = Rm;
6814  let Inst{15}    = 0;
6815  let Inst{14-12} = opc;
6816  let Inst{11-10} = 0b10;
6817  let Inst{9-5}   = Rn;
6818  let Inst{4-0}   = Rd;
6819}
6820
6821multiclass SIMDZipVector<bits<3>opc, string asm,
6822                         SDNode OpNode> {
6823  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6824      asm, ".8b", OpNode, v8i8>;
6825  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6826      asm, ".16b", OpNode, v16i8>;
6827  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6828      asm, ".4h", OpNode, v4i16>;
6829  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6830      asm, ".8h", OpNode, v8i16>;
6831  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6832      asm, ".2s", OpNode, v2i32>;
6833  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6834      asm, ".4s", OpNode, v4i32>;
6835  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6836      asm, ".2d", OpNode, v2i64>;
6837
6838  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6839        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6840  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6841        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6842  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6843        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6844  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6845        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6846  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6847        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6848}
6849
6850//----------------------------------------------------------------------------
6851// AdvSIMD three register scalar instructions
6852//----------------------------------------------------------------------------
6853
6854let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6855class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6856                        RegisterClass regtype, string asm,
6857                        list<dag> pattern>
6858  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6859      "\t$Rd, $Rn, $Rm", "", pattern>,
6860    Sched<[WriteVd]> {
6861  bits<5> Rd;
6862  bits<5> Rn;
6863  bits<5> Rm;
6864  let Inst{31-30} = 0b01;
6865  let Inst{29}    = U;
6866  let Inst{28-24} = 0b11110;
6867  let Inst{23-21} = size;
6868  let Inst{20-16} = Rm;
6869  let Inst{15-11} = opcode;
6870  let Inst{10}    = 1;
6871  let Inst{9-5}   = Rn;
6872  let Inst{4-0}   = Rd;
6873}
6874
6875let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6876class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6877                        dag oops, dag iops, string asm,
6878            list<dag> pattern>
6879  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6880    Sched<[WriteVd]> {
6881  bits<5> Rd;
6882  bits<5> Rn;
6883  bits<5> Rm;
6884  let Inst{31-30} = 0b01;
6885  let Inst{29}    = U;
6886  let Inst{28-24} = 0b11110;
6887  let Inst{23-22} = size;
6888  let Inst{21}    = R;
6889  let Inst{20-16} = Rm;
6890  let Inst{15-11} = opcode;
6891  let Inst{10}    = 1;
6892  let Inst{9-5}   = Rn;
6893  let Inst{4-0}   = Rd;
6894}
6895
6896multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6897                            SDPatternOperator OpNode> {
6898  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6899    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6900}
6901
6902multiclass SIMDThreeScalarBHSD<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  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6907  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6908  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6909
6910  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6911            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6912  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6913            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6914}
6915
6916multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6917                             SDPatternOperator OpNode> {
6918  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6919                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6920  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6921}
6922
6923multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
6924  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6925                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6926                                     asm, []>;
6927  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6928                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6929                                     asm, []>;
6930}
6931
6932multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6933                             SDPatternOperator OpNode = null_frag,
6934                             Predicate pred = HasNEON> {
6935  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in {
6936    let Predicates = [pred] in {
6937    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6938      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6939    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6940      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6941    }
6942    let Predicates = [pred, HasFullFP16] in {
6943    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6944      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
6945    }
6946  }
6947
6948  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6949            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6950}
6951
6952multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6953                                SDPatternOperator OpNode = null_frag> {
6954  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in {
6955    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6956      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6957    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6958      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6959    let Predicates = [HasNEON, HasFullFP16] in {
6960    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6961      []>;
6962    } // Predicates = [HasNEON, HasFullFP16]
6963  }
6964
6965  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6966            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6967}
6968
6969class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6970              dag oops, dag iops, string asm, string cstr, list<dag> pat>
6971  : I<oops, iops, asm,
6972      "\t$Rd, $Rn, $Rm", cstr, pat>,
6973    Sched<[WriteVd]> {
6974  bits<5> Rd;
6975  bits<5> Rn;
6976  bits<5> Rm;
6977  let Inst{31-30} = 0b01;
6978  let Inst{29}    = U;
6979  let Inst{28-24} = 0b11110;
6980  let Inst{23-22} = size;
6981  let Inst{21}    = 1;
6982  let Inst{20-16} = Rm;
6983  let Inst{15-11} = opcode;
6984  let Inst{10}    = 0;
6985  let Inst{9-5}   = Rn;
6986  let Inst{4-0}   = Rd;
6987}
6988
6989let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6990multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6991                                  SDPatternOperator OpNode = null_frag> {
6992  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6993                                      (outs FPR32:$Rd),
6994                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6995  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6996                                      (outs FPR64:$Rd),
6997                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6998            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6999}
7000
7001let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7002multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
7003                                  SDPatternOperator OpNode = null_frag> {
7004  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7005                                      (outs FPR32:$dst),
7006                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
7007                                      asm, "$Rd = $dst", []>;
7008  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7009                                      (outs FPR64:$dst),
7010                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
7011                                      asm, "$Rd = $dst",
7012            [(set (i64 FPR64:$dst),
7013                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7014}
7015
7016//----------------------------------------------------------------------------
7017// AdvSIMD two register scalar instructions
7018//----------------------------------------------------------------------------
7019
7020let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7021class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7022                        RegisterClass regtype, RegisterClass regtype2,
7023                        string asm, list<dag> pat>
7024  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
7025      "\t$Rd, $Rn", "", pat>,
7026    Sched<[WriteVd]> {
7027  bits<5> Rd;
7028  bits<5> Rn;
7029  let Inst{31-30} = 0b01;
7030  let Inst{29}    = U;
7031  let Inst{28-24} = 0b11110;
7032  let Inst{23-22} = size;
7033  let Inst{21} = 0b1;
7034  let Inst{20-19} = size2;
7035  let Inst{18-17} = 0b00;
7036  let Inst{16-12} = opcode;
7037  let Inst{11-10} = 0b10;
7038  let Inst{9-5}   = Rn;
7039  let Inst{4-0}   = Rd;
7040}
7041
7042let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7043class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
7044                        RegisterClass regtype, RegisterClass regtype2,
7045                        string asm, list<dag> pat>
7046  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
7047      "\t$Rd, $Rn", "$Rd = $dst", pat>,
7048    Sched<[WriteVd]> {
7049  bits<5> Rd;
7050  bits<5> Rn;
7051  let Inst{31-30} = 0b01;
7052  let Inst{29}    = U;
7053  let Inst{28-24} = 0b11110;
7054  let Inst{23-22} = size;
7055  let Inst{21-17} = 0b10000;
7056  let Inst{16-12} = opcode;
7057  let Inst{11-10} = 0b10;
7058  let Inst{9-5}   = Rn;
7059  let Inst{4-0}   = Rd;
7060}
7061
7062
7063let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7064class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7065                        RegisterClass regtype, string asm, string zero>
7066  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7067      "\t$Rd, $Rn, #" # zero, "", []>,
7068    Sched<[WriteVd]> {
7069  bits<5> Rd;
7070  bits<5> Rn;
7071  let Inst{31-30} = 0b01;
7072  let Inst{29}    = U;
7073  let Inst{28-24} = 0b11110;
7074  let Inst{23-22} = size;
7075  let Inst{21} = 0b1;
7076  let Inst{20-19} = size2;
7077  let Inst{18-17} = 0b00;
7078  let Inst{16-12} = opcode;
7079  let Inst{11-10} = 0b10;
7080  let Inst{9-5}   = Rn;
7081  let Inst{4-0}   = Rd;
7082}
7083
7084let mayRaiseFPException = 1 in
7085class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7086  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7087     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
7088    Sched<[WriteVd]> {
7089  bits<5> Rd;
7090  bits<5> Rn;
7091  let Inst{31-17} = 0b011111100110000;
7092  let Inst{16-12} = opcode;
7093  let Inst{11-10} = 0b10;
7094  let Inst{9-5}   = Rn;
7095  let Inst{4-0}   = Rd;
7096}
7097
7098multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7099                             SDPatternOperator OpNode> {
7100  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7101
7102  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7103            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7104}
7105
7106multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7107                              SDPatternOperator OpNode> {
7108  let mayRaiseFPException = 1 in {
7109  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7110  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7111  let Predicates = [HasNEON, HasFullFP16] in {
7112  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7113  }
7114  }
7115
7116  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7117                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7118  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7119                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7120  let Predicates = [HasNEON, HasFullFP16] in {
7121  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7122                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7123  }
7124
7125  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7126            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7127}
7128
7129multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7130                          SDPatternOperator OpNode = null_frag> {
7131  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7132    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7133
7134  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7135            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7136}
7137
7138let mayRaiseFPException = 1 in
7139multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm,
7140                           Predicate pred = HasNEON> {
7141  let Predicates = [pred] in {
7142  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7143  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7144  }
7145  let Predicates = [pred, HasFullFP16] in {
7146  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7147  }
7148}
7149
7150let mayRaiseFPException = 1 in
7151multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7152                              SDPatternOperator OpNode> {
7153  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7154                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7155  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7156                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7157  let Predicates = [HasNEON, HasFullFP16] in {
7158  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7159                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7160  }
7161}
7162
7163multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7164                             SDPatternOperator OpNode = null_frag> {
7165  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7166    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7167           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7168    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7169           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7170    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7171    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7172  }
7173
7174  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7175            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7176}
7177
7178multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7179                                 Intrinsic OpNode> {
7180  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7181    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7182        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7183    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7184        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7185    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7186    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7187  }
7188
7189  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7190            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7191}
7192
7193
7194
7195let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7196multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7197                                 SDPatternOperator OpNode = null_frag> {
7198  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7199        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7200  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7201  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7202}
7203
7204//----------------------------------------------------------------------------
7205// AdvSIMD scalar pairwise instructions
7206//----------------------------------------------------------------------------
7207
7208let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7209class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7210                        RegisterOperand regtype, RegisterOperand vectype,
7211                        string asm, string kind>
7212  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7213      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7214    Sched<[WriteVd]> {
7215  bits<5> Rd;
7216  bits<5> Rn;
7217  let Inst{31-30} = 0b01;
7218  let Inst{29}    = U;
7219  let Inst{28-24} = 0b11110;
7220  let Inst{23-22} = size;
7221  let Inst{21-17} = 0b11000;
7222  let Inst{16-12} = opcode;
7223  let Inst{11-10} = 0b10;
7224  let Inst{9-5}   = Rn;
7225  let Inst{4-0}   = Rd;
7226}
7227
7228multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7229  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7230                                      asm, ".2d">;
7231}
7232
7233let mayRaiseFPException = 1 in
7234multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7235  let Predicates = [HasNEON, HasFullFP16] in {
7236  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7237                                      asm, ".2h">;
7238  }
7239  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7240                                      asm, ".2s">;
7241  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7242                                      asm, ".2d">;
7243}
7244
7245//----------------------------------------------------------------------------
7246// AdvSIMD across lanes instructions
7247//----------------------------------------------------------------------------
7248
7249let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7250class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7251                          RegisterClass regtype, RegisterOperand vectype,
7252                          string asm, string kind, list<dag> pattern>
7253  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7254      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7255    Sched<[!if(Q, WriteVq, WriteVd)]> {
7256  bits<5> Rd;
7257  bits<5> Rn;
7258  let Inst{31}    = 0;
7259  let Inst{30}    = Q;
7260  let Inst{29}    = U;
7261  let Inst{28-24} = 0b01110;
7262  let Inst{23-22} = size;
7263  let Inst{21-17} = 0b11000;
7264  let Inst{16-12} = opcode;
7265  let Inst{11-10} = 0b10;
7266  let Inst{9-5}   = Rn;
7267  let Inst{4-0}   = Rd;
7268}
7269
7270multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7271                              string asm> {
7272  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7273                                   asm, ".8b", []>;
7274  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7275                                   asm, ".16b", []>;
7276  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7277                                   asm, ".4h", []>;
7278  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7279                                   asm, ".8h", []>;
7280  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7281                                   asm, ".4s", []>;
7282}
7283
7284multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7285  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7286                                   asm, ".8b", []>;
7287  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7288                                   asm, ".16b", []>;
7289  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7290                                   asm, ".4h", []>;
7291  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7292                                   asm, ".8h", []>;
7293  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7294                                   asm, ".4s", []>;
7295}
7296
7297let mayRaiseFPException = 1 in
7298multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7299                            Intrinsic intOp> {
7300  let Predicates = [HasNEON, HasFullFP16] in {
7301  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7302                                   asm, ".4h",
7303        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7304  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7305                                   asm, ".8h",
7306        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7307  } // Predicates = [HasNEON, HasFullFP16]
7308  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7309                                   asm, ".4s",
7310        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7311}
7312
7313//----------------------------------------------------------------------------
7314// AdvSIMD INS/DUP instructions
7315//----------------------------------------------------------------------------
7316
7317// FIXME: There has got to be a better way to factor these. ugh.
7318
7319class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7320                     string operands, string constraints, list<dag> pattern>
7321  : I<outs, ins, asm, operands, constraints, pattern>,
7322    Sched<[!if(Q, WriteVq, WriteVd)]> {
7323  bits<5> Rd;
7324  bits<5> Rn;
7325  let Inst{31} = 0;
7326  let Inst{30} = Q;
7327  let Inst{29} = op;
7328  let Inst{28-21} = 0b01110000;
7329  let Inst{15} = 0;
7330  let Inst{10} = 1;
7331  let Inst{9-5} = Rn;
7332  let Inst{4-0} = Rd;
7333}
7334
7335class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7336                      RegisterOperand vecreg, RegisterClass regtype>
7337  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7338                   "{\t$Rd" # size # ", $Rn" #
7339                   "|" # size # "\t$Rd, $Rn}", "",
7340                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7341  let Inst{20-16} = imm5;
7342  let Inst{14-11} = 0b0001;
7343}
7344
7345class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7346                         ValueType vectype, ValueType insreg,
7347                         RegisterOperand vecreg, Operand idxtype,
7348                         SDNode OpNode>
7349  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7350                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7351                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7352                 [(set (vectype vecreg:$Rd),
7353                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7354  let Inst{14-11} = 0b0000;
7355}
7356
7357class SIMDDup64FromElement
7358  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7359                       VectorIndexD, AArch64duplane64> {
7360  bits<1> idx;
7361  let Inst{20} = idx;
7362  let Inst{19-16} = 0b1000;
7363}
7364
7365class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7366                           RegisterOperand vecreg>
7367  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7368                       VectorIndexS, AArch64duplane32> {
7369  bits<2> idx;
7370  let Inst{20-19} = idx;
7371  let Inst{18-16} = 0b100;
7372}
7373
7374class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7375                           RegisterOperand vecreg>
7376  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7377                       VectorIndexH, AArch64duplane16> {
7378  bits<3> idx;
7379  let Inst{20-18} = idx;
7380  let Inst{17-16} = 0b10;
7381}
7382
7383class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7384                          RegisterOperand vecreg>
7385  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7386                       VectorIndexB, AArch64duplane8> {
7387  bits<4> idx;
7388  let Inst{20-17} = idx;
7389  let Inst{16} = 1;
7390}
7391
7392class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7393                  Operand idxtype, string asm, list<dag> pattern>
7394  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7395                   "{\t$Rd, $Rn" # size # "$idx" #
7396                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7397  let Inst{14-11} = imm4;
7398}
7399
7400class SIMDSMov<bit Q, string size, RegisterClass regtype,
7401               Operand idxtype>
7402  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7403class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7404               Operand idxtype>
7405  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7406      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7407
7408class SIMDMovAlias<string asm, string size, Instruction inst,
7409                   RegisterClass regtype, Operand idxtype>
7410    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7411                    "|" # size # "\t$dst, $src$idx}",
7412                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7413
7414multiclass SMov {
7415  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7416  // streaming mode.
7417  let Predicates = [HasNEONorSME] in {
7418    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
7419      let Inst{20-16} = 0b00001;
7420    }
7421    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
7422      let Inst{20-16} = 0b00001;
7423    }
7424    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
7425      let Inst{20-16} = 0b00010;
7426    }
7427    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
7428      let Inst{20-16} = 0b00010;
7429    }
7430    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
7431      let Inst{20-16} = 0b00100;
7432    }
7433  }
7434  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7435    bits<4> idx;
7436    let Inst{20-17} = idx;
7437    let Inst{16} = 1;
7438  }
7439  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7440    bits<4> idx;
7441    let Inst{20-17} = idx;
7442    let Inst{16} = 1;
7443  }
7444  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7445    bits<3> idx;
7446    let Inst{20-18} = idx;
7447    let Inst{17-16} = 0b10;
7448  }
7449  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7450    bits<3> idx;
7451    let Inst{20-18} = idx;
7452    let Inst{17-16} = 0b10;
7453  }
7454  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7455    bits<2> idx;
7456    let Inst{20-19} = idx;
7457    let Inst{18-16} = 0b100;
7458  }
7459}
7460
7461multiclass UMov {
7462  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7463  // streaming mode.
7464  let Predicates = [HasNEONorSME] in {
7465    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
7466      let Inst{20-16} = 0b00001;
7467    }
7468    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
7469      let Inst{20-16} = 0b00010;
7470    }
7471    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
7472      let Inst{20-16} = 0b00100;
7473    }
7474    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
7475      let Inst{20-16} = 0b01000;
7476    }
7477    def : SIMDMovAlias<"mov", ".s",
7478                       !cast<Instruction>(NAME # vi32_idx0),
7479                       GPR32, VectorIndex0>;
7480    def : SIMDMovAlias<"mov", ".d",
7481                       !cast<Instruction>(NAME # vi64_idx0),
7482                       GPR64, VectorIndex0>;
7483  }
7484  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7485    bits<4> idx;
7486    let Inst{20-17} = idx;
7487    let Inst{16} = 1;
7488  }
7489  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7490    bits<3> idx;
7491    let Inst{20-18} = idx;
7492    let Inst{17-16} = 0b10;
7493  }
7494  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7495    bits<2> idx;
7496    let Inst{20-19} = idx;
7497    let Inst{18-16} = 0b100;
7498  }
7499  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7500    bits<1> idx;
7501    let Inst{20} = idx;
7502    let Inst{19-16} = 0b1000;
7503  }
7504  def : SIMDMovAlias<"mov", ".s",
7505                     !cast<Instruction>(NAME#"vi32"),
7506                     GPR32, VectorIndexS>;
7507  def : SIMDMovAlias<"mov", ".d",
7508                     !cast<Instruction>(NAME#"vi64"),
7509                     GPR64, VectorIndexD>;
7510}
7511
7512class SIMDInsFromMain<string size, ValueType vectype,
7513                      RegisterClass regtype, Operand idxtype>
7514  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7515                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7516                   "{\t$Rd" # size # "$idx, $Rn" #
7517                   "|" # size # "\t$Rd$idx, $Rn}",
7518                   "$Rd = $dst",
7519            [(set V128:$dst,
7520              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7521  let Inst{14-11} = 0b0011;
7522}
7523
7524class SIMDInsFromElement<string size, ValueType vectype,
7525                         ValueType elttype, Operand idxtype>
7526  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7527                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7528                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7529                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7530                   "$Rd = $dst",
7531         [(set V128:$dst,
7532               (vector_insert
7533                 (vectype V128:$Rd),
7534                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7535                 idxtype:$idx))]>;
7536
7537class SIMDInsMainMovAlias<string size, Instruction inst,
7538                          RegisterClass regtype, Operand idxtype>
7539    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7540                        "|" # size #"\t$dst$idx, $src}",
7541                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7542class SIMDInsElementMovAlias<string size, Instruction inst,
7543                             Operand idxtype>
7544    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7545                      # "|" # size #"\t$dst$idx, $src$idx2}",
7546                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7547
7548
7549multiclass SIMDIns {
7550  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7551    bits<4> idx;
7552    let Inst{20-17} = idx;
7553    let Inst{16} = 1;
7554  }
7555  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7556    bits<3> idx;
7557    let Inst{20-18} = idx;
7558    let Inst{17-16} = 0b10;
7559  }
7560  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7561    bits<2> idx;
7562    let Inst{20-19} = idx;
7563    let Inst{18-16} = 0b100;
7564  }
7565  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7566    bits<1> idx;
7567    let Inst{20} = idx;
7568    let Inst{19-16} = 0b1000;
7569  }
7570
7571  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7572    bits<4> idx;
7573    bits<4> idx2;
7574    let Inst{20-17} = idx;
7575    let Inst{16} = 1;
7576    let Inst{14-11} = idx2;
7577  }
7578  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7579    bits<3> idx;
7580    bits<3> idx2;
7581    let Inst{20-18} = idx;
7582    let Inst{17-16} = 0b10;
7583    let Inst{14-12} = idx2;
7584    let Inst{11} = {?};
7585  }
7586  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7587    bits<2> idx;
7588    bits<2> idx2;
7589    let Inst{20-19} = idx;
7590    let Inst{18-16} = 0b100;
7591    let Inst{14-13} = idx2;
7592    let Inst{12-11} = {?,?};
7593  }
7594  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7595    bits<1> idx;
7596    bits<1> idx2;
7597    let Inst{20} = idx;
7598    let Inst{19-16} = 0b1000;
7599    let Inst{14} = idx2;
7600    let Inst{13-11} = {?,?,?};
7601  }
7602
7603  // For all forms of the INS instruction, the "mov" mnemonic is the
7604  // preferred alias. Why they didn't just call the instruction "mov" in
7605  // the first place is a very good question indeed...
7606  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7607                         GPR32, VectorIndexB>;
7608  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7609                         GPR32, VectorIndexH>;
7610  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7611                         GPR32, VectorIndexS>;
7612  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7613                         GPR64, VectorIndexD>;
7614
7615  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7616                         VectorIndexB>;
7617  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7618                         VectorIndexH>;
7619  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7620                         VectorIndexS>;
7621  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7622                         VectorIndexD>;
7623}
7624
7625//----------------------------------------------------------------------------
7626// AdvSIMD TBL/TBX
7627//----------------------------------------------------------------------------
7628
7629let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7630class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7631                          RegisterOperand listtype, string asm, string kind>
7632  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7633       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7634    Sched<[!if(Q, WriteVq, WriteVd)]> {
7635  bits<5> Vd;
7636  bits<5> Vn;
7637  bits<5> Vm;
7638  let Inst{31}    = 0;
7639  let Inst{30}    = Q;
7640  let Inst{29-21} = 0b001110000;
7641  let Inst{20-16} = Vm;
7642  let Inst{15}    = 0;
7643  let Inst{14-13} = len;
7644  let Inst{12}    = op;
7645  let Inst{11-10} = 0b00;
7646  let Inst{9-5}   = Vn;
7647  let Inst{4-0}   = Vd;
7648}
7649
7650let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7651class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7652                          RegisterOperand listtype, string asm, string kind>
7653  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7654       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7655    Sched<[!if(Q, WriteVq, WriteVd)]> {
7656  bits<5> Vd;
7657  bits<5> Vn;
7658  bits<5> Vm;
7659  let Inst{31}    = 0;
7660  let Inst{30}    = Q;
7661  let Inst{29-21} = 0b001110000;
7662  let Inst{20-16} = Vm;
7663  let Inst{15}    = 0;
7664  let Inst{14-13} = len;
7665  let Inst{12}    = op;
7666  let Inst{11-10} = 0b00;
7667  let Inst{9-5}   = Vn;
7668  let Inst{4-0}   = Vd;
7669}
7670
7671class SIMDTableLookupAlias<string asm, Instruction inst,
7672                          RegisterOperand vectype, RegisterOperand listtype>
7673    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7674                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7675
7676multiclass SIMDTableLookup<bit op, string asm> {
7677  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7678                                      asm, ".8b">;
7679  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7680                                      asm, ".8b">;
7681  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7682                                      asm, ".8b">;
7683  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7684                                      asm, ".8b">;
7685  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7686                                      asm, ".16b">;
7687  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7688                                      asm, ".16b">;
7689  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7690                                      asm, ".16b">;
7691  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7692                                      asm, ".16b">;
7693
7694  def : SIMDTableLookupAlias<asm # ".8b",
7695                         !cast<Instruction>(NAME#"v8i8One"),
7696                         V64, VecListOne128>;
7697  def : SIMDTableLookupAlias<asm # ".8b",
7698                         !cast<Instruction>(NAME#"v8i8Two"),
7699                         V64, VecListTwo128>;
7700  def : SIMDTableLookupAlias<asm # ".8b",
7701                         !cast<Instruction>(NAME#"v8i8Three"),
7702                         V64, VecListThree128>;
7703  def : SIMDTableLookupAlias<asm # ".8b",
7704                         !cast<Instruction>(NAME#"v8i8Four"),
7705                         V64, VecListFour128>;
7706  def : SIMDTableLookupAlias<asm # ".16b",
7707                         !cast<Instruction>(NAME#"v16i8One"),
7708                         V128, VecListOne128>;
7709  def : SIMDTableLookupAlias<asm # ".16b",
7710                         !cast<Instruction>(NAME#"v16i8Two"),
7711                         V128, VecListTwo128>;
7712  def : SIMDTableLookupAlias<asm # ".16b",
7713                         !cast<Instruction>(NAME#"v16i8Three"),
7714                         V128, VecListThree128>;
7715  def : SIMDTableLookupAlias<asm # ".16b",
7716                         !cast<Instruction>(NAME#"v16i8Four"),
7717                         V128, VecListFour128>;
7718}
7719
7720multiclass SIMDTableLookupTied<bit op, string asm> {
7721  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7722                                      asm, ".8b">;
7723  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7724                                      asm, ".8b">;
7725  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7726                                      asm, ".8b">;
7727  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7728                                      asm, ".8b">;
7729  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7730                                      asm, ".16b">;
7731  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7732                                      asm, ".16b">;
7733  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7734                                      asm, ".16b">;
7735  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7736                                      asm, ".16b">;
7737
7738  def : SIMDTableLookupAlias<asm # ".8b",
7739                         !cast<Instruction>(NAME#"v8i8One"),
7740                         V64, VecListOne128>;
7741  def : SIMDTableLookupAlias<asm # ".8b",
7742                         !cast<Instruction>(NAME#"v8i8Two"),
7743                         V64, VecListTwo128>;
7744  def : SIMDTableLookupAlias<asm # ".8b",
7745                         !cast<Instruction>(NAME#"v8i8Three"),
7746                         V64, VecListThree128>;
7747  def : SIMDTableLookupAlias<asm # ".8b",
7748                         !cast<Instruction>(NAME#"v8i8Four"),
7749                         V64, VecListFour128>;
7750  def : SIMDTableLookupAlias<asm # ".16b",
7751                         !cast<Instruction>(NAME#"v16i8One"),
7752                         V128, VecListOne128>;
7753  def : SIMDTableLookupAlias<asm # ".16b",
7754                         !cast<Instruction>(NAME#"v16i8Two"),
7755                         V128, VecListTwo128>;
7756  def : SIMDTableLookupAlias<asm # ".16b",
7757                         !cast<Instruction>(NAME#"v16i8Three"),
7758                         V128, VecListThree128>;
7759  def : SIMDTableLookupAlias<asm # ".16b",
7760                         !cast<Instruction>(NAME#"v16i8Four"),
7761                         V128, VecListFour128>;
7762}
7763
7764
7765//----------------------------------------------------------------------------
7766// AdvSIMD scalar DUP
7767//----------------------------------------------------------------------------
7768let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7769class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
7770                        string asm, string kind, Operand idxtype>
7771  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
7772       "{\t$dst, $src" # kind # "$idx" #
7773       "|\t$dst, $src$idx}", "", []>,
7774    Sched<[WriteVd]> {
7775  bits<5> dst;
7776  bits<5> src;
7777  let Inst{31-21} = 0b01011110000;
7778  let Inst{15-10} = 0b000001;
7779  let Inst{9-5}   = src;
7780  let Inst{4-0}   = dst;
7781}
7782
7783class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
7784      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7785    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7786                    # "|\t$dst, $src$index}",
7787                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7788
7789
7790multiclass SIMDScalarDUP<string asm> {
7791  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
7792    bits<4> idx;
7793    let Inst{20-17} = idx;
7794    let Inst{16} = 1;
7795  }
7796  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
7797    bits<3> idx;
7798    let Inst{20-18} = idx;
7799    let Inst{17-16} = 0b10;
7800  }
7801  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
7802    bits<2> idx;
7803    let Inst{20-19} = idx;
7804    let Inst{18-16} = 0b100;
7805  }
7806  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
7807    bits<1> idx;
7808    let Inst{20} = idx;
7809    let Inst{19-16} = 0b1000;
7810  }
7811
7812  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7813                                                          VectorIndexD:$idx)))),
7814            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7815
7816  // 'DUP' mnemonic aliases.
7817  def : SIMDScalarDUPAlias<"dup", ".b",
7818                           !cast<Instruction>(NAME#"i8"),
7819                           FPR8, V128, VectorIndexB>;
7820  def : SIMDScalarDUPAlias<"dup", ".h",
7821                           !cast<Instruction>(NAME#"i16"),
7822                           FPR16, V128, VectorIndexH>;
7823  def : SIMDScalarDUPAlias<"dup", ".s",
7824                           !cast<Instruction>(NAME#"i32"),
7825                           FPR32, V128, VectorIndexS>;
7826  def : SIMDScalarDUPAlias<"dup", ".d",
7827                           !cast<Instruction>(NAME#"i64"),
7828                           FPR64, V128, VectorIndexD>;
7829}
7830
7831//----------------------------------------------------------------------------
7832// AdvSIMD modified immediate instructions
7833//----------------------------------------------------------------------------
7834
7835class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7836                          string asm, string op_string,
7837                          string cstr, list<dag> pattern>
7838  : I<oops, iops, asm, op_string, cstr, pattern>,
7839    Sched<[!if(Q, WriteVq, WriteVd)]> {
7840  bits<5> Rd;
7841  bits<8> imm8;
7842  let Inst{31}    = 0;
7843  let Inst{30}    = Q;
7844  let Inst{29}    = op;
7845  let Inst{28-19} = 0b0111100000;
7846  let Inst{18-16} = imm8{7-5};
7847  let Inst{11} = op2;
7848  let Inst{10} = 1;
7849  let Inst{9-5}   = imm8{4-0};
7850  let Inst{4-0}   = Rd;
7851}
7852
7853class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7854                                Operand immtype, dag opt_shift_iop,
7855                                string opt_shift, string asm, string kind,
7856                                list<dag> pattern>
7857  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7858                        !con((ins immtype:$imm8), opt_shift_iop), asm,
7859                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
7860                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7861                        "", pattern> {
7862  let DecoderMethod = "DecodeModImmInstruction";
7863}
7864
7865class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7866                                Operand immtype, dag opt_shift_iop,
7867                                string opt_shift, string asm, string kind,
7868                                list<dag> pattern>
7869  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7870                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7871                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7872                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7873                        "$Rd = $dst", pattern> {
7874  let DecoderMethod = "DecodeModImmTiedInstruction";
7875}
7876
7877class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7878                                     RegisterOperand vectype, string asm,
7879                                     string kind, list<dag> pattern>
7880  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7881                              (ins logical_vec_shift:$shift),
7882                              "$shift", asm, kind, pattern> {
7883  bits<2> shift;
7884  let Inst{15}    = b15_b12{1};
7885  let Inst{14-13} = shift;
7886  let Inst{12}    = b15_b12{0};
7887}
7888
7889class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7890                                     RegisterOperand vectype, string asm,
7891                                     string kind, list<dag> pattern>
7892  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7893                              (ins logical_vec_shift:$shift),
7894                              "$shift", asm, kind, pattern> {
7895  bits<2> shift;
7896  let Inst{15}    = b15_b12{1};
7897  let Inst{14-13} = shift;
7898  let Inst{12}    = b15_b12{0};
7899}
7900
7901
7902class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7903                                         RegisterOperand vectype, string asm,
7904                                         string kind, list<dag> pattern>
7905  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7906                              (ins logical_vec_hw_shift:$shift),
7907                              "$shift", asm, kind, pattern> {
7908  bits<2> shift;
7909  let Inst{15} = b15_b12{1};
7910  let Inst{14} = 0;
7911  let Inst{13} = shift{0};
7912  let Inst{12} = b15_b12{0};
7913}
7914
7915class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7916                                         RegisterOperand vectype, string asm,
7917                                         string kind, list<dag> pattern>
7918  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7919                              (ins logical_vec_hw_shift:$shift),
7920                              "$shift", asm, kind, pattern> {
7921  bits<2> shift;
7922  let Inst{15} = b15_b12{1};
7923  let Inst{14} = 0;
7924  let Inst{13} = shift{0};
7925  let Inst{12} = b15_b12{0};
7926}
7927
7928multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7929                                      string asm> {
7930  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7931                                                 asm, ".4h", []>;
7932  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7933                                                 asm, ".8h", []>;
7934
7935  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7936                                             asm, ".2s", []>;
7937  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7938                                             asm, ".4s", []>;
7939}
7940
7941multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7942                                      bits<2> w_cmode, string asm,
7943                                      SDNode OpNode> {
7944  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7945                                                 asm, ".4h",
7946             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7947                                             imm0_255:$imm8,
7948                                             (i32 imm:$shift)))]>;
7949  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7950                                                 asm, ".8h",
7951             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7952                                              imm0_255:$imm8,
7953                                              (i32 imm:$shift)))]>;
7954
7955  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7956                                             asm, ".2s",
7957             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7958                                             imm0_255:$imm8,
7959                                             (i32 imm:$shift)))]>;
7960  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7961                                             asm, ".4s",
7962             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7963                                              imm0_255:$imm8,
7964                                              (i32 imm:$shift)))]>;
7965}
7966
7967class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7968                             RegisterOperand vectype, string asm,
7969                             string kind, list<dag> pattern>
7970  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7971                              (ins move_vec_shift:$shift),
7972                              "$shift", asm, kind, pattern> {
7973  bits<1> shift;
7974  let Inst{15-13} = cmode{3-1};
7975  let Inst{12}    = shift;
7976}
7977
7978class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7979                                   RegisterOperand vectype,
7980                                   Operand imm_type, string asm,
7981                                   string kind, list<dag> pattern>
7982  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7983                              asm, kind, pattern> {
7984  let Inst{15-12} = cmode;
7985}
7986
7987class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7988                                   list<dag> pattern>
7989  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7990                        "\t$Rd, $imm8", "", pattern> {
7991  let Inst{15-12} = cmode;
7992  let DecoderMethod = "DecodeModImmInstruction";
7993}
7994
7995//----------------------------------------------------------------------------
7996// AdvSIMD indexed element
7997//----------------------------------------------------------------------------
7998
7999let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8000class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8001                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8002                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8003                      string apple_kind, string dst_kind, string lhs_kind,
8004                      string rhs_kind, list<dag> pattern>
8005  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
8006      asm,
8007      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8008      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
8009    Sched<[WriteVd]> {
8010  bits<5> Rd;
8011  bits<5> Rn;
8012  bits<5> Rm;
8013
8014  let Inst{31}    = 0;
8015  let Inst{30}    = Q;
8016  let Inst{29}    = U;
8017  let Inst{28}    = Scalar;
8018  let Inst{27-24} = 0b1111;
8019  let Inst{23-22} = size;
8020  // Bit 21 must be set by the derived class.
8021  let Inst{20-16} = Rm;
8022  let Inst{15-12} = opc;
8023  // Bit 11 must be set by the derived class.
8024  let Inst{10}    = 0;
8025  let Inst{9-5}   = Rn;
8026  let Inst{4-0}   = Rd;
8027}
8028
8029let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8030class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8031                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8032                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8033                      string apple_kind, string dst_kind, string lhs_kind,
8034                      string rhs_kind, list<dag> pattern>
8035  : I<(outs dst_reg:$dst),
8036      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
8037      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8038      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
8039    Sched<[WriteVd]> {
8040  bits<5> Rd;
8041  bits<5> Rn;
8042  bits<5> Rm;
8043
8044  let Inst{31}    = 0;
8045  let Inst{30}    = Q;
8046  let Inst{29}    = U;
8047  let Inst{28}    = Scalar;
8048  let Inst{27-24} = 0b1111;
8049  let Inst{23-22} = size;
8050  // Bit 21 must be set by the derived class.
8051  let Inst{20-16} = Rm;
8052  let Inst{15-12} = opc;
8053  // Bit 11 must be set by the derived class.
8054  let Inst{10}    = 0;
8055  let Inst{9-5}   = Rn;
8056  let Inst{4-0}   = Rd;
8057}
8058
8059
8060//----------------------------------------------------------------------------
8061// Armv8.6 BFloat16 Extension
8062//----------------------------------------------------------------------------
8063let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8064
8065class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8066                                   string kind2, RegisterOperand RegType,
8067                                   ValueType AccumType, ValueType InputType>
8068  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8069                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8070                                            (InputType RegType:$Rn),
8071                                            (InputType RegType:$Rm)))]> {
8072  let AsmString = !strconcat(asm,
8073                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8074                               ", $Rm" # kind2 # "}");
8075}
8076
8077multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8078  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8079                                           v2f32, v4bf16>;
8080  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8081                                           v4f32, v8bf16>;
8082}
8083
8084class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
8085                                      string dst_kind, string lhs_kind,
8086                                      string rhs_kind,
8087                                      RegisterOperand RegType,
8088                                      ValueType AccumType,
8089                                      ValueType InputType>
8090  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
8091                        RegType, RegType, V128, VectorIndexS,
8092                        asm, "", dst_kind, lhs_kind, rhs_kind,
8093        [(set (AccumType RegType:$dst),
8094              (AccumType (int_aarch64_neon_bfdot
8095                                 (AccumType RegType:$Rd),
8096                                 (InputType RegType:$Rn),
8097                                 (InputType (bitconvert (AccumType
8098                                    (AArch64duplane32 (v4f32 V128:$Rm),
8099                                        VectorIndexS:$idx)))))))]> {
8100
8101  bits<2> idx;
8102  let Inst{21}    = idx{0};  // L
8103  let Inst{11}    = idx{1};  // H
8104}
8105
8106multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
8107
8108  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
8109                                               ".2h", V64, v2f32, v4bf16>;
8110  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
8111                                              ".2h", V128, v4f32, v8bf16>;
8112}
8113
8114let mayRaiseFPException = 1 in
8115class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
8116  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
8117              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
8118                                               (v8bf16 V128:$Rn),
8119                                               (v8bf16 V128:$Rm)))]> {
8120  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
8121}
8122
8123let mayRaiseFPException = 1 in
8124class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
8125  : I<(outs V128:$dst),
8126      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
8127      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
8128          [(set (v4f32 V128:$dst),
8129                (v4f32 (OpNode (v4f32 V128:$Rd),
8130                               (v8bf16 V128:$Rn),
8131                               (v8bf16
8132                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
8133                                      VectorIndexH:$idx)))))]>,
8134    Sched<[WriteVq]> {
8135  bits<5> Rd;
8136  bits<5> Rn;
8137  bits<4> Rm;
8138  bits<3> idx;
8139
8140  let Inst{31}    = 0;
8141  let Inst{30}    = Q;
8142  let Inst{29-22} = 0b00111111;
8143  let Inst{21-20} = idx{1-0};
8144  let Inst{19-16} = Rm;
8145  let Inst{15-12} = 0b1111;
8146  let Inst{11}    = idx{2};   // H
8147  let Inst{10}    = 0;
8148  let Inst{9-5}   = Rn;
8149  let Inst{4-0}   = Rd;
8150}
8151
8152class SIMDThreeSameVectorBF16MatrixMul<string asm>
8153  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
8154                                V128, asm, ".4s",
8155                          [(set (v4f32 V128:$dst),
8156                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
8157                                                         (v8bf16 V128:$Rn),
8158                                                         (v8bf16 V128:$Rm)))]> {
8159  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8160                                    ", $Rm", ".8h", "}");
8161}
8162
8163let mayRaiseFPException = 1 in
8164class SIMD_BFCVTN
8165  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8166                           "bfcvtn", ".4h", ".4s",
8167    [(set (v8bf16 V128:$Rd),
8168          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8169
8170let mayRaiseFPException = 1 in
8171class SIMD_BFCVTN2
8172  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8173                           "bfcvtn2", ".8h", ".4s",
8174    [(set (v8bf16 V128:$dst),
8175          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8176
8177let mayRaiseFPException = 1 in
8178class BF16ToSinglePrecision<string asm>
8179  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8180    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8181    Sched<[WriteFCvt]> {
8182  bits<5> Rd;
8183  bits<5> Rn;
8184  let Inst{31-10} = 0b0001111001100011010000;
8185  let Inst{9-5}   = Rn;
8186  let Inst{4-0}   = Rd;
8187}
8188} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8189
8190//----------------------------------------------------------------------------
8191// Armv8.6 Matrix Multiply Extension
8192//----------------------------------------------------------------------------
8193
8194class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8195  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8196              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8197                                               (v16i8 V128:$Rn),
8198                                               (v16i8 V128:$Rm)))]> {
8199  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8200}
8201
8202//----------------------------------------------------------------------------
8203// ARMv8.2-A Dot Product Instructions (Indexed)
8204class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
8205                                      string dst_kind, string lhs_kind, string rhs_kind,
8206                                      RegisterOperand RegType,
8207                                      ValueType AccumType, ValueType InputType,
8208                                      SDPatternOperator OpNode> :
8209        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
8210                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8211        [(set (AccumType RegType:$dst),
8212              (AccumType (OpNode (AccumType RegType:$Rd),
8213                                 (InputType RegType:$Rn),
8214                                 (InputType (bitconvert (AccumType
8215                                    (AArch64duplane32 (v4i32 V128:$Rm),
8216                                        VectorIndexS:$idx)))))))]> {
8217  bits<2> idx;
8218  let Inst{21}    = idx{0};  // L
8219  let Inst{11}    = idx{1};  // H
8220}
8221
8222multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8223                                       SDPatternOperator OpNode> {
8224  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
8225                                              V64, v2i32, v8i8, OpNode>;
8226  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
8227                                              V128, v4i32, v16i8, OpNode>;
8228}
8229
8230// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8231let mayRaiseFPException = 1 in
8232class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
8233                                      string dst_kind, string lhs_kind,
8234                                      string rhs_kind, RegisterOperand RegType,
8235                                      ValueType AccumType, ValueType InputType,
8236                                      SDPatternOperator OpNode> :
8237        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
8238                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8239          [(set (AccumType RegType:$dst),
8240                (AccumType (OpNode (AccumType RegType:$Rd),
8241                                   (InputType RegType:$Rn),
8242                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
8243                                                VectorIndexH:$idx)))))]> {
8244  // idx = H:L:M
8245  bits<3> idx;
8246  let Inst{11} = idx{2}; // H
8247  let Inst{21} = idx{1}; // L
8248  let Inst{20} = idx{0}; // M
8249}
8250
8251multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8252                                       SDPatternOperator OpNode> {
8253  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8254                                              V64, v2f32, v4f16, OpNode>;
8255  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8256                                              V128, v4f32, v8f16, OpNode>;
8257}
8258
8259let mayRaiseFPException = 1 in
8260multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8261                         SDPatternOperator OpNode> {
8262  let Predicates = [HasNEON, HasFullFP16] in {
8263  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8264                                      V64, V64,
8265                                      V128_lo, VectorIndexH,
8266                                      asm, ".4h", ".4h", ".4h", ".h",
8267    [(set (v4f16 V64:$Rd),
8268        (OpNode (v4f16 V64:$Rn),
8269         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8270    bits<3> idx;
8271    let Inst{11} = idx{2};
8272    let Inst{21} = idx{1};
8273    let Inst{20} = idx{0};
8274  }
8275
8276  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8277                                      V128, V128,
8278                                      V128_lo, VectorIndexH,
8279                                      asm, ".8h", ".8h", ".8h", ".h",
8280    [(set (v8f16 V128:$Rd),
8281        (OpNode (v8f16 V128:$Rn),
8282         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8283    bits<3> idx;
8284    let Inst{11} = idx{2};
8285    let Inst{21} = idx{1};
8286    let Inst{20} = idx{0};
8287  }
8288  } // Predicates = [HasNEON, HasFullFP16]
8289
8290  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8291                                      V64, V64,
8292                                      V128, VectorIndexS,
8293                                      asm, ".2s", ".2s", ".2s", ".s",
8294    [(set (v2f32 V64:$Rd),
8295        (OpNode (v2f32 V64:$Rn),
8296         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8297    bits<2> idx;
8298    let Inst{11} = idx{1};
8299    let Inst{21} = idx{0};
8300  }
8301
8302  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8303                                      V128, V128,
8304                                      V128, VectorIndexS,
8305                                      asm, ".4s", ".4s", ".4s", ".s",
8306    [(set (v4f32 V128:$Rd),
8307        (OpNode (v4f32 V128:$Rn),
8308         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8309    bits<2> idx;
8310    let Inst{11} = idx{1};
8311    let Inst{21} = idx{0};
8312  }
8313
8314  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8315                                      V128, V128,
8316                                      V128, VectorIndexD,
8317                                      asm, ".2d", ".2d", ".2d", ".d",
8318    [(set (v2f64 V128:$Rd),
8319        (OpNode (v2f64 V128:$Rn),
8320         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8321    bits<1> idx;
8322    let Inst{11} = idx{0};
8323    let Inst{21} = 0;
8324  }
8325
8326  let Predicates = [HasNEON, HasFullFP16] in {
8327  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8328                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8329                                      asm, ".h", "", "", ".h",
8330    [(set (f16 FPR16Op:$Rd),
8331          (OpNode (f16 FPR16Op:$Rn),
8332                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8333                                       VectorIndexH:$idx))))]> {
8334    bits<3> idx;
8335    let Inst{11} = idx{2};
8336    let Inst{21} = idx{1};
8337    let Inst{20} = idx{0};
8338  }
8339  } // Predicates = [HasNEON, HasFullFP16]
8340
8341  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8342                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8343                                      asm, ".s", "", "", ".s",
8344    [(set (f32 FPR32Op:$Rd),
8345          (OpNode (f32 FPR32Op:$Rn),
8346                  (f32 (vector_extract (v4f32 V128:$Rm),
8347                                       VectorIndexS:$idx))))]> {
8348    bits<2> idx;
8349    let Inst{11} = idx{1};
8350    let Inst{21} = idx{0};
8351  }
8352
8353  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8354                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8355                                      asm, ".d", "", "", ".d",
8356    [(set (f64 FPR64Op:$Rd),
8357          (OpNode (f64 FPR64Op:$Rn),
8358                  (f64 (vector_extract (v2f64 V128:$Rm),
8359                                       VectorIndexD:$idx))))]> {
8360    bits<1> idx;
8361    let Inst{11} = idx{0};
8362    let Inst{21} = 0;
8363  }
8364}
8365
8366multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8367  let Predicates = [HasNEON, HasFullFP16] in {
8368  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8369  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8370                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8371                                           VectorIndexH:$idx))),
8372            (!cast<Instruction>(INST # "v8i16_indexed")
8373                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8374  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8375                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8376            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8377                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8378
8379  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8380                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8381                                           VectorIndexH:$idx))),
8382            (!cast<Instruction>(INST # "v4i16_indexed")
8383                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8384  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8385                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8386            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8387                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8388
8389  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8390                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8391            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8392                V128_lo:$Rm, VectorIndexH:$idx)>;
8393  } // Predicates = [HasNEON, HasFullFP16]
8394
8395  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8396  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8397                           (AArch64duplane32 (v4f32 V128:$Rm),
8398                                           VectorIndexS:$idx))),
8399            (!cast<Instruction>(INST # v2i32_indexed)
8400                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8401  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8402                           (AArch64dup (f32 FPR32Op:$Rm)))),
8403            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8404                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8405
8406
8407  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8408  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8409                           (AArch64duplane32 (v4f32 V128:$Rm),
8410                                           VectorIndexS:$idx))),
8411            (!cast<Instruction>(INST # "v4i32_indexed")
8412                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8413  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8414                           (AArch64dup (f32 FPR32Op:$Rm)))),
8415            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8416                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8417
8418  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8419  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8420                           (AArch64duplane64 (v2f64 V128:$Rm),
8421                                           VectorIndexD:$idx))),
8422            (!cast<Instruction>(INST # "v2i64_indexed")
8423                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8424  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8425                           (AArch64dup (f64 FPR64Op:$Rm)))),
8426            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8427                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8428
8429  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8430  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8431                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8432            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8433                V128:$Rm, VectorIndexS:$idx)>;
8434
8435  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8436  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8437                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8438            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8439                V128:$Rm, VectorIndexD:$idx)>;
8440}
8441
8442let mayRaiseFPException = 1 in
8443multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8444  let Predicates = [HasNEON, HasFullFP16] in {
8445  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8446                                          V128_lo, VectorIndexH,
8447                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8448    bits<3> idx;
8449    let Inst{11} = idx{2};
8450    let Inst{21} = idx{1};
8451    let Inst{20} = idx{0};
8452  }
8453
8454  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8455                                          V128, V128,
8456                                          V128_lo, VectorIndexH,
8457                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8458    bits<3> idx;
8459    let Inst{11} = idx{2};
8460    let Inst{21} = idx{1};
8461    let Inst{20} = idx{0};
8462  }
8463  } // Predicates = [HasNEON, HasFullFP16]
8464
8465  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8466                                          V128, VectorIndexS,
8467                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8468    bits<2> idx;
8469    let Inst{11} = idx{1};
8470    let Inst{21} = idx{0};
8471  }
8472
8473  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8474                                      V128, V128,
8475                                      V128, VectorIndexS,
8476                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8477    bits<2> idx;
8478    let Inst{11} = idx{1};
8479    let Inst{21} = idx{0};
8480  }
8481
8482  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8483                                      V128, V128,
8484                                      V128, VectorIndexD,
8485                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8486    bits<1> idx;
8487    let Inst{11} = idx{0};
8488    let Inst{21} = 0;
8489  }
8490
8491  let Predicates = [HasNEON, HasFullFP16] in {
8492  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8493                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8494                                      asm, ".h", "", "", ".h", []> {
8495    bits<3> idx;
8496    let Inst{11} = idx{2};
8497    let Inst{21} = idx{1};
8498    let Inst{20} = idx{0};
8499  }
8500  } // Predicates = [HasNEON, HasFullFP16]
8501
8502  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8503                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8504                                      asm, ".s", "", "", ".s", []> {
8505    bits<2> idx;
8506    let Inst{11} = idx{1};
8507    let Inst{21} = idx{0};
8508  }
8509
8510  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8511                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8512                                      asm, ".d", "", "", ".d", []> {
8513    bits<1> idx;
8514    let Inst{11} = idx{0};
8515    let Inst{21} = 0;
8516  }
8517}
8518
8519multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8520                                 SDPatternOperator OpNodeLaneQ> {
8521
8522  def : Pat<(v4i16 (OpNodeLane
8523                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8524                     VectorIndexS32b:$idx)),
8525            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8526              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8527              (UImmS1XForm $idx))>;
8528
8529  def : Pat<(v4i16 (OpNodeLaneQ
8530                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8531                     VectorIndexH32b:$idx)),
8532            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8533              (UImmS1XForm $idx))>;
8534
8535  def : Pat<(v8i16 (OpNodeLane
8536                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8537                     VectorIndexS32b:$idx)),
8538            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8539              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8540              (UImmS1XForm $idx))>;
8541
8542  def : Pat<(v8i16 (OpNodeLaneQ
8543                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8544                     VectorIndexH32b:$idx)),
8545            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8546              (UImmS1XForm $idx))>;
8547
8548  def : Pat<(v2i32 (OpNodeLane
8549                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8550                     VectorIndexD32b:$idx)),
8551            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8552              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8553              (UImmS1XForm $idx))>;
8554
8555  def : Pat<(v2i32 (OpNodeLaneQ
8556                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8557                     VectorIndexS32b:$idx)),
8558            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8559              (UImmS1XForm $idx))>;
8560
8561  def : Pat<(v4i32 (OpNodeLane
8562                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8563                     VectorIndexD32b:$idx)),
8564            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8565              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8566              (UImmS1XForm $idx))>;
8567
8568  def : Pat<(v4i32 (OpNodeLaneQ
8569                     (v4i32 V128:$Rn),
8570                     (v4i32 V128:$Rm),
8571                     VectorIndexS32b:$idx)),
8572            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8573              (UImmS1XForm $idx))>;
8574
8575}
8576
8577multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8578                         SDPatternOperator OpNode> {
8579  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8580                                      V128_lo, VectorIndexH,
8581                                      asm, ".4h", ".4h", ".4h", ".h",
8582    [(set (v4i16 V64:$Rd),
8583        (OpNode (v4i16 V64:$Rn),
8584         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8585    bits<3> idx;
8586    let Inst{11} = idx{2};
8587    let Inst{21} = idx{1};
8588    let Inst{20} = idx{0};
8589  }
8590
8591  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8592                                      V128, V128,
8593                                      V128_lo, VectorIndexH,
8594                                      asm, ".8h", ".8h", ".8h", ".h",
8595    [(set (v8i16 V128:$Rd),
8596       (OpNode (v8i16 V128:$Rn),
8597         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8598    bits<3> idx;
8599    let Inst{11} = idx{2};
8600    let Inst{21} = idx{1};
8601    let Inst{20} = idx{0};
8602  }
8603
8604  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8605                                      V64, V64,
8606                                      V128, VectorIndexS,
8607                                      asm, ".2s", ".2s", ".2s",  ".s",
8608    [(set (v2i32 V64:$Rd),
8609       (OpNode (v2i32 V64:$Rn),
8610          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8611    bits<2> idx;
8612    let Inst{11} = idx{1};
8613    let Inst{21} = idx{0};
8614  }
8615
8616  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8617                                      V128, V128,
8618                                      V128, VectorIndexS,
8619                                      asm, ".4s", ".4s", ".4s", ".s",
8620    [(set (v4i32 V128:$Rd),
8621       (OpNode (v4i32 V128:$Rn),
8622          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8623    bits<2> idx;
8624    let Inst{11} = idx{1};
8625    let Inst{21} = idx{0};
8626  }
8627
8628  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8629                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8630                                      asm, ".h", "", "", ".h", []> {
8631    bits<3> idx;
8632    let Inst{11} = idx{2};
8633    let Inst{21} = idx{1};
8634    let Inst{20} = idx{0};
8635  }
8636
8637  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8638                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8639                                      asm, ".s", "", "", ".s",
8640      [(set (i32 FPR32Op:$Rd),
8641            (OpNode FPR32Op:$Rn,
8642                    (i32 (vector_extract (v4i32 V128:$Rm),
8643                                         VectorIndexS:$idx))))]> {
8644    bits<2> idx;
8645    let Inst{11} = idx{1};
8646    let Inst{21} = idx{0};
8647  }
8648}
8649
8650multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8651                               SDPatternOperator OpNode> {
8652  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8653                                      V64, V64,
8654                                      V128_lo, VectorIndexH,
8655                                      asm, ".4h", ".4h", ".4h", ".h",
8656    [(set (v4i16 V64:$Rd),
8657        (OpNode (v4i16 V64:$Rn),
8658         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8659    bits<3> idx;
8660    let Inst{11} = idx{2};
8661    let Inst{21} = idx{1};
8662    let Inst{20} = idx{0};
8663  }
8664
8665  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8666                                      V128, V128,
8667                                      V128_lo, VectorIndexH,
8668                                      asm, ".8h", ".8h", ".8h", ".h",
8669    [(set (v8i16 V128:$Rd),
8670       (OpNode (v8i16 V128:$Rn),
8671         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8672    bits<3> idx;
8673    let Inst{11} = idx{2};
8674    let Inst{21} = idx{1};
8675    let Inst{20} = idx{0};
8676  }
8677
8678  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8679                                      V64, V64,
8680                                      V128, VectorIndexS,
8681                                      asm, ".2s", ".2s", ".2s", ".s",
8682    [(set (v2i32 V64:$Rd),
8683       (OpNode (v2i32 V64:$Rn),
8684          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8685    bits<2> idx;
8686    let Inst{11} = idx{1};
8687    let Inst{21} = idx{0};
8688  }
8689
8690  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8691                                      V128, V128,
8692                                      V128, VectorIndexS,
8693                                      asm, ".4s", ".4s", ".4s", ".s",
8694    [(set (v4i32 V128:$Rd),
8695       (OpNode (v4i32 V128:$Rn),
8696          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8697    bits<2> idx;
8698    let Inst{11} = idx{1};
8699    let Inst{21} = idx{0};
8700  }
8701}
8702
8703multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8704                                   SDPatternOperator OpNode> {
8705  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8706                                          V128_lo, VectorIndexH,
8707                                          asm, ".4h", ".4h", ".4h", ".h",
8708    [(set (v4i16 V64:$dst),
8709        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8710         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8711    bits<3> idx;
8712    let Inst{11} = idx{2};
8713    let Inst{21} = idx{1};
8714    let Inst{20} = idx{0};
8715  }
8716
8717  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8718                                      V128, V128,
8719                                      V128_lo, VectorIndexH,
8720                                      asm, ".8h", ".8h", ".8h", ".h",
8721    [(set (v8i16 V128:$dst),
8722       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8723         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8724    bits<3> idx;
8725    let Inst{11} = idx{2};
8726    let Inst{21} = idx{1};
8727    let Inst{20} = idx{0};
8728  }
8729
8730  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8731                                      V64, V64,
8732                                      V128, VectorIndexS,
8733                                      asm, ".2s", ".2s", ".2s", ".s",
8734    [(set (v2i32 V64:$dst),
8735       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8736          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8737    bits<2> idx;
8738    let Inst{11} = idx{1};
8739    let Inst{21} = idx{0};
8740  }
8741
8742  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8743                                      V128, V128,
8744                                      V128, VectorIndexS,
8745                                      asm, ".4s", ".4s", ".4s", ".s",
8746    [(set (v4i32 V128:$dst),
8747       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8748          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8749    bits<2> idx;
8750    let Inst{11} = idx{1};
8751    let Inst{21} = idx{0};
8752  }
8753}
8754
8755multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8756                             SDPatternOperator OpNode> {
8757  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8758                                      V128, V64,
8759                                      V128_lo, VectorIndexH,
8760                                      asm, ".4s", ".4s", ".4h", ".h",
8761    [(set (v4i32 V128:$Rd),
8762        (OpNode (v4i16 V64:$Rn),
8763         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8764    bits<3> idx;
8765    let Inst{11} = idx{2};
8766    let Inst{21} = idx{1};
8767    let Inst{20} = idx{0};
8768  }
8769
8770  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8771                                      V128, V128,
8772                                      V128_lo, VectorIndexH,
8773                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8774    [(set (v4i32 V128:$Rd),
8775          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
8776                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8777
8778    bits<3> idx;
8779    let Inst{11} = idx{2};
8780    let Inst{21} = idx{1};
8781    let Inst{20} = idx{0};
8782  }
8783
8784  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8785                                      V128, V64,
8786                                      V128, VectorIndexS,
8787                                      asm, ".2d", ".2d", ".2s", ".s",
8788    [(set (v2i64 V128:$Rd),
8789        (OpNode (v2i32 V64:$Rn),
8790         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8791    bits<2> idx;
8792    let Inst{11} = idx{1};
8793    let Inst{21} = idx{0};
8794  }
8795
8796  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8797                                      V128, V128,
8798                                      V128, VectorIndexS,
8799                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8800    [(set (v2i64 V128:$Rd),
8801          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
8802                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8803    bits<2> idx;
8804    let Inst{11} = idx{1};
8805    let Inst{21} = idx{0};
8806  }
8807
8808  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8809                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8810                                      asm, ".h", "", "", ".h", []> {
8811    bits<3> idx;
8812    let Inst{11} = idx{2};
8813    let Inst{21} = idx{1};
8814    let Inst{20} = idx{0};
8815  }
8816
8817  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8818                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8819                                      asm, ".s", "", "", ".s", []> {
8820    bits<2> idx;
8821    let Inst{11} = idx{1};
8822    let Inst{21} = idx{0};
8823  }
8824}
8825
8826multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8827                                       SDPatternOperator Accum> {
8828  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8829                                      V128, V64,
8830                                      V128_lo, VectorIndexH,
8831                                      asm, ".4s", ".4s", ".4h", ".h",
8832    [(set (v4i32 V128:$dst),
8833          (Accum (v4i32 V128:$Rd),
8834                 (v4i32 (int_aarch64_neon_sqdmull
8835                             (v4i16 V64:$Rn),
8836                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8837                                                    VectorIndexH:$idx))))))]> {
8838    bits<3> idx;
8839    let Inst{11} = idx{2};
8840    let Inst{21} = idx{1};
8841    let Inst{20} = idx{0};
8842  }
8843
8844  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8845  // intermediate EXTRACT_SUBREG would be untyped.
8846  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8847                (i32 (vector_extract (v4i32
8848                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8849                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8850                                                    VectorIndexH:$idx)))),
8851                         (i64 0))))),
8852            (EXTRACT_SUBREG
8853                (!cast<Instruction>(NAME # v4i16_indexed)
8854                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8855                    V128_lo:$Rm, VectorIndexH:$idx),
8856                ssub)>;
8857
8858  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8859                                      V128, V128,
8860                                      V128_lo, VectorIndexH,
8861                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8862    [(set (v4i32 V128:$dst),
8863          (Accum (v4i32 V128:$Rd),
8864                 (v4i32 (int_aarch64_neon_sqdmull
8865                            (extract_high_v8i16 (v8i16 V128:$Rn)),
8866                            (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))))]> {
8867    bits<3> idx;
8868    let Inst{11} = idx{2};
8869    let Inst{21} = idx{1};
8870    let Inst{20} = idx{0};
8871  }
8872
8873  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8874                                      V128, V64,
8875                                      V128, VectorIndexS,
8876                                      asm, ".2d", ".2d", ".2s", ".s",
8877    [(set (v2i64 V128:$dst),
8878        (Accum (v2i64 V128:$Rd),
8879               (v2i64 (int_aarch64_neon_sqdmull
8880                          (v2i32 V64:$Rn),
8881                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8882                                                 VectorIndexS:$idx))))))]> {
8883    bits<2> idx;
8884    let Inst{11} = idx{1};
8885    let Inst{21} = idx{0};
8886  }
8887
8888  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8889                                      V128, V128,
8890                                      V128, VectorIndexS,
8891                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8892    [(set (v2i64 V128:$dst),
8893          (Accum (v2i64 V128:$Rd),
8894                 (v2i64 (int_aarch64_neon_sqdmull
8895                            (extract_high_v4i32 (v4i32 V128:$Rn)),
8896                            (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
8897    bits<2> idx;
8898    let Inst{11} = idx{1};
8899    let Inst{21} = idx{0};
8900  }
8901
8902  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8903                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8904                                      asm, ".h", "", "", ".h", []> {
8905    bits<3> idx;
8906    let Inst{11} = idx{2};
8907    let Inst{21} = idx{1};
8908    let Inst{20} = idx{0};
8909  }
8910
8911
8912  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8913                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8914                                      asm, ".s", "", "", ".s",
8915    [(set (i64 FPR64Op:$dst),
8916          (Accum (i64 FPR64Op:$Rd),
8917                 (i64 (int_aarch64_neon_sqdmulls_scalar
8918                            (i32 FPR32Op:$Rn),
8919                            (i32 (vector_extract (v4i32 V128:$Rm),
8920                                                 VectorIndexS:$idx))))))]> {
8921
8922    bits<2> idx;
8923    let Inst{11} = idx{1};
8924    let Inst{21} = idx{0};
8925  }
8926}
8927
8928multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8929                                   SDPatternOperator OpNode> {
8930  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8931  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8932                                      V128, V64,
8933                                      V128_lo, VectorIndexH,
8934                                      asm, ".4s", ".4s", ".4h", ".h",
8935    [(set (v4i32 V128:$Rd),
8936        (OpNode (v4i16 V64:$Rn),
8937         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8938    bits<3> idx;
8939    let Inst{11} = idx{2};
8940    let Inst{21} = idx{1};
8941    let Inst{20} = idx{0};
8942  }
8943
8944  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8945                                      V128, V128,
8946                                      V128_lo, VectorIndexH,
8947                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8948    [(set (v4i32 V128:$Rd),
8949          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
8950                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8951
8952    bits<3> idx;
8953    let Inst{11} = idx{2};
8954    let Inst{21} = idx{1};
8955    let Inst{20} = idx{0};
8956  }
8957
8958  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8959                                      V128, V64,
8960                                      V128, VectorIndexS,
8961                                      asm, ".2d", ".2d", ".2s", ".s",
8962    [(set (v2i64 V128:$Rd),
8963        (OpNode (v2i32 V64:$Rn),
8964         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8965    bits<2> idx;
8966    let Inst{11} = idx{1};
8967    let Inst{21} = idx{0};
8968  }
8969
8970  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8971                                      V128, V128,
8972                                      V128, VectorIndexS,
8973                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8974    [(set (v2i64 V128:$Rd),
8975          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
8976                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
8977    bits<2> idx;
8978    let Inst{11} = idx{1};
8979    let Inst{21} = idx{0};
8980  }
8981  }
8982}
8983
8984multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8985                                       SDPatternOperator OpNode> {
8986  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8987  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8988                                      V128, V64,
8989                                      V128_lo, VectorIndexH,
8990                                      asm, ".4s", ".4s", ".4h", ".h",
8991    [(set (v4i32 V128:$dst),
8992        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8993         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8994    bits<3> idx;
8995    let Inst{11} = idx{2};
8996    let Inst{21} = idx{1};
8997    let Inst{20} = idx{0};
8998  }
8999
9000  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9001                                      V128, V128,
9002                                      V128_lo, VectorIndexH,
9003                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9004    [(set (v4i32 V128:$dst),
9005          (OpNode (v4i32 V128:$Rd),
9006                  (extract_high_v8i16 (v8i16 V128:$Rn)),
9007                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9008    bits<3> idx;
9009    let Inst{11} = idx{2};
9010    let Inst{21} = idx{1};
9011    let Inst{20} = idx{0};
9012  }
9013
9014  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9015                                      V128, V64,
9016                                      V128, VectorIndexS,
9017                                      asm, ".2d", ".2d", ".2s", ".s",
9018    [(set (v2i64 V128:$dst),
9019        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
9020         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9021    bits<2> idx;
9022    let Inst{11} = idx{1};
9023    let Inst{21} = idx{0};
9024  }
9025
9026  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9027                                      V128, V128,
9028                                      V128, VectorIndexS,
9029                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9030    [(set (v2i64 V128:$dst),
9031          (OpNode (v2i64 V128:$Rd),
9032                  (extract_high_v4i32 (v4i32 V128:$Rn)),
9033                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9034    bits<2> idx;
9035    let Inst{11} = idx{1};
9036    let Inst{21} = idx{0};
9037  }
9038  }
9039}
9040
9041//----------------------------------------------------------------------------
9042// AdvSIMD scalar shift by immediate
9043//----------------------------------------------------------------------------
9044
9045let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9046class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
9047                     RegisterClass regtype1, RegisterClass regtype2,
9048                     Operand immtype, string asm, list<dag> pattern>
9049  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
9050      asm, "\t$Rd, $Rn, $imm", "", pattern>,
9051    Sched<[WriteVd]> {
9052  bits<5> Rd;
9053  bits<5> Rn;
9054  bits<7> imm;
9055  let Inst{31-30} = 0b01;
9056  let Inst{29}    = U;
9057  let Inst{28-23} = 0b111110;
9058  let Inst{22-16} = fixed_imm;
9059  let Inst{15-11} = opc;
9060  let Inst{10}    = 1;
9061  let Inst{9-5} = Rn;
9062  let Inst{4-0} = Rd;
9063}
9064
9065let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9066class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
9067                     RegisterClass regtype1, RegisterClass regtype2,
9068                     Operand immtype, string asm, list<dag> pattern>
9069  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
9070      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
9071    Sched<[WriteVd]> {
9072  bits<5> Rd;
9073  bits<5> Rn;
9074  bits<7> imm;
9075  let Inst{31-30} = 0b01;
9076  let Inst{29}    = U;
9077  let Inst{28-23} = 0b111110;
9078  let Inst{22-16} = fixed_imm;
9079  let Inst{15-11} = opc;
9080  let Inst{10}    = 1;
9081  let Inst{9-5} = Rn;
9082  let Inst{4-0} = Rd;
9083}
9084
9085
9086multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
9087  let Predicates = [HasNEON, HasFullFP16] in {
9088  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9089                              FPR16, FPR16, vecshiftR16, asm, []> {
9090    let Inst{19-16} = imm{3-0};
9091  }
9092  } // Predicates = [HasNEON, HasFullFP16]
9093  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9094                              FPR32, FPR32, vecshiftR32, asm, []> {
9095    let Inst{20-16} = imm{4-0};
9096  }
9097  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9098                              FPR64, FPR64, vecshiftR64, asm, []> {
9099    let Inst{21-16} = imm{5-0};
9100  }
9101}
9102
9103multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
9104                             SDPatternOperator OpNode> {
9105  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9106                              FPR64, FPR64, vecshiftR64, asm,
9107  [(set (i64 FPR64:$Rd),
9108     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
9109    let Inst{21-16} = imm{5-0};
9110  }
9111
9112  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
9113            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
9114}
9115
9116multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
9117                                 SDPatternOperator OpNode = null_frag> {
9118  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9119                              FPR64, FPR64, vecshiftR64, asm,
9120  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
9121                                                   (i32 vecshiftR64:$imm)))]> {
9122    let Inst{21-16} = imm{5-0};
9123  }
9124
9125  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
9126                           (i32 vecshiftR64:$imm))),
9127            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
9128                                            vecshiftR64:$imm)>;
9129}
9130
9131multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
9132                             SDPatternOperator OpNode> {
9133  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9134                              FPR64, FPR64, vecshiftL64, asm,
9135    [(set (i64 FPR64:$Rd),
9136       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9137    let Inst{21-16} = imm{5-0};
9138  }
9139
9140  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9141            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9142}
9143
9144let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9145multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
9146  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9147                              FPR64, FPR64, vecshiftL64, asm, []> {
9148    let Inst{21-16} = imm{5-0};
9149  }
9150}
9151
9152let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9153multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
9154                               SDPatternOperator OpNode = null_frag> {
9155  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9156                              FPR8, FPR16, vecshiftR8, asm, []> {
9157    let Inst{18-16} = imm{2-0};
9158  }
9159
9160  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9161                              FPR16, FPR32, vecshiftR16, asm, []> {
9162    let Inst{19-16} = imm{3-0};
9163  }
9164
9165  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9166                              FPR32, FPR64, vecshiftR32, asm,
9167    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9168    let Inst{20-16} = imm{4-0};
9169  }
9170}
9171
9172multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9173                                SDPatternOperator OpNode> {
9174  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9175                              FPR8, FPR8, vecshiftL8, asm, []> {
9176    let Inst{18-16} = imm{2-0};
9177  }
9178
9179  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9180                              FPR16, FPR16, vecshiftL16, asm, []> {
9181    let Inst{19-16} = imm{3-0};
9182  }
9183
9184  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9185                              FPR32, FPR32, vecshiftL32, asm,
9186    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9187    let Inst{20-16} = imm{4-0};
9188  }
9189
9190  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9191                              FPR64, FPR64, vecshiftL64, asm,
9192    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9193    let Inst{21-16} = imm{5-0};
9194  }
9195
9196  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9197            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9198}
9199
9200multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9201  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9202                              FPR8, FPR8, vecshiftR8, asm, []> {
9203    let Inst{18-16} = imm{2-0};
9204  }
9205
9206  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9207                              FPR16, FPR16, vecshiftR16, asm, []> {
9208    let Inst{19-16} = imm{3-0};
9209  }
9210
9211  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9212                              FPR32, FPR32, vecshiftR32, asm, []> {
9213    let Inst{20-16} = imm{4-0};
9214  }
9215
9216  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9217                              FPR64, FPR64, vecshiftR64, asm, []> {
9218    let Inst{21-16} = imm{5-0};
9219  }
9220}
9221
9222//----------------------------------------------------------------------------
9223// AdvSIMD vector x indexed element
9224//----------------------------------------------------------------------------
9225
9226let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9227class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9228                     RegisterOperand dst_reg, RegisterOperand src_reg,
9229                     Operand immtype,
9230                     string asm, string dst_kind, string src_kind,
9231                     list<dag> pattern>
9232  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9233      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9234           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9235    Sched<[!if(Q, WriteVq, WriteVd)]> {
9236  bits<5> Rd;
9237  bits<5> Rn;
9238  let Inst{31}    = 0;
9239  let Inst{30}    = Q;
9240  let Inst{29}    = U;
9241  let Inst{28-23} = 0b011110;
9242  let Inst{22-16} = fixed_imm;
9243  let Inst{15-11} = opc;
9244  let Inst{10}    = 1;
9245  let Inst{9-5}   = Rn;
9246  let Inst{4-0}   = Rd;
9247}
9248
9249let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9250class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9251                     RegisterOperand vectype1, RegisterOperand vectype2,
9252                     Operand immtype,
9253                     string asm, string dst_kind, string src_kind,
9254                     list<dag> pattern>
9255  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9256      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9257           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9258    Sched<[!if(Q, WriteVq, WriteVd)]> {
9259  bits<5> Rd;
9260  bits<5> Rn;
9261  let Inst{31}    = 0;
9262  let Inst{30}    = Q;
9263  let Inst{29}    = U;
9264  let Inst{28-23} = 0b011110;
9265  let Inst{22-16} = fixed_imm;
9266  let Inst{15-11} = opc;
9267  let Inst{10}    = 1;
9268  let Inst{9-5}   = Rn;
9269  let Inst{4-0}   = Rd;
9270}
9271
9272multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9273                              Intrinsic OpNode> {
9274  let Predicates = [HasNEON, HasFullFP16] in {
9275  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9276                                  V64, V64, vecshiftR16,
9277                                  asm, ".4h", ".4h",
9278      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9279    bits<4> imm;
9280    let Inst{19-16} = imm;
9281  }
9282
9283  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9284                                  V128, V128, vecshiftR16,
9285                                  asm, ".8h", ".8h",
9286      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9287    bits<4> imm;
9288    let Inst{19-16} = imm;
9289  }
9290  } // Predicates = [HasNEON, HasFullFP16]
9291  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9292                                  V64, V64, vecshiftR32,
9293                                  asm, ".2s", ".2s",
9294      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9295    bits<5> imm;
9296    let Inst{20-16} = imm;
9297  }
9298
9299  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9300                                  V128, V128, vecshiftR32,
9301                                  asm, ".4s", ".4s",
9302      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9303    bits<5> imm;
9304    let Inst{20-16} = imm;
9305  }
9306
9307  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9308                                  V128, V128, vecshiftR64,
9309                                  asm, ".2d", ".2d",
9310      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9311    bits<6> imm;
9312    let Inst{21-16} = imm;
9313  }
9314}
9315
9316multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9317                                  Intrinsic OpNode> {
9318  let Predicates = [HasNEON, HasFullFP16] in {
9319  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9320                                  V64, V64, vecshiftR16,
9321                                  asm, ".4h", ".4h",
9322      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9323    bits<4> imm;
9324    let Inst{19-16} = imm;
9325  }
9326
9327  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9328                                  V128, V128, vecshiftR16,
9329                                  asm, ".8h", ".8h",
9330      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9331    bits<4> imm;
9332    let Inst{19-16} = imm;
9333  }
9334  } // Predicates = [HasNEON, HasFullFP16]
9335
9336  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9337                                  V64, V64, vecshiftR32,
9338                                  asm, ".2s", ".2s",
9339      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9340    bits<5> imm;
9341    let Inst{20-16} = imm;
9342  }
9343
9344  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9345                                  V128, V128, vecshiftR32,
9346                                  asm, ".4s", ".4s",
9347      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9348    bits<5> imm;
9349    let Inst{20-16} = imm;
9350  }
9351
9352  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9353                                  V128, V128, vecshiftR64,
9354                                  asm, ".2d", ".2d",
9355      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9356    bits<6> imm;
9357    let Inst{21-16} = imm;
9358  }
9359}
9360
9361multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9362                                     SDPatternOperator OpNode> {
9363  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9364                                  V64, V128, vecshiftR16Narrow,
9365                                  asm, ".8b", ".8h",
9366      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9367    bits<3> imm;
9368    let Inst{18-16} = imm;
9369  }
9370
9371  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9372                                  V128, V128, vecshiftR16Narrow,
9373                                  asm#"2", ".16b", ".8h", []> {
9374    bits<3> imm;
9375    let Inst{18-16} = imm;
9376    let hasSideEffects = 0;
9377  }
9378
9379  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9380                                  V64, V128, vecshiftR32Narrow,
9381                                  asm, ".4h", ".4s",
9382      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9383    bits<4> imm;
9384    let Inst{19-16} = imm;
9385  }
9386
9387  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9388                                  V128, V128, vecshiftR32Narrow,
9389                                  asm#"2", ".8h", ".4s", []> {
9390    bits<4> imm;
9391    let Inst{19-16} = imm;
9392    let hasSideEffects = 0;
9393  }
9394
9395  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9396                                  V64, V128, vecshiftR64Narrow,
9397                                  asm, ".2s", ".2d",
9398      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9399    bits<5> imm;
9400    let Inst{20-16} = imm;
9401  }
9402
9403  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9404                                  V128, V128, vecshiftR64Narrow,
9405                                  asm#"2", ".4s", ".2d", []> {
9406    bits<5> imm;
9407    let Inst{20-16} = imm;
9408    let hasSideEffects = 0;
9409  }
9410
9411  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9412  // themselves, so put them here instead.
9413
9414  // Patterns involving what's effectively an insert high and a normal
9415  // intrinsic, represented by CONCAT_VECTORS.
9416  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9417                                                   vecshiftR16Narrow:$imm)),
9418            (!cast<Instruction>(NAME # "v16i8_shift")
9419                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9420                V128:$Rn, vecshiftR16Narrow:$imm)>;
9421  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9422                                                     vecshiftR32Narrow:$imm)),
9423            (!cast<Instruction>(NAME # "v8i16_shift")
9424                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9425                V128:$Rn, vecshiftR32Narrow:$imm)>;
9426  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9427                                                     vecshiftR64Narrow:$imm)),
9428            (!cast<Instruction>(NAME # "v4i32_shift")
9429                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9430                V128:$Rn, vecshiftR64Narrow:$imm)>;
9431}
9432
9433multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9434                                SDPatternOperator OpNode> {
9435  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9436                                  V64, V64, vecshiftL8,
9437                                  asm, ".8b", ".8b",
9438                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9439                       (i32 vecshiftL8:$imm)))]> {
9440    bits<3> imm;
9441    let Inst{18-16} = imm;
9442  }
9443
9444  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9445                                  V128, V128, vecshiftL8,
9446                                  asm, ".16b", ".16b",
9447             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9448                   (i32 vecshiftL8:$imm)))]> {
9449    bits<3> imm;
9450    let Inst{18-16} = imm;
9451  }
9452
9453  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9454                                  V64, V64, vecshiftL16,
9455                                  asm, ".4h", ".4h",
9456              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9457                    (i32 vecshiftL16:$imm)))]> {
9458    bits<4> imm;
9459    let Inst{19-16} = imm;
9460  }
9461
9462  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9463                                  V128, V128, vecshiftL16,
9464                                  asm, ".8h", ".8h",
9465            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9466                  (i32 vecshiftL16:$imm)))]> {
9467    bits<4> imm;
9468    let Inst{19-16} = imm;
9469  }
9470
9471  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9472                                  V64, V64, vecshiftL32,
9473                                  asm, ".2s", ".2s",
9474              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9475                    (i32 vecshiftL32:$imm)))]> {
9476    bits<5> imm;
9477    let Inst{20-16} = imm;
9478  }
9479
9480  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9481                                  V128, V128, vecshiftL32,
9482                                  asm, ".4s", ".4s",
9483            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9484                  (i32 vecshiftL32:$imm)))]> {
9485    bits<5> imm;
9486    let Inst{20-16} = imm;
9487  }
9488
9489  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9490                                  V128, V128, vecshiftL64,
9491                                  asm, ".2d", ".2d",
9492            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9493                  (i32 vecshiftL64:$imm)))]> {
9494    bits<6> imm;
9495    let Inst{21-16} = imm;
9496  }
9497}
9498
9499multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9500                                SDPatternOperator OpNode> {
9501  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9502                                  V64, V64, vecshiftR8,
9503                                  asm, ".8b", ".8b",
9504                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9505                       (i32 vecshiftR8:$imm)))]> {
9506    bits<3> imm;
9507    let Inst{18-16} = imm;
9508  }
9509
9510  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9511                                  V128, V128, vecshiftR8,
9512                                  asm, ".16b", ".16b",
9513             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9514                   (i32 vecshiftR8:$imm)))]> {
9515    bits<3> imm;
9516    let Inst{18-16} = imm;
9517  }
9518
9519  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9520                                  V64, V64, vecshiftR16,
9521                                  asm, ".4h", ".4h",
9522              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9523                    (i32 vecshiftR16:$imm)))]> {
9524    bits<4> imm;
9525    let Inst{19-16} = imm;
9526  }
9527
9528  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9529                                  V128, V128, vecshiftR16,
9530                                  asm, ".8h", ".8h",
9531            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9532                  (i32 vecshiftR16:$imm)))]> {
9533    bits<4> imm;
9534    let Inst{19-16} = imm;
9535  }
9536
9537  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9538                                  V64, V64, vecshiftR32,
9539                                  asm, ".2s", ".2s",
9540              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9541                    (i32 vecshiftR32:$imm)))]> {
9542    bits<5> imm;
9543    let Inst{20-16} = imm;
9544  }
9545
9546  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9547                                  V128, V128, vecshiftR32,
9548                                  asm, ".4s", ".4s",
9549            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9550                  (i32 vecshiftR32:$imm)))]> {
9551    bits<5> imm;
9552    let Inst{20-16} = imm;
9553  }
9554
9555  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9556                                  V128, V128, vecshiftR64,
9557                                  asm, ".2d", ".2d",
9558            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9559                  (i32 vecshiftR64:$imm)))]> {
9560    bits<6> imm;
9561    let Inst{21-16} = imm;
9562  }
9563}
9564
9565let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9566multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9567                                    SDPatternOperator OpNode = null_frag> {
9568  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9569                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9570                 [(set (v8i8 V64:$dst),
9571                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9572                           (i32 vecshiftR8:$imm)))]> {
9573    bits<3> imm;
9574    let Inst{18-16} = imm;
9575  }
9576
9577  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9578                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9579             [(set (v16i8 V128:$dst),
9580               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9581                       (i32 vecshiftR8:$imm)))]> {
9582    bits<3> imm;
9583    let Inst{18-16} = imm;
9584  }
9585
9586  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9587                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9588              [(set (v4i16 V64:$dst),
9589                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9590                        (i32 vecshiftR16:$imm)))]> {
9591    bits<4> imm;
9592    let Inst{19-16} = imm;
9593  }
9594
9595  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9596                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9597            [(set (v8i16 V128:$dst),
9598              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9599                      (i32 vecshiftR16:$imm)))]> {
9600    bits<4> imm;
9601    let Inst{19-16} = imm;
9602  }
9603
9604  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9605                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9606              [(set (v2i32 V64:$dst),
9607                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9608                        (i32 vecshiftR32:$imm)))]> {
9609    bits<5> imm;
9610    let Inst{20-16} = imm;
9611  }
9612
9613  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9614                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9615            [(set (v4i32 V128:$dst),
9616              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9617                      (i32 vecshiftR32:$imm)))]> {
9618    bits<5> imm;
9619    let Inst{20-16} = imm;
9620  }
9621
9622  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9623                                  V128, V128, vecshiftR64,
9624                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9625              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9626                      (i32 vecshiftR64:$imm)))]> {
9627    bits<6> imm;
9628    let Inst{21-16} = imm;
9629  }
9630}
9631
9632multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9633                                    SDPatternOperator OpNode = null_frag> {
9634  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9635                                  V64, V64, vecshiftL8,
9636                                  asm, ".8b", ".8b",
9637                    [(set (v8i8 V64:$dst),
9638                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9639                                  (i32 vecshiftL8:$imm)))]> {
9640    bits<3> imm;
9641    let Inst{18-16} = imm;
9642  }
9643
9644  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9645                                  V128, V128, vecshiftL8,
9646                                  asm, ".16b", ".16b",
9647                    [(set (v16i8 V128:$dst),
9648                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9649                                  (i32 vecshiftL8:$imm)))]> {
9650    bits<3> imm;
9651    let Inst{18-16} = imm;
9652  }
9653
9654  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9655                                  V64, V64, vecshiftL16,
9656                                  asm, ".4h", ".4h",
9657                    [(set (v4i16 V64:$dst),
9658                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9659                                   (i32 vecshiftL16:$imm)))]> {
9660    bits<4> imm;
9661    let Inst{19-16} = imm;
9662  }
9663
9664  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9665                                  V128, V128, vecshiftL16,
9666                                  asm, ".8h", ".8h",
9667                    [(set (v8i16 V128:$dst),
9668                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9669                                  (i32 vecshiftL16:$imm)))]> {
9670    bits<4> imm;
9671    let Inst{19-16} = imm;
9672  }
9673
9674  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9675                                  V64, V64, vecshiftL32,
9676                                  asm, ".2s", ".2s",
9677                    [(set (v2i32 V64:$dst),
9678                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9679                                  (i32 vecshiftL32:$imm)))]> {
9680    bits<5> imm;
9681    let Inst{20-16} = imm;
9682  }
9683
9684  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9685                                  V128, V128, vecshiftL32,
9686                                  asm, ".4s", ".4s",
9687                    [(set (v4i32 V128:$dst),
9688                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9689                                  (i32 vecshiftL32:$imm)))]> {
9690    bits<5> imm;
9691    let Inst{20-16} = imm;
9692  }
9693
9694  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9695                                  V128, V128, vecshiftL64,
9696                                  asm, ".2d", ".2d",
9697                    [(set (v2i64 V128:$dst),
9698                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9699                                  (i32 vecshiftL64:$imm)))]> {
9700    bits<6> imm;
9701    let Inst{21-16} = imm;
9702  }
9703}
9704
9705multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9706                                   SDPatternOperator OpNode> {
9707  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9708                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9709      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9710    bits<3> imm;
9711    let Inst{18-16} = imm;
9712  }
9713
9714  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9715                                  V128, V128, vecshiftL8,
9716                                  asm#"2", ".8h", ".16b",
9717      [(set (v8i16 V128:$Rd),
9718            (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)), vecshiftL8:$imm))]> {
9719    bits<3> imm;
9720    let Inst{18-16} = imm;
9721  }
9722
9723  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9724                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9725      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9726    bits<4> imm;
9727    let Inst{19-16} = imm;
9728  }
9729
9730  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9731                                  V128, V128, vecshiftL16,
9732                                  asm#"2", ".4s", ".8h",
9733      [(set (v4i32 V128:$Rd),
9734            (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)), vecshiftL16:$imm))]> {
9735
9736    bits<4> imm;
9737    let Inst{19-16} = imm;
9738  }
9739
9740  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9741                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9742      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9743    bits<5> imm;
9744    let Inst{20-16} = imm;
9745  }
9746
9747  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9748                                  V128, V128, vecshiftL32,
9749                                  asm#"2", ".2d", ".4s",
9750      [(set (v2i64 V128:$Rd),
9751            (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)), vecshiftL32:$imm))]> {
9752    bits<5> imm;
9753    let Inst{20-16} = imm;
9754  }
9755}
9756
9757
9758//---
9759// Vector load/store
9760//---
9761// SIMD ldX/stX no-index memory references don't allow the optional
9762// ", #0" constant and handle post-indexing explicitly, so we use
9763// a more specialized parse method for them. Otherwise, it's the same as
9764// the general GPR64sp handling.
9765
9766class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9767                   string asm, dag oops, dag iops, list<dag> pattern>
9768  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9769  bits<5> Vt;
9770  bits<5> Rn;
9771  let Inst{31} = 0;
9772  let Inst{30} = Q;
9773  let Inst{29-23} = 0b0011000;
9774  let Inst{22} = L;
9775  let Inst{21-16} = 0b000000;
9776  let Inst{15-12} = opcode;
9777  let Inst{11-10} = size;
9778  let Inst{9-5} = Rn;
9779  let Inst{4-0} = Vt;
9780}
9781
9782class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9783                       string asm, dag oops, dag iops>
9784  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9785  bits<5> Vt;
9786  bits<5> Rn;
9787  bits<5> Xm;
9788  let Inst{31} = 0;
9789  let Inst{30} = Q;
9790  let Inst{29-23} = 0b0011001;
9791  let Inst{22} = L;
9792  let Inst{21} = 0;
9793  let Inst{20-16} = Xm;
9794  let Inst{15-12} = opcode;
9795  let Inst{11-10} = size;
9796  let Inst{9-5} = Rn;
9797  let Inst{4-0} = Vt;
9798}
9799
9800// The immediate form of AdvSIMD post-indexed addressing is encoded with
9801// register post-index addressing from the zero register.
9802multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9803                           int Offset, int Size> {
9804  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9805  //      "ld1\t$Vt, [$Rn], #16"
9806  // may get mapped to
9807  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9808  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9809                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9810                      GPR64sp:$Rn,
9811                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9812                      XZR), 1>;
9813
9814  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9815  //      "ld1.8b\t$Vt, [$Rn], #16"
9816  // may get mapped to
9817  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9818  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9819                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9820                      GPR64sp:$Rn,
9821                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9822                      XZR), 0>;
9823
9824  // E.g. "ld1.8b { v0, v1 }, [x1]"
9825  //      "ld1\t$Vt, [$Rn]"
9826  // may get mapped to
9827  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9828  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9829                  (!cast<Instruction>(BaseName # Count # "v" # layout)
9830                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9831                      GPR64sp:$Rn), 0>;
9832
9833  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9834  //      "ld1\t$Vt, [$Rn], $Xm"
9835  // may get mapped to
9836  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9837  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9838                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9839                      GPR64sp:$Rn,
9840                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9841                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9842}
9843
9844multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9845                       int Offset128, int Offset64, bits<4> opcode> {
9846  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9847    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9848                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9849                           (ins GPR64sp:$Rn), []>;
9850    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9851                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9852                           (ins GPR64sp:$Rn), []>;
9853    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9854                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9855                           (ins GPR64sp:$Rn), []>;
9856    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9857                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9858                           (ins GPR64sp:$Rn), []>;
9859    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9860                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9861                           (ins GPR64sp:$Rn), []>;
9862    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9863                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9864                           (ins GPR64sp:$Rn), []>;
9865    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9866                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9867                           (ins GPR64sp:$Rn), []>;
9868
9869
9870    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9871                       (outs GPR64sp:$wback,
9872                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
9873                       (ins GPR64sp:$Rn,
9874                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9875    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9876                       (outs GPR64sp:$wback,
9877                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
9878                       (ins GPR64sp:$Rn,
9879                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9880    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9881                       (outs GPR64sp:$wback,
9882                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
9883                       (ins GPR64sp:$Rn,
9884                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9885    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9886                       (outs GPR64sp:$wback,
9887                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
9888                       (ins GPR64sp:$Rn,
9889                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9890    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9891                       (outs GPR64sp:$wback,
9892                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
9893                       (ins GPR64sp:$Rn,
9894                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9895    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9896                       (outs GPR64sp:$wback,
9897                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
9898                       (ins GPR64sp:$Rn,
9899                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9900    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9901                       (outs GPR64sp:$wback,
9902                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
9903                       (ins GPR64sp:$Rn,
9904                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9905  }
9906
9907  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9908  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9909  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9910  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9911  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9912  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9913  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9914}
9915
9916// Only ld1/st1 has a v1d version.
9917multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9918                       int Offset128, int Offset64, bits<4> opcode> {
9919  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9920    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9921                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9922                                 GPR64sp:$Rn), []>;
9923    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9924                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9925                                GPR64sp:$Rn), []>;
9926    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9927                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9928                                GPR64sp:$Rn), []>;
9929    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9930                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9931                                GPR64sp:$Rn), []>;
9932    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9933                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9934                                GPR64sp:$Rn), []>;
9935    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9936                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9937                                GPR64sp:$Rn), []>;
9938    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9939                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9940                                GPR64sp:$Rn), []>;
9941
9942    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9943                       (outs GPR64sp:$wback),
9944                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9945                            GPR64sp:$Rn,
9946                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9947    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9948                       (outs GPR64sp:$wback),
9949                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9950                            GPR64sp:$Rn,
9951                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9952    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9953                       (outs GPR64sp:$wback),
9954                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9955                            GPR64sp:$Rn,
9956                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9957    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9958                       (outs GPR64sp:$wback),
9959                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9960                            GPR64sp:$Rn,
9961                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9962    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9963                       (outs GPR64sp:$wback),
9964                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9965                            GPR64sp:$Rn,
9966                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9967    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9968                       (outs GPR64sp:$wback),
9969                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9970                            GPR64sp:$Rn,
9971                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9972    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9973                       (outs GPR64sp:$wback),
9974                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9975                            GPR64sp:$Rn,
9976                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9977  }
9978
9979  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9980  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9981  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9982  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9983  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9984  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9985  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9986}
9987
9988multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9989                       int Offset128, int Offset64, bits<4> opcode>
9990  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9991
9992  // LD1 instructions have extra "1d" variants.
9993  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9994    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9995                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9996                           (ins GPR64sp:$Rn), []>;
9997
9998    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9999                       (outs GPR64sp:$wback,
10000                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
10001                       (ins GPR64sp:$Rn,
10002                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10003  }
10004
10005  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10006}
10007
10008multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
10009                       int Offset128, int Offset64, bits<4> opcode>
10010  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10011
10012  // ST1 instructions have extra "1d" variants.
10013  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
10014    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
10015                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10016                                GPR64sp:$Rn), []>;
10017
10018    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
10019                       (outs GPR64sp:$wback),
10020                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10021                            GPR64sp:$Rn,
10022                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10023  }
10024
10025  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10026}
10027
10028multiclass SIMDLd1Multiple<string asm> {
10029  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10030  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10031  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10032  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10033}
10034
10035multiclass SIMDSt1Multiple<string asm> {
10036  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10037  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10038  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10039  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10040}
10041
10042multiclass SIMDLd2Multiple<string asm> {
10043  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10044}
10045
10046multiclass SIMDSt2Multiple<string asm> {
10047  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10048}
10049
10050multiclass SIMDLd3Multiple<string asm> {
10051  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10052}
10053
10054multiclass SIMDSt3Multiple<string asm> {
10055  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10056}
10057
10058multiclass SIMDLd4Multiple<string asm> {
10059  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10060}
10061
10062multiclass SIMDSt4Multiple<string asm> {
10063  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10064}
10065
10066//---
10067// AdvSIMD Load/store single-element
10068//---
10069
10070class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
10071                         string asm, string operands, string cst,
10072                         dag oops, dag iops, list<dag> pattern>
10073  : I<oops, iops, asm, operands, cst, pattern> {
10074  bits<5> Vt;
10075  bits<5> Rn;
10076  let Inst{31} = 0;
10077  let Inst{29-24} = 0b001101;
10078  let Inst{22} = L;
10079  let Inst{21} = R;
10080  let Inst{15-13} = opcode;
10081  let Inst{9-5} = Rn;
10082  let Inst{4-0} = Vt;
10083}
10084
10085class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
10086                         string asm, string operands, string cst,
10087                         dag oops, dag iops, list<dag> pattern>
10088  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
10089  bits<5> Vt;
10090  bits<5> Rn;
10091  let Inst{31} = 0;
10092  let Inst{29-24} = 0b001101;
10093  let Inst{22} = L;
10094  let Inst{21} = R;
10095  let Inst{15-13} = opcode;
10096  let Inst{9-5} = Rn;
10097  let Inst{4-0} = Vt;
10098}
10099
10100
10101let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10102class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
10103                  DAGOperand listtype>
10104  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
10105                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
10106                       []> {
10107  let Inst{30} = Q;
10108  let Inst{23} = 0;
10109  let Inst{20-16} = 0b00000;
10110  let Inst{12} = S;
10111  let Inst{11-10} = size;
10112}
10113let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10114class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
10115                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
10116  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
10117                       "$Rn = $wback",
10118                       (outs GPR64sp:$wback, listtype:$Vt),
10119                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
10120  bits<5> Xm;
10121  let Inst{30} = Q;
10122  let Inst{23} = 1;
10123  let Inst{20-16} = Xm;
10124  let Inst{12} = S;
10125  let Inst{11-10} = size;
10126}
10127
10128multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
10129                          int Offset, int Size> {
10130  // E.g. "ld1r { v0.8b }, [x1], #1"
10131  //      "ld1r.8b\t$Vt, [$Rn], #1"
10132  // may get mapped to
10133  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10134  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10135                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10136                      GPR64sp:$Rn,
10137                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10138                      XZR), 1>;
10139
10140  // E.g. "ld1r.8b { v0 }, [x1], #1"
10141  //      "ld1r.8b\t$Vt, [$Rn], #1"
10142  // may get mapped to
10143  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10144  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10145                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10146                      GPR64sp:$Rn,
10147                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10148                      XZR), 0>;
10149
10150  // E.g. "ld1r.8b { v0 }, [x1]"
10151  //      "ld1r.8b\t$Vt, [$Rn]"
10152  // may get mapped to
10153  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10154  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10155                  (!cast<Instruction>(BaseName # "v" # layout)
10156                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10157                      GPR64sp:$Rn), 0>;
10158
10159  // E.g. "ld1r.8b { v0 }, [x1], x2"
10160  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10161  // may get mapped to
10162  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10163  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10164                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10165                      GPR64sp:$Rn,
10166                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10167                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10168}
10169
10170multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10171  int Offset1, int Offset2, int Offset4, int Offset8> {
10172  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10173                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10174  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10175                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10176  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10177                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10178  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10179                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10180  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10181                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10182  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10183                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10184  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10185                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10186  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10187                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10188
10189  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10190                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10191                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10192  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10193                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10194                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10195  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10196                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10197                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10198  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10199                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10200                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10201  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10202                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10203                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10204  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10205                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10206                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10207  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10208                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10209                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10210  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10211                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10212                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10213
10214  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10215  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10216  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10217  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10218  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10219  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10220  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10221  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10222}
10223
10224class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10225                      dag oops, dag iops, list<dag> pattern>
10226  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10227                       pattern> {
10228  // idx encoded in Q:S:size fields.
10229  bits<4> idx;
10230  let Inst{30} = idx{3};
10231  let Inst{23} = 0;
10232  let Inst{20-16} = 0b00000;
10233  let Inst{12} = idx{2};
10234  let Inst{11-10} = idx{1-0};
10235}
10236class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10237                      dag oops, dag iops, list<dag> pattern>
10238  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10239                           oops, iops, pattern> {
10240  // idx encoded in Q:S:size fields.
10241  bits<4> idx;
10242  let Inst{30} = idx{3};
10243  let Inst{23} = 0;
10244  let Inst{20-16} = 0b00000;
10245  let Inst{12} = idx{2};
10246  let Inst{11-10} = idx{1-0};
10247}
10248class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10249                          dag oops, dag iops>
10250  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10251                       "$Rn = $wback", oops, iops, []> {
10252  // idx encoded in Q:S:size fields.
10253  bits<4> idx;
10254  bits<5> Xm;
10255  let Inst{30} = idx{3};
10256  let Inst{23} = 1;
10257  let Inst{20-16} = Xm;
10258  let Inst{12} = idx{2};
10259  let Inst{11-10} = idx{1-0};
10260}
10261class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10262                          dag oops, dag iops>
10263  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10264                           "$Rn = $wback", oops, iops, []> {
10265  // idx encoded in Q:S:size fields.
10266  bits<4> idx;
10267  bits<5> Xm;
10268  let Inst{30} = idx{3};
10269  let Inst{23} = 1;
10270  let Inst{20-16} = Xm;
10271  let Inst{12} = idx{2};
10272  let Inst{11-10} = idx{1-0};
10273}
10274
10275class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10276                      dag oops, dag iops, list<dag> pattern>
10277  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10278                       pattern> {
10279  // idx encoded in Q:S:size<1> fields.
10280  bits<3> idx;
10281  let Inst{30} = idx{2};
10282  let Inst{23} = 0;
10283  let Inst{20-16} = 0b00000;
10284  let Inst{12} = idx{1};
10285  let Inst{11} = idx{0};
10286  let Inst{10} = size;
10287}
10288class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10289                      dag oops, dag iops, list<dag> pattern>
10290  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10291                           oops, iops, pattern> {
10292  // idx encoded in Q:S:size<1> fields.
10293  bits<3> idx;
10294  let Inst{30} = idx{2};
10295  let Inst{23} = 0;
10296  let Inst{20-16} = 0b00000;
10297  let Inst{12} = idx{1};
10298  let Inst{11} = idx{0};
10299  let Inst{10} = size;
10300}
10301
10302class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10303                          dag oops, dag iops>
10304  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10305                       "$Rn = $wback", oops, iops, []> {
10306  // idx encoded in Q:S:size<1> fields.
10307  bits<3> idx;
10308  bits<5> Xm;
10309  let Inst{30} = idx{2};
10310  let Inst{23} = 1;
10311  let Inst{20-16} = Xm;
10312  let Inst{12} = idx{1};
10313  let Inst{11} = idx{0};
10314  let Inst{10} = size;
10315}
10316class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10317                          dag oops, dag iops>
10318  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10319                           "$Rn = $wback", oops, iops, []> {
10320  // idx encoded in Q:S:size<1> fields.
10321  bits<3> idx;
10322  bits<5> Xm;
10323  let Inst{30} = idx{2};
10324  let Inst{23} = 1;
10325  let Inst{20-16} = Xm;
10326  let Inst{12} = idx{1};
10327  let Inst{11} = idx{0};
10328  let Inst{10} = size;
10329}
10330class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10331                      dag oops, dag iops, list<dag> pattern>
10332  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10333                       pattern> {
10334  // idx encoded in Q:S fields.
10335  bits<2> idx;
10336  let Inst{30} = idx{1};
10337  let Inst{23} = 0;
10338  let Inst{20-16} = 0b00000;
10339  let Inst{12} = idx{0};
10340  let Inst{11-10} = size;
10341}
10342class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10343                      dag oops, dag iops, list<dag> pattern>
10344  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10345                           oops, iops, pattern> {
10346  // idx encoded in Q:S fields.
10347  bits<2> idx;
10348  let Inst{30} = idx{1};
10349  let Inst{23} = 0;
10350  let Inst{20-16} = 0b00000;
10351  let Inst{12} = idx{0};
10352  let Inst{11-10} = size;
10353}
10354class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10355                          string asm, dag oops, dag iops>
10356  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10357                       "$Rn = $wback", oops, iops, []> {
10358  // idx encoded in Q:S fields.
10359  bits<2> idx;
10360  bits<5> Xm;
10361  let Inst{30} = idx{1};
10362  let Inst{23} = 1;
10363  let Inst{20-16} = Xm;
10364  let Inst{12} = idx{0};
10365  let Inst{11-10} = size;
10366}
10367class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10368                          string asm, dag oops, dag iops>
10369  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10370                           "$Rn = $wback", oops, iops, []> {
10371  // idx encoded in Q:S fields.
10372  bits<2> idx;
10373  bits<5> Xm;
10374  let Inst{30} = idx{1};
10375  let Inst{23} = 1;
10376  let Inst{20-16} = Xm;
10377  let Inst{12} = idx{0};
10378  let Inst{11-10} = size;
10379}
10380class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10381                      dag oops, dag iops, list<dag> pattern>
10382  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10383                       pattern> {
10384  // idx encoded in Q field.
10385  bits<1> idx;
10386  let Inst{30} = idx;
10387  let Inst{23} = 0;
10388  let Inst{20-16} = 0b00000;
10389  let Inst{12} = 0;
10390  let Inst{11-10} = size;
10391}
10392class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10393                      dag oops, dag iops, list<dag> pattern>
10394  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10395                           oops, iops, pattern> {
10396  // idx encoded in Q field.
10397  bits<1> idx;
10398  let Inst{30} = idx;
10399  let Inst{23} = 0;
10400  let Inst{20-16} = 0b00000;
10401  let Inst{12} = 0;
10402  let Inst{11-10} = size;
10403}
10404class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10405                          string asm, dag oops, dag iops>
10406  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10407                       "$Rn = $wback", oops, iops, []> {
10408  // idx encoded in Q field.
10409  bits<1> idx;
10410  bits<5> Xm;
10411  let Inst{30} = idx;
10412  let Inst{23} = 1;
10413  let Inst{20-16} = Xm;
10414  let Inst{12} = 0;
10415  let Inst{11-10} = size;
10416}
10417class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10418                          string asm, dag oops, dag iops>
10419  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10420                           "$Rn = $wback", oops, iops, []> {
10421  // idx encoded in Q field.
10422  bits<1> idx;
10423  bits<5> Xm;
10424  let Inst{30} = idx;
10425  let Inst{23} = 1;
10426  let Inst{20-16} = Xm;
10427  let Inst{12} = 0;
10428  let Inst{11-10} = size;
10429}
10430
10431let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10432multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10433                         RegisterOperand listtype,
10434                         RegisterOperand GPR64pi> {
10435  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10436                           (outs listtype:$dst),
10437                           (ins listtype:$Vt, VectorIndexB:$idx,
10438                                GPR64sp:$Rn), []>;
10439
10440  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10441                            (outs GPR64sp:$wback, listtype:$dst),
10442                            (ins listtype:$Vt, VectorIndexB:$idx,
10443                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10444}
10445let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10446multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10447                         RegisterOperand listtype,
10448                         RegisterOperand GPR64pi> {
10449  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10450                            (outs listtype:$dst),
10451                            (ins listtype:$Vt, VectorIndexH:$idx,
10452                                 GPR64sp:$Rn), []>;
10453
10454  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10455                            (outs GPR64sp:$wback, listtype:$dst),
10456                            (ins listtype:$Vt, VectorIndexH:$idx,
10457                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10458}
10459let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10460multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10461                         RegisterOperand listtype,
10462                         RegisterOperand GPR64pi> {
10463  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10464                            (outs listtype:$dst),
10465                            (ins listtype:$Vt, VectorIndexS:$idx,
10466                                 GPR64sp:$Rn), []>;
10467
10468  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10469                            (outs GPR64sp:$wback, listtype:$dst),
10470                            (ins listtype:$Vt, VectorIndexS:$idx,
10471                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10472}
10473let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10474multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10475                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10476  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10477                            (outs listtype:$dst),
10478                            (ins listtype:$Vt, VectorIndexD:$idx,
10479                                 GPR64sp:$Rn), []>;
10480
10481  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10482                            (outs GPR64sp:$wback, listtype:$dst),
10483                            (ins listtype:$Vt, VectorIndexD:$idx,
10484                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10485}
10486let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10487multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10488                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10489  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10490                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10491                                        GPR64sp:$Rn), []>;
10492
10493  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10494                                    (outs GPR64sp:$wback),
10495                                    (ins listtype:$Vt, VectorIndexB:$idx,
10496                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10497}
10498let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10499multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10500                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10501  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10502                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10503                                         GPR64sp:$Rn), []>;
10504
10505  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10506                            (outs GPR64sp:$wback),
10507                            (ins listtype:$Vt, VectorIndexH:$idx,
10508                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10509}
10510let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10511multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10512                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10513  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10514                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10515                                         GPR64sp:$Rn), []>;
10516
10517  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10518                            (outs GPR64sp:$wback),
10519                            (ins listtype:$Vt, VectorIndexS:$idx,
10520                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10521}
10522let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10523multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10524                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10525  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10526                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10527                                         GPR64sp:$Rn), []>;
10528
10529  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10530                            (outs GPR64sp:$wback),
10531                            (ins listtype:$Vt, VectorIndexD:$idx,
10532                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10533}
10534
10535multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10536                                 string Count, int Offset, Operand idxtype> {
10537  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10538  //      "ld1\t$Vt, [$Rn], #1"
10539  // may get mapped to
10540  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10541  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10542                  (!cast<Instruction>(NAME # Type  # "_POST")
10543                      GPR64sp:$Rn,
10544                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10545                      idxtype:$idx, XZR), 1>;
10546
10547  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10548  //      "ld1.8b\t$Vt, [$Rn], #1"
10549  // may get mapped to
10550  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10551  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10552                  (!cast<Instruction>(NAME # Type # "_POST")
10553                      GPR64sp:$Rn,
10554                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10555                      idxtype:$idx, XZR), 0>;
10556
10557  // E.g. "ld1.8b { v0 }[0], [x1]"
10558  //      "ld1.8b\t$Vt, [$Rn]"
10559  // may get mapped to
10560  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10561  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10562                      (!cast<Instruction>(NAME # Type)
10563                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10564                         idxtype:$idx, GPR64sp:$Rn), 0>;
10565
10566  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10567  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10568  // may get mapped to
10569  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10570  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10571                      (!cast<Instruction>(NAME # Type # "_POST")
10572                         GPR64sp:$Rn,
10573                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10574                         idxtype:$idx,
10575                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10576}
10577
10578multiclass SIMDLdSt1SingleAliases<string asm> {
10579  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10580  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10581  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10582  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10583}
10584
10585multiclass SIMDLdSt2SingleAliases<string asm> {
10586  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10587  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10588  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10589  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10590}
10591
10592multiclass SIMDLdSt3SingleAliases<string asm> {
10593  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10594  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10595  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10596  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10597}
10598
10599multiclass SIMDLdSt4SingleAliases<string asm> {
10600  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10601  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10602  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10603  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10604}
10605} // end of 'let Predicates = [HasNEON]'
10606
10607//----------------------------------------------------------------------------
10608// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10609//----------------------------------------------------------------------------
10610
10611let Predicates = [HasNEON, HasRDM] in {
10612
10613class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10614                                    RegisterOperand regtype, string asm,
10615                                    string kind, list<dag> pattern>
10616  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10617                                pattern> {
10618}
10619multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10620                                             SDPatternOperator op> {
10621  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10622    [(set (v4i16 V64:$dst),
10623          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
10624  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10625    [(set (v8i16 V128:$dst),
10626          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
10627  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10628    [(set (v2i32 V64:$dst),
10629          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
10630  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10631    [(set (v4i32 V128:$dst),
10632          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
10633}
10634
10635multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10636                                     SDPatternOperator op> {
10637  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10638                                          V64, V64, V128_lo, VectorIndexH,
10639                                          asm, ".4h", ".4h", ".4h", ".h",
10640    [(set (v4i16 V64:$dst),
10641          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10642                     (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10643                                              VectorIndexH:$idx)))))]> {
10644    bits<3> idx;
10645    let Inst{11} = idx{2};
10646    let Inst{21} = idx{1};
10647    let Inst{20} = idx{0};
10648  }
10649
10650  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10651                                          V128, V128, V128_lo, VectorIndexH,
10652                                          asm, ".8h", ".8h", ".8h", ".h",
10653    [(set (v8i16 V128:$dst),
10654          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10655                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10656                                              VectorIndexH:$idx)))))]> {
10657    bits<3> idx;
10658    let Inst{11} = idx{2};
10659    let Inst{21} = idx{1};
10660    let Inst{20} = idx{0};
10661  }
10662
10663  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10664                                          V64, V64, V128, VectorIndexS,
10665                                          asm, ".2s", ".2s", ".2s", ".s",
10666    [(set (v2i32 V64:$dst),
10667          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10668                     (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10669                                              VectorIndexS:$idx)))))]> {
10670    bits<2> idx;
10671    let Inst{11} = idx{1};
10672    let Inst{21} = idx{0};
10673  }
10674
10675  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10676                                          V128, V128, V128, VectorIndexS,
10677                                          asm, ".4s", ".4s", ".4s", ".s",
10678    [(set (v4i32 V128:$dst),
10679          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10680                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10681                                              VectorIndexS:$idx)))))]> {
10682    bits<2> idx;
10683    let Inst{11} = idx{1};
10684    let Inst{21} = idx{0};
10685  }
10686
10687  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10688                                        FPR16Op, FPR16Op, V128_lo,
10689                                        VectorIndexH, asm, ".h", "", "", ".h",
10690                                        []> {
10691    bits<3> idx;
10692    let Inst{11} = idx{2};
10693    let Inst{21} = idx{1};
10694    let Inst{20} = idx{0};
10695  }
10696
10697  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10698                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10699                                        asm, ".s", "", "", ".s",
10700    [(set (i32 FPR32Op:$dst),
10701          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
10702                   (i32 (vector_extract (v4i32 V128:$Rm),
10703                                        VectorIndexS:$idx)))))]> {
10704    bits<2> idx;
10705    let Inst{11} = idx{1};
10706    let Inst{21} = idx{0};
10707  }
10708}
10709} // let Predicates = [HasNeon, HasRDM]
10710
10711//----------------------------------------------------------------------------
10712// ARMv8.3 Complex ADD/MLA instructions
10713//----------------------------------------------------------------------------
10714
10715class ComplexRotationOperand<int Angle, int Remainder, string Type>
10716  : AsmOperandClass {
10717  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10718  let DiagnosticType = "InvalidComplexRotation" # Type;
10719  let Name = "ComplexRotation" # Type;
10720}
10721def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10722                                                  SDNodeXForm<imm, [{
10723  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10724}]>> {
10725  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10726  let PrintMethod = "printComplexRotationOp<90, 0>";
10727}
10728def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10729                                                  SDNodeXForm<imm, [{
10730  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10731}]>> {
10732  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10733  let PrintMethod = "printComplexRotationOp<180, 90>";
10734}
10735let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
10736class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10737                                     RegisterOperand regtype, Operand rottype,
10738                                     string asm, string kind, list<dag> pattern>
10739  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10740      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10741      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10742    Sched<[!if(Q, WriteVq, WriteVd)]> {
10743  bits<5> Rd;
10744  bits<5> Rn;
10745  bits<5> Rm;
10746  bits<1> rot;
10747  let Inst{31}    = 0;
10748  let Inst{30}    = Q;
10749  let Inst{29}    = U;
10750  let Inst{28-24} = 0b01110;
10751  let Inst{23-22} = size;
10752  let Inst{21}    = 0;
10753  let Inst{20-16} = Rm;
10754  let Inst{15-13} = opcode;
10755  // Non-tied version (FCADD) only has one rotation bit
10756  let Inst{12}    = rot;
10757  let Inst{11}    = 0;
10758  let Inst{10}    = 1;
10759  let Inst{9-5}   = Rn;
10760  let Inst{4-0}   = Rd;
10761}
10762
10763//8.3 CompNum - Floating-point complex number support
10764multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10765                                          string asm, SDPatternOperator OpNode>{
10766  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10767  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10768              asm, ".4h",
10769              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10770                                              (v4f16 V64:$Rn),
10771                                              (v4f16 V64:$Rm),
10772                                              (i32 rottype:$rot)))]>;
10773
10774  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10775              asm, ".8h",
10776              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10777                                               (v8f16 V128:$Rn),
10778                                               (v8f16 V128:$Rm),
10779                                               (i32 rottype:$rot)))]>;
10780  }
10781
10782  let Predicates = [HasComplxNum, HasNEON] in {
10783  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10784              asm, ".2s",
10785              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10786                                              (v2f32 V64:$Rn),
10787                                              (v2f32 V64:$Rm),
10788                                              (i32 rottype:$rot)))]>;
10789
10790  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10791              asm, ".4s",
10792              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10793                                               (v4f32 V128:$Rn),
10794                                               (v4f32 V128:$Rm),
10795                                               (i32 rottype:$rot)))]>;
10796
10797  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10798              asm, ".2d",
10799              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10800                                               (v2f64 V128:$Rn),
10801                                               (v2f64 V128:$Rm),
10802                                               (i32 rottype:$rot)))]>;
10803  }
10804}
10805
10806let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
10807class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10808                                         bits<3> opcode,
10809                                         RegisterOperand regtype,
10810                                         Operand rottype, string asm,
10811                                         string kind, list<dag> pattern>
10812  : I<(outs regtype:$dst),
10813      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10814      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10815      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10816    Sched<[!if(Q, WriteVq, WriteVd)]> {
10817  bits<5> Rd;
10818  bits<5> Rn;
10819  bits<5> Rm;
10820  bits<2> rot;
10821  let Inst{31}    = 0;
10822  let Inst{30}    = Q;
10823  let Inst{29}    = U;
10824  let Inst{28-24} = 0b01110;
10825  let Inst{23-22} = size;
10826  let Inst{21}    = 0;
10827  let Inst{20-16} = Rm;
10828  let Inst{15-13} = opcode;
10829  let Inst{12-11} = rot;
10830  let Inst{10}    = 1;
10831  let Inst{9-5}   = Rn;
10832  let Inst{4-0}   = Rd;
10833}
10834
10835multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10836                                             Operand rottype, string asm,
10837                                             SDPatternOperator OpNode> {
10838  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10839  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10840              rottype, asm, ".4h",
10841              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10842                                              (v4f16 V64:$Rn),
10843                                              (v4f16 V64:$Rm),
10844                                              (i32 rottype:$rot)))]>;
10845
10846  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10847              rottype, asm, ".8h",
10848              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10849                                               (v8f16 V128:$Rn),
10850                                               (v8f16 V128:$Rm),
10851                                               (i32 rottype:$rot)))]>;
10852  }
10853
10854  let Predicates = [HasComplxNum, HasNEON] in {
10855  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10856              rottype, asm, ".2s",
10857              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10858                                              (v2f32 V64:$Rn),
10859                                              (v2f32 V64:$Rm),
10860                                              (i32 rottype:$rot)))]>;
10861
10862  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10863              rottype, asm, ".4s",
10864              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10865                                               (v4f32 V128:$Rn),
10866                                               (v4f32 V128:$Rm),
10867                                               (i32 rottype:$rot)))]>;
10868
10869  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10870              rottype, asm, ".2d",
10871              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10872                                               (v2f64 V128:$Rn),
10873                                               (v2f64 V128:$Rm),
10874                                               (i32 rottype:$rot)))]>;
10875  }
10876}
10877
10878let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1 in
10879class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10880                                 bit opc1, bit opc2, RegisterOperand dst_reg,
10881                                 RegisterOperand lhs_reg,
10882                                 RegisterOperand rhs_reg, Operand vec_idx,
10883                                 Operand rottype, string asm, string apple_kind,
10884                                 string dst_kind, string lhs_kind,
10885                                 string rhs_kind, list<dag> pattern>
10886  : I<(outs dst_reg:$dst),
10887      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10888      asm,
10889      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10890      "$idx, $rot" # "|" # apple_kind #
10891      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10892    Sched<[!if(Q, WriteVq, WriteVd)]> {
10893  bits<5> Rd;
10894  bits<5> Rn;
10895  bits<5> Rm;
10896  bits<2> rot;
10897
10898  let Inst{31}    = 0;
10899  let Inst{30}    = Q;
10900  let Inst{29}    = U;
10901  let Inst{28}    = Scalar;
10902  let Inst{27-24} = 0b1111;
10903  let Inst{23-22} = size;
10904  // Bit 21 must be set by the derived class.
10905  let Inst{20-16} = Rm;
10906  let Inst{15}    = opc1;
10907  let Inst{14-13} = rot;
10908  let Inst{12}    = opc2;
10909  // Bit 11 must be set by the derived class.
10910  let Inst{10}    = 0;
10911  let Inst{9-5}   = Rn;
10912  let Inst{4-0}   = Rd;
10913}
10914
10915// The complex instructions index by pairs of elements, so the VectorIndexes
10916// don't match the lane types, and the index bits are different to the other
10917// classes.
10918multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
10919                                     string asm> {
10920  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10921  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10922                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10923                      ".4h", ".h", []> {
10924    bits<1> idx;
10925    let Inst{11} = 0;
10926    let Inst{21} = idx{0};
10927  }
10928
10929  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10930                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10931                      ".8h", ".8h", ".h", []> {
10932    bits<2> idx;
10933    let Inst{11} = idx{1};
10934    let Inst{21} = idx{0};
10935  }
10936  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10937
10938  let Predicates = [HasComplxNum, HasNEON] in {
10939  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10940                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10941                      ".4s", ".4s", ".s", []> {
10942    bits<1> idx;
10943    let Inst{11} = idx{0};
10944    let Inst{21} = 0;
10945  }
10946  } // Predicates = [HasComplxNum, HasNEON]
10947}
10948
10949//----------------------------------------------------------------------------
10950// Crypto extensions
10951//----------------------------------------------------------------------------
10952
10953let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10954class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10955              list<dag> pat>
10956  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10957    Sched<[WriteVq]>{
10958  bits<5> Rd;
10959  bits<5> Rn;
10960  let Inst{31-16} = 0b0100111000101000;
10961  let Inst{15-12} = opc;
10962  let Inst{11-10} = 0b10;
10963  let Inst{9-5}   = Rn;
10964  let Inst{4-0}   = Rd;
10965}
10966
10967class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10968  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10969            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10970
10971class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10972  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10973            "$Rd = $dst",
10974            [(set (v16i8 V128:$dst),
10975                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10976
10977let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10978class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10979                     dag oops, dag iops, list<dag> pat>
10980  : I<oops, iops, asm,
10981      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10982      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10983    Sched<[WriteVq]>{
10984  bits<5> Rd;
10985  bits<5> Rn;
10986  bits<5> Rm;
10987  let Inst{31-21} = 0b01011110000;
10988  let Inst{20-16} = Rm;
10989  let Inst{15}    = 0;
10990  let Inst{14-12} = opc;
10991  let Inst{11-10} = 0b00;
10992  let Inst{9-5}   = Rn;
10993  let Inst{4-0}   = Rd;
10994}
10995
10996class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10997  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10998                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10999                   [(set (v4i32 FPR128:$dst),
11000                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
11001                                 (v4i32 V128:$Rm)))]>;
11002
11003class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
11004  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
11005                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
11006                   [(set (v4i32 V128:$dst),
11007                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11008                                 (v4i32 V128:$Rm)))]>;
11009
11010class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
11011  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11012                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
11013                   [(set (v4i32 FPR128:$dst),
11014                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
11015                                 (v4i32 V128:$Rm)))]>;
11016
11017let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11018class SHA2OpInst<bits<4> opc, string asm, string kind,
11019                 string cstr, dag oops, dag iops,
11020                 list<dag> pat>
11021  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
11022                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
11023    Sched<[WriteVq]>{
11024  bits<5> Rd;
11025  bits<5> Rn;
11026  let Inst{31-16} = 0b0101111000101000;
11027  let Inst{15-12} = opc;
11028  let Inst{11-10} = 0b10;
11029  let Inst{9-5}   = Rn;
11030  let Inst{4-0}   = Rd;
11031}
11032
11033class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
11034  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
11035               (ins V128:$Rd, V128:$Rn),
11036               [(set (v4i32 V128:$dst),
11037                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
11038
11039class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
11040  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
11041               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
11042
11043// Armv8.2-A Crypto extensions
11044class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
11045                    list<dag> pattern>
11046  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
11047  bits<5> Vd;
11048  bits<5> Vn;
11049  let Inst{31-25} = 0b1100111;
11050  let Inst{9-5}   = Vn;
11051  let Inst{4-0}   = Vd;
11052}
11053
11054class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
11055  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
11056                  "$Vd = $Vdst", []> {
11057  let Inst{31-25} = 0b1100111;
11058  let Inst{24-21} = 0b0110;
11059  let Inst{20-15} = 0b000001;
11060  let Inst{14}    = op0;
11061  let Inst{13-12} = 0b00;
11062  let Inst{11-10} = op1;
11063}
11064class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
11065  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
11066class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
11067  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
11068
11069class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
11070                string asmops, string cst>
11071  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
11072  bits<5> Vm;
11073  let Inst{24-21} = 0b0011;
11074  let Inst{20-16} = Vm;
11075  let Inst{15}    = 0b1;
11076  let Inst{14}    = op0;
11077  let Inst{13-12} = 0b00;
11078  let Inst{11-10} = op1;
11079}
11080class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
11081  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11082              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
11083class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
11084  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11085              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11086class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
11087  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11088              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
11089class CryptoRRRTied_4S<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.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11092class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11093  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11094              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11095
11096class CryptoRRRR<bits<2>op0, string asm, string asmops>
11097  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11098                  asmops, "", []> {
11099  bits<5> Vm;
11100  bits<5> Va;
11101  let Inst{24-23} = 0b00;
11102  let Inst{22-21} = op0;
11103  let Inst{20-16} = Vm;
11104  let Inst{15}    = 0b0;
11105  let Inst{14-10} = Va;
11106}
11107class CryptoRRRR_16B<bits<2>op0, string asm>
11108 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11109                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11110}
11111class CryptoRRRR_4S<bits<2>op0, string asm>
11112 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11113                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11114}
11115
11116class CryptoRRRi6<string asm>
11117  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11118                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11119                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11120  bits<6> imm;
11121  bits<5> Vm;
11122  let Inst{24-21} = 0b0100;
11123  let Inst{20-16} = Vm;
11124  let Inst{15-10} = imm;
11125  let Inst{9-5}   = Vn;
11126  let Inst{4-0}   = Vd;
11127}
11128
11129class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11130  : BaseCryptoV82<(outs V128:$Vdst),
11131                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11132                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11133                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11134  bits<2> imm;
11135  bits<5> Vm;
11136  let Inst{24-21} = 0b0010;
11137  let Inst{20-16} = Vm;
11138  let Inst{15}    = 0b1;
11139  let Inst{14}    = op0;
11140  let Inst{13-12} = imm;
11141  let Inst{11-10} = op1;
11142}
11143
11144//----------------------------------------------------------------------------
11145// v8.1 atomic instructions extension:
11146// * CAS
11147// * CASP
11148// * SWP
11149// * LDOPregister<OP>, and aliases STOPregister<OP>
11150
11151// Instruction encodings:
11152//
11153//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11154// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11155// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11156// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11157// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11158// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11159
11160// Instruction syntax:
11161//
11162// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11163// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11164// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11165// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11166// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11167// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11168// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11169// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11170// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11171// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11172
11173let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11174class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11175                      string cstr, list<dag> pattern>
11176      : I<oops, iops, asm, operands, cstr, pattern> {
11177  bits<2> Sz;
11178  bit NP;
11179  bit Acq;
11180  bit Rel;
11181  bits<5> Rs;
11182  bits<5> Rn;
11183  bits<5> Rt;
11184  let Inst{31-30} = Sz;
11185  let Inst{29-24} = 0b001000;
11186  let Inst{23} = NP;
11187  let Inst{22} = Acq;
11188  let Inst{21} = 0b1;
11189  let Inst{20-16} = Rs;
11190  let Inst{15} = Rel;
11191  let Inst{14-10} = 0b11111;
11192  let Inst{9-5} = Rn;
11193  let Inst{4-0} = Rt;
11194  let Predicates = [HasLSE];
11195}
11196
11197class BaseCAS<string order, string size, RegisterClass RC>
11198      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11199                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11200                        "$out = $Rs",[]>,
11201        Sched<[WriteAtomic]> {
11202  let NP = 1;
11203}
11204
11205multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11206  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11207  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11208  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11209  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11210}
11211
11212class BaseCASP<string order, string size, RegisterOperand RC>
11213      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11214                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11215                        "$out = $Rs",[]>,
11216        Sched<[WriteAtomic]> {
11217  let NP = 0;
11218}
11219
11220multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11221  let Sz = 0b00, Acq = Acq, Rel = Rel in
11222    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11223  let Sz = 0b01, Acq = Acq, Rel = Rel in
11224    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11225}
11226
11227let Predicates = [HasLSE] in
11228class BaseSWP<string order, string size, RegisterClass RC>
11229      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11230          "\t$Rs, $Rt, [$Rn]","",[]>,
11231        Sched<[WriteAtomic]> {
11232  bits<2> Sz;
11233  bit Acq;
11234  bit Rel;
11235  bits<5> Rs;
11236  bits<3> opc = 0b000;
11237  bits<5> Rn;
11238  bits<5> Rt;
11239  let Inst{31-30} = Sz;
11240  let Inst{29-24} = 0b111000;
11241  let Inst{23} = Acq;
11242  let Inst{22} = Rel;
11243  let Inst{21} = 0b1;
11244  let Inst{20-16} = Rs;
11245  let Inst{15} = 0b1;
11246  let Inst{14-12} = opc;
11247  let Inst{11-10} = 0b00;
11248  let Inst{9-5} = Rn;
11249  let Inst{4-0} = Rt;
11250  let Predicates = [HasLSE];
11251}
11252
11253multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11254  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11255  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11256  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11257  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11258}
11259
11260let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11261class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11262      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11263          "\t$Rs, $Rt, [$Rn]","",[]>,
11264        Sched<[WriteAtomic]> {
11265  bits<2> Sz;
11266  bit Acq;
11267  bit Rel;
11268  bits<5> Rs;
11269  bits<3> opc;
11270  bits<5> Rn;
11271  bits<5> Rt;
11272  let Inst{31-30} = Sz;
11273  let Inst{29-24} = 0b111000;
11274  let Inst{23} = Acq;
11275  let Inst{22} = Rel;
11276  let Inst{21} = 0b1;
11277  let Inst{20-16} = Rs;
11278  let Inst{15} = 0b0;
11279  let Inst{14-12} = opc;
11280  let Inst{11-10} = 0b00;
11281  let Inst{9-5} = Rn;
11282  let Inst{4-0} = Rt;
11283  let Predicates = [HasLSE];
11284}
11285
11286multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11287                        string order> {
11288  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11289    def B : BaseLDOPregister<op, order, "b", GPR32>;
11290  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11291    def H : BaseLDOPregister<op, order, "h", GPR32>;
11292  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11293    def W : BaseLDOPregister<op, order, "", GPR32>;
11294  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11295    def X : BaseLDOPregister<op, order, "", GPR64>;
11296}
11297
11298// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11299// complex DAG for DstRHS.
11300let Predicates = [HasLSE] in
11301multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11302                                         string size, dag SrcRHS, dag DstRHS> {
11303  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11304            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11305  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11306            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11307  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11308            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11309  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11310            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11311  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11312            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11313}
11314
11315multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11316                                     string size, dag RHS> {
11317  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11318}
11319
11320multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11321                                         string size, dag LHS, dag RHS> {
11322  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11323}
11324
11325multiclass LDOPregister_patterns<string inst, string op> {
11326  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11327  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11328  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11329  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11330}
11331
11332multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11333  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11334                        (i64 GPR64:$Rm),
11335                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11336  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11337                        (i32 GPR32:$Rm),
11338                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11339  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11340                        (i32 GPR32:$Rm),
11341                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11342  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11343                        (i32 GPR32:$Rm),
11344                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11345}
11346
11347let Predicates = [HasLSE] in
11348multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11349                                        string size, dag OLD, dag NEW> {
11350  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11351            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11352  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11353            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11354  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11355            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11356  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11357            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11358  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11359            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11360}
11361
11362multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11363                                    string size, dag OLD, dag NEW> {
11364  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11365}
11366
11367multiclass CASregister_patterns<string inst, string op> {
11368  defm : CASregister_patterns_ord<inst, "X", op, "64",
11369                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11370  defm : CASregister_patterns_ord<inst, "W", op, "32",
11371                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11372  defm : CASregister_patterns_ord<inst, "H", op, "16",
11373                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11374  defm : CASregister_patterns_ord<inst, "B", op, "8",
11375                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11376}
11377
11378let Predicates = [HasLSE] in
11379class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11380                        Instruction inst> :
11381      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11382
11383multiclass STOPregister<string asm, string instr> {
11384  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11385                    !cast<Instruction>(instr # "LB")>;
11386  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11387                    !cast<Instruction>(instr # "LH")>;
11388  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11389                    !cast<Instruction>(instr # "LW")>;
11390  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11391                    !cast<Instruction>(instr # "LX")>;
11392  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11393                    !cast<Instruction>(instr # "B")>;
11394  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11395                    !cast<Instruction>(instr # "H")>;
11396  def : BaseSTOPregister<asm,        GPR32, WZR,
11397                    !cast<Instruction>(instr # "W")>;
11398  def : BaseSTOPregister<asm,        GPR64, XZR,
11399                    !cast<Instruction>(instr # "X")>;
11400}
11401
11402class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11403                        dag iops, dag oops, list<dag> pat>
11404    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11405      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11406  bits<5> Rt;
11407  bits<5> Rn;
11408  let Inst{31-21} = 0b11111000001;
11409  let Inst{15}    = 1;
11410  let Inst{14-12} = opc;
11411  let Inst{11-10} = 0b00;
11412  let Inst{9-5}   = Rn;
11413  let Inst{4-0}   = Rt;
11414
11415  let Predicates = [HasV8_7a];
11416}
11417
11418class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11419                      list<dag> pat = []>
11420    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11421  let Inst{20-16} = 0b11111;
11422}
11423
11424class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11425    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11426                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11427  bits<5> Rs;
11428  let Inst{20-16} = Rs;
11429}
11430
11431class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
11432                             bits<2> op2, string asm>
11433  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
11434      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
11435      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
11436      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
11437    Sched<[]> {
11438  bits<5> Rd;
11439  bits<5> Rs;
11440  bits<5> Rn;
11441  let Inst{31-27} = 0b00011;
11442  let Inst{26} = isMove;
11443  let Inst{25-24} = 0b01;
11444  let Inst{23-22} = opcode;
11445  let Inst{21} = 0b0;
11446  let Inst{20-16} = Rs;
11447  let Inst{15-14} = op2;
11448  let Inst{13-12} = op1;
11449  let Inst{11-10} = 0b01;
11450  let Inst{9-5} = Rn;
11451  let Inst{4-0} = Rd;
11452
11453  let DecoderMethod = "DecodeCPYMemOpInstruction";
11454  let mayLoad = 1;
11455  let mayStore = 1;
11456}
11457
11458class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11459  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
11460
11461class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
11462  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
11463
11464class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
11465                        string asm>
11466  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
11467      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
11468      asm, "\t[$Rd]!, $Rn!, $Rm",
11469      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
11470    Sched<[]> {
11471  bits<5> Rd;
11472  bits<5> Rn;
11473  bits<5> Rm;
11474  let Inst{31-27} = 0b00011;
11475  let Inst{26} = isTagging;
11476  let Inst{25-21} = 0b01110;
11477  let Inst{20-16} = Rm;
11478  let Inst{15-14} = opcode;
11479  let Inst{13} = op2;
11480  let Inst{12} = op1;
11481  let Inst{11-10} = 0b01;
11482  let Inst{9-5} = Rn;
11483  let Inst{4-0} = Rd;
11484
11485  let DecoderMethod = "DecodeSETMemOpInstruction";
11486  let mayLoad = 0;
11487  let mayStore = 1;
11488}
11489
11490class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
11491  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
11492
11493class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
11494  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
11495
11496multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
11497  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
11498  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
11499  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
11500  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
11501  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
11502  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
11503  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
11504  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
11505  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
11506  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
11507  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
11508  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
11509  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
11510  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
11511  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
11512  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
11513}
11514
11515multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
11516  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
11517  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
11518  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
11519  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
11520  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
11521  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
11522  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
11523  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
11524  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
11525  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
11526  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
11527  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
11528  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
11529  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
11530  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
11531  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
11532}
11533
11534multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
11535  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
11536  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
11537  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
11538  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
11539}
11540
11541multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
11542  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
11543  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
11544  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
11545  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
11546}
11547
11548//----------------------------------------------------------------------------
11549// Allow the size specifier tokens to be upper case, not just lower.
11550def : TokenAlias<".4B", ".4b">;  // Add dot product
11551def : TokenAlias<".8B", ".8b">;
11552def : TokenAlias<".4H", ".4h">;
11553def : TokenAlias<".2S", ".2s">;
11554def : TokenAlias<".1D", ".1d">;
11555def : TokenAlias<".16B", ".16b">;
11556def : TokenAlias<".8H", ".8h">;
11557def : TokenAlias<".4S", ".4s">;
11558def : TokenAlias<".2D", ".2d">;
11559def : TokenAlias<".1Q", ".1q">;
11560def : TokenAlias<".2H", ".2h">;
11561def : TokenAlias<".B", ".b">;
11562def : TokenAlias<".H", ".h">;
11563def : TokenAlias<".S", ".s">;
11564def : TokenAlias<".D", ".d">;
11565def : TokenAlias<".Q", ".q">;
11566