AArch64InstrFormats.td revision 360784
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// AArch64 Instruction Format
24class AArch64Inst<Format f, string cstr> : Instruction {
25  field bits<32> Inst; // Instruction encoding.
26  // Mask of bits that cause an encoding to be UNPREDICTABLE.
27  // If a bit is set, then if the corresponding bit in the
28  // target encoding differs from its value in the "Inst" field,
29  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
30  field bits<32> Unpredictable = 0;
31  // SoftFail is the generic name for this field, but we alias it so
32  // as to make it more obvious what it means in ARM-land.
33  field bits<32> SoftFail = Unpredictable;
34  let Namespace   = "AArch64";
35  Format F        = f;
36  bits<2> Form    = F.Value;
37  let Pattern     = [];
38  let Constraints = cstr;
39}
40
41class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
42  : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
43
44// Pseudo instructions (don't have encoding information)
45class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
46    : AArch64Inst<PseudoFrm, cstr> {
47  dag OutOperandList = oops;
48  dag InOperandList  = iops;
49  let Pattern        = pattern;
50  let isCodeGenOnly  = 1;
51}
52
53// Real instructions (have encoding information)
54class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
55  let Pattern = pattern;
56  let Size = 4;
57}
58
59// Enum describing whether an instruction is
60// destructive in its first source operand.
61class DestructiveInstTypeEnum<bits<1> val> {
62  bits<1> Value = val;
63}
64def NotDestructive  : DestructiveInstTypeEnum<0>;
65def Destructive     : DestructiveInstTypeEnum<1>;
66
67// Normal instructions
68class I<dag oops, dag iops, string asm, string operands, string cstr,
69        list<dag> pattern>
70    : EncodedI<cstr, pattern> {
71  dag OutOperandList = oops;
72  dag InOperandList  = iops;
73  let AsmString      = !strconcat(asm, operands);
74
75  // Destructive operations (SVE)
76  DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
77  ElementSizeEnum ElementSize = ElementSizeB;
78
79  let TSFlags{3} = DestructiveInstType.Value;
80  let TSFlags{2-0} = ElementSize.Value;
81}
82
83class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
84class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
85class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
86
87// Helper fragment for an extract of the high portion of a 128-bit vector.
88def extract_high_v16i8 :
89   UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
90def extract_high_v8i16 :
91   UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
92def extract_high_v4i32 :
93   UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
94def extract_high_v2i64 :
95   UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
96
97//===----------------------------------------------------------------------===//
98// Asm Operand Classes.
99//
100
101// Shifter operand for arithmetic shifted encodings.
102def ShifterOperand : AsmOperandClass {
103  let Name = "Shifter";
104}
105
106// Shifter operand for mov immediate encodings.
107def MovImm32ShifterOperand : AsmOperandClass {
108  let SuperClasses = [ShifterOperand];
109  let Name = "MovImm32Shifter";
110  let RenderMethod = "addShifterOperands";
111  let DiagnosticType = "InvalidMovImm32Shift";
112}
113def MovImm64ShifterOperand : AsmOperandClass {
114  let SuperClasses = [ShifterOperand];
115  let Name = "MovImm64Shifter";
116  let RenderMethod = "addShifterOperands";
117  let DiagnosticType = "InvalidMovImm64Shift";
118}
119
120// Shifter operand for arithmetic register shifted encodings.
121class ArithmeticShifterOperand<int width> : AsmOperandClass {
122  let SuperClasses = [ShifterOperand];
123  let Name = "ArithmeticShifter" # width;
124  let PredicateMethod = "isArithmeticShifter<" # width # ">";
125  let RenderMethod = "addShifterOperands";
126  let DiagnosticType = "AddSubRegShift" # width;
127}
128
129def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
130def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
131
132// Shifter operand for logical register shifted encodings.
133class LogicalShifterOperand<int width> : AsmOperandClass {
134  let SuperClasses = [ShifterOperand];
135  let Name = "LogicalShifter" # width;
136  let PredicateMethod = "isLogicalShifter<" # width # ">";
137  let RenderMethod = "addShifterOperands";
138  let DiagnosticType = "AddSubRegShift" # width;
139}
140
141def LogicalShifterOperand32 : LogicalShifterOperand<32>;
142def LogicalShifterOperand64 : LogicalShifterOperand<64>;
143
144// Shifter operand for logical vector 128/64-bit shifted encodings.
145def LogicalVecShifterOperand : AsmOperandClass {
146  let SuperClasses = [ShifterOperand];
147  let Name = "LogicalVecShifter";
148  let RenderMethod = "addShifterOperands";
149}
150def LogicalVecHalfWordShifterOperand : AsmOperandClass {
151  let SuperClasses = [LogicalVecShifterOperand];
152  let Name = "LogicalVecHalfWordShifter";
153  let RenderMethod = "addShifterOperands";
154}
155
156// The "MSL" shifter on the vector MOVI instruction.
157def MoveVecShifterOperand : AsmOperandClass {
158  let SuperClasses = [ShifterOperand];
159  let Name = "MoveVecShifter";
160  let RenderMethod = "addShifterOperands";
161}
162
163// Extend operand for arithmetic encodings.
164def ExtendOperand : AsmOperandClass {
165  let Name = "Extend";
166  let DiagnosticType = "AddSubRegExtendLarge";
167}
168def ExtendOperand64 : AsmOperandClass {
169  let SuperClasses = [ExtendOperand];
170  let Name = "Extend64";
171  let DiagnosticType = "AddSubRegExtendSmall";
172}
173// 'extend' that's a lsl of a 64-bit register.
174def ExtendOperandLSL64 : AsmOperandClass {
175  let SuperClasses = [ExtendOperand];
176  let Name = "ExtendLSL64";
177  let RenderMethod = "addExtend64Operands";
178  let DiagnosticType = "AddSubRegExtendLarge";
179}
180
181// 8-bit floating-point immediate encodings.
182def FPImmOperand : AsmOperandClass {
183  let Name = "FPImm";
184  let ParserMethod = "tryParseFPImm<true>";
185  let DiagnosticType = "InvalidFPImm";
186}
187
188def CondCode : AsmOperandClass {
189  let Name = "CondCode";
190  let DiagnosticType = "InvalidCondCode";
191}
192
193// A 32-bit register pasrsed as 64-bit
194def GPR32as64Operand : AsmOperandClass {
195  let Name = "GPR32as64";
196  let ParserMethod =
197      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
198}
199def GPR32as64 : RegisterOperand<GPR32> {
200  let ParserMatchClass = GPR32as64Operand;
201}
202
203// A 64-bit register pasrsed as 32-bit
204def GPR64as32Operand : AsmOperandClass {
205  let Name = "GPR64as32";
206  let ParserMethod =
207      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
208}
209def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
210  let ParserMatchClass = GPR64as32Operand;
211}
212
213// 8-bit immediate for AdvSIMD where 64-bit values of the form:
214// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
215// are encoded as the eight bit value 'abcdefgh'.
216def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
217
218class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
219  let Name = "UImm" # Width # "s" # Scale;
220  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
221  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
222  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
223}
224
225class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
226  let Name = "SImm" # Width # "s" # Scale;
227  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
228  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
229  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
230}
231
232//===----------------------------------------------------------------------===//
233// Operand Definitions.
234//
235
236// ADR[P] instruction labels.
237def AdrpOperand : AsmOperandClass {
238  let Name = "AdrpLabel";
239  let ParserMethod = "tryParseAdrpLabel";
240  let DiagnosticType = "InvalidLabel";
241}
242def adrplabel : Operand<i64> {
243  let EncoderMethod = "getAdrLabelOpValue";
244  let PrintMethod = "printAdrpLabel";
245  let ParserMatchClass = AdrpOperand;
246}
247
248def AdrOperand : AsmOperandClass {
249  let Name = "AdrLabel";
250  let ParserMethod = "tryParseAdrLabel";
251  let DiagnosticType = "InvalidLabel";
252}
253def adrlabel : Operand<i64> {
254  let EncoderMethod = "getAdrLabelOpValue";
255  let ParserMatchClass = AdrOperand;
256}
257
258class SImmOperand<int width> : AsmOperandClass {
259  let Name = "SImm" # width;
260  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
261  let RenderMethod = "addImmOperands";
262  let PredicateMethod = "isSImm<" # width # ">";
263}
264
265
266class AsmImmRange<int Low, int High> : AsmOperandClass {
267  let Name = "Imm" # Low # "_" # High;
268  let DiagnosticType = "InvalidImm" # Low # "_" # High;
269  let RenderMethod = "addImmOperands";
270  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
271}
272
273// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
274def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
275def simm10Scaled : Operand<i64> {
276  let ParserMatchClass = SImm10s8Operand;
277  let DecoderMethod = "DecodeSImm<10>";
278  let PrintMethod = "printImmScale<8>";
279}
280
281def simm9s16 : Operand<i64> {
282  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
283  let DecoderMethod = "DecodeSImm<9>";
284  let PrintMethod = "printImmScale<16>";
285}
286
287// uimm6 predicate - True if the immediate is in the range [0, 63].
288def UImm6Operand : AsmOperandClass {
289  let Name = "UImm6";
290  let DiagnosticType = "InvalidImm0_63";
291}
292
293def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
294  let ParserMatchClass = UImm6Operand;
295}
296
297def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
298  let ParserMatchClass = AsmImmRange<0, 65535>;
299}
300
301def SImm9Operand : SImmOperand<9>;
302def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
303  let ParserMatchClass = SImm9Operand;
304  let DecoderMethod = "DecodeSImm<9>";
305}
306
307def SImm8Operand : SImmOperand<8>;
308def simm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 127; }]> {
309  let ParserMatchClass = SImm8Operand;
310  let DecoderMethod = "DecodeSImm<8>";
311}
312
313def SImm6Operand : SImmOperand<6>;
314def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
315  let ParserMatchClass = SImm6Operand;
316  let DecoderMethod = "DecodeSImm<6>";
317}
318
319def SImm5Operand : SImmOperand<5>;
320def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
321  let ParserMatchClass = SImm5Operand;
322  let DecoderMethod = "DecodeSImm<5>";
323}
324
325def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
326  let ParserMatchClass = SImm5Operand;
327  let DecoderMethod = "DecodeSImm<5>";
328}
329
330// simm7sN predicate - True if the immediate is a multiple of N in the range
331// [-64 * N, 63 * N].
332
333def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
334def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
335def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
336
337def simm7s4 : Operand<i32> {
338  let ParserMatchClass = SImm7s4Operand;
339  let PrintMethod = "printImmScale<4>";
340}
341
342def simm7s8 : Operand<i32> {
343  let ParserMatchClass = SImm7s8Operand;
344  let PrintMethod = "printImmScale<8>";
345}
346
347def simm7s16 : Operand<i32> {
348  let ParserMatchClass = SImm7s16Operand;
349  let PrintMethod = "printImmScale<16>";
350}
351
352def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
353def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
354def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
355def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
356def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
357
358def am_indexedu6s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedU6S128", []>;
359def am_indexeds9s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedS9S128", []>;
360
361def UImmS2XForm : SDNodeXForm<imm, [{
362  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
363}]>;
364def UImmS4XForm : SDNodeXForm<imm, [{
365  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
366}]>;
367def UImmS8XForm : SDNodeXForm<imm, [{
368  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
369}]>;
370
371// uimm5sN predicate - True if the immediate is a multiple of N in the range
372// [0 * N, 32 * N].
373def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
374def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
375def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
376
377def uimm5s2 : Operand<i64>, ImmLeaf<i64,
378                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
379                UImmS2XForm> {
380  let ParserMatchClass = UImm5s2Operand;
381  let PrintMethod = "printImmScale<2>";
382}
383def uimm5s4 : Operand<i64>, ImmLeaf<i64,
384                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
385                UImmS4XForm> {
386  let ParserMatchClass = UImm5s4Operand;
387  let PrintMethod = "printImmScale<4>";
388}
389def uimm5s8 : Operand<i64>, ImmLeaf<i64,
390                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
391                UImmS8XForm> {
392  let ParserMatchClass = UImm5s8Operand;
393  let PrintMethod = "printImmScale<8>";
394}
395
396// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
397// instead of ImmLeaf (Constant)
398def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
399                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
400                UImmS2XForm> {
401  let ParserMatchClass = UImm5s2Operand;
402  let PrintMethod = "printImmScale<2>";
403}
404def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
405                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
406                UImmS4XForm> {
407  let ParserMatchClass = UImm5s4Operand;
408  let PrintMethod = "printImmScale<4>";
409}
410def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
411                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
412                UImmS8XForm> {
413  let ParserMatchClass = UImm5s8Operand;
414  let PrintMethod = "printImmScale<8>";
415}
416
417// uimm6sN predicate - True if the immediate is a multiple of N in the range
418// [0 * N, 64 * N].
419def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
420def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
421def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
422def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
423def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
424
425def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
426  let ParserMatchClass = UImm6s1Operand;
427}
428def uimm6s2 : Operand<i64>, ImmLeaf<i64,
429[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
430  let PrintMethod = "printImmScale<2>";
431  let ParserMatchClass = UImm6s2Operand;
432}
433def uimm6s4 : Operand<i64>, ImmLeaf<i64,
434[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
435  let PrintMethod = "printImmScale<4>";
436  let ParserMatchClass = UImm6s4Operand;
437}
438def uimm6s8 : Operand<i64>, ImmLeaf<i64,
439[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
440  let PrintMethod = "printImmScale<8>";
441  let ParserMatchClass = UImm6s8Operand;
442}
443def uimm6s16 : Operand<i64>, ImmLeaf<i64,
444[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
445  let PrintMethod = "printImmScale<16>";
446  let ParserMatchClass = UImm6s16Operand;
447}
448
449// simm6sN predicate - True if the immediate is a multiple of N in the range
450// [-32 * N, 31 * N].
451def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
452def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
453  let ParserMatchClass = SImm6s1Operand;
454  let DecoderMethod = "DecodeSImm<6>";
455}
456
457// simm4sN predicate - True if the immediate is a multiple of N in the range
458// [ -8* N, 7 * N].
459def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
460def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
461def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
462def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
463def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
464
465def simm4s1 : Operand<i64>, ImmLeaf<i64,
466[{ return Imm >=-8  && Imm <= 7; }]> {
467  let ParserMatchClass = SImm4s1Operand;
468  let DecoderMethod = "DecodeSImm<4>";
469}
470
471def simm4s2 : Operand<i64>, ImmLeaf<i64,
472[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }]> {
473  let PrintMethod = "printImmScale<2>";
474  let ParserMatchClass = SImm4s2Operand;
475  let DecoderMethod = "DecodeSImm<4>";
476}
477
478def simm4s3 : Operand<i64>, ImmLeaf<i64,
479[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }]> {
480  let PrintMethod = "printImmScale<3>";
481  let ParserMatchClass = SImm4s3Operand;
482  let DecoderMethod = "DecodeSImm<4>";
483}
484
485def simm4s4 : Operand<i64>, ImmLeaf<i64,
486[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }]> {
487  let PrintMethod = "printImmScale<4>";
488  let ParserMatchClass = SImm4s4Operand;
489  let DecoderMethod = "DecodeSImm<4>";
490}
491def simm4s16 : Operand<i64>, ImmLeaf<i64,
492[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }]> {
493  let PrintMethod = "printImmScale<16>";
494  let ParserMatchClass = SImm4s16Operand;
495  let DecoderMethod = "DecodeSImm<4>";
496}
497
498def Imm1_8Operand : AsmImmRange<1, 8>;
499def Imm1_16Operand : AsmImmRange<1, 16>;
500def Imm1_32Operand : AsmImmRange<1, 32>;
501def Imm1_64Operand : AsmImmRange<1, 64>;
502
503class BranchTarget<int N> : AsmOperandClass {
504  let Name = "BranchTarget" # N;
505  let DiagnosticType = "InvalidLabel";
506  let PredicateMethod = "isBranchTarget<" # N # ">";
507}
508
509class PCRelLabel<int N> : BranchTarget<N> {
510  let Name = "PCRelLabel" # N;
511}
512
513def BranchTarget14Operand : BranchTarget<14>;
514def BranchTarget26Operand : BranchTarget<26>;
515def PCRelLabel19Operand   : PCRelLabel<19>;
516
517def MovWSymbolG3AsmOperand : AsmOperandClass {
518  let Name = "MovWSymbolG3";
519  let RenderMethod = "addImmOperands";
520}
521
522def movw_symbol_g3 : Operand<i32> {
523  let ParserMatchClass = MovWSymbolG3AsmOperand;
524}
525
526def MovWSymbolG2AsmOperand : AsmOperandClass {
527  let Name = "MovWSymbolG2";
528  let RenderMethod = "addImmOperands";
529}
530
531def movw_symbol_g2 : Operand<i32> {
532  let ParserMatchClass = MovWSymbolG2AsmOperand;
533}
534
535def MovWSymbolG1AsmOperand : AsmOperandClass {
536  let Name = "MovWSymbolG1";
537  let RenderMethod = "addImmOperands";
538}
539
540def movw_symbol_g1 : Operand<i32> {
541  let ParserMatchClass = MovWSymbolG1AsmOperand;
542}
543
544def MovWSymbolG0AsmOperand : AsmOperandClass {
545  let Name = "MovWSymbolG0";
546  let RenderMethod = "addImmOperands";
547}
548
549def movw_symbol_g0 : Operand<i32> {
550  let ParserMatchClass = MovWSymbolG0AsmOperand;
551}
552
553class fixedpoint_i32<ValueType FloatVT>
554  : Operand<FloatVT>,
555    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
556  let EncoderMethod = "getFixedPointScaleOpValue";
557  let DecoderMethod = "DecodeFixedPointScaleImm32";
558  let ParserMatchClass = Imm1_32Operand;
559}
560
561class fixedpoint_i64<ValueType FloatVT>
562  : Operand<FloatVT>,
563    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
564  let EncoderMethod = "getFixedPointScaleOpValue";
565  let DecoderMethod = "DecodeFixedPointScaleImm64";
566  let ParserMatchClass = Imm1_64Operand;
567}
568
569def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
570def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
571def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
572
573def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
574def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
575def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
576
577def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
578  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
579}]> {
580  let EncoderMethod = "getVecShiftR8OpValue";
581  let DecoderMethod = "DecodeVecShiftR8Imm";
582  let ParserMatchClass = Imm1_8Operand;
583}
584def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
585  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
586}]> {
587  let EncoderMethod = "getVecShiftR16OpValue";
588  let DecoderMethod = "DecodeVecShiftR16Imm";
589  let ParserMatchClass = Imm1_16Operand;
590}
591def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
592  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
593}]> {
594  let EncoderMethod = "getVecShiftR16OpValue";
595  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
596  let ParserMatchClass = Imm1_8Operand;
597}
598def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
599  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
600}]> {
601  let EncoderMethod = "getVecShiftR32OpValue";
602  let DecoderMethod = "DecodeVecShiftR32Imm";
603  let ParserMatchClass = Imm1_32Operand;
604}
605def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
606  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
607}]> {
608  let EncoderMethod = "getVecShiftR32OpValue";
609  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
610  let ParserMatchClass = Imm1_16Operand;
611}
612def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
613  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
614}]> {
615  let EncoderMethod = "getVecShiftR64OpValue";
616  let DecoderMethod = "DecodeVecShiftR64Imm";
617  let ParserMatchClass = Imm1_64Operand;
618}
619def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
620  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
621}]> {
622  let EncoderMethod = "getVecShiftR64OpValue";
623  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
624  let ParserMatchClass = Imm1_32Operand;
625}
626
627// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
628// (ImmLeaf)
629def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
630  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
631}]> {
632  let EncoderMethod = "getVecShiftR8OpValue";
633  let DecoderMethod = "DecodeVecShiftR8Imm";
634  let ParserMatchClass = Imm1_8Operand;
635}
636def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
637  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
638}]> {
639  let EncoderMethod = "getVecShiftR16OpValue";
640  let DecoderMethod = "DecodeVecShiftR16Imm";
641  let ParserMatchClass = Imm1_16Operand;
642}
643def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
644  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
645}]> {
646  let EncoderMethod = "getVecShiftR32OpValue";
647  let DecoderMethod = "DecodeVecShiftR32Imm";
648  let ParserMatchClass = Imm1_32Operand;
649}
650
651def Imm0_1Operand : AsmImmRange<0, 1>;
652def Imm0_7Operand : AsmImmRange<0, 7>;
653def Imm0_15Operand : AsmImmRange<0, 15>;
654def Imm0_31Operand : AsmImmRange<0, 31>;
655def Imm0_63Operand : AsmImmRange<0, 63>;
656
657def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
658  return (((uint32_t)Imm) < 8);
659}]> {
660  let EncoderMethod = "getVecShiftL8OpValue";
661  let DecoderMethod = "DecodeVecShiftL8Imm";
662  let ParserMatchClass = Imm0_7Operand;
663}
664def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
665  return (((uint32_t)Imm) < 16);
666}]> {
667  let EncoderMethod = "getVecShiftL16OpValue";
668  let DecoderMethod = "DecodeVecShiftL16Imm";
669  let ParserMatchClass = Imm0_15Operand;
670}
671def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
672  return (((uint32_t)Imm) < 32);
673}]> {
674  let EncoderMethod = "getVecShiftL32OpValue";
675  let DecoderMethod = "DecodeVecShiftL32Imm";
676  let ParserMatchClass = Imm0_31Operand;
677}
678def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
679  return (((uint32_t)Imm) < 64);
680}]> {
681  let EncoderMethod = "getVecShiftL64OpValue";
682  let DecoderMethod = "DecodeVecShiftL64Imm";
683  let ParserMatchClass = Imm0_63Operand;
684}
685
686
687// Crazy immediate formats used by 32-bit and 64-bit logical immediate
688// instructions for splatting repeating bit patterns across the immediate.
689def logical_imm32_XFORM : SDNodeXForm<imm, [{
690  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
691  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
692}]>;
693def logical_imm64_XFORM : SDNodeXForm<imm, [{
694  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
695  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
696}]>;
697
698def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
699  GISDNodeXFormEquiv<logical_imm32_XFORM>;
700def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
701  GISDNodeXFormEquiv<logical_imm64_XFORM>;
702
703let DiagnosticType = "LogicalSecondSource" in {
704  def LogicalImm32Operand : AsmOperandClass {
705    let Name = "LogicalImm32";
706    let PredicateMethod = "isLogicalImm<int32_t>";
707    let RenderMethod = "addLogicalImmOperands<int32_t>";
708  }
709  def LogicalImm64Operand : AsmOperandClass {
710    let Name = "LogicalImm64";
711    let PredicateMethod = "isLogicalImm<int64_t>";
712    let RenderMethod = "addLogicalImmOperands<int64_t>";
713  }
714  def LogicalImm32NotOperand : AsmOperandClass {
715    let Name = "LogicalImm32Not";
716    let PredicateMethod = "isLogicalImm<int32_t>";
717    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
718  }
719  def LogicalImm64NotOperand : AsmOperandClass {
720    let Name = "LogicalImm64Not";
721    let PredicateMethod = "isLogicalImm<int64_t>";
722    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
723  }
724}
725def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
726  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
727}], logical_imm32_XFORM> {
728  let PrintMethod = "printLogicalImm<int32_t>";
729  let ParserMatchClass = LogicalImm32Operand;
730}
731def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
732  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
733}], logical_imm64_XFORM> {
734  let PrintMethod = "printLogicalImm<int64_t>";
735  let ParserMatchClass = LogicalImm64Operand;
736}
737def logical_imm32_not : Operand<i32> {
738  let ParserMatchClass = LogicalImm32NotOperand;
739}
740def logical_imm64_not : Operand<i64> {
741  let ParserMatchClass = LogicalImm64NotOperand;
742}
743
744// iXX_imm0_65535 predicates - True if the immediate is in the range [0,65535].
745let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
746def i32_imm0_65535 : Operand<i32>, TImmLeaf<i32, [{
747  return ((uint32_t)Imm) < 65536;
748}]>;
749
750def i64_imm0_65535 : Operand<i64>, TImmLeaf<i64, [{
751  return ((uint64_t)Imm) < 65536;
752}]>;
753}
754
755// imm0_255 predicate - True if the immediate is in the range [0,255].
756def Imm0_255Operand : AsmImmRange<0,255>;
757
758def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
759  return ((uint32_t)Imm) < 256;
760}]> {
761  let ParserMatchClass = Imm0_255Operand;
762  let PrintMethod = "printImm";
763}
764
765// imm0_127 predicate - True if the immediate is in the range [0,127]
766def Imm0_127Operand : AsmImmRange<0, 127>;
767def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
768  return ((uint32_t)Imm) < 128;
769}]> {
770  let ParserMatchClass = Imm0_127Operand;
771  let PrintMethod = "printImm";
772}
773
774def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
775  return ((uint64_t)Imm) < 128;
776}]> {
777  let ParserMatchClass = Imm0_127Operand;
778  let PrintMethod = "printImm";
779}
780
781// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
782// for all shift-amounts.
783
784// imm0_63 predicate - True if the immediate is in the range [0,63]
785def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
786  return ((uint64_t)Imm) < 64;
787}]> {
788  let ParserMatchClass = Imm0_63Operand;
789}
790
791// imm0_31 predicate - True if the immediate is in the range [0,31]
792def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
793  return ((uint64_t)Imm) < 32;
794}]> {
795  let ParserMatchClass = Imm0_31Operand;
796}
797
798// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
799// instead of Contant (ImmLeaf)
800def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
801  return ((uint64_t)Imm) < 32;
802}]> {
803  let ParserMatchClass = Imm0_31Operand;
804}
805
806// True if the 32-bit immediate is in the range [0,31]
807def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
808  return ((uint64_t)Imm) < 32;
809}]> {
810  let ParserMatchClass = Imm0_31Operand;
811}
812
813// imm0_1 predicate - True if the immediate is in the range [0,1]
814def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
815  return ((uint64_t)Imm) < 2;
816}]> {
817  let ParserMatchClass = Imm0_1Operand;
818}
819
820// imm0_15 predicate - True if the immediate is in the range [0,15]
821def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
822  return ((uint64_t)Imm) < 16;
823}]> {
824  let ParserMatchClass = Imm0_15Operand;
825}
826
827// imm0_7 predicate - True if the immediate is in the range [0,7]
828def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
829  return ((uint64_t)Imm) < 8;
830}]> {
831  let ParserMatchClass = Imm0_7Operand;
832}
833
834// imm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
835def imm32_0_7 : Operand<i32>, ImmLeaf<i32, [{
836  return ((uint32_t)Imm) < 8;
837}]> {
838  let ParserMatchClass = Imm0_7Operand;
839}
840
841// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
842def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
843  return ((uint32_t)Imm) < 16;
844}]> {
845  let ParserMatchClass = Imm0_15Operand;
846}
847
848// An arithmetic shifter operand:
849//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
850//  {5-0} - imm6
851class arith_shift<ValueType Ty, int width> : Operand<Ty> {
852  let PrintMethod = "printShifter";
853  let ParserMatchClass = !cast<AsmOperandClass>(
854                         "ArithmeticShifterOperand" # width);
855}
856
857def arith_shift32 : arith_shift<i32, 32>;
858def arith_shift64 : arith_shift<i64, 64>;
859
860class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
861    : Operand<Ty>,
862      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
863  let PrintMethod = "printShiftedRegister";
864  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
865}
866
867def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
868def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
869
870def gi_arith_shifted_reg32 :
871  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
872  GIComplexPatternEquiv<arith_shifted_reg32>;
873
874def gi_arith_shifted_reg64 :
875  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
876  GIComplexPatternEquiv<arith_shifted_reg64>;
877
878// An arithmetic shifter operand:
879//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
880//  {5-0} - imm6
881class logical_shift<int width> : Operand<i32> {
882  let PrintMethod = "printShifter";
883  let ParserMatchClass = !cast<AsmOperandClass>(
884                         "LogicalShifterOperand" # width);
885}
886
887def logical_shift32 : logical_shift<32>;
888def logical_shift64 : logical_shift<64>;
889
890class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
891    : Operand<Ty>,
892      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
893  let PrintMethod = "printShiftedRegister";
894  let MIOperandInfo = (ops regclass, shiftop);
895}
896
897def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
898def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
899
900def gi_logical_shifted_reg32 :
901  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
902  GIComplexPatternEquiv<logical_shifted_reg32>;
903
904def gi_logical_shifted_reg64 :
905  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
906  GIComplexPatternEquiv<logical_shifted_reg64>;
907
908// A logical vector shifter operand:
909//  {7-6} - shift type: 00 = lsl
910//  {5-0} - imm6: #0, #8, #16, or #24
911def logical_vec_shift : Operand<i32> {
912  let PrintMethod = "printShifter";
913  let EncoderMethod = "getVecShifterOpValue";
914  let ParserMatchClass = LogicalVecShifterOperand;
915}
916
917// A logical vector half-word shifter operand:
918//  {7-6} - shift type: 00 = lsl
919//  {5-0} - imm6: #0 or #8
920def logical_vec_hw_shift : Operand<i32> {
921  let PrintMethod = "printShifter";
922  let EncoderMethod = "getVecShifterOpValue";
923  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
924}
925
926// A vector move shifter operand:
927//  {0} - imm1: #8 or #16
928def move_vec_shift : Operand<i32> {
929  let PrintMethod = "printShifter";
930  let EncoderMethod = "getMoveVecShifterOpValue";
931  let ParserMatchClass = MoveVecShifterOperand;
932}
933
934let DiagnosticType = "AddSubSecondSource" in {
935  def AddSubImmOperand : AsmOperandClass {
936    let Name = "AddSubImm";
937    let ParserMethod = "tryParseImmWithOptionalShift";
938    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
939  }
940  def AddSubImmNegOperand : AsmOperandClass {
941    let Name = "AddSubImmNeg";
942    let ParserMethod = "tryParseImmWithOptionalShift";
943    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
944  }
945}
946// An ADD/SUB immediate shifter operand:
947//  second operand:
948//  {7-6} - shift type: 00 = lsl
949//  {5-0} - imm6: #0 or #12
950class addsub_shifted_imm<ValueType Ty>
951    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
952  let PrintMethod = "printAddSubImm";
953  let EncoderMethod = "getAddSubImmOpValue";
954  let ParserMatchClass = AddSubImmOperand;
955  let MIOperandInfo = (ops i32imm, i32imm);
956}
957
958class addsub_shifted_imm_neg<ValueType Ty>
959    : Operand<Ty> {
960  let EncoderMethod = "getAddSubImmOpValue";
961  let ParserMatchClass = AddSubImmNegOperand;
962  let MIOperandInfo = (ops i32imm, i32imm);
963}
964
965def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
966def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
967def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
968def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
969
970def gi_addsub_shifted_imm32 :
971    GIComplexOperandMatcher<s32, "selectArithImmed">,
972    GIComplexPatternEquiv<addsub_shifted_imm32>;
973
974def gi_addsub_shifted_imm64 :
975    GIComplexOperandMatcher<s64, "selectArithImmed">,
976    GIComplexPatternEquiv<addsub_shifted_imm64>;
977
978class neg_addsub_shifted_imm<ValueType Ty>
979    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
980  let PrintMethod = "printAddSubImm";
981  let EncoderMethod = "getAddSubImmOpValue";
982  let ParserMatchClass = AddSubImmOperand;
983  let MIOperandInfo = (ops i32imm, i32imm);
984}
985
986def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
987def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
988
989def gi_neg_addsub_shifted_imm32 :
990    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
991    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
992
993def gi_neg_addsub_shifted_imm64 :
994    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
995    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
996
997// An extend operand:
998//  {5-3} - extend type
999//  {2-0} - imm3
1000def arith_extend : Operand<i32> {
1001  let PrintMethod = "printArithExtend";
1002  let ParserMatchClass = ExtendOperand;
1003}
1004def arith_extend64 : Operand<i32> {
1005  let PrintMethod = "printArithExtend";
1006  let ParserMatchClass = ExtendOperand64;
1007}
1008
1009// 'extend' that's a lsl of a 64-bit register.
1010def arith_extendlsl64 : Operand<i32> {
1011  let PrintMethod = "printArithExtend";
1012  let ParserMatchClass = ExtendOperandLSL64;
1013}
1014
1015class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1016                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1017  let PrintMethod = "printExtendedRegister";
1018  let MIOperandInfo = (ops GPR32, arith_extend);
1019}
1020
1021class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1022                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1023  let PrintMethod = "printExtendedRegister";
1024  let MIOperandInfo = (ops GPR32, arith_extend64);
1025}
1026
1027def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1028def gi_arith_extended_reg32_i32 :
1029    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1030    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1031
1032def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1033def gi_arith_extended_reg32_i64 :
1034    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1035    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1036
1037def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1038def gi_arith_extended_reg32to64_i64 :
1039    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1040    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1041
1042// Floating-point immediate.
1043def fpimm16 : Operand<f16>,
1044              FPImmLeaf<f16, [{
1045      return AArch64_AM::getFP16Imm(Imm) != -1;
1046    }], SDNodeXForm<fpimm, [{
1047      APFloat InVal = N->getValueAPF();
1048      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1049      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1050    }]>> {
1051  let ParserMatchClass = FPImmOperand;
1052  let PrintMethod = "printFPImmOperand";
1053}
1054def fpimm32 : Operand<f32>,
1055              FPImmLeaf<f32, [{
1056      return AArch64_AM::getFP32Imm(Imm) != -1;
1057    }], SDNodeXForm<fpimm, [{
1058      APFloat InVal = N->getValueAPF();
1059      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1060      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1061    }]>> {
1062  let ParserMatchClass = FPImmOperand;
1063  let PrintMethod = "printFPImmOperand";
1064}
1065def fpimm64 : Operand<f64>,
1066              FPImmLeaf<f64, [{
1067      return AArch64_AM::getFP64Imm(Imm) != -1;
1068    }], SDNodeXForm<fpimm, [{
1069      APFloat InVal = N->getValueAPF();
1070      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1071      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1072    }]>> {
1073  let ParserMatchClass = FPImmOperand;
1074  let PrintMethod = "printFPImmOperand";
1075}
1076
1077def fpimm8 : Operand<i32> {
1078  let ParserMatchClass = FPImmOperand;
1079  let PrintMethod = "printFPImmOperand";
1080}
1081
1082def fpimm0 : FPImmLeaf<fAny, [{
1083  return Imm.isExactlyValue(+0.0);
1084}]>;
1085
1086// Vector lane operands
1087class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1088  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1089  let DiagnosticType = "Invalid" # Name;
1090  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1091  let RenderMethod = "addVectorIndexOperands";
1092}
1093
1094class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc, code pred>
1095    : Operand<ty>, ImmLeaf<ty, pred> {
1096  let ParserMatchClass = mc;
1097  let PrintMethod = "printVectorIndex";
1098}
1099
1100def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1101def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1102def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1103def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1104def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1105
1106def VectorIndex1 : AsmVectorIndexOpnd<i64, VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
1107def VectorIndexB : AsmVectorIndexOpnd<i64, VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1108def VectorIndexH : AsmVectorIndexOpnd<i64, VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1109def VectorIndexS : AsmVectorIndexOpnd<i64, VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1110def VectorIndexD : AsmVectorIndexOpnd<i64, VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
1111
1112def VectorIndex132b : AsmVectorIndexOpnd<i32, VectorIndex1Operand, [{ return ((uint64_t)Imm) == 1; }]>;
1113def VectorIndexB32b : AsmVectorIndexOpnd<i32, VectorIndexBOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1114def VectorIndexH32b : AsmVectorIndexOpnd<i32, VectorIndexHOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1115def VectorIndexS32b : AsmVectorIndexOpnd<i32, VectorIndexSOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1116def VectorIndexD32b : AsmVectorIndexOpnd<i32, VectorIndexDOperand, [{ return ((uint64_t)Imm) < 2; }]>;
1117
1118def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1119def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1120def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1121def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1122def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1123
1124def sve_elm_idx_extdup_b
1125  : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupBOperand, [{ return ((uint64_t)Imm) < 64; }]>;
1126def sve_elm_idx_extdup_h
1127  : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupHOperand, [{ return ((uint64_t)Imm) < 32; }]>;
1128def sve_elm_idx_extdup_s
1129  : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupSOperand, [{ return ((uint64_t)Imm) < 16; }]>;
1130def sve_elm_idx_extdup_d
1131  : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupDOperand, [{ return ((uint64_t)Imm) < 8; }]>;
1132def sve_elm_idx_extdup_q
1133  : AsmVectorIndexOpnd<i64, SVEVectorIndexExtDupQOperand, [{ return ((uint64_t)Imm) < 4; }]>;
1134
1135// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1136// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1137// are encoded as the eight bit value 'abcdefgh'.
1138def simdimmtype10 : Operand<i32>,
1139                    FPImmLeaf<f64, [{
1140      return AArch64_AM::isAdvSIMDModImmType10(
1141                 Imm.bitcastToAPInt().getZExtValue());
1142    }], SDNodeXForm<fpimm, [{
1143      APFloat InVal = N->getValueAPF();
1144      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1145                                                           .bitcastToAPInt()
1146                                                           .getZExtValue());
1147      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1148    }]>> {
1149  let ParserMatchClass = SIMDImmType10Operand;
1150  let PrintMethod = "printSIMDType10Operand";
1151}
1152
1153
1154//---
1155// System management
1156//---
1157
1158// Base encoding for system instruction operands.
1159let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1160class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1161                  list<dag> pattern = []>
1162    : I<oops, iops, asm, operands, "", pattern> {
1163  let Inst{31-22} = 0b1101010100;
1164  let Inst{21}    = L;
1165}
1166
1167// System instructions which do not have an Rt register.
1168class SimpleSystemI<bit L, dag iops, string asm, string operands,
1169                    list<dag> pattern = []>
1170    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1171  let Inst{4-0} = 0b11111;
1172}
1173
1174// System instructions which have an Rt register.
1175class RtSystemI<bit L, dag oops, dag iops, string asm, string operands>
1176    : BaseSystemI<L, oops, iops, asm, operands>,
1177      Sched<[WriteSys]> {
1178  bits<5> Rt;
1179  let Inst{4-0} = Rt;
1180}
1181
1182// System instructions for transactional memory extension
1183class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1184                    string asm, string operands, list<dag> pattern>
1185    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1186      Sched<[WriteSys]> {
1187  let Inst{20-12} = 0b000110011;
1188  let Inst{11-8} = CRm;
1189  let Inst{7-5} = op2;
1190  let DecoderMethod = "";
1191
1192  let mayLoad = 1;
1193  let mayStore = 1;
1194}
1195
1196// System instructions for transactional memory - single input operand
1197class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1198    : TMBaseSystemI<0b1, CRm, 0b011,
1199                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1200  bits<5> Rt;
1201  let Inst{4-0} = Rt;
1202}
1203
1204// System instructions for transactional memory - no operand
1205class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1206    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1207  let Inst{4-0} = 0b11111;
1208}
1209
1210// System instructions for exit from transactions
1211class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1212    : I<(outs), (ins i64_imm0_65535:$imm), asm, "\t$imm", "", pattern>,
1213      Sched<[WriteSys]> {
1214  bits<16> imm;
1215  let Inst{31-24} = 0b11010100;
1216  let Inst{23-21} = op1;
1217  let Inst{20-5}  = imm;
1218  let Inst{4-0}   = 0b00000;
1219}
1220
1221// Hint instructions that take both a CRm and a 3-bit immediate.
1222// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1223// model patterns with sufficiently fine granularity
1224let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1225  class HintI<string mnemonic>
1226      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1227                      [(int_aarch64_hint imm0_127:$imm)]>,
1228        Sched<[WriteHint]> {
1229    bits <7> imm;
1230    let Inst{20-12} = 0b000110010;
1231    let Inst{11-5} = imm;
1232  }
1233
1234// System instructions taking a single literal operand which encodes into
1235// CRm. op2 differentiates the opcodes.
1236def BarrierAsmOperand : AsmOperandClass {
1237  let Name = "Barrier";
1238  let ParserMethod = "tryParseBarrierOperand";
1239}
1240def barrier_op : Operand<i32> {
1241  let PrintMethod = "printBarrierOption";
1242  let ParserMatchClass = BarrierAsmOperand;
1243}
1244class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1245                 list<dag> pattern = []>
1246    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1247      Sched<[WriteBarrier]> {
1248  bits<4> CRm;
1249  let Inst{20-12} = 0b000110011;
1250  let Inst{11-8} = CRm;
1251  let Inst{7-5} = opc;
1252}
1253
1254class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1255    : SimpleSystemI<0, (ins), asm, "", pattern>,
1256      Sched<[]> {
1257  bits<4> CRm;
1258  let CRm = 0b0011;
1259  let Inst{31-12} = 0b11010101000000110010;
1260  let Inst{11-8} = CRm;
1261  let Inst{7-5} = op2;
1262  let Inst{4-0} = 0b11111;
1263}
1264
1265// MRS/MSR system instructions. These have different operand classes because
1266// a different subset of registers can be accessed through each instruction.
1267def MRSSystemRegisterOperand : AsmOperandClass {
1268  let Name = "MRSSystemRegister";
1269  let ParserMethod = "tryParseSysReg";
1270  let DiagnosticType = "MRS";
1271}
1272// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1273def mrs_sysreg_op : Operand<i32> {
1274  let ParserMatchClass = MRSSystemRegisterOperand;
1275  let DecoderMethod = "DecodeMRSSystemRegister";
1276  let PrintMethod = "printMRSSystemRegister";
1277}
1278
1279def MSRSystemRegisterOperand : AsmOperandClass {
1280  let Name = "MSRSystemRegister";
1281  let ParserMethod = "tryParseSysReg";
1282  let DiagnosticType = "MSR";
1283}
1284def msr_sysreg_op : Operand<i32> {
1285  let ParserMatchClass = MSRSystemRegisterOperand;
1286  let DecoderMethod = "DecodeMSRSystemRegister";
1287  let PrintMethod = "printMSRSystemRegister";
1288}
1289
1290def PSBHintOperand : AsmOperandClass {
1291  let Name = "PSBHint";
1292  let ParserMethod = "tryParsePSBHint";
1293}
1294def psbhint_op : Operand<i32> {
1295  let ParserMatchClass = PSBHintOperand;
1296  let PrintMethod = "printPSBHintOp";
1297  let MCOperandPredicate = [{
1298    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1299    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1300    if (!MCOp.isImm())
1301      return false;
1302    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1303  }];
1304}
1305
1306def BTIHintOperand : AsmOperandClass {
1307  let Name = "BTIHint";
1308  let ParserMethod = "tryParseBTIHint";
1309}
1310def btihint_op : Operand<i32> {
1311  let ParserMatchClass = BTIHintOperand;
1312  let PrintMethod = "printBTIHintOp";
1313  let MCOperandPredicate = [{
1314    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1315    if (!MCOp.isImm())
1316      return false;
1317    return AArch64BTIHint::lookupBTIByEncoding((MCOp.getImm() ^ 32) >> 1) != nullptr;
1318  }];
1319}
1320
1321class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1322                       "mrs", "\t$Rt, $systemreg"> {
1323  bits<16> systemreg;
1324  let Inst{20-5} = systemreg;
1325}
1326
1327// FIXME: Some of these def NZCV, others don't. Best way to model that?
1328// Explicitly modeling each of the system register as a register class
1329// would do it, but feels like overkill at this point.
1330class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1331                       "msr", "\t$systemreg, $Rt"> {
1332  bits<16> systemreg;
1333  let Inst{20-5} = systemreg;
1334}
1335
1336def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1337  let Name = "SystemPStateFieldWithImm0_15";
1338  let ParserMethod = "tryParseSysReg";
1339}
1340def pstatefield4_op : Operand<i32> {
1341  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1342  let PrintMethod = "printSystemPStateField";
1343}
1344
1345// Instructions to modify PSTATE, no input reg
1346let Defs = [NZCV] in
1347class PstateWriteSimple<dag iops, string asm, string operands>
1348  : SimpleSystemI<0, iops, asm, operands> {
1349
1350  let Inst{20-19} = 0b00;
1351  let Inst{15-12} = 0b0100;
1352}
1353
1354class MSRpstateImm0_15
1355  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1356                  "\t$pstatefield, $imm">,
1357    Sched<[WriteSys]> {
1358
1359  bits<6> pstatefield;
1360  bits<4> imm;
1361  let Inst{18-16} = pstatefield{5-3};
1362  let Inst{11-8} = imm;
1363  let Inst{7-5} = pstatefield{2-0};
1364
1365  let DecoderMethod = "DecodeSystemPStateInstruction";
1366  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1367  // Fail the decoder should attempt to decode the instruction as MSRI.
1368  let hasCompleteDecoder = 0;
1369}
1370
1371def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1372  let Name = "SystemPStateFieldWithImm0_1";
1373  let ParserMethod = "tryParseSysReg";
1374}
1375def pstatefield1_op : Operand<i32> {
1376  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1377  let PrintMethod = "printSystemPStateField";
1378}
1379
1380class MSRpstateImm0_1
1381  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1382                 "\t$pstatefield, $imm">,
1383    Sched<[WriteSys]> {
1384
1385  bits<6> pstatefield;
1386  bit imm;
1387  let Inst{18-16} = pstatefield{5-3};
1388  let Inst{11-9} = 0b000;
1389  let Inst{8} = imm;
1390  let Inst{7-5} = pstatefield{2-0};
1391
1392  let DecoderMethod = "DecodeSystemPStateInstruction";
1393  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1394  // Fail the decoder should attempt to decode the instruction as MSRI.
1395  let hasCompleteDecoder = 0;
1396}
1397
1398// SYS and SYSL generic system instructions.
1399def SysCRAsmOperand : AsmOperandClass {
1400  let Name = "SysCR";
1401  let ParserMethod = "tryParseSysCROperand";
1402}
1403
1404def sys_cr_op : Operand<i32> {
1405  let PrintMethod = "printSysCROperand";
1406  let ParserMatchClass = SysCRAsmOperand;
1407}
1408
1409class SystemXtI<bit L, string asm>
1410  : RtSystemI<L, (outs),
1411       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1412       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1413  bits<3> op1;
1414  bits<4> Cn;
1415  bits<4> Cm;
1416  bits<3> op2;
1417  let Inst{20-19} = 0b01;
1418  let Inst{18-16} = op1;
1419  let Inst{15-12} = Cn;
1420  let Inst{11-8}  = Cm;
1421  let Inst{7-5}   = op2;
1422}
1423
1424class SystemLXtI<bit L, string asm>
1425  : RtSystemI<L, (outs),
1426       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1427       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1428  bits<3> op1;
1429  bits<4> Cn;
1430  bits<4> Cm;
1431  bits<3> op2;
1432  let Inst{20-19} = 0b01;
1433  let Inst{18-16} = op1;
1434  let Inst{15-12} = Cn;
1435  let Inst{11-8}  = Cm;
1436  let Inst{7-5}   = op2;
1437}
1438
1439
1440// Branch (register) instructions:
1441//
1442//  case opc of
1443//    0001 blr
1444//    0000 br
1445//    0101 dret
1446//    0100 eret
1447//    0010 ret
1448//    otherwise UNDEFINED
1449class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1450                    string operands, list<dag> pattern>
1451    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1452  let Inst{31-25} = 0b1101011;
1453  let Inst{24-21} = opc;
1454  let Inst{20-16} = 0b11111;
1455  let Inst{15-10} = 0b000000;
1456  let Inst{4-0}   = 0b00000;
1457}
1458
1459class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1460    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1461  bits<5> Rn;
1462  let Inst{9-5} = Rn;
1463}
1464
1465let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1466class SpecialReturn<bits<4> opc, string asm>
1467    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1468  let Inst{9-5} = 0b11111;
1469}
1470
1471let mayLoad = 1 in
1472class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1473  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1474  Sched<[]> {
1475  bits<5> Rn;
1476  bits<5> Rt;
1477  let Inst{31-30} = sz;
1478  let Inst{29-10} = 0b11100010111111110000;
1479  let Inst{9-5} = Rn;
1480  let Inst{4-0} = Rt;
1481}
1482
1483class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1484               list<dag> pattern>
1485  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1486  let isAuthenticated = 1;
1487  let Inst{31-25} = 0b1101011;
1488  let Inst{20-11} = 0b1111100001;
1489  let Inst{10} = M;
1490  let Inst{4-0} = 0b11111;
1491}
1492
1493class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1494  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1495  bits<5> Rn;
1496  bits<5> Rm;
1497  let Inst{24-22} = 0b100;
1498  let Inst{21} = op;
1499  let Inst{9-5} = Rn;
1500  let Inst{4-0} = Rm;
1501}
1502
1503class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1504  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1505  bits<5> Rn;
1506  let Inst{24} = 0;
1507  let Inst{23-21} = opc;
1508  let Inst{9-5} = Rn;
1509}
1510
1511let Uses = [LR,SP] in
1512class AuthReturn<bits<3> op, bits<1> M, string asm>
1513  : AuthBase<M, (outs), (ins), asm, "", []> {
1514  let Inst{24} = 0;
1515  let Inst{23-21} = op;
1516  let Inst{9-0} = 0b1111111111;
1517}
1518
1519let mayLoad = 1 in
1520class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1521                   string operands, string cstr, Operand opr>
1522  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1523  bits<10> offset;
1524  bits<5> Rn;
1525  bits<5> Rt;
1526  let isAuthenticated = 1;
1527  let Inst{31-24} = 0b11111000;
1528  let Inst{23} = M;
1529  let Inst{22} = offset{9};
1530  let Inst{21} = 1;
1531  let Inst{20-12} = offset{8-0};
1532  let Inst{11} = W;
1533  let Inst{10} = 1;
1534  let Inst{9-5} = Rn;
1535  let Inst{4-0} = Rt;
1536}
1537
1538multiclass AuthLoad<bit M, string asm, Operand opr> {
1539  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1540                               (ins GPR64sp:$Rn, opr:$offset),
1541                               asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1542  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1543                               (ins GPR64sp:$Rn, opr:$offset),
1544                               asm, "\t$Rt, [$Rn, $offset]!",
1545                               "$Rn = $wback,@earlyclobber $wback", opr>;
1546
1547  def : InstAlias<asm # "\t$Rt, [$Rn]",
1548                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1549
1550  def : InstAlias<asm # "\t$Rt, [$wback]!",
1551                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1552}
1553
1554//---
1555// Conditional branch instruction.
1556//---
1557
1558// Condition code.
1559// 4-bit immediate. Pretty-printed as <cc>
1560def ccode : Operand<i32> {
1561  let PrintMethod = "printCondCode";
1562  let ParserMatchClass = CondCode;
1563}
1564def inv_ccode : Operand<i32> {
1565  // AL and NV are invalid in the aliases which use inv_ccode
1566  let PrintMethod = "printInverseCondCode";
1567  let ParserMatchClass = CondCode;
1568  let MCOperandPredicate = [{
1569    return MCOp.isImm() &&
1570           MCOp.getImm() != AArch64CC::AL &&
1571           MCOp.getImm() != AArch64CC::NV;
1572  }];
1573}
1574
1575// Conditional branch target. 19-bit immediate. The low two bits of the target
1576// offset are implied zero and so are not part of the immediate.
1577def am_brcond : Operand<OtherVT> {
1578  let EncoderMethod = "getCondBranchTargetOpValue";
1579  let DecoderMethod = "DecodePCRelLabel19";
1580  let PrintMethod = "printAlignedLabel";
1581  let ParserMatchClass = PCRelLabel19Operand;
1582  let OperandType = "OPERAND_PCREL";
1583}
1584
1585class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1586                     "b", ".$cond\t$target", "",
1587                     [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1588                   Sched<[WriteBr]> {
1589  let isBranch = 1;
1590  let isTerminator = 1;
1591  let Uses = [NZCV];
1592
1593  bits<4> cond;
1594  bits<19> target;
1595  let Inst{31-24} = 0b01010100;
1596  let Inst{23-5} = target;
1597  let Inst{4} = 0;
1598  let Inst{3-0} = cond;
1599}
1600
1601//---
1602// Compare-and-branch instructions.
1603//---
1604class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1605    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1606         asm, "\t$Rt, $target", "",
1607         [(node regtype:$Rt, bb:$target)]>,
1608      Sched<[WriteBr]> {
1609  let isBranch = 1;
1610  let isTerminator = 1;
1611
1612  bits<5> Rt;
1613  bits<19> target;
1614  let Inst{30-25} = 0b011010;
1615  let Inst{24}    = op;
1616  let Inst{23-5}  = target;
1617  let Inst{4-0}   = Rt;
1618}
1619
1620multiclass CmpBranch<bit op, string asm, SDNode node> {
1621  def W : BaseCmpBranch<GPR32, op, asm, node> {
1622    let Inst{31} = 0;
1623  }
1624  def X : BaseCmpBranch<GPR64, op, asm, node> {
1625    let Inst{31} = 1;
1626  }
1627}
1628
1629//---
1630// Test-bit-and-branch instructions.
1631//---
1632// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1633// the target offset are implied zero and so are not part of the immediate.
1634def am_tbrcond : Operand<OtherVT> {
1635  let EncoderMethod = "getTestBranchTargetOpValue";
1636  let PrintMethod = "printAlignedLabel";
1637  let ParserMatchClass = BranchTarget14Operand;
1638  let OperandType = "OPERAND_PCREL";
1639}
1640
1641// AsmOperand classes to emit (or not) special diagnostics
1642def TBZImm0_31Operand : AsmOperandClass {
1643  let Name = "TBZImm0_31";
1644  let PredicateMethod = "isImmInRange<0,31>";
1645  let RenderMethod = "addImmOperands";
1646}
1647def TBZImm32_63Operand : AsmOperandClass {
1648  let Name = "Imm32_63";
1649  let PredicateMethod = "isImmInRange<32,63>";
1650  let DiagnosticType = "InvalidImm0_63";
1651  let RenderMethod = "addImmOperands";
1652}
1653
1654class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1655  return (((uint32_t)Imm) < 32);
1656}]> {
1657  let ParserMatchClass = matcher;
1658}
1659
1660def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1661def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1662
1663def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1664  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1665}]> {
1666  let ParserMatchClass = TBZImm32_63Operand;
1667}
1668
1669class BaseTestBranch<RegisterClass regtype, Operand immtype,
1670                     bit op, string asm, SDNode node>
1671    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1672       asm, "\t$Rt, $bit_off, $target", "",
1673       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1674      Sched<[WriteBr]> {
1675  let isBranch = 1;
1676  let isTerminator = 1;
1677
1678  bits<5> Rt;
1679  bits<6> bit_off;
1680  bits<14> target;
1681
1682  let Inst{30-25} = 0b011011;
1683  let Inst{24}    = op;
1684  let Inst{23-19} = bit_off{4-0};
1685  let Inst{18-5}  = target;
1686  let Inst{4-0}   = Rt;
1687
1688  let DecoderMethod = "DecodeTestAndBranch";
1689}
1690
1691multiclass TestBranch<bit op, string asm, SDNode node> {
1692  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1693    let Inst{31} = 0;
1694  }
1695
1696  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1697    let Inst{31} = 1;
1698  }
1699
1700  // Alias X-reg with 0-31 imm to W-Reg.
1701  def : InstAlias<asm # "\t$Rd, $imm, $target",
1702                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1703                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1704  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1705            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1706            tbz_imm0_31_diag:$imm, bb:$target)>;
1707}
1708
1709//---
1710// Unconditional branch (immediate) instructions.
1711//---
1712def am_b_target : Operand<OtherVT> {
1713  let EncoderMethod = "getBranchTargetOpValue";
1714  let PrintMethod = "printAlignedLabel";
1715  let ParserMatchClass = BranchTarget26Operand;
1716  let OperandType = "OPERAND_PCREL";
1717}
1718def am_bl_target : Operand<i64> {
1719  let EncoderMethod = "getBranchTargetOpValue";
1720  let PrintMethod = "printAlignedLabel";
1721  let ParserMatchClass = BranchTarget26Operand;
1722  let OperandType = "OPERAND_PCREL";
1723}
1724
1725class BImm<bit op, dag iops, string asm, list<dag> pattern>
1726    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1727  bits<26> addr;
1728  let Inst{31}    = op;
1729  let Inst{30-26} = 0b00101;
1730  let Inst{25-0}  = addr;
1731
1732  let DecoderMethod = "DecodeUnconditionalBranch";
1733}
1734
1735class BranchImm<bit op, string asm, list<dag> pattern>
1736    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1737class CallImm<bit op, string asm, list<dag> pattern>
1738    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1739
1740//---
1741// Basic one-operand data processing instructions.
1742//---
1743
1744let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1745class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1746                         SDPatternOperator node>
1747  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1748      [(set regtype:$Rd, (node regtype:$Rn))]>,
1749    Sched<[WriteI, ReadI]> {
1750  bits<5> Rd;
1751  bits<5> Rn;
1752
1753  let Inst{30-13} = 0b101101011000000000;
1754  let Inst{12-10} = opc;
1755  let Inst{9-5}   = Rn;
1756  let Inst{4-0}   = Rd;
1757}
1758
1759let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1760multiclass OneOperandData<bits<3> opc, string asm,
1761                          SDPatternOperator node = null_frag> {
1762  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1763    let Inst{31} = 0;
1764  }
1765
1766  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1767    let Inst{31} = 1;
1768  }
1769}
1770
1771class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1772    : BaseOneOperandData<opc, GPR32, asm, node> {
1773  let Inst{31} = 0;
1774}
1775
1776class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1777    : BaseOneOperandData<opc, GPR64, asm, node> {
1778  let Inst{31} = 1;
1779}
1780
1781class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1782  : I<(outs GPR64:$Rd), (ins GPR64sp:$Rn), asm, "\t$Rd, $Rn", "",
1783      []>,
1784    Sched<[WriteI, ReadI]> {
1785  bits<5> Rd;
1786  bits<5> Rn;
1787  let Inst{31-15} = 0b11011010110000010;
1788  let Inst{14-12} = opcode_prefix;
1789  let Inst{11-10} = opcode;
1790  let Inst{9-5} = Rn;
1791  let Inst{4-0} = Rd;
1792}
1793
1794class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1795  : I<(outs GPR64:$Rd), (ins), asm, "\t$Rd", "", []>, Sched<[]> {
1796  bits<5> Rd;
1797  let Inst{31-15} = 0b11011010110000010;
1798  let Inst{14-12} = opcode_prefix;
1799  let Inst{11-10} = opcode;
1800  let Inst{9-5} = 0b11111;
1801  let Inst{4-0} = Rd;
1802}
1803
1804class SignAuthTwoOperand<bits<4> opc, string asm,
1805                         SDPatternOperator OpNode>
1806  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1807      asm, "\t$Rd, $Rn, $Rm", "",
1808      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1809    Sched<[WriteI, ReadI, ReadI]> {
1810  bits<5> Rd;
1811  bits<5> Rn;
1812  bits<5> Rm;
1813  let Inst{31-21} = 0b10011010110;
1814  let Inst{20-16} = Rm;
1815  let Inst{15-14} = 0b00;
1816  let Inst{13-10} = opc;
1817  let Inst{9-5}   = Rn;
1818  let Inst{4-0}   = Rd;
1819}
1820
1821// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
1822class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
1823    : I<(outs), iops, asm, ops, "", []>,
1824      Sched<[WriteI, ReadI, ReadI]> {
1825  let Uses = [NZCV];
1826  bits<5> Rn;
1827  let Inst{31}    = sf;
1828  let Inst{30-15} = 0b0111010000000000;
1829  let Inst{14}    = sz;
1830  let Inst{13-10} = 0b0010;
1831  let Inst{9-5}   = Rn;
1832  let Inst{4-0}   = 0b01101;
1833}
1834
1835class FlagRotate<dag iops, string asm, string ops>
1836    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
1837  bits<6> imm;
1838  bits<4> mask;
1839  let Inst{20-15} = imm;
1840  let Inst{13-10} = 0b0001;
1841  let Inst{4}     = 0b0;
1842  let Inst{3-0}   = mask;
1843}
1844
1845//---
1846// Basic two-operand data processing instructions.
1847//---
1848class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1849                          list<dag> pattern>
1850    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
1851        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
1852      Sched<[WriteI, ReadI, ReadI]> {
1853  let Uses = [NZCV];
1854  bits<5> Rd;
1855  bits<5> Rn;
1856  bits<5> Rm;
1857  let Inst{30}    = isSub;
1858  let Inst{28-21} = 0b11010000;
1859  let Inst{20-16} = Rm;
1860  let Inst{15-10} = 0;
1861  let Inst{9-5}   = Rn;
1862  let Inst{4-0}   = Rd;
1863}
1864
1865class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
1866                      SDNode OpNode>
1867    : BaseBaseAddSubCarry<isSub, regtype, asm,
1868        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
1869
1870class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
1871                              SDNode OpNode>
1872    : BaseBaseAddSubCarry<isSub, regtype, asm,
1873        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
1874         (implicit NZCV)]> {
1875  let Defs = [NZCV];
1876}
1877
1878multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
1879                       SDNode OpNode, SDNode OpNode_setflags> {
1880  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
1881    let Inst{31} = 0;
1882    let Inst{29} = 0;
1883  }
1884  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
1885    let Inst{31} = 1;
1886    let Inst{29} = 0;
1887  }
1888
1889  // Sets flags.
1890  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
1891                                    OpNode_setflags> {
1892    let Inst{31} = 0;
1893    let Inst{29} = 1;
1894  }
1895  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
1896                                    OpNode_setflags> {
1897    let Inst{31} = 1;
1898    let Inst{29} = 1;
1899  }
1900}
1901
1902class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
1903                     SDPatternOperator OpNode,
1904                     RegisterClass in1regtype = regtype,
1905                     RegisterClass in2regtype = regtype>
1906  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
1907      asm, "\t$Rd, $Rn, $Rm", "",
1908      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
1909  bits<5> Rd;
1910  bits<5> Rn;
1911  bits<5> Rm;
1912  let Inst{30-21} = 0b0011010110;
1913  let Inst{20-16} = Rm;
1914  let Inst{15-14} = 0b00;
1915  let Inst{13-10} = opc;
1916  let Inst{9-5}   = Rn;
1917  let Inst{4-0}   = Rd;
1918}
1919
1920class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
1921              SDPatternOperator OpNode>
1922    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
1923  let Inst{10}    = isSigned;
1924}
1925
1926multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
1927  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
1928           Sched<[WriteID32, ReadID, ReadID]> {
1929    let Inst{31} = 0;
1930  }
1931  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
1932           Sched<[WriteID64, ReadID, ReadID]> {
1933    let Inst{31} = 1;
1934  }
1935}
1936
1937class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
1938                SDPatternOperator OpNode = null_frag>
1939  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
1940    Sched<[WriteIS, ReadI]> {
1941  let Inst{11-10} = shift_type;
1942}
1943
1944multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
1945  def Wr : BaseShift<shift_type, GPR32, asm> {
1946    let Inst{31} = 0;
1947  }
1948
1949  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
1950    let Inst{31} = 1;
1951  }
1952
1953  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
1954            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
1955                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
1956
1957  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
1958            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1959
1960  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
1961            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1962
1963  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
1964            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
1965
1966  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
1967            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
1968                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
1969
1970  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
1971            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
1972                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
1973}
1974
1975class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
1976    : InstAlias<asm#"\t$dst, $src1, $src2",
1977                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
1978
1979class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
1980                       RegisterClass addtype, string asm,
1981                       list<dag> pattern>
1982  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
1983      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
1984  bits<5> Rd;
1985  bits<5> Rn;
1986  bits<5> Rm;
1987  bits<5> Ra;
1988  let Inst{30-24} = 0b0011011;
1989  let Inst{23-21} = opc;
1990  let Inst{20-16} = Rm;
1991  let Inst{15}    = isSub;
1992  let Inst{14-10} = Ra;
1993  let Inst{9-5}   = Rn;
1994  let Inst{4-0}   = Rd;
1995}
1996
1997multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
1998  // MADD/MSUB generation is decided by MachineCombiner.cpp
1999  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
2000      [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
2001      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2002    let Inst{31} = 0;
2003  }
2004
2005  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
2006      [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
2007      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2008    let Inst{31} = 1;
2009  }
2010}
2011
2012class WideMulAccum<bit isSub, bits<3> opc, string asm,
2013                   SDNode AccNode, SDNode ExtNode>
2014  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2015    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2016                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2017    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2018  let Inst{31} = 1;
2019}
2020
2021class MulHi<bits<3> opc, string asm, SDNode OpNode>
2022  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2023      asm, "\t$Rd, $Rn, $Rm", "",
2024      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2025    Sched<[WriteIM64, ReadIM, ReadIM]> {
2026  bits<5> Rd;
2027  bits<5> Rn;
2028  bits<5> Rm;
2029  let Inst{31-24} = 0b10011011;
2030  let Inst{23-21} = opc;
2031  let Inst{20-16} = Rm;
2032  let Inst{15}    = 0;
2033  let Inst{9-5}   = Rn;
2034  let Inst{4-0}   = Rd;
2035
2036  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2037  // (i.e. all bits 1) but is ignored by the processor.
2038  let PostEncoderMethod = "fixMulHigh";
2039}
2040
2041class MulAccumWAlias<string asm, Instruction inst>
2042    : InstAlias<asm#"\t$dst, $src1, $src2",
2043                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2044class MulAccumXAlias<string asm, Instruction inst>
2045    : InstAlias<asm#"\t$dst, $src1, $src2",
2046                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2047class WideMulAccumAlias<string asm, Instruction inst>
2048    : InstAlias<asm#"\t$dst, $src1, $src2",
2049                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2050
2051class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2052              SDPatternOperator OpNode, string asm>
2053  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2054      asm, "\t$Rd, $Rn, $Rm", "",
2055      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2056    Sched<[WriteISReg, ReadI, ReadISReg]> {
2057  bits<5> Rd;
2058  bits<5> Rn;
2059  bits<5> Rm;
2060
2061  let Inst{31} = sf;
2062  let Inst{30-21} = 0b0011010110;
2063  let Inst{20-16} = Rm;
2064  let Inst{15-13} = 0b010;
2065  let Inst{12} = C;
2066  let Inst{11-10} = sz;
2067  let Inst{9-5} = Rn;
2068  let Inst{4-0} = Rd;
2069  let Predicates = [HasCRC];
2070}
2071
2072//---
2073// Address generation.
2074//---
2075
2076class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2077    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2078        pattern>,
2079      Sched<[WriteI]> {
2080  bits<5>  Xd;
2081  bits<21> label;
2082  let Inst{31}    = page;
2083  let Inst{30-29} = label{1-0};
2084  let Inst{28-24} = 0b10000;
2085  let Inst{23-5}  = label{20-2};
2086  let Inst{4-0}   = Xd;
2087
2088  let DecoderMethod = "DecodeAdrInstruction";
2089}
2090
2091//---
2092// Move immediate.
2093//---
2094
2095def movimm32_imm : Operand<i32> {
2096  let ParserMatchClass = AsmImmRange<0, 65535>;
2097  let EncoderMethod = "getMoveWideImmOpValue";
2098  let PrintMethod = "printImm";
2099}
2100def movimm32_shift : Operand<i32> {
2101  let PrintMethod = "printShifter";
2102  let ParserMatchClass = MovImm32ShifterOperand;
2103}
2104def movimm64_shift : Operand<i32> {
2105  let PrintMethod = "printShifter";
2106  let ParserMatchClass = MovImm64ShifterOperand;
2107}
2108
2109let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2110class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2111                        string asm>
2112  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2113       asm, "\t$Rd, $imm$shift", "", []>,
2114    Sched<[WriteImm]> {
2115  bits<5> Rd;
2116  bits<16> imm;
2117  bits<6> shift;
2118  let Inst{30-29} = opc;
2119  let Inst{28-23} = 0b100101;
2120  let Inst{22-21} = shift{5-4};
2121  let Inst{20-5}  = imm;
2122  let Inst{4-0}   = Rd;
2123
2124  let DecoderMethod = "DecodeMoveImmInstruction";
2125}
2126
2127multiclass MoveImmediate<bits<2> opc, string asm> {
2128  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2129    let Inst{31} = 0;
2130  }
2131
2132  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2133    let Inst{31} = 1;
2134  }
2135}
2136
2137let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2138class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2139                          string asm>
2140  : I<(outs regtype:$Rd),
2141      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2142       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2143    Sched<[WriteI, ReadI]> {
2144  bits<5> Rd;
2145  bits<16> imm;
2146  bits<6> shift;
2147  let Inst{30-29} = opc;
2148  let Inst{28-23} = 0b100101;
2149  let Inst{22-21} = shift{5-4};
2150  let Inst{20-5}  = imm;
2151  let Inst{4-0}   = Rd;
2152
2153  let DecoderMethod = "DecodeMoveImmInstruction";
2154}
2155
2156multiclass InsertImmediate<bits<2> opc, string asm> {
2157  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2158    let Inst{31} = 0;
2159  }
2160
2161  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2162    let Inst{31} = 1;
2163  }
2164}
2165
2166//---
2167// Add/Subtract
2168//---
2169
2170class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2171                    string asm_inst, string asm_ops,
2172                    dag inputs, dag pattern>
2173    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2174      Sched<[WriteI, ReadI]> {
2175  bits<5>  Rd;
2176  bits<5>  Rn;
2177  let Inst{30}    = isSub;
2178  let Inst{29}    = setFlags;
2179  let Inst{28-24} = 0b10001;
2180  let Inst{9-5}   = Rn;
2181  let Inst{4-0}   = Rd;
2182}
2183
2184class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2185                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2186                     string asm_inst, SDPatternOperator OpNode>
2187    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2188                    (ins srcRegtype:$Rn, immtype:$imm),
2189                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2190  bits<14> imm;
2191  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2192  let Inst{21-10} = imm{11-0};
2193  let DecoderMethod = "DecodeAddSubImmShift";
2194}
2195
2196class BaseAddSubRegPseudo<RegisterClass regtype,
2197                          SDPatternOperator OpNode>
2198    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2199             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2200      Sched<[WriteI, ReadI, ReadI]>;
2201
2202class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2203                     arith_shifted_reg shifted_regtype, string asm,
2204                     SDPatternOperator OpNode>
2205    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2206        asm, "\t$Rd, $Rn, $Rm", "",
2207        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2208      Sched<[WriteISReg, ReadI, ReadISReg]> {
2209  // The operands are in order to match the 'addr' MI operands, so we
2210  // don't need an encoder method and by-name matching. Just use the default
2211  // in-order handling. Since we're using by-order, make sure the names
2212  // do not match.
2213  bits<5> dst;
2214  bits<5> src1;
2215  bits<5> src2;
2216  bits<8> shift;
2217  let Inst{30}    = isSub;
2218  let Inst{29}    = setFlags;
2219  let Inst{28-24} = 0b01011;
2220  let Inst{23-22} = shift{7-6};
2221  let Inst{21}    = 0;
2222  let Inst{20-16} = src2;
2223  let Inst{15-10} = shift{5-0};
2224  let Inst{9-5}   = src1;
2225  let Inst{4-0}   = dst;
2226
2227  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2228}
2229
2230class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2231                     RegisterClass src1Regtype, Operand src2Regtype,
2232                     string asm, SDPatternOperator OpNode>
2233    : I<(outs dstRegtype:$R1),
2234        (ins src1Regtype:$R2, src2Regtype:$R3),
2235        asm, "\t$R1, $R2, $R3", "",
2236        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2237      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2238  bits<5> Rd;
2239  bits<5> Rn;
2240  bits<5> Rm;
2241  bits<6> ext;
2242  let Inst{30}    = isSub;
2243  let Inst{29}    = setFlags;
2244  let Inst{28-24} = 0b01011;
2245  let Inst{23-21} = 0b001;
2246  let Inst{20-16} = Rm;
2247  let Inst{15-13} = ext{5-3};
2248  let Inst{12-10} = ext{2-0};
2249  let Inst{9-5}   = Rn;
2250  let Inst{4-0}   = Rd;
2251
2252  let DecoderMethod = "DecodeAddSubERegInstruction";
2253}
2254
2255let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2256class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2257                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2258                       Operand ext_op, string asm>
2259    : I<(outs dstRegtype:$Rd),
2260        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2261        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2262      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2263  bits<5> Rd;
2264  bits<5> Rn;
2265  bits<5> Rm;
2266  bits<6> ext;
2267  let Inst{30}    = isSub;
2268  let Inst{29}    = setFlags;
2269  let Inst{28-24} = 0b01011;
2270  let Inst{23-21} = 0b001;
2271  let Inst{20-16} = Rm;
2272  let Inst{15}    = ext{5};
2273  let Inst{12-10} = ext{2-0};
2274  let Inst{9-5}   = Rn;
2275  let Inst{4-0}   = Rd;
2276
2277  let DecoderMethod = "DecodeAddSubERegInstruction";
2278}
2279
2280// Aliases for register+register add/subtract.
2281class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2282                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2283                     int shiftExt>
2284    : InstAlias<asm#"\t$dst, $src1, $src2",
2285                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2286                      shiftExt)>;
2287
2288multiclass AddSub<bit isSub, string mnemonic, string alias,
2289                  SDPatternOperator OpNode = null_frag> {
2290  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2291  // Add/Subtract immediate
2292  // Increase the weight of the immediate variant to try to match it before
2293  // the extended register variant.
2294  // We used to match the register variant before the immediate when the
2295  // register argument could be implicitly zero-extended.
2296  let AddedComplexity = 6 in
2297  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2298                           mnemonic, OpNode> {
2299    let Inst{31} = 0;
2300  }
2301  let AddedComplexity = 6 in
2302  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2303                           mnemonic, OpNode> {
2304    let Inst{31} = 1;
2305  }
2306
2307  // Add/Subtract register - Only used for CodeGen
2308  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2309  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2310
2311  // Add/Subtract shifted register
2312  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2313                           OpNode> {
2314    let Inst{31} = 0;
2315  }
2316  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2317                           OpNode> {
2318    let Inst{31} = 1;
2319  }
2320  }
2321
2322  // Add/Subtract extended register
2323  let AddedComplexity = 1, hasSideEffects = 0 in {
2324  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2325                           arith_extended_reg32_i32, mnemonic, OpNode> {
2326    let Inst{31} = 0;
2327  }
2328  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2329                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2330    let Inst{31} = 1;
2331  }
2332  }
2333
2334  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2335                               arith_extendlsl64, mnemonic> {
2336    // UXTX and SXTX only.
2337    let Inst{14-13} = 0b11;
2338    let Inst{31} = 1;
2339  }
2340
2341  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2342  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2343                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2344                      addsub_shifted_imm32_neg:$imm), 0>;
2345  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2346                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2347                       addsub_shifted_imm64_neg:$imm), 0>;
2348
2349  // Register/register aliases with no shift when SP is not used.
2350  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2351                       GPR32, GPR32, GPR32, 0>;
2352  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2353                       GPR64, GPR64, GPR64, 0>;
2354
2355  // Register/register aliases with no shift when either the destination or
2356  // first source register is SP.
2357  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2358                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2359  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2360                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2361  def : AddSubRegAlias<mnemonic,
2362                       !cast<Instruction>(NAME#"Xrx64"),
2363                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2364  def : AddSubRegAlias<mnemonic,
2365                       !cast<Instruction>(NAME#"Xrx64"),
2366                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2367}
2368
2369multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2370                   string alias, string cmpAlias> {
2371  let isCompare = 1, Defs = [NZCV] in {
2372  // Add/Subtract immediate
2373  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2374                           mnemonic, OpNode> {
2375    let Inst{31} = 0;
2376  }
2377  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2378                           mnemonic, OpNode> {
2379    let Inst{31} = 1;
2380  }
2381
2382  // Add/Subtract register
2383  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2384  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2385
2386  // Add/Subtract shifted register
2387  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2388                           OpNode> {
2389    let Inst{31} = 0;
2390  }
2391  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2392                           OpNode> {
2393    let Inst{31} = 1;
2394  }
2395
2396  // Add/Subtract extended register
2397  let AddedComplexity = 1 in {
2398  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2399                           arith_extended_reg32_i32, mnemonic, OpNode> {
2400    let Inst{31} = 0;
2401  }
2402  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2403                           arith_extended_reg32_i64, mnemonic, OpNode> {
2404    let Inst{31} = 1;
2405  }
2406  }
2407
2408  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2409                               arith_extendlsl64, mnemonic> {
2410    // UXTX and SXTX only.
2411    let Inst{14-13} = 0b11;
2412    let Inst{31} = 1;
2413  }
2414  } // Defs = [NZCV]
2415
2416  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2417  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2418                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2419                      addsub_shifted_imm32_neg:$imm), 0>;
2420  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2421                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2422                       addsub_shifted_imm64_neg:$imm), 0>;
2423
2424  // Compare aliases
2425  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2426                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2427  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2428                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2429  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2430                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2431  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2432                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2433  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2434                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2435  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2436                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2437  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2438                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2439
2440  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2441  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2442                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2443  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2444                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2445
2446  // Compare shorthands
2447  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2448                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2449  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2450                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2451  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2452                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2453  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2454                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2455
2456  // Register/register aliases with no shift when SP is not used.
2457  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2458                       GPR32, GPR32, GPR32, 0>;
2459  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2460                       GPR64, GPR64, GPR64, 0>;
2461
2462  // Register/register aliases with no shift when the first source register
2463  // is SP.
2464  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2465                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2466  def : AddSubRegAlias<mnemonic,
2467                       !cast<Instruction>(NAME#"Xrx64"),
2468                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2469}
2470
2471class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2472      : BaseAddSubImm<
2473          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2474          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2475          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2476  bits<6> imm6;
2477  bits<4> imm4;
2478  let Inst{31} = 1;
2479  let Inst{23-22} = 0b10;
2480  let Inst{21-16} = imm6;
2481  let Inst{15-14} = 0b00;
2482  let Inst{13-10} = imm4;
2483  let Unpredictable{15-14} = 0b11;
2484}
2485
2486class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2487      : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2488  let Inst{31} = 1;
2489  let Inst{29} = setsFlags;
2490}
2491
2492//---
2493// Extract
2494//---
2495def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2496                                      SDTCisPtrTy<3>]>;
2497def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2498
2499class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2500                     list<dag> patterns>
2501    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2502         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2503      Sched<[WriteExtr, ReadExtrHi]> {
2504  bits<5> Rd;
2505  bits<5> Rn;
2506  bits<5> Rm;
2507  bits<6> imm;
2508
2509  let Inst{30-23} = 0b00100111;
2510  let Inst{21}    = 0;
2511  let Inst{20-16} = Rm;
2512  let Inst{15-10} = imm;
2513  let Inst{9-5}   = Rn;
2514  let Inst{4-0}   = Rd;
2515}
2516
2517multiclass ExtractImm<string asm> {
2518  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2519                      [(set GPR32:$Rd,
2520                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2521    let Inst{31} = 0;
2522    let Inst{22} = 0;
2523    // imm<5> must be zero.
2524    let imm{5}   = 0;
2525  }
2526  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2527                      [(set GPR64:$Rd,
2528                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2529
2530    let Inst{31} = 1;
2531    let Inst{22} = 1;
2532  }
2533}
2534
2535//---
2536// Bitfield
2537//---
2538
2539let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2540class BaseBitfieldImm<bits<2> opc,
2541                      RegisterClass regtype, Operand imm_type, string asm>
2542    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2543         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2544      Sched<[WriteIS, ReadI]> {
2545  bits<5> Rd;
2546  bits<5> Rn;
2547  bits<6> immr;
2548  bits<6> imms;
2549
2550  let Inst{30-29} = opc;
2551  let Inst{28-23} = 0b100110;
2552  let Inst{21-16} = immr;
2553  let Inst{15-10} = imms;
2554  let Inst{9-5}   = Rn;
2555  let Inst{4-0}   = Rd;
2556}
2557
2558multiclass BitfieldImm<bits<2> opc, string asm> {
2559  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2560    let Inst{31} = 0;
2561    let Inst{22} = 0;
2562    // imms<5> and immr<5> must be zero, else ReservedValue().
2563    let Inst{21} = 0;
2564    let Inst{15} = 0;
2565  }
2566  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2567    let Inst{31} = 1;
2568    let Inst{22} = 1;
2569  }
2570}
2571
2572let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2573class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2574                      RegisterClass regtype, Operand imm_type, string asm>
2575    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2576                             imm_type:$imms),
2577         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2578      Sched<[WriteIS, ReadI]> {
2579  bits<5> Rd;
2580  bits<5> Rn;
2581  bits<6> immr;
2582  bits<6> imms;
2583
2584  let Inst{30-29} = opc;
2585  let Inst{28-23} = 0b100110;
2586  let Inst{21-16} = immr;
2587  let Inst{15-10} = imms;
2588  let Inst{9-5}   = Rn;
2589  let Inst{4-0}   = Rd;
2590}
2591
2592multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2593  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2594    let Inst{31} = 0;
2595    let Inst{22} = 0;
2596    // imms<5> and immr<5> must be zero, else ReservedValue().
2597    let Inst{21} = 0;
2598    let Inst{15} = 0;
2599  }
2600  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2601    let Inst{31} = 1;
2602    let Inst{22} = 1;
2603  }
2604}
2605
2606//---
2607// Logical
2608//---
2609
2610// Logical (immediate)
2611class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2612                     RegisterClass sregtype, Operand imm_type, string asm,
2613                     list<dag> pattern>
2614    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2615         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2616      Sched<[WriteI, ReadI]> {
2617  bits<5>  Rd;
2618  bits<5>  Rn;
2619  bits<13> imm;
2620  let Inst{30-29} = opc;
2621  let Inst{28-23} = 0b100100;
2622  let Inst{22}    = imm{12};
2623  let Inst{21-16} = imm{11-6};
2624  let Inst{15-10} = imm{5-0};
2625  let Inst{9-5}   = Rn;
2626  let Inst{4-0}   = Rd;
2627
2628  let DecoderMethod = "DecodeLogicalImmInstruction";
2629}
2630
2631// Logical (shifted register)
2632class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2633                      logical_shifted_reg shifted_regtype, string asm,
2634                      list<dag> pattern>
2635    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2636        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2637      Sched<[WriteISReg, ReadI, ReadISReg]> {
2638  // The operands are in order to match the 'addr' MI operands, so we
2639  // don't need an encoder method and by-name matching. Just use the default
2640  // in-order handling. Since we're using by-order, make sure the names
2641  // do not match.
2642  bits<5> dst;
2643  bits<5> src1;
2644  bits<5> src2;
2645  bits<8> shift;
2646  let Inst{30-29} = opc;
2647  let Inst{28-24} = 0b01010;
2648  let Inst{23-22} = shift{7-6};
2649  let Inst{21}    = N;
2650  let Inst{20-16} = src2;
2651  let Inst{15-10} = shift{5-0};
2652  let Inst{9-5}   = src1;
2653  let Inst{4-0}   = dst;
2654
2655  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2656}
2657
2658// Aliases for register+register logical instructions.
2659class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2660    : InstAlias<asm#"\t$dst, $src1, $src2",
2661                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2662
2663multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2664                      string Alias> {
2665  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2666  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2667                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2668                                               logical_imm32:$imm))]> {
2669    let Inst{31} = 0;
2670    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2671  }
2672  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2673  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2674                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2675                                               logical_imm64:$imm))]> {
2676    let Inst{31} = 1;
2677  }
2678
2679  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2680                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2681                      logical_imm32_not:$imm), 0>;
2682  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2683                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2684                       logical_imm64_not:$imm), 0>;
2685}
2686
2687multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2688                       string Alias> {
2689  let isCompare = 1, Defs = [NZCV] in {
2690  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2691      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2692    let Inst{31} = 0;
2693    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2694  }
2695  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2696      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2697    let Inst{31} = 1;
2698  }
2699  } // end Defs = [NZCV]
2700
2701  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2702                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2703                      logical_imm32_not:$imm), 0>;
2704  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2705                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2706                       logical_imm64_not:$imm), 0>;
2707}
2708
2709class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2710    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2711             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2712      Sched<[WriteI, ReadI, ReadI]>;
2713
2714// Split from LogicalImm as not all instructions have both.
2715multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2716                      SDPatternOperator OpNode> {
2717  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2718  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2719  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2720  }
2721
2722  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2723                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2724                                                 logical_shifted_reg32:$Rm))]> {
2725    let Inst{31} = 0;
2726  }
2727  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2728                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2729                                                 logical_shifted_reg64:$Rm))]> {
2730    let Inst{31} = 1;
2731  }
2732
2733  def : LogicalRegAlias<mnemonic,
2734                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2735  def : LogicalRegAlias<mnemonic,
2736                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2737}
2738
2739// Split from LogicalReg to allow setting NZCV Defs
2740multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2741                       SDPatternOperator OpNode = null_frag> {
2742  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2743  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2744  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2745
2746  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2747            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2748    let Inst{31} = 0;
2749  }
2750  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2751            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2752    let Inst{31} = 1;
2753  }
2754  } // Defs = [NZCV]
2755
2756  def : LogicalRegAlias<mnemonic,
2757                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2758  def : LogicalRegAlias<mnemonic,
2759                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2760}
2761
2762//---
2763// Conditionally set flags
2764//---
2765
2766let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2767class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2768                            string mnemonic, SDNode OpNode>
2769    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2770         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2771         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2772                             (i32 imm:$cond), NZCV))]>,
2773      Sched<[WriteI, ReadI]> {
2774  let Uses = [NZCV];
2775  let Defs = [NZCV];
2776
2777  bits<5> Rn;
2778  bits<5> imm;
2779  bits<4> nzcv;
2780  bits<4> cond;
2781
2782  let Inst{30}    = op;
2783  let Inst{29-21} = 0b111010010;
2784  let Inst{20-16} = imm;
2785  let Inst{15-12} = cond;
2786  let Inst{11-10} = 0b10;
2787  let Inst{9-5}   = Rn;
2788  let Inst{4}     = 0b0;
2789  let Inst{3-0}   = nzcv;
2790}
2791
2792let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2793class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2794                            SDNode OpNode>
2795    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2796         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2797         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2798                             (i32 imm:$cond), NZCV))]>,
2799      Sched<[WriteI, ReadI, ReadI]> {
2800  let Uses = [NZCV];
2801  let Defs = [NZCV];
2802
2803  bits<5> Rn;
2804  bits<5> Rm;
2805  bits<4> nzcv;
2806  bits<4> cond;
2807
2808  let Inst{30}    = op;
2809  let Inst{29-21} = 0b111010010;
2810  let Inst{20-16} = Rm;
2811  let Inst{15-12} = cond;
2812  let Inst{11-10} = 0b00;
2813  let Inst{9-5}   = Rn;
2814  let Inst{4}     = 0b0;
2815  let Inst{3-0}   = nzcv;
2816}
2817
2818multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
2819  // immediate operand variants
2820  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
2821    let Inst{31} = 0;
2822  }
2823  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
2824    let Inst{31} = 1;
2825  }
2826  // register operand variants
2827  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
2828    let Inst{31} = 0;
2829  }
2830  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
2831    let Inst{31} = 1;
2832  }
2833}
2834
2835//---
2836// Conditional select
2837//---
2838
2839class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
2840    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2841         asm, "\t$Rd, $Rn, $Rm, $cond", "",
2842         [(set regtype:$Rd,
2843               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
2844      Sched<[WriteI, ReadI, ReadI]> {
2845  let Uses = [NZCV];
2846
2847  bits<5> Rd;
2848  bits<5> Rn;
2849  bits<5> Rm;
2850  bits<4> cond;
2851
2852  let Inst{30}    = op;
2853  let Inst{29-21} = 0b011010100;
2854  let Inst{20-16} = Rm;
2855  let Inst{15-12} = cond;
2856  let Inst{11-10} = op2;
2857  let Inst{9-5}   = Rn;
2858  let Inst{4-0}   = Rd;
2859}
2860
2861multiclass CondSelect<bit op, bits<2> op2, string asm> {
2862  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
2863    let Inst{31} = 0;
2864  }
2865  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
2866    let Inst{31} = 1;
2867  }
2868}
2869
2870class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
2871                       PatFrag frag>
2872    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
2873         asm, "\t$Rd, $Rn, $Rm, $cond", "",
2874         [(set regtype:$Rd,
2875               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
2876               (i32 imm:$cond), NZCV))]>,
2877      Sched<[WriteI, ReadI, ReadI]> {
2878  let Uses = [NZCV];
2879
2880  bits<5> Rd;
2881  bits<5> Rn;
2882  bits<5> Rm;
2883  bits<4> cond;
2884
2885  let Inst{30}    = op;
2886  let Inst{29-21} = 0b011010100;
2887  let Inst{20-16} = Rm;
2888  let Inst{15-12} = cond;
2889  let Inst{11-10} = op2;
2890  let Inst{9-5}   = Rn;
2891  let Inst{4-0}   = Rd;
2892}
2893
2894def inv_cond_XFORM : SDNodeXForm<imm, [{
2895  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
2896  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
2897                                   MVT::i32);
2898}]>;
2899
2900multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
2901  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
2902    let Inst{31} = 0;
2903  }
2904  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
2905    let Inst{31} = 1;
2906  }
2907
2908  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
2909            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
2910                                           (inv_cond_XFORM imm:$cond))>;
2911
2912  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
2913            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
2914                                           (inv_cond_XFORM imm:$cond))>;
2915}
2916
2917//---
2918// Special Mask Value
2919//---
2920def maski8_or_more : Operand<i32>,
2921  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
2922}
2923def maski16_or_more : Operand<i32>,
2924  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
2925}
2926
2927
2928//---
2929// Load/store
2930//---
2931
2932// (unsigned immediate)
2933// Indexed for 8-bit registers. offset is in range [0,4095].
2934def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
2935def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
2936def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
2937def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
2938def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
2939
2940def gi_am_indexed8 :
2941    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
2942    GIComplexPatternEquiv<am_indexed8>;
2943def gi_am_indexed16 :
2944    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
2945    GIComplexPatternEquiv<am_indexed16>;
2946def gi_am_indexed32 :
2947    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
2948    GIComplexPatternEquiv<am_indexed32>;
2949def gi_am_indexed64 :
2950    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
2951    GIComplexPatternEquiv<am_indexed64>;
2952def gi_am_indexed128 :
2953    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
2954    GIComplexPatternEquiv<am_indexed128>;
2955
2956class UImm12OffsetOperand<int Scale> : AsmOperandClass {
2957  let Name = "UImm12Offset" # Scale;
2958  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
2959  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
2960  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
2961}
2962
2963def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
2964def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
2965def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
2966def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
2967def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
2968
2969class uimm12_scaled<int Scale> : Operand<i64> {
2970  let ParserMatchClass
2971   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
2972  let EncoderMethod
2973   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
2974  let PrintMethod = "printUImm12Offset<" # Scale # ">";
2975}
2976
2977def uimm12s1 : uimm12_scaled<1>;
2978def uimm12s2 : uimm12_scaled<2>;
2979def uimm12s4 : uimm12_scaled<4>;
2980def uimm12s8 : uimm12_scaled<8>;
2981def uimm12s16 : uimm12_scaled<16>;
2982
2983class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
2984                      string asm, list<dag> pattern>
2985    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
2986  bits<5> Rt;
2987
2988  bits<5> Rn;
2989  bits<12> offset;
2990
2991  let Inst{31-30} = sz;
2992  let Inst{29-27} = 0b111;
2993  let Inst{26}    = V;
2994  let Inst{25-24} = 0b01;
2995  let Inst{23-22} = opc;
2996  let Inst{21-10} = offset;
2997  let Inst{9-5}   = Rn;
2998  let Inst{4-0}   = Rt;
2999
3000  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3001}
3002
3003multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3004                  Operand indextype, string asm, list<dag> pattern> {
3005  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3006  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3007                           (ins GPR64sp:$Rn, indextype:$offset),
3008                           asm, pattern>,
3009           Sched<[WriteLD]>;
3010
3011  def : InstAlias<asm # "\t$Rt, [$Rn]",
3012                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3013}
3014
3015multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3016             Operand indextype, string asm, list<dag> pattern> {
3017  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3018  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3019                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3020                           asm, pattern>,
3021           Sched<[WriteST]>;
3022
3023  def : InstAlias<asm # "\t$Rt, [$Rn]",
3024                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3025}
3026
3027// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3028// substitute zero-registers automatically.
3029//
3030// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3031//       into StoreUI.
3032multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3033             Operand indextype, string asm, list<dag> pattern> {
3034  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3035  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3036                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3037                           asm, pattern>,
3038           Sched<[WriteST]>;
3039
3040  def : InstAlias<asm # "\t$Rt, [$Rn]",
3041                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3042}
3043
3044def PrefetchOperand : AsmOperandClass {
3045  let Name = "Prefetch";
3046  let ParserMethod = "tryParsePrefetch";
3047}
3048def prfop : Operand<i32> {
3049  let PrintMethod = "printPrefetchOp";
3050  let ParserMatchClass = PrefetchOperand;
3051}
3052
3053let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3054class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3055    : BaseLoadStoreUI<sz, V, opc,
3056                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3057                      asm, pat>,
3058      Sched<[WriteLD]>;
3059
3060//---
3061// Load literal
3062//---
3063
3064// Load literal address: 19-bit immediate. The low two bits of the target
3065// offset are implied zero and so are not part of the immediate.
3066def am_ldrlit : Operand<iPTR> {
3067  let EncoderMethod = "getLoadLiteralOpValue";
3068  let DecoderMethod = "DecodePCRelLabel19";
3069  let PrintMethod = "printAlignedLabel";
3070  let ParserMatchClass = PCRelLabel19Operand;
3071  let OperandType = "OPERAND_PCREL";
3072}
3073
3074let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3075class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3076    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3077        asm, "\t$Rt, $label", "", pat>,
3078      Sched<[WriteLD]> {
3079  bits<5> Rt;
3080  bits<19> label;
3081  let Inst{31-30} = opc;
3082  let Inst{29-27} = 0b011;
3083  let Inst{26}    = V;
3084  let Inst{25-24} = 0b00;
3085  let Inst{23-5}  = label;
3086  let Inst{4-0}   = Rt;
3087}
3088
3089let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3090class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3091    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3092        asm, "\t$Rt, $label", "", pat>,
3093      Sched<[WriteLD]> {
3094  bits<5> Rt;
3095  bits<19> label;
3096  let Inst{31-30} = opc;
3097  let Inst{29-27} = 0b011;
3098  let Inst{26}    = V;
3099  let Inst{25-24} = 0b00;
3100  let Inst{23-5}  = label;
3101  let Inst{4-0}   = Rt;
3102}
3103
3104//---
3105// Load/store register offset
3106//---
3107
3108def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
3109def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
3110def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
3111def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
3112def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
3113
3114def gi_ro_Xindexed8 :
3115    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3116    GIComplexPatternEquiv<ro_Xindexed8>;
3117def gi_ro_Xindexed16 :
3118    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3119    GIComplexPatternEquiv<ro_Xindexed16>;
3120def gi_ro_Xindexed32 :
3121    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3122    GIComplexPatternEquiv<ro_Xindexed32>;
3123def gi_ro_Xindexed64 :
3124    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3125    GIComplexPatternEquiv<ro_Xindexed64>;
3126def gi_ro_Xindexed128 :
3127    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3128    GIComplexPatternEquiv<ro_Xindexed128>;
3129
3130def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
3131def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
3132def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
3133def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
3134def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
3135
3136def gi_ro_Windexed8 :
3137    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3138    GIComplexPatternEquiv<ro_Windexed8>;
3139def gi_ro_Windexed16 :
3140    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3141    GIComplexPatternEquiv<ro_Windexed16>;
3142def gi_ro_Windexed32 :
3143    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3144    GIComplexPatternEquiv<ro_Windexed32>;
3145def gi_ro_Windexed64 :
3146    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3147    GIComplexPatternEquiv<ro_Windexed64>;
3148def gi_ro_Windexed128 :
3149    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3150    GIComplexPatternEquiv<ro_Windexed128>;
3151
3152class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3153  let Name = "Mem" # Reg # "Extend" # Width;
3154  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3155  let RenderMethod = "addMemExtendOperands";
3156  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3157}
3158
3159def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3160  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3161  // the trivial shift.
3162  let RenderMethod = "addMemExtend8Operands";
3163}
3164def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3165def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3166def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3167def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3168
3169def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3170  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3171  // the trivial shift.
3172  let RenderMethod = "addMemExtend8Operands";
3173}
3174def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3175def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3176def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3177def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3178
3179class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3180        : Operand<i32> {
3181  let ParserMatchClass = ParserClass;
3182  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3183  let DecoderMethod = "DecodeMemExtend";
3184  let EncoderMethod = "getMemExtendOpValue";
3185  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3186}
3187
3188def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3189def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3190def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3191def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3192def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3193
3194def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3195def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3196def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3197def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3198def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3199
3200class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3201                  Operand wextend, Operand xextend>  {
3202  // CodeGen-level pattern covering the entire addressing mode.
3203  ComplexPattern Wpat = windex;
3204  ComplexPattern Xpat = xindex;
3205
3206  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3207  Operand Wext = wextend;
3208  Operand Xext = xextend;
3209}
3210
3211def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3212def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3213def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3214def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3215def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3216                       ro_Xextend128>;
3217
3218class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3219                      string asm, dag ins, dag outs, list<dag> pat>
3220    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3221  bits<5> Rt;
3222  bits<5> Rn;
3223  bits<5> Rm;
3224  bits<2> extend;
3225  let Inst{31-30} = sz;
3226  let Inst{29-27} = 0b111;
3227  let Inst{26}    = V;
3228  let Inst{25-24} = 0b00;
3229  let Inst{23-22} = opc;
3230  let Inst{21}    = 1;
3231  let Inst{20-16} = Rm;
3232  let Inst{15}    = extend{1}; // sign extend Rm?
3233  let Inst{14}    = 1;
3234  let Inst{12}    = extend{0}; // do shift?
3235  let Inst{11-10} = 0b10;
3236  let Inst{9-5}   = Rn;
3237  let Inst{4-0}   = Rt;
3238}
3239
3240class ROInstAlias<string asm, RegisterOperand regtype, Instruction INST>
3241  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3242              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3243
3244multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3245                   string asm, ValueType Ty, SDPatternOperator loadop> {
3246  let AddedComplexity = 10 in
3247  def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3248                 (outs regtype:$Rt),
3249                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3250                 [(set (Ty regtype:$Rt),
3251                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3252                                             ro_Wextend8:$extend)))]>,
3253           Sched<[WriteLDIdx, ReadAdrBase]> {
3254    let Inst{13} = 0b0;
3255  }
3256
3257  let AddedComplexity = 10 in
3258  def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3259                 (outs regtype:$Rt),
3260                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3261                 [(set (Ty regtype:$Rt),
3262                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3263                                             ro_Xextend8:$extend)))]>,
3264           Sched<[WriteLDIdx, ReadAdrBase]> {
3265    let Inst{13} = 0b1;
3266  }
3267
3268  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3269}
3270
3271multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3272                    string asm, ValueType Ty, SDPatternOperator storeop> {
3273  let AddedComplexity = 10 in
3274  def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3275                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3276                 [(storeop (Ty regtype:$Rt),
3277                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3278                                         ro_Wextend8:$extend))]>,
3279            Sched<[WriteSTIdx, ReadAdrBase]> {
3280    let Inst{13} = 0b0;
3281  }
3282
3283  let AddedComplexity = 10 in
3284  def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3285                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3286                 [(storeop (Ty regtype:$Rt),
3287                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3288                                         ro_Xextend8:$extend))]>,
3289            Sched<[WriteSTIdx, ReadAdrBase]> {
3290    let Inst{13} = 0b1;
3291  }
3292
3293  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3294}
3295
3296class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3297                      string asm, dag ins, dag outs, list<dag> pat>
3298    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3299  bits<5> Rt;
3300  bits<5> Rn;
3301  bits<5> Rm;
3302  bits<2> extend;
3303  let Inst{31-30} = sz;
3304  let Inst{29-27} = 0b111;
3305  let Inst{26}    = V;
3306  let Inst{25-24} = 0b00;
3307  let Inst{23-22} = opc;
3308  let Inst{21}    = 1;
3309  let Inst{20-16} = Rm;
3310  let Inst{15}    = extend{1}; // sign extend Rm?
3311  let Inst{14}    = 1;
3312  let Inst{12}    = extend{0}; // do shift?
3313  let Inst{11-10} = 0b10;
3314  let Inst{9-5}   = Rn;
3315  let Inst{4-0}   = Rt;
3316}
3317
3318multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3319                    string asm, ValueType Ty, SDPatternOperator loadop> {
3320  let AddedComplexity = 10 in
3321  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3322                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3323                 [(set (Ty regtype:$Rt),
3324                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3325                                              ro_Wextend16:$extend)))]>,
3326            Sched<[WriteLDIdx, ReadAdrBase]> {
3327    let Inst{13} = 0b0;
3328  }
3329
3330  let AddedComplexity = 10 in
3331  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3332                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3333                 [(set (Ty regtype:$Rt),
3334                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3335                                             ro_Xextend16:$extend)))]>,
3336            Sched<[WriteLDIdx, ReadAdrBase]> {
3337    let Inst{13} = 0b1;
3338  }
3339
3340  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3341}
3342
3343multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3344                     string asm, ValueType Ty, SDPatternOperator storeop> {
3345  let AddedComplexity = 10 in
3346  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3347                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3348                [(storeop (Ty regtype:$Rt),
3349                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3350                                         ro_Wextend16:$extend))]>,
3351           Sched<[WriteSTIdx, ReadAdrBase]> {
3352    let Inst{13} = 0b0;
3353  }
3354
3355  let AddedComplexity = 10 in
3356  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3357                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3358                [(storeop (Ty regtype:$Rt),
3359                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3360                                         ro_Xextend16:$extend))]>,
3361           Sched<[WriteSTIdx, ReadAdrBase]> {
3362    let Inst{13} = 0b1;
3363  }
3364
3365  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3366}
3367
3368class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3369                      string asm, dag ins, dag outs, list<dag> pat>
3370    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3371  bits<5> Rt;
3372  bits<5> Rn;
3373  bits<5> Rm;
3374  bits<2> extend;
3375  let Inst{31-30} = sz;
3376  let Inst{29-27} = 0b111;
3377  let Inst{26}    = V;
3378  let Inst{25-24} = 0b00;
3379  let Inst{23-22} = opc;
3380  let Inst{21}    = 1;
3381  let Inst{20-16} = Rm;
3382  let Inst{15}    = extend{1}; // sign extend Rm?
3383  let Inst{14}    = 1;
3384  let Inst{12}    = extend{0}; // do shift?
3385  let Inst{11-10} = 0b10;
3386  let Inst{9-5}   = Rn;
3387  let Inst{4-0}   = Rt;
3388}
3389
3390multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3391                    string asm, ValueType Ty, SDPatternOperator loadop> {
3392  let AddedComplexity = 10 in
3393  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3394                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3395                 [(set (Ty regtype:$Rt),
3396                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3397                                              ro_Wextend32:$extend)))]>,
3398           Sched<[WriteLDIdx, ReadAdrBase]> {
3399    let Inst{13} = 0b0;
3400  }
3401
3402  let AddedComplexity = 10 in
3403  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3404                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3405                 [(set (Ty regtype:$Rt),
3406                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3407                                              ro_Xextend32:$extend)))]>,
3408           Sched<[WriteLDIdx, ReadAdrBase]> {
3409    let Inst{13} = 0b1;
3410  }
3411
3412  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3413}
3414
3415multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3416                     string asm, ValueType Ty, SDPatternOperator storeop> {
3417  let AddedComplexity = 10 in
3418  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3419                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3420                [(storeop (Ty regtype:$Rt),
3421                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3422                                         ro_Wextend32:$extend))]>,
3423            Sched<[WriteSTIdx, ReadAdrBase]> {
3424    let Inst{13} = 0b0;
3425  }
3426
3427  let AddedComplexity = 10 in
3428  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3429                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3430                [(storeop (Ty regtype:$Rt),
3431                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3432                                        ro_Xextend32:$extend))]>,
3433            Sched<[WriteSTIdx, ReadAdrBase]> {
3434    let Inst{13} = 0b1;
3435  }
3436
3437  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3438}
3439
3440class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3441                      string asm, dag ins, dag outs, list<dag> pat>
3442    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3443  bits<5> Rt;
3444  bits<5> Rn;
3445  bits<5> Rm;
3446  bits<2> extend;
3447  let Inst{31-30} = sz;
3448  let Inst{29-27} = 0b111;
3449  let Inst{26}    = V;
3450  let Inst{25-24} = 0b00;
3451  let Inst{23-22} = opc;
3452  let Inst{21}    = 1;
3453  let Inst{20-16} = Rm;
3454  let Inst{15}    = extend{1}; // sign extend Rm?
3455  let Inst{14}    = 1;
3456  let Inst{12}    = extend{0}; // do shift?
3457  let Inst{11-10} = 0b10;
3458  let Inst{9-5}   = Rn;
3459  let Inst{4-0}   = Rt;
3460}
3461
3462multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3463                    string asm, ValueType Ty, SDPatternOperator loadop> {
3464  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3465  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3466                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3467                [(set (Ty regtype:$Rt),
3468                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3469                                             ro_Wextend64:$extend)))]>,
3470           Sched<[WriteLDIdx, ReadAdrBase]> {
3471    let Inst{13} = 0b0;
3472  }
3473
3474  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3475  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3476                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3477                 [(set (Ty regtype:$Rt),
3478                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3479                                              ro_Xextend64:$extend)))]>,
3480           Sched<[WriteLDIdx, ReadAdrBase]> {
3481    let Inst{13} = 0b1;
3482  }
3483
3484  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3485}
3486
3487multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3488                     string asm, ValueType Ty, SDPatternOperator storeop> {
3489  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3490  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3491                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3492                [(storeop (Ty regtype:$Rt),
3493                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3494                                         ro_Wextend64:$extend))]>,
3495            Sched<[WriteSTIdx, ReadAdrBase]> {
3496    let Inst{13} = 0b0;
3497  }
3498
3499  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3500  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3501                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3502                [(storeop (Ty regtype:$Rt),
3503                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3504                                         ro_Xextend64:$extend))]>,
3505            Sched<[WriteSTIdx, ReadAdrBase]> {
3506    let Inst{13} = 0b1;
3507  }
3508
3509  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3510}
3511
3512class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3513                      string asm, dag ins, dag outs, list<dag> pat>
3514    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3515  bits<5> Rt;
3516  bits<5> Rn;
3517  bits<5> Rm;
3518  bits<2> extend;
3519  let Inst{31-30} = sz;
3520  let Inst{29-27} = 0b111;
3521  let Inst{26}    = V;
3522  let Inst{25-24} = 0b00;
3523  let Inst{23-22} = opc;
3524  let Inst{21}    = 1;
3525  let Inst{20-16} = Rm;
3526  let Inst{15}    = extend{1}; // sign extend Rm?
3527  let Inst{14}    = 1;
3528  let Inst{12}    = extend{0}; // do shift?
3529  let Inst{11-10} = 0b10;
3530  let Inst{9-5}   = Rn;
3531  let Inst{4-0}   = Rt;
3532}
3533
3534multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3535                     string asm, ValueType Ty, SDPatternOperator loadop> {
3536  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3537  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3538                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3539                 [(set (Ty regtype:$Rt),
3540                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3541                                               ro_Wextend128:$extend)))]>,
3542            Sched<[WriteLDIdx, ReadAdrBase]> {
3543    let Inst{13} = 0b0;
3544  }
3545
3546  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3547  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3548                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3549                 [(set (Ty regtype:$Rt),
3550                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3551                                               ro_Xextend128:$extend)))]>,
3552            Sched<[WriteLDIdx, ReadAdrBase]> {
3553    let Inst{13} = 0b1;
3554  }
3555
3556  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3557}
3558
3559multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3560                      string asm, ValueType Ty, SDPatternOperator storeop> {
3561  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3562  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3563               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3564                []>,
3565            Sched<[WriteSTIdx, ReadAdrBase]> {
3566    let Inst{13} = 0b0;
3567  }
3568
3569  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3570  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3571               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3572                []>,
3573            Sched<[WriteSTIdx, ReadAdrBase]> {
3574    let Inst{13} = 0b1;
3575  }
3576
3577  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3578}
3579
3580let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3581class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3582                     string asm, list<dag> pat>
3583    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3584      Sched<[WriteLD]> {
3585  bits<5> Rt;
3586  bits<5> Rn;
3587  bits<5> Rm;
3588  bits<2> extend;
3589  let Inst{31-30} = sz;
3590  let Inst{29-27} = 0b111;
3591  let Inst{26}    = V;
3592  let Inst{25-24} = 0b00;
3593  let Inst{23-22} = opc;
3594  let Inst{21}    = 1;
3595  let Inst{20-16} = Rm;
3596  let Inst{15}    = extend{1}; // sign extend Rm?
3597  let Inst{14}    = 1;
3598  let Inst{12}    = extend{0}; // do shift?
3599  let Inst{11-10} = 0b10;
3600  let Inst{9-5}   = Rn;
3601  let Inst{4-0}   = Rt;
3602}
3603
3604multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3605  def roW : BasePrefetchRO<sz, V, opc, (outs),
3606                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3607                asm, [(AArch64Prefetch imm:$Rt,
3608                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3609                                                    ro_Wextend64:$extend))]> {
3610    let Inst{13} = 0b0;
3611  }
3612
3613  def roX : BasePrefetchRO<sz, V, opc, (outs),
3614                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3615                asm,  [(AArch64Prefetch imm:$Rt,
3616                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3617                                                     ro_Xextend64:$extend))]> {
3618    let Inst{13} = 0b1;
3619  }
3620
3621  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3622               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3623                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3624}
3625
3626//---
3627// Load/store unscaled immediate
3628//---
3629
3630def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3631def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3632def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3633def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3634def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3635
3636def gi_am_unscaled8 :
3637    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3638    GIComplexPatternEquiv<am_unscaled8>;
3639def gi_am_unscaled16 :
3640    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3641    GIComplexPatternEquiv<am_unscaled16>;
3642def gi_am_unscaled32 :
3643    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3644    GIComplexPatternEquiv<am_unscaled32>;
3645def gi_am_unscaled64 :
3646    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3647    GIComplexPatternEquiv<am_unscaled64>;
3648def gi_am_unscaled128 :
3649    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3650    GIComplexPatternEquiv<am_unscaled128>;
3651
3652
3653class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3654                           string asm, list<dag> pattern>
3655    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3656  bits<5> Rt;
3657  bits<5> Rn;
3658  bits<9> offset;
3659  let Inst{31-30} = sz;
3660  let Inst{29-27} = 0b111;
3661  let Inst{26}    = V;
3662  let Inst{25-24} = 0b00;
3663  let Inst{23-22} = opc;
3664  let Inst{21}    = 0;
3665  let Inst{20-12} = offset;
3666  let Inst{11-10} = 0b00;
3667  let Inst{9-5}   = Rn;
3668  let Inst{4-0}   = Rt;
3669
3670  let DecoderMethod = "DecodeSignedLdStInstruction";
3671}
3672
3673// Armv8.4 LDAPR & STLR with Immediate Offset instruction
3674multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3675                              RegisterOperand regtype > {
3676  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3677                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3678          Sched<[WriteST]> {
3679    let Inst{29} = 0;
3680    let Inst{24} = 1;
3681  }
3682  def : InstAlias<asm # "\t$Rt, [$Rn]",
3683                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3684}
3685
3686multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3687                               RegisterOperand regtype > {
3688  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3689                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3690                               asm, []>,
3691          Sched<[WriteST]> {
3692    let Inst{29} = 0;
3693    let Inst{24} = 1;
3694  }
3695  def : InstAlias<asm # "\t$Rt, [$Rn]",
3696                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3697}
3698
3699multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3700                   string asm, list<dag> pattern> {
3701  let AddedComplexity = 1 in // try this before LoadUI
3702  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3703                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3704          Sched<[WriteLD]>;
3705
3706  def : InstAlias<asm # "\t$Rt, [$Rn]",
3707                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3708}
3709
3710multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3711                         string asm, list<dag> pattern> {
3712  let AddedComplexity = 1 in // try this before StoreUI
3713  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3714                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3715                               asm, pattern>,
3716          Sched<[WriteST]>;
3717
3718  def : InstAlias<asm # "\t$Rt, [$Rn]",
3719                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3720}
3721
3722multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3723                            list<dag> pat> {
3724  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3725  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3726                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3727                               asm, pat>,
3728          Sched<[WriteLD]>;
3729
3730  def : InstAlias<asm # "\t$Rt, [$Rn]",
3731                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3732}
3733
3734//---
3735// Load/store unscaled immediate, unprivileged
3736//---
3737
3738class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3739                                dag oops, dag iops, string asm>
3740    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3741  bits<5> Rt;
3742  bits<5> Rn;
3743  bits<9> offset;
3744  let Inst{31-30} = sz;
3745  let Inst{29-27} = 0b111;
3746  let Inst{26}    = V;
3747  let Inst{25-24} = 0b00;
3748  let Inst{23-22} = opc;
3749  let Inst{21}    = 0;
3750  let Inst{20-12} = offset;
3751  let Inst{11-10} = 0b10;
3752  let Inst{9-5}   = Rn;
3753  let Inst{4-0}   = Rt;
3754
3755  let DecoderMethod = "DecodeSignedLdStInstruction";
3756}
3757
3758multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3759                            RegisterClass regtype, string asm> {
3760  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3761  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3762                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
3763          Sched<[WriteLD]>;
3764
3765  def : InstAlias<asm # "\t$Rt, [$Rn]",
3766                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3767}
3768
3769multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3770                             RegisterClass regtype, string asm> {
3771  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3772  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3773                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3774                                 asm>,
3775          Sched<[WriteST]>;
3776
3777  def : InstAlias<asm # "\t$Rt, [$Rn]",
3778                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3779}
3780
3781//---
3782// Load/store pre-indexed
3783//---
3784
3785class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3786                          string asm, string cstr, list<dag> pat>
3787    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3788  bits<5> Rt;
3789  bits<5> Rn;
3790  bits<9> offset;
3791  let Inst{31-30} = sz;
3792  let Inst{29-27} = 0b111;
3793  let Inst{26}    = V;
3794  let Inst{25-24} = 0;
3795  let Inst{23-22} = opc;
3796  let Inst{21}    = 0;
3797  let Inst{20-12} = offset;
3798  let Inst{11-10} = 0b11;
3799  let Inst{9-5}   = Rn;
3800  let Inst{4-0}   = Rt;
3801
3802  let DecoderMethod = "DecodeSignedLdStInstruction";
3803}
3804
3805let hasSideEffects = 0 in {
3806let mayStore = 0, mayLoad = 1 in
3807class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3808             string asm>
3809    : BaseLoadStorePreIdx<sz, V, opc,
3810                     (outs GPR64sp:$wback, regtype:$Rt),
3811                     (ins GPR64sp:$Rn, simm9:$offset), asm,
3812                     "$Rn = $wback,@earlyclobber $wback", []>,
3813      Sched<[WriteLD, WriteAdr]>;
3814
3815let mayStore = 1, mayLoad = 0 in
3816class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3817                  string asm, SDPatternOperator storeop, ValueType Ty>
3818    : BaseLoadStorePreIdx<sz, V, opc,
3819                      (outs GPR64sp:$wback),
3820                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3821                      asm, "$Rn = $wback,@earlyclobber $wback",
3822      [(set GPR64sp:$wback,
3823            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3824      Sched<[WriteAdr, WriteST]>;
3825} // hasSideEffects = 0
3826
3827//---
3828// Load/store post-indexed
3829//---
3830
3831class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3832                          string asm, string cstr, list<dag> pat>
3833    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
3834  bits<5> Rt;
3835  bits<5> Rn;
3836  bits<9> offset;
3837  let Inst{31-30} = sz;
3838  let Inst{29-27} = 0b111;
3839  let Inst{26}    = V;
3840  let Inst{25-24} = 0b00;
3841  let Inst{23-22} = opc;
3842  let Inst{21}    = 0b0;
3843  let Inst{20-12} = offset;
3844  let Inst{11-10} = 0b01;
3845  let Inst{9-5}   = Rn;
3846  let Inst{4-0}   = Rt;
3847
3848  let DecoderMethod = "DecodeSignedLdStInstruction";
3849}
3850
3851let hasSideEffects = 0 in {
3852let mayStore = 0, mayLoad = 1 in
3853class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3854             string asm>
3855    : BaseLoadStorePostIdx<sz, V, opc,
3856                      (outs GPR64sp:$wback, regtype:$Rt),
3857                      (ins GPR64sp:$Rn, simm9:$offset),
3858                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
3859      Sched<[WriteLD, WriteAdr]>;
3860
3861let mayStore = 1, mayLoad = 0 in
3862class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3863                   string asm, SDPatternOperator storeop, ValueType Ty>
3864    : BaseLoadStorePostIdx<sz, V, opc,
3865                      (outs GPR64sp:$wback),
3866                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3867                       asm, "$Rn = $wback,@earlyclobber $wback",
3868      [(set GPR64sp:$wback,
3869            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
3870    Sched<[WriteAdr, WriteST]>;
3871} // hasSideEffects = 0
3872
3873
3874//---
3875// Load/store pair
3876//---
3877
3878// (indexed, offset)
3879
3880class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
3881                              string asm>
3882    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
3883  bits<5> Rt;
3884  bits<5> Rt2;
3885  bits<5> Rn;
3886  bits<7> offset;
3887  let Inst{31-30} = opc;
3888  let Inst{29-27} = 0b101;
3889  let Inst{26}    = V;
3890  let Inst{25-23} = 0b010;
3891  let Inst{22}    = L;
3892  let Inst{21-15} = offset;
3893  let Inst{14-10} = Rt2;
3894  let Inst{9-5}   = Rn;
3895  let Inst{4-0}   = Rt;
3896
3897  let DecoderMethod = "DecodePairLdStInstruction";
3898}
3899
3900multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3901                          Operand indextype, string asm> {
3902  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
3903  def i : BaseLoadStorePairOffset<opc, V, 1,
3904                                  (outs regtype:$Rt, regtype:$Rt2),
3905                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
3906          Sched<[WriteLD, WriteLDHi]>;
3907
3908  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3909                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3910                                                  GPR64sp:$Rn, 0)>;
3911}
3912
3913
3914multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
3915                           Operand indextype, string asm> {
3916  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
3917  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
3918                                  (ins regtype:$Rt, regtype:$Rt2,
3919                                       GPR64sp:$Rn, indextype:$offset),
3920                                  asm>,
3921          Sched<[WriteSTP]>;
3922
3923  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
3924                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
3925                                                  GPR64sp:$Rn, 0)>;
3926}
3927
3928// (pre-indexed)
3929class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3930                              string asm>
3931    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
3932  bits<5> Rt;
3933  bits<5> Rt2;
3934  bits<5> Rn;
3935  bits<7> offset;
3936  let Inst{31-30} = opc;
3937  let Inst{29-27} = 0b101;
3938  let Inst{26}    = V;
3939  let Inst{25-23} = 0b011;
3940  let Inst{22}    = L;
3941  let Inst{21-15} = offset;
3942  let Inst{14-10} = Rt2;
3943  let Inst{9-5}   = Rn;
3944  let Inst{4-0}   = Rt;
3945
3946  let DecoderMethod = "DecodePairLdStInstruction";
3947}
3948
3949let hasSideEffects = 0 in {
3950let mayStore = 0, mayLoad = 1 in
3951class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3952                     Operand indextype, string asm>
3953    : BaseLoadStorePairPreIdx<opc, V, 1,
3954                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3955                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
3956      Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3957
3958let mayStore = 1, mayLoad = 0 in
3959class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
3960                      Operand indextype, string asm>
3961    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
3962                             (ins regtype:$Rt, regtype:$Rt2,
3963                                  GPR64sp:$Rn, indextype:$offset),
3964                             asm>,
3965      Sched<[WriteAdr, WriteSTP]>;
3966} // hasSideEffects = 0
3967
3968// (post-indexed)
3969
3970class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
3971                              string asm>
3972    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
3973  bits<5> Rt;
3974  bits<5> Rt2;
3975  bits<5> Rn;
3976  bits<7> offset;
3977  let Inst{31-30} = opc;
3978  let Inst{29-27} = 0b101;
3979  let Inst{26}    = V;
3980  let Inst{25-23} = 0b001;
3981  let Inst{22}    = L;
3982  let Inst{21-15} = offset;
3983  let Inst{14-10} = Rt2;
3984  let Inst{9-5}   = Rn;
3985  let Inst{4-0}   = Rt;
3986
3987  let DecoderMethod = "DecodePairLdStInstruction";
3988}
3989
3990let hasSideEffects = 0 in {
3991let mayStore = 0, mayLoad = 1 in
3992class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
3993                      Operand idxtype, string asm>
3994    : BaseLoadStorePairPostIdx<opc, V, 1,
3995                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
3996                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
3997      Sched<[WriteLD, WriteLDHi, WriteAdr]>;
3998
3999let mayStore = 1, mayLoad = 0 in
4000class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4001                       Operand idxtype, string asm>
4002    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4003                             (ins regtype:$Rt, regtype:$Rt2,
4004                                  GPR64sp:$Rn, idxtype:$offset),
4005                             asm>,
4006      Sched<[WriteAdr, WriteSTP]>;
4007} // hasSideEffects = 0
4008
4009//  (no-allocate)
4010
4011class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4012                              string asm>
4013    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4014  bits<5> Rt;
4015  bits<5> Rt2;
4016  bits<5> Rn;
4017  bits<7> offset;
4018  let Inst{31-30} = opc;
4019  let Inst{29-27} = 0b101;
4020  let Inst{26}    = V;
4021  let Inst{25-23} = 0b000;
4022  let Inst{22}    = L;
4023  let Inst{21-15} = offset;
4024  let Inst{14-10} = Rt2;
4025  let Inst{9-5}   = Rn;
4026  let Inst{4-0}   = Rt;
4027
4028  let DecoderMethod = "DecodePairLdStInstruction";
4029}
4030
4031multiclass LoadPairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
4032                           Operand indextype, string asm> {
4033  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4034  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4035                                   (outs regtype:$Rt, regtype:$Rt2),
4036                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4037          Sched<[WriteLD, WriteLDHi]>;
4038
4039
4040  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4041                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4042                                                  GPR64sp:$Rn, 0)>;
4043}
4044
4045multiclass StorePairNoAlloc<bits<2> opc, bit V, RegisterClass regtype,
4046                      Operand indextype, string asm> {
4047  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4048  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4049                                   (ins regtype:$Rt, regtype:$Rt2,
4050                                        GPR64sp:$Rn, indextype:$offset),
4051                                   asm>,
4052          Sched<[WriteSTP]>;
4053
4054  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4055                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4056                                                  GPR64sp:$Rn, 0)>;
4057}
4058
4059//---
4060// Load/store exclusive
4061//---
4062
4063// True exclusive operations write to and/or read from the system's exclusive
4064// monitors, which as far as a compiler is concerned can be modelled as a
4065// random shared memory address. Hence LoadExclusive mayStore.
4066//
4067// Since these instructions have the undefined register bits set to 1 in
4068// their canonical form, we need a post encoder method to set those bits
4069// to 1 when encoding these instructions. We do this using the
4070// fixLoadStoreExclusive function. This function has template parameters:
4071//
4072// fixLoadStoreExclusive<int hasRs, int hasRt2>
4073//
4074// hasRs indicates that the instruction uses the Rs field, so we won't set
4075// it to 1 (and the same for Rt2). We don't need template parameters for
4076// the other register fields since Rt and Rn are always used.
4077//
4078let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4079class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4080                             dag oops, dag iops, string asm, string operands>
4081    : I<oops, iops, asm, operands, "", []> {
4082  let Inst{31-30} = sz;
4083  let Inst{29-24} = 0b001000;
4084  let Inst{23}    = o2;
4085  let Inst{22}    = L;
4086  let Inst{21}    = o1;
4087  let Inst{15}    = o0;
4088
4089  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4090}
4091
4092// Neither Rs nor Rt2 operands.
4093class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4094                               dag oops, dag iops, string asm, string operands>
4095    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4096  bits<5> Rt;
4097  bits<5> Rn;
4098  let Inst{20-16} = 0b11111;
4099  let Unpredictable{20-16} = 0b11111;
4100  let Inst{14-10} = 0b11111;
4101  let Unpredictable{14-10} = 0b11111;
4102  let Inst{9-5} = Rn;
4103  let Inst{4-0} = Rt;
4104
4105  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4106}
4107
4108// Simple load acquires don't set the exclusive monitor
4109let mayLoad = 1, mayStore = 0 in
4110class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4111                  RegisterClass regtype, string asm>
4112    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4113                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4114      Sched<[WriteLD]>;
4115
4116class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4117                    RegisterClass regtype, string asm>
4118    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4119                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4120      Sched<[WriteLD]>;
4121
4122class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4123                       RegisterClass regtype, string asm>
4124    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4125                             (outs regtype:$Rt, regtype:$Rt2),
4126                             (ins GPR64sp0:$Rn), asm,
4127                             "\t$Rt, $Rt2, [$Rn]">,
4128      Sched<[WriteLD, WriteLDHi]> {
4129  bits<5> Rt;
4130  bits<5> Rt2;
4131  bits<5> Rn;
4132  let Inst{14-10} = Rt2;
4133  let Inst{9-5} = Rn;
4134  let Inst{4-0} = Rt;
4135
4136  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4137}
4138
4139// Simple store release operations do not check the exclusive monitor.
4140let mayLoad = 0, mayStore = 1 in
4141class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4142                   RegisterClass regtype, string asm>
4143    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4144                               (ins regtype:$Rt, GPR64sp0:$Rn),
4145                               asm, "\t$Rt, [$Rn]">,
4146      Sched<[WriteST]>;
4147
4148let mayLoad = 1, mayStore = 1 in
4149class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4150                     RegisterClass regtype, string asm>
4151    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4152                             (ins regtype:$Rt, GPR64sp0:$Rn),
4153                             asm, "\t$Ws, $Rt, [$Rn]">,
4154      Sched<[WriteSTX]> {
4155  bits<5> Ws;
4156  bits<5> Rt;
4157  bits<5> Rn;
4158  let Inst{20-16} = Ws;
4159  let Inst{9-5} = Rn;
4160  let Inst{4-0} = Rt;
4161
4162  let Constraints = "@earlyclobber $Ws";
4163  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4164}
4165
4166class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4167                         RegisterClass regtype, string asm>
4168    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4169                             (outs GPR32:$Ws),
4170                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4171                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4172      Sched<[WriteSTX]> {
4173  bits<5> Ws;
4174  bits<5> Rt;
4175  bits<5> Rt2;
4176  bits<5> Rn;
4177  let Inst{20-16} = Ws;
4178  let Inst{14-10} = Rt2;
4179  let Inst{9-5} = Rn;
4180  let Inst{4-0} = Rt;
4181
4182  let Constraints = "@earlyclobber $Ws";
4183}
4184
4185// Armv8.5-A Memory Tagging Extension
4186class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4187                 string asm_opnds, string cstr, dag oops, dag iops>
4188    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4189      Sched<[]> {
4190  bits<5> Rn;
4191
4192  let Inst{31-24} = 0b11011001;
4193  let Inst{23-22} = opc1;
4194  let Inst{21}    = 1;
4195  // Inst{20-12} defined by subclass
4196  let Inst{11-10} = opc2;
4197  let Inst{9-5}   = Rn;
4198  // Inst{4-0} defined by subclass
4199}
4200
4201class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4202                   dag oops, dag iops>
4203    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4204                  "", oops, iops> {
4205  bits<5> Rt;
4206
4207  let Inst{20-12} = 0b000000000;
4208  let Inst{4-0}   = Rt;
4209
4210  let mayLoad = Load;
4211}
4212
4213class MemTagLoad<string asm_insn, string asm_opnds>
4214    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4215                 (outs GPR64:$wback),
4216                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4217  bits<5> Rt;
4218  bits<9> offset;
4219
4220  let Inst{20-12} = offset;
4221  let Inst{4-0}   = Rt;
4222
4223  let mayLoad = 1;
4224}
4225
4226class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4227                     string asm_opnds, string cstr, dag oops, dag iops>
4228    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4229  bits<5> Rt;
4230  bits<9> offset;
4231
4232  let Inst{20-12} = offset;
4233  let Inst{4-0}   = Rt;
4234
4235  let mayStore = 1;
4236}
4237
4238multiclass MemTagStore<bits<2> opc1, string insn> {
4239  def Offset :
4240    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4241                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4242  def PreIndex :
4243    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4244                    "$Rn = $wback",
4245                    (outs GPR64sp:$wback),
4246                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4247  def PostIndex :
4248    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4249                    "$Rn = $wback",
4250                    (outs GPR64sp:$wback),
4251                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4252
4253  def : InstAlias<insn # "\t$Rt, [$Rn]",
4254                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4255}
4256
4257//---
4258// Exception generation
4259//---
4260
4261let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4262class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4263    : I<(outs), (ins i32_imm0_65535:$imm), asm, "\t$imm", "", []>,
4264      Sched<[WriteSys]> {
4265  bits<16> imm;
4266  let Inst{31-24} = 0b11010100;
4267  let Inst{23-21} = op1;
4268  let Inst{20-5}  = imm;
4269  let Inst{4-2}   = 0b000;
4270  let Inst{1-0}   = ll;
4271}
4272
4273//---
4274// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4275//--
4276let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4277class UDFType<bits<16> opc, string asm>
4278  : I<(outs), (ins uimm16:$imm),
4279       asm, "\t$imm", "", []>,
4280    Sched<[]> {
4281  bits<16> imm;
4282  let Inst{31-16} = opc;
4283  let Inst{15-0} = imm;
4284}
4285}
4286let Predicates = [HasFPARMv8] in {
4287
4288//---
4289// Floating point to integer conversion
4290//---
4291
4292class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4293                      RegisterClass srcType, RegisterClass dstType,
4294                      string asm, list<dag> pattern>
4295    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4296         asm, "\t$Rd, $Rn", "", pattern>,
4297      Sched<[WriteFCvt]> {
4298  bits<5> Rd;
4299  bits<5> Rn;
4300  let Inst{30-29} = 0b00;
4301  let Inst{28-24} = 0b11110;
4302  let Inst{23-22} = type;
4303  let Inst{21}    = 1;
4304  let Inst{20-19} = rmode;
4305  let Inst{18-16} = opcode;
4306  let Inst{15-10} = 0;
4307  let Inst{9-5}   = Rn;
4308  let Inst{4-0}   = Rd;
4309}
4310
4311let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4312class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4313                      RegisterClass srcType, RegisterClass dstType,
4314                      Operand immType, string asm, list<dag> pattern>
4315    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4316         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4317      Sched<[WriteFCvt]> {
4318  bits<5> Rd;
4319  bits<5> Rn;
4320  bits<6> scale;
4321  let Inst{30-29} = 0b00;
4322  let Inst{28-24} = 0b11110;
4323  let Inst{23-22} = type;
4324  let Inst{21}    = 0;
4325  let Inst{20-19} = rmode;
4326  let Inst{18-16} = opcode;
4327  let Inst{15-10} = scale;
4328  let Inst{9-5}   = Rn;
4329  let Inst{4-0}   = Rd;
4330}
4331
4332multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4333           SDPatternOperator OpN> {
4334  // Unscaled half-precision to 32-bit
4335  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4336                                     [(set GPR32:$Rd, (OpN FPR16:$Rn))]> {
4337    let Inst{31} = 0; // 32-bit GPR flag
4338    let Predicates = [HasFullFP16];
4339  }
4340
4341  // Unscaled half-precision to 64-bit
4342  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4343                                     [(set GPR64:$Rd, (OpN FPR16:$Rn))]> {
4344    let Inst{31} = 1; // 64-bit GPR flag
4345    let Predicates = [HasFullFP16];
4346  }
4347
4348  // Unscaled single-precision to 32-bit
4349  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4350                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4351    let Inst{31} = 0; // 32-bit GPR flag
4352  }
4353
4354  // Unscaled single-precision to 64-bit
4355  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4356                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4357    let Inst{31} = 1; // 64-bit GPR flag
4358  }
4359
4360  // Unscaled double-precision to 32-bit
4361  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4362                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4363    let Inst{31} = 0; // 32-bit GPR flag
4364  }
4365
4366  // Unscaled double-precision to 64-bit
4367  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4368                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4369    let Inst{31} = 1; // 64-bit GPR flag
4370  }
4371}
4372
4373multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4374                             SDPatternOperator OpN> {
4375  // Scaled half-precision to 32-bit
4376  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4377                              fixedpoint_f16_i32, asm,
4378              [(set GPR32:$Rd, (OpN (fmul FPR16:$Rn,
4379                                          fixedpoint_f16_i32:$scale)))]> {
4380    let Inst{31} = 0; // 32-bit GPR flag
4381    let scale{5} = 1;
4382    let Predicates = [HasFullFP16];
4383  }
4384
4385  // Scaled half-precision to 64-bit
4386  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4387                              fixedpoint_f16_i64, asm,
4388              [(set GPR64:$Rd, (OpN (fmul FPR16:$Rn,
4389                                          fixedpoint_f16_i64:$scale)))]> {
4390    let Inst{31} = 1; // 64-bit GPR flag
4391    let Predicates = [HasFullFP16];
4392  }
4393
4394  // Scaled single-precision to 32-bit
4395  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4396                              fixedpoint_f32_i32, asm,
4397              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4398                                          fixedpoint_f32_i32:$scale)))]> {
4399    let Inst{31} = 0; // 32-bit GPR flag
4400    let scale{5} = 1;
4401  }
4402
4403  // Scaled single-precision to 64-bit
4404  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4405                              fixedpoint_f32_i64, asm,
4406              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4407                                          fixedpoint_f32_i64:$scale)))]> {
4408    let Inst{31} = 1; // 64-bit GPR flag
4409  }
4410
4411  // Scaled double-precision to 32-bit
4412  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4413                              fixedpoint_f64_i32, asm,
4414              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4415                                          fixedpoint_f64_i32:$scale)))]> {
4416    let Inst{31} = 0; // 32-bit GPR flag
4417    let scale{5} = 1;
4418  }
4419
4420  // Scaled double-precision to 64-bit
4421  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4422                              fixedpoint_f64_i64, asm,
4423              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4424                                          fixedpoint_f64_i64:$scale)))]> {
4425    let Inst{31} = 1; // 64-bit GPR flag
4426  }
4427}
4428
4429//---
4430// Integer to floating point conversion
4431//---
4432
4433let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4434class BaseIntegerToFP<bit isUnsigned,
4435                      RegisterClass srcType, RegisterClass dstType,
4436                      Operand immType, string asm, list<dag> pattern>
4437    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4438         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4439      Sched<[WriteFCvt]> {
4440  bits<5> Rd;
4441  bits<5> Rn;
4442  bits<6> scale;
4443  let Inst{30-24} = 0b0011110;
4444  let Inst{21-17} = 0b00001;
4445  let Inst{16}    = isUnsigned;
4446  let Inst{15-10} = scale;
4447  let Inst{9-5}   = Rn;
4448  let Inst{4-0}   = Rd;
4449}
4450
4451class BaseIntegerToFPUnscaled<bit isUnsigned,
4452                      RegisterClass srcType, RegisterClass dstType,
4453                      ValueType dvt, string asm, SDNode node>
4454    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4455         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4456      Sched<[WriteFCvt]> {
4457  bits<5> Rd;
4458  bits<5> Rn;
4459  bits<6> scale;
4460  let Inst{30-24} = 0b0011110;
4461  let Inst{21-17} = 0b10001;
4462  let Inst{16}    = isUnsigned;
4463  let Inst{15-10} = 0b000000;
4464  let Inst{9-5}   = Rn;
4465  let Inst{4-0}   = Rd;
4466}
4467
4468multiclass IntegerToFP<bit isUnsigned, string asm, SDNode node> {
4469  // Unscaled
4470  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4471    let Inst{31} = 0; // 32-bit GPR flag
4472    let Inst{23-22} = 0b11; // 16-bit FPR flag
4473    let Predicates = [HasFullFP16];
4474  }
4475
4476  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4477    let Inst{31} = 0; // 32-bit GPR flag
4478    let Inst{23-22} = 0b00; // 32-bit FPR flag
4479  }
4480
4481  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4482    let Inst{31} = 0; // 32-bit GPR flag
4483    let Inst{23-22} = 0b01; // 64-bit FPR flag
4484  }
4485
4486  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4487    let Inst{31} = 1; // 64-bit GPR flag
4488    let Inst{23-22} = 0b11; // 16-bit FPR flag
4489    let Predicates = [HasFullFP16];
4490  }
4491
4492  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4493    let Inst{31} = 1; // 64-bit GPR flag
4494    let Inst{23-22} = 0b00; // 32-bit FPR flag
4495  }
4496
4497  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4498    let Inst{31} = 1; // 64-bit GPR flag
4499    let Inst{23-22} = 0b01; // 64-bit FPR flag
4500  }
4501
4502  // Scaled
4503  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4504                             [(set FPR16:$Rd,
4505                                   (fdiv (node GPR32:$Rn),
4506                                         fixedpoint_f16_i32:$scale))]> {
4507    let Inst{31} = 0; // 32-bit GPR flag
4508    let Inst{23-22} = 0b11; // 16-bit FPR flag
4509    let scale{5} = 1;
4510    let Predicates = [HasFullFP16];
4511  }
4512
4513  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4514                             [(set FPR32:$Rd,
4515                                   (fdiv (node GPR32:$Rn),
4516                                         fixedpoint_f32_i32:$scale))]> {
4517    let Inst{31} = 0; // 32-bit GPR flag
4518    let Inst{23-22} = 0b00; // 32-bit FPR flag
4519    let scale{5} = 1;
4520  }
4521
4522  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4523                             [(set FPR64:$Rd,
4524                                   (fdiv (node GPR32:$Rn),
4525                                         fixedpoint_f64_i32:$scale))]> {
4526    let Inst{31} = 0; // 32-bit GPR flag
4527    let Inst{23-22} = 0b01; // 64-bit FPR flag
4528    let scale{5} = 1;
4529  }
4530
4531  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4532                             [(set FPR16:$Rd,
4533                                   (fdiv (node GPR64:$Rn),
4534                                         fixedpoint_f16_i64:$scale))]> {
4535    let Inst{31} = 1; // 64-bit GPR flag
4536    let Inst{23-22} = 0b11; // 16-bit FPR flag
4537    let Predicates = [HasFullFP16];
4538  }
4539
4540  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4541                             [(set FPR32:$Rd,
4542                                   (fdiv (node GPR64:$Rn),
4543                                         fixedpoint_f32_i64:$scale))]> {
4544    let Inst{31} = 1; // 64-bit GPR flag
4545    let Inst{23-22} = 0b00; // 32-bit FPR flag
4546  }
4547
4548  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4549                             [(set FPR64:$Rd,
4550                                   (fdiv (node GPR64:$Rn),
4551                                         fixedpoint_f64_i64:$scale))]> {
4552    let Inst{31} = 1; // 64-bit GPR flag
4553    let Inst{23-22} = 0b01; // 64-bit FPR flag
4554  }
4555}
4556
4557//---
4558// Unscaled integer <-> floating point conversion (i.e. FMOV)
4559//---
4560
4561let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4562class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4563                      RegisterClass srcType, RegisterClass dstType,
4564                      string asm>
4565    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4566        // We use COPY_TO_REGCLASS for these bitconvert operations.
4567        // copyPhysReg() expands the resultant COPY instructions after
4568        // regalloc is done. This gives greater freedom for the allocator
4569        // and related passes (coalescing, copy propagation, et. al.) to
4570        // be more effective.
4571        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4572      Sched<[WriteFCopy]> {
4573  bits<5> Rd;
4574  bits<5> Rn;
4575  let Inst{30-24} = 0b0011110;
4576  let Inst{21}    = 1;
4577  let Inst{20-19} = rmode;
4578  let Inst{18-16} = opcode;
4579  let Inst{15-10} = 0b000000;
4580  let Inst{9-5}   = Rn;
4581  let Inst{4-0}   = Rd;
4582}
4583
4584let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4585class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4586                     RegisterClass srcType, RegisterOperand dstType, string asm,
4587                     string kind>
4588    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4589        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4590      Sched<[WriteFCopy]> {
4591  bits<5> Rd;
4592  bits<5> Rn;
4593  let Inst{30-23} = 0b00111101;
4594  let Inst{21}    = 1;
4595  let Inst{20-19} = rmode;
4596  let Inst{18-16} = opcode;
4597  let Inst{15-10} = 0b000000;
4598  let Inst{9-5}   = Rn;
4599  let Inst{4-0}   = Rd;
4600
4601  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4602}
4603
4604let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4605class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4606                     RegisterOperand srcType, RegisterClass dstType, string asm,
4607                     string kind>
4608    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4609        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4610      Sched<[WriteFCopy]> {
4611  bits<5> Rd;
4612  bits<5> Rn;
4613  let Inst{30-23} = 0b00111101;
4614  let Inst{21}    = 1;
4615  let Inst{20-19} = rmode;
4616  let Inst{18-16} = opcode;
4617  let Inst{15-10} = 0b000000;
4618  let Inst{9-5}   = Rn;
4619  let Inst{4-0}   = Rd;
4620
4621  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4622}
4623
4624
4625multiclass UnscaledConversion<string asm> {
4626  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4627    let Inst{31} = 0; // 32-bit GPR flag
4628    let Inst{23-22} = 0b11; // 16-bit FPR flag
4629    let Predicates = [HasFullFP16];
4630  }
4631
4632  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4633    let Inst{31} = 1; // 64-bit GPR flag
4634    let Inst{23-22} = 0b11; // 16-bit FPR flag
4635    let Predicates = [HasFullFP16];
4636  }
4637
4638  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4639    let Inst{31} = 0; // 32-bit GPR flag
4640    let Inst{23-22} = 0b00; // 32-bit FPR flag
4641  }
4642
4643  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4644    let Inst{31} = 1; // 64-bit GPR flag
4645    let Inst{23-22} = 0b01; // 64-bit FPR flag
4646  }
4647
4648  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4649    let Inst{31} = 0; // 32-bit GPR flag
4650    let Inst{23-22} = 0b11; // 16-bit FPR flag
4651    let Predicates = [HasFullFP16];
4652  }
4653
4654  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4655    let Inst{31} = 1; // 64-bit GPR flag
4656    let Inst{23-22} = 0b11; // 16-bit FPR flag
4657    let Predicates = [HasFullFP16];
4658  }
4659
4660  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4661    let Inst{31} = 0; // 32-bit GPR flag
4662    let Inst{23-22} = 0b00; // 32-bit FPR flag
4663  }
4664
4665  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4666    let Inst{31} = 1; // 64-bit GPR flag
4667    let Inst{23-22} = 0b01; // 64-bit FPR flag
4668  }
4669
4670  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4671                                             asm, ".d"> {
4672    let Inst{31} = 1;
4673    let Inst{22} = 0;
4674  }
4675
4676  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4677                                               asm, ".d"> {
4678    let Inst{31} = 1;
4679    let Inst{22} = 0;
4680  }
4681}
4682
4683//---
4684// Floating point conversion
4685//---
4686
4687class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4688                       RegisterClass srcType, string asm, list<dag> pattern>
4689    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4690      Sched<[WriteFCvt]> {
4691  bits<5> Rd;
4692  bits<5> Rn;
4693  let Inst{31-24} = 0b00011110;
4694  let Inst{23-22} = type;
4695  let Inst{21-17} = 0b10001;
4696  let Inst{16-15} = opcode;
4697  let Inst{14-10} = 0b10000;
4698  let Inst{9-5}   = Rn;
4699  let Inst{4-0}   = Rd;
4700}
4701
4702multiclass FPConversion<string asm> {
4703  // Double-precision to Half-precision
4704  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4705                             [(set FPR16:$Rd, (any_fpround FPR64:$Rn))]>;
4706
4707  // Double-precision to Single-precision
4708  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4709                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
4710
4711  // Half-precision to Double-precision
4712  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4713                             [(set FPR64:$Rd, (fpextend FPR16:$Rn))]>;
4714
4715  // Half-precision to Single-precision
4716  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4717                             [(set FPR32:$Rd, (fpextend FPR16:$Rn))]>;
4718
4719  // Single-precision to Double-precision
4720  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4721                             [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4722
4723  // Single-precision to Half-precision
4724  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4725                             [(set FPR16:$Rd, (any_fpround FPR32:$Rn))]>;
4726}
4727
4728//---
4729// Single operand floating point data processing
4730//---
4731
4732let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4733class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4734                              ValueType vt, string asm, SDPatternOperator node>
4735    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4736         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4737      Sched<[WriteF]> {
4738  bits<5> Rd;
4739  bits<5> Rn;
4740  let Inst{31-24} = 0b00011110;
4741  let Inst{21}    = 0b1;
4742  let Inst{20-15} = opcode;
4743  let Inst{14-10} = 0b10000;
4744  let Inst{9-5}   = Rn;
4745  let Inst{4-0}   = Rd;
4746}
4747
4748multiclass SingleOperandFPData<bits<4> opcode, string asm,
4749                               SDPatternOperator node = null_frag> {
4750
4751  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4752    let Inst{23-22} = 0b11; // 16-bit size flag
4753    let Predicates = [HasFullFP16];
4754  }
4755
4756  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4757    let Inst{23-22} = 0b00; // 32-bit size flag
4758  }
4759
4760  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4761    let Inst{23-22} = 0b01; // 64-bit size flag
4762  }
4763}
4764
4765multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4766                  SDPatternOperator node = null_frag>{
4767
4768  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4769    let Inst{23-22} = 0b00; // 32-bit registers
4770  }
4771
4772  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4773    let Inst{23-22} = 0b01; // 64-bit registers
4774  }
4775}
4776
4777// FRInt[32|64][Z|N] instructions
4778multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4779      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4780
4781//---
4782// Two operand floating point data processing
4783//---
4784
4785let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4786class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4787                           string asm, list<dag> pat>
4788    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4789         asm, "\t$Rd, $Rn, $Rm", "", pat>,
4790      Sched<[WriteF]> {
4791  bits<5> Rd;
4792  bits<5> Rn;
4793  bits<5> Rm;
4794  let Inst{31-24} = 0b00011110;
4795  let Inst{21}    = 1;
4796  let Inst{20-16} = Rm;
4797  let Inst{15-12} = opcode;
4798  let Inst{11-10} = 0b10;
4799  let Inst{9-5}   = Rn;
4800  let Inst{4-0}   = Rd;
4801}
4802
4803multiclass TwoOperandFPData<bits<4> opcode, string asm,
4804                            SDPatternOperator node = null_frag> {
4805  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4806                         [(set (f16 FPR16:$Rd),
4807                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4808    let Inst{23-22} = 0b11; // 16-bit size flag
4809    let Predicates = [HasFullFP16];
4810  }
4811
4812  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4813                         [(set (f32 FPR32:$Rd),
4814                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
4815    let Inst{23-22} = 0b00; // 32-bit size flag
4816  }
4817
4818  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4819                         [(set (f64 FPR64:$Rd),
4820                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
4821    let Inst{23-22} = 0b01; // 64-bit size flag
4822  }
4823}
4824
4825multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
4826  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4827                  [(set FPR16:$Rd, (fneg (node FPR16:$Rn, (f16 FPR16:$Rm))))]> {
4828    let Inst{23-22} = 0b11; // 16-bit size flag
4829    let Predicates = [HasFullFP16];
4830  }
4831
4832  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
4833                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
4834    let Inst{23-22} = 0b00; // 32-bit size flag
4835  }
4836
4837  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
4838                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
4839    let Inst{23-22} = 0b01; // 64-bit size flag
4840  }
4841}
4842
4843
4844//---
4845// Three operand floating point data processing
4846//---
4847
4848class BaseThreeOperandFPData<bit isNegated, bit isSub,
4849                             RegisterClass regtype, string asm, list<dag> pat>
4850    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
4851         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
4852      Sched<[WriteFMul]> {
4853  bits<5> Rd;
4854  bits<5> Rn;
4855  bits<5> Rm;
4856  bits<5> Ra;
4857  let Inst{31-24} = 0b00011111;
4858  let Inst{21}    = isNegated;
4859  let Inst{20-16} = Rm;
4860  let Inst{15}    = isSub;
4861  let Inst{14-10} = Ra;
4862  let Inst{9-5}   = Rn;
4863  let Inst{4-0}   = Rd;
4864}
4865
4866multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
4867                              SDPatternOperator node> {
4868  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
4869            [(set FPR16:$Rd,
4870                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
4871    let Inst{23-22} = 0b11; // 16-bit size flag
4872    let Predicates = [HasFullFP16];
4873  }
4874
4875  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
4876            [(set FPR32:$Rd,
4877                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
4878    let Inst{23-22} = 0b00; // 32-bit size flag
4879  }
4880
4881  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
4882            [(set FPR64:$Rd,
4883                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
4884    let Inst{23-22} = 0b01; // 64-bit size flag
4885  }
4886}
4887
4888//---
4889// Floating point data comparisons
4890//---
4891
4892let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4893class BaseOneOperandFPComparison<bit signalAllNans,
4894                                 RegisterClass regtype, string asm,
4895                                 list<dag> pat>
4896    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
4897      Sched<[WriteFCmp]> {
4898  bits<5> Rn;
4899  let Inst{31-24} = 0b00011110;
4900  let Inst{21}    = 1;
4901
4902  let Inst{15-10} = 0b001000;
4903  let Inst{9-5}   = Rn;
4904  let Inst{4}     = signalAllNans;
4905  let Inst{3-0}   = 0b1000;
4906
4907  // Rm should be 0b00000 canonically, but we need to accept any value.
4908  let PostEncoderMethod = "fixOneOperandFPComparison";
4909}
4910
4911let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4912class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
4913                                string asm, list<dag> pat>
4914    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
4915      Sched<[WriteFCmp]> {
4916  bits<5> Rm;
4917  bits<5> Rn;
4918  let Inst{31-24} = 0b00011110;
4919  let Inst{21}    = 1;
4920  let Inst{20-16} = Rm;
4921  let Inst{15-10} = 0b001000;
4922  let Inst{9-5}   = Rn;
4923  let Inst{4}     = signalAllNans;
4924  let Inst{3-0}   = 0b0000;
4925}
4926
4927multiclass FPComparison<bit signalAllNans, string asm,
4928                        SDPatternOperator OpNode = null_frag> {
4929  let Defs = [NZCV] in {
4930  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
4931      [(OpNode FPR16:$Rn, (f16 FPR16:$Rm)), (implicit NZCV)]> {
4932    let Inst{23-22} = 0b11;
4933    let Predicates = [HasFullFP16];
4934  }
4935
4936  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
4937      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
4938    let Inst{23-22} = 0b11;
4939    let Predicates = [HasFullFP16];
4940  }
4941
4942  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
4943      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
4944    let Inst{23-22} = 0b00;
4945  }
4946
4947  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
4948      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
4949    let Inst{23-22} = 0b00;
4950  }
4951
4952  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
4953      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
4954    let Inst{23-22} = 0b01;
4955  }
4956
4957  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
4958      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
4959    let Inst{23-22} = 0b01;
4960  }
4961  } // Defs = [NZCV]
4962}
4963
4964//---
4965// Floating point conditional comparisons
4966//---
4967
4968let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4969class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
4970                           string mnemonic, list<dag> pat>
4971    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
4972         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
4973      Sched<[WriteFCmp]> {
4974  let Uses = [NZCV];
4975  let Defs = [NZCV];
4976
4977  bits<5> Rn;
4978  bits<5> Rm;
4979  bits<4> nzcv;
4980  bits<4> cond;
4981
4982  let Inst{31-24} = 0b00011110;
4983  let Inst{21}    = 1;
4984  let Inst{20-16} = Rm;
4985  let Inst{15-12} = cond;
4986  let Inst{11-10} = 0b01;
4987  let Inst{9-5}   = Rn;
4988  let Inst{4}     = signalAllNans;
4989  let Inst{3-0}   = nzcv;
4990}
4991
4992multiclass FPCondComparison<bit signalAllNans, string mnemonic,
4993                            SDPatternOperator OpNode = null_frag> {
4994  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
4995      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
4996                          (i32 imm:$cond), NZCV))]> {
4997    let Inst{23-22} = 0b11;
4998    let Predicates = [HasFullFP16];
4999  }
5000
5001  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5002      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5003                          (i32 imm:$cond), NZCV))]> {
5004    let Inst{23-22} = 0b00;
5005  }
5006
5007  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5008      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5009                          (i32 imm:$cond), NZCV))]> {
5010    let Inst{23-22} = 0b01;
5011  }
5012}
5013
5014//---
5015// Floating point conditional select
5016//---
5017
5018class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5019    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5020         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5021         [(set regtype:$Rd,
5022               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5023                          (i32 imm:$cond), NZCV))]>,
5024      Sched<[WriteF]> {
5025  bits<5> Rd;
5026  bits<5> Rn;
5027  bits<5> Rm;
5028  bits<4> cond;
5029
5030  let Inst{31-24} = 0b00011110;
5031  let Inst{21}    = 1;
5032  let Inst{20-16} = Rm;
5033  let Inst{15-12} = cond;
5034  let Inst{11-10} = 0b11;
5035  let Inst{9-5}   = Rn;
5036  let Inst{4-0}   = Rd;
5037}
5038
5039multiclass FPCondSelect<string asm> {
5040  let Uses = [NZCV] in {
5041  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5042    let Inst{23-22} = 0b11;
5043    let Predicates = [HasFullFP16];
5044  }
5045
5046  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5047    let Inst{23-22} = 0b00;
5048  }
5049
5050  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5051    let Inst{23-22} = 0b01;
5052  }
5053  } // Uses = [NZCV]
5054}
5055
5056//---
5057// Floating move immediate
5058//---
5059
5060class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5061  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5062      [(set regtype:$Rd, fpimmtype:$imm)]>,
5063    Sched<[WriteFImm]> {
5064  bits<5> Rd;
5065  bits<8> imm;
5066  let Inst{31-24} = 0b00011110;
5067  let Inst{21}    = 1;
5068  let Inst{20-13} = imm;
5069  let Inst{12-5}  = 0b10000000;
5070  let Inst{4-0}   = Rd;
5071}
5072
5073multiclass FPMoveImmediate<string asm> {
5074  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5075    let Inst{23-22} = 0b11;
5076    let Predicates = [HasFullFP16];
5077  }
5078
5079  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5080    let Inst{23-22} = 0b00;
5081  }
5082
5083  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5084    let Inst{23-22} = 0b01;
5085  }
5086}
5087} // end of 'let Predicates = [HasFPARMv8]'
5088
5089//----------------------------------------------------------------------------
5090// AdvSIMD
5091//----------------------------------------------------------------------------
5092
5093let Predicates = [HasNEON] in {
5094
5095//----------------------------------------------------------------------------
5096// AdvSIMD three register vector instructions
5097//----------------------------------------------------------------------------
5098
5099let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5100class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5101                        RegisterOperand regtype, string asm, string kind,
5102                        list<dag> pattern>
5103  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5104      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5105      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5106    Sched<[WriteV]> {
5107  bits<5> Rd;
5108  bits<5> Rn;
5109  bits<5> Rm;
5110  let Inst{31}    = 0;
5111  let Inst{30}    = Q;
5112  let Inst{29}    = U;
5113  let Inst{28-24} = 0b01110;
5114  let Inst{23-21} = size;
5115  let Inst{20-16} = Rm;
5116  let Inst{15-11} = opcode;
5117  let Inst{10}    = 1;
5118  let Inst{9-5}   = Rn;
5119  let Inst{4-0}   = Rd;
5120}
5121
5122let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5123class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5124                        RegisterOperand regtype, string asm, string kind,
5125                        list<dag> pattern>
5126  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5127      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5128      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5129    Sched<[WriteV]> {
5130  bits<5> Rd;
5131  bits<5> Rn;
5132  bits<5> Rm;
5133  let Inst{31}    = 0;
5134  let Inst{30}    = Q;
5135  let Inst{29}    = U;
5136  let Inst{28-24} = 0b01110;
5137  let Inst{23-21} = size;
5138  let Inst{20-16} = Rm;
5139  let Inst{15-11} = opcode;
5140  let Inst{10}    = 1;
5141  let Inst{9-5}   = Rn;
5142  let Inst{4-0}   = Rd;
5143}
5144
5145// All operand sizes distinguished in the encoding.
5146multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5147                               SDPatternOperator OpNode> {
5148  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5149                                      asm, ".8b",
5150         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5151  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5152                                      asm, ".16b",
5153         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5154  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5155                                      asm, ".4h",
5156         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5157  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5158                                      asm, ".8h",
5159         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5160  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5161                                      asm, ".2s",
5162         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5163  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5164                                      asm, ".4s",
5165         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5166  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5167                                      asm, ".2d",
5168         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5169}
5170
5171multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5172  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5173          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5174  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5175          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5176  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5177          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5178
5179  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5180          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5181  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5182          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5183  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5184          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5185  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5186          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5187}
5188
5189// As above, but D sized elements unsupported.
5190multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5191                                  SDPatternOperator OpNode> {
5192  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5193                                      asm, ".8b",
5194        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5195  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5196                                      asm, ".16b",
5197        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5198  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5199                                      asm, ".4h",
5200        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5201  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5202                                      asm, ".8h",
5203        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5204  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5205                                      asm, ".2s",
5206        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5207  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5208                                      asm, ".4s",
5209        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5210}
5211
5212multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5213                                  SDPatternOperator OpNode> {
5214  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5215                                      asm, ".8b",
5216      [(set (v8i8 V64:$dst),
5217            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5218  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5219                                      asm, ".16b",
5220      [(set (v16i8 V128:$dst),
5221            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5222  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5223                                      asm, ".4h",
5224      [(set (v4i16 V64:$dst),
5225            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5226  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5227                                      asm, ".8h",
5228      [(set (v8i16 V128:$dst),
5229            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5230  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5231                                      asm, ".2s",
5232      [(set (v2i32 V64:$dst),
5233            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5234  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5235                                      asm, ".4s",
5236      [(set (v4i32 V128:$dst),
5237            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5238}
5239
5240// As above, but only B sized elements supported.
5241multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5242                                SDPatternOperator OpNode> {
5243  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5244                                      asm, ".8b",
5245    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5246  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5247                                      asm, ".16b",
5248    [(set (v16i8 V128:$Rd),
5249          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5250}
5251
5252// As above, but only floating point elements supported.
5253multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5254                                 string asm, SDPatternOperator OpNode> {
5255  let Predicates = [HasNEON, HasFullFP16] in {
5256  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5257                                      asm, ".4h",
5258        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5259  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5260                                      asm, ".8h",
5261        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5262  } // Predicates = [HasNEON, HasFullFP16]
5263  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5264                                      asm, ".2s",
5265        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5266  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5267                                      asm, ".4s",
5268        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5269  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5270                                      asm, ".2d",
5271        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5272}
5273
5274multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5275                                    string asm,
5276                                    SDPatternOperator OpNode> {
5277  let Predicates = [HasNEON, HasFullFP16] in {
5278  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5279                                      asm, ".4h",
5280        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5281  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5282                                      asm, ".8h",
5283        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5284  } // Predicates = [HasNEON, HasFullFP16]
5285  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5286                                      asm, ".2s",
5287        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5288  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5289                                      asm, ".4s",
5290        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5291  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5292                                      asm, ".2d",
5293        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5294}
5295
5296multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5297                                 string asm, SDPatternOperator OpNode> {
5298  let Predicates = [HasNEON, HasFullFP16] in {
5299  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5300                                      asm, ".4h",
5301     [(set (v4f16 V64:$dst),
5302           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5303  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5304                                      asm, ".8h",
5305     [(set (v8f16 V128:$dst),
5306           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5307  } // Predicates = [HasNEON, HasFullFP16]
5308  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5309                                      asm, ".2s",
5310     [(set (v2f32 V64:$dst),
5311           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5312  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5313                                      asm, ".4s",
5314     [(set (v4f32 V128:$dst),
5315           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5316  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5317                                      asm, ".2d",
5318     [(set (v2f64 V128:$dst),
5319           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5320}
5321
5322// As above, but D and B sized elements unsupported.
5323multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5324                                SDPatternOperator OpNode> {
5325  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5326                                      asm, ".4h",
5327        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5328  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5329                                      asm, ".8h",
5330        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5331  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5332                                      asm, ".2s",
5333        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5334  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5335                                      asm, ".4s",
5336        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5337}
5338
5339// Logical three vector ops share opcode bits, and only use B sized elements.
5340multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5341                                  SDPatternOperator OpNode = null_frag> {
5342  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5343                                     asm, ".8b",
5344                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5345  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5346                                     asm, ".16b",
5347                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5348
5349  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5350          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5351  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5352          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5353  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5354          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5355
5356  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5357      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5358  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5359      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5360  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5361      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5362}
5363
5364multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5365                                  string asm, SDPatternOperator OpNode> {
5366  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5367                                     asm, ".8b",
5368             [(set (v8i8 V64:$dst),
5369                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5370  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5371                                     asm, ".16b",
5372             [(set (v16i8 V128:$dst),
5373                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5374                           (v16i8 V128:$Rm)))]>;
5375
5376  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5377                           (v4i16 V64:$RHS))),
5378          (!cast<Instruction>(NAME#"v8i8")
5379            V64:$LHS, V64:$MHS, V64:$RHS)>;
5380  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5381                           (v2i32 V64:$RHS))),
5382          (!cast<Instruction>(NAME#"v8i8")
5383            V64:$LHS, V64:$MHS, V64:$RHS)>;
5384  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5385                           (v1i64 V64:$RHS))),
5386          (!cast<Instruction>(NAME#"v8i8")
5387            V64:$LHS, V64:$MHS, V64:$RHS)>;
5388
5389  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5390                           (v8i16 V128:$RHS))),
5391      (!cast<Instruction>(NAME#"v16i8")
5392        V128:$LHS, V128:$MHS, V128:$RHS)>;
5393  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5394                           (v4i32 V128:$RHS))),
5395      (!cast<Instruction>(NAME#"v16i8")
5396        V128:$LHS, V128:$MHS, V128:$RHS)>;
5397  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5398                           (v2i64 V128:$RHS))),
5399      (!cast<Instruction>(NAME#"v16i8")
5400        V128:$LHS, V128:$MHS, V128:$RHS)>;
5401}
5402
5403// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5404// bytes from S-sized elements.
5405class BaseSIMDThreeSameVectorDot<bit Q, bit U, string asm, string kind1,
5406                                 string kind2, RegisterOperand RegType,
5407                                 ValueType AccumType, ValueType InputType,
5408                                 SDPatternOperator OpNode> :
5409        BaseSIMDThreeSameVectorTied<Q, U, 0b100, 0b10010, RegType, asm, kind1,
5410        [(set (AccumType RegType:$dst),
5411              (OpNode (AccumType RegType:$Rd),
5412                      (InputType RegType:$Rn),
5413                      (InputType RegType:$Rm)))]> {
5414  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5415}
5416
5417multiclass SIMDThreeSameVectorDot<bit U, string asm, SDPatternOperator OpNode> {
5418  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, asm, ".2s", ".8b", V64,
5419                                         v2i32, v8i8, OpNode>;
5420  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, asm, ".4s", ".16b", V128,
5421                                         v4i32, v16i8, OpNode>;
5422}
5423
5424// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5425// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5426// 8H to 4S, when Q=1).
5427class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5428                                 string kind2, RegisterOperand RegType,
5429                                 ValueType AccumType, ValueType InputType,
5430                                 SDPatternOperator OpNode> :
5431        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5432		[(set (AccumType RegType:$dst),
5433              (OpNode (AccumType RegType:$Rd),
5434                      (InputType RegType:$Rn),
5435                      (InputType RegType:$Rm)))]> {
5436  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5437  let Inst{13} = b13;
5438}
5439
5440multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5441                                  SDPatternOperator OpNode> {
5442  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5443                                         v2f32, v4f16, OpNode>;
5444  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5445                                         v4f32, v8f16, OpNode>;
5446}
5447
5448
5449//----------------------------------------------------------------------------
5450// AdvSIMD two register vector instructions.
5451//----------------------------------------------------------------------------
5452
5453let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5454class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5455                            bits<2> size2, RegisterOperand regtype, string asm,
5456                            string dstkind, string srckind, list<dag> pattern>
5457  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5458      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5459      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5460    Sched<[WriteV]> {
5461  bits<5> Rd;
5462  bits<5> Rn;
5463  let Inst{31}    = 0;
5464  let Inst{30}    = Q;
5465  let Inst{29}    = U;
5466  let Inst{28-24} = 0b01110;
5467  let Inst{23-22} = size;
5468  let Inst{21} = 0b1;
5469  let Inst{20-19} = size2;
5470  let Inst{18-17} = 0b00;
5471  let Inst{16-12} = opcode;
5472  let Inst{11-10} = 0b10;
5473  let Inst{9-5}   = Rn;
5474  let Inst{4-0}   = Rd;
5475}
5476
5477let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5478class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5479                                bits<2> size2, RegisterOperand regtype,
5480                                string asm, string dstkind, string srckind,
5481                                list<dag> pattern>
5482  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5483      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5484      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5485    Sched<[WriteV]> {
5486  bits<5> Rd;
5487  bits<5> Rn;
5488  let Inst{31}    = 0;
5489  let Inst{30}    = Q;
5490  let Inst{29}    = U;
5491  let Inst{28-24} = 0b01110;
5492  let Inst{23-22} = size;
5493  let Inst{21} = 0b1;
5494  let Inst{20-19} = size2;
5495  let Inst{18-17} = 0b00;
5496  let Inst{16-12} = opcode;
5497  let Inst{11-10} = 0b10;
5498  let Inst{9-5}   = Rn;
5499  let Inst{4-0}   = Rd;
5500}
5501
5502// Supports B, H, and S element sizes.
5503multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5504                            SDPatternOperator OpNode> {
5505  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5506                                      asm, ".8b", ".8b",
5507                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5508  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5509                                      asm, ".16b", ".16b",
5510                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5511  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5512                                      asm, ".4h", ".4h",
5513                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5514  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5515                                      asm, ".8h", ".8h",
5516                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5517  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5518                                      asm, ".2s", ".2s",
5519                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5520  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5521                                      asm, ".4s", ".4s",
5522                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5523}
5524
5525class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5526                            RegisterOperand regtype, string asm, string dstkind,
5527                            string srckind, string amount>
5528  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5529      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5530      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5531    Sched<[WriteV]> {
5532  bits<5> Rd;
5533  bits<5> Rn;
5534  let Inst{31}    = 0;
5535  let Inst{30}    = Q;
5536  let Inst{29-24} = 0b101110;
5537  let Inst{23-22} = size;
5538  let Inst{21-10} = 0b100001001110;
5539  let Inst{9-5}   = Rn;
5540  let Inst{4-0}   = Rd;
5541}
5542
5543multiclass SIMDVectorLShiftLongBySizeBHS {
5544  let hasSideEffects = 0 in {
5545  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5546                                             "shll", ".8h",  ".8b", "8">;
5547  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5548                                             "shll2", ".8h", ".16b", "8">;
5549  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5550                                             "shll", ".4s",  ".4h", "16">;
5551  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5552                                             "shll2", ".4s", ".8h", "16">;
5553  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5554                                             "shll", ".2d",  ".2s", "32">;
5555  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5556                                             "shll2", ".2d", ".4s", "32">;
5557  }
5558}
5559
5560// Supports all element sizes.
5561multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5562                             SDPatternOperator OpNode> {
5563  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5564                                      asm, ".4h", ".8b",
5565               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5566  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5567                                      asm, ".8h", ".16b",
5568               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5569  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5570                                      asm, ".2s", ".4h",
5571               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5572  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5573                                      asm, ".4s", ".8h",
5574               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5575  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5576                                      asm, ".1d", ".2s",
5577               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5578  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5579                                      asm, ".2d", ".4s",
5580               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5581}
5582
5583multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5584                                 SDPatternOperator OpNode> {
5585  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5586                                          asm, ".4h", ".8b",
5587      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5588                                      (v8i8 V64:$Rn)))]>;
5589  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5590                                          asm, ".8h", ".16b",
5591      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5592                                      (v16i8 V128:$Rn)))]>;
5593  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5594                                          asm, ".2s", ".4h",
5595      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5596                                      (v4i16 V64:$Rn)))]>;
5597  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5598                                          asm, ".4s", ".8h",
5599      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5600                                      (v8i16 V128:$Rn)))]>;
5601  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5602                                          asm, ".1d", ".2s",
5603      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5604                                      (v2i32 V64:$Rn)))]>;
5605  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5606                                          asm, ".2d", ".4s",
5607      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5608                                      (v4i32 V128:$Rn)))]>;
5609}
5610
5611// Supports all element sizes, except 1xD.
5612multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5613                                  SDPatternOperator OpNode> {
5614  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5615                                    asm, ".8b", ".8b",
5616    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5617  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5618                                    asm, ".16b", ".16b",
5619    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5620  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5621                                    asm, ".4h", ".4h",
5622    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5623  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5624                                    asm, ".8h", ".8h",
5625    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5626  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5627                                    asm, ".2s", ".2s",
5628    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5629  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5630                                    asm, ".4s", ".4s",
5631    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5632  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5633                                    asm, ".2d", ".2d",
5634    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5635}
5636
5637multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5638                             SDPatternOperator OpNode = null_frag> {
5639  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5640                                asm, ".8b", ".8b",
5641    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5642  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5643                                asm, ".16b", ".16b",
5644    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5645  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5646                                asm, ".4h", ".4h",
5647    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5648  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5649                                asm, ".8h", ".8h",
5650    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5651  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5652                                asm, ".2s", ".2s",
5653    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5654  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5655                                asm, ".4s", ".4s",
5656    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5657  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5658                                asm, ".2d", ".2d",
5659    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5660}
5661
5662
5663// Supports only B element sizes.
5664multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5665                          SDPatternOperator OpNode> {
5666  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5667                                asm, ".8b", ".8b",
5668                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5669  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5670                                asm, ".16b", ".16b",
5671                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5672
5673}
5674
5675// Supports only B and H element sizes.
5676multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5677                                SDPatternOperator OpNode> {
5678  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5679                                asm, ".8b", ".8b",
5680                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5681  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5682                                asm, ".16b", ".16b",
5683                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5684  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5685                                asm, ".4h", ".4h",
5686                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5687  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5688                                asm, ".8h", ".8h",
5689                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5690}
5691
5692// Supports H, S and D element sizes, uses high bit of the size field
5693// as an extra opcode bit.
5694multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5695                           SDPatternOperator OpNode> {
5696  let Predicates = [HasNEON, HasFullFP16] in {
5697  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5698                                asm, ".4h", ".4h",
5699                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5700  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5701                                asm, ".8h", ".8h",
5702                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5703  } // Predicates = [HasNEON, HasFullFP16]
5704  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5705                                asm, ".2s", ".2s",
5706                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5707  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5708                                asm, ".4s", ".4s",
5709                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5710  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5711                                asm, ".2d", ".2d",
5712                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5713}
5714
5715// Supports only S and D element sizes
5716multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5717                           SDPatternOperator OpNode = null_frag> {
5718
5719  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5720                                asm, ".2s", ".2s",
5721                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5722  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5723                                asm, ".4s", ".4s",
5724                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5725  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5726                                asm, ".2d", ".2d",
5727                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5728}
5729
5730multiclass FRIntNNTVector<bit U, bit op, string asm,
5731                          SDPatternOperator OpNode = null_frag> :
5732           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5733
5734// Supports only S element size.
5735multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5736                           SDPatternOperator OpNode> {
5737  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5738                                asm, ".2s", ".2s",
5739                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5740  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5741                                asm, ".4s", ".4s",
5742                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5743}
5744
5745
5746multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5747                           SDPatternOperator OpNode> {
5748  let Predicates = [HasNEON, HasFullFP16] in {
5749  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5750                                asm, ".4h", ".4h",
5751                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5752  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5753                                asm, ".8h", ".8h",
5754                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5755  } // Predicates = [HasNEON, HasFullFP16]
5756  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5757                                asm, ".2s", ".2s",
5758                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5759  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5760                                asm, ".4s", ".4s",
5761                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5762  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5763                                asm, ".2d", ".2d",
5764                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5765}
5766
5767multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5768                           SDPatternOperator OpNode> {
5769  let Predicates = [HasNEON, HasFullFP16] in {
5770  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5771                                asm, ".4h", ".4h",
5772                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5773  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5774                                asm, ".8h", ".8h",
5775                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5776  } // Predicates = [HasNEON, HasFullFP16]
5777  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5778                                asm, ".2s", ".2s",
5779                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5780  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5781                                asm, ".4s", ".4s",
5782                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5783  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5784                                asm, ".2d", ".2d",
5785                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5786}
5787
5788
5789class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5790                           RegisterOperand inreg, RegisterOperand outreg,
5791                           string asm, string outkind, string inkind,
5792                           list<dag> pattern>
5793  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
5794      "{\t$Rd" # outkind # ", $Rn" # inkind #
5795      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
5796    Sched<[WriteV]> {
5797  bits<5> Rd;
5798  bits<5> Rn;
5799  let Inst{31}    = 0;
5800  let Inst{30}    = Q;
5801  let Inst{29}    = U;
5802  let Inst{28-24} = 0b01110;
5803  let Inst{23-22} = size;
5804  let Inst{21-17} = 0b10000;
5805  let Inst{16-12} = opcode;
5806  let Inst{11-10} = 0b10;
5807  let Inst{9-5}   = Rn;
5808  let Inst{4-0}   = Rd;
5809}
5810
5811class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5812                           RegisterOperand inreg, RegisterOperand outreg,
5813                           string asm, string outkind, string inkind,
5814                           list<dag> pattern>
5815  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
5816      "{\t$Rd" # outkind # ", $Rn" # inkind #
5817      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5818    Sched<[WriteV]> {
5819  bits<5> Rd;
5820  bits<5> Rn;
5821  let Inst{31}    = 0;
5822  let Inst{30}    = Q;
5823  let Inst{29}    = U;
5824  let Inst{28-24} = 0b01110;
5825  let Inst{23-22} = size;
5826  let Inst{21-17} = 0b10000;
5827  let Inst{16-12} = opcode;
5828  let Inst{11-10} = 0b10;
5829  let Inst{9-5}   = Rn;
5830  let Inst{4-0}   = Rd;
5831}
5832
5833multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
5834                              SDPatternOperator OpNode> {
5835  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
5836                                      asm, ".8b", ".8h",
5837        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5838  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
5839                                      asm#"2", ".16b", ".8h", []>;
5840  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
5841                                      asm, ".4h", ".4s",
5842        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5843  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
5844                                      asm#"2", ".8h", ".4s", []>;
5845  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
5846                                      asm, ".2s", ".2d",
5847        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5848  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
5849                                      asm#"2", ".4s", ".2d", []>;
5850
5851  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
5852            (!cast<Instruction>(NAME # "v16i8")
5853                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5854  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
5855            (!cast<Instruction>(NAME # "v8i16")
5856                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5857  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
5858            (!cast<Instruction>(NAME # "v4i32")
5859                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
5860}
5861
5862class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
5863                           bits<5> opcode, RegisterOperand regtype, string asm,
5864                           string kind, string zero, ValueType dty,
5865                           ValueType sty, SDNode OpNode>
5866  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5867      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
5868      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
5869      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
5870    Sched<[WriteV]> {
5871  bits<5> Rd;
5872  bits<5> Rn;
5873  let Inst{31}    = 0;
5874  let Inst{30}    = Q;
5875  let Inst{29}    = U;
5876  let Inst{28-24} = 0b01110;
5877  let Inst{23-22} = size;
5878  let Inst{21} = 0b1;
5879  let Inst{20-19} = size2;
5880  let Inst{18-17} = 0b00;
5881  let Inst{16-12} = opcode;
5882  let Inst{11-10} = 0b10;
5883  let Inst{9-5}   = Rn;
5884  let Inst{4-0}   = Rd;
5885}
5886
5887// Comparisons support all element sizes, except 1xD.
5888multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
5889                            SDNode OpNode> {
5890  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
5891                                     asm, ".8b", "0",
5892                                     v8i8, v8i8, OpNode>;
5893  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
5894                                     asm, ".16b", "0",
5895                                     v16i8, v16i8, OpNode>;
5896  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
5897                                     asm, ".4h", "0",
5898                                     v4i16, v4i16, OpNode>;
5899  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
5900                                     asm, ".8h", "0",
5901                                     v8i16, v8i16, OpNode>;
5902  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
5903                                     asm, ".2s", "0",
5904                                     v2i32, v2i32, OpNode>;
5905  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
5906                                     asm, ".4s", "0",
5907                                     v4i32, v4i32, OpNode>;
5908  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
5909                                     asm, ".2d", "0",
5910                                     v2i64, v2i64, OpNode>;
5911}
5912
5913// FP Comparisons support only S and D element sizes (and H for v8.2a).
5914multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
5915                              string asm, SDNode OpNode> {
5916
5917  let Predicates = [HasNEON, HasFullFP16] in {
5918  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
5919                                     asm, ".4h", "0.0",
5920                                     v4i16, v4f16, OpNode>;
5921  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
5922                                     asm, ".8h", "0.0",
5923                                     v8i16, v8f16, OpNode>;
5924  } // Predicates = [HasNEON, HasFullFP16]
5925  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
5926                                     asm, ".2s", "0.0",
5927                                     v2i32, v2f32, OpNode>;
5928  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
5929                                     asm, ".4s", "0.0",
5930                                     v4i32, v4f32, OpNode>;
5931  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
5932                                     asm, ".2d", "0.0",
5933                                     v2i64, v2f64, OpNode>;
5934
5935  let Predicates = [HasNEON, HasFullFP16] in {
5936  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
5937                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5938  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
5939                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5940  }
5941  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
5942                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5943  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
5944                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5945  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
5946                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5947  let Predicates = [HasNEON, HasFullFP16] in {
5948  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
5949                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
5950  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
5951                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
5952  }
5953  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
5954                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
5955  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
5956                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
5957  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
5958                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
5959}
5960
5961let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5962class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5963                             RegisterOperand outtype, RegisterOperand intype,
5964                             string asm, string VdTy, string VnTy,
5965                             list<dag> pattern>
5966  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
5967      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
5968    Sched<[WriteV]> {
5969  bits<5> Rd;
5970  bits<5> Rn;
5971  let Inst{31}    = 0;
5972  let Inst{30}    = Q;
5973  let Inst{29}    = U;
5974  let Inst{28-24} = 0b01110;
5975  let Inst{23-22} = size;
5976  let Inst{21-17} = 0b10000;
5977  let Inst{16-12} = opcode;
5978  let Inst{11-10} = 0b10;
5979  let Inst{9-5}   = Rn;
5980  let Inst{4-0}   = Rd;
5981}
5982
5983class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5984                             RegisterOperand outtype, RegisterOperand intype,
5985                             string asm, string VdTy, string VnTy,
5986                             list<dag> pattern>
5987  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
5988      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
5989    Sched<[WriteV]> {
5990  bits<5> Rd;
5991  bits<5> Rn;
5992  let Inst{31}    = 0;
5993  let Inst{30}    = Q;
5994  let Inst{29}    = U;
5995  let Inst{28-24} = 0b01110;
5996  let Inst{23-22} = size;
5997  let Inst{21-17} = 0b10000;
5998  let Inst{16-12} = opcode;
5999  let Inst{11-10} = 0b10;
6000  let Inst{9-5}   = Rn;
6001  let Inst{4-0}   = Rd;
6002}
6003
6004multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6005  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6006                                    asm, ".4s", ".4h", []>;
6007  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6008                                    asm#"2", ".4s", ".8h", []>;
6009  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6010                                    asm, ".2d", ".2s", []>;
6011  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6012                                    asm#"2", ".2d", ".4s", []>;
6013}
6014
6015multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6016  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6017                                    asm, ".4h", ".4s", []>;
6018  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6019                                    asm#"2", ".8h", ".4s", []>;
6020  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6021                                    asm, ".2s", ".2d", []>;
6022  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6023                                    asm#"2", ".4s", ".2d", []>;
6024}
6025
6026multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6027                                     Intrinsic OpNode> {
6028  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6029                                     asm, ".2s", ".2d",
6030                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6031  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6032                                    asm#"2", ".4s", ".2d", []>;
6033
6034  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6035            (!cast<Instruction>(NAME # "v4f32")
6036                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6037}
6038
6039//----------------------------------------------------------------------------
6040// AdvSIMD three register different-size vector instructions.
6041//----------------------------------------------------------------------------
6042
6043let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6044class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6045                      RegisterOperand outtype, RegisterOperand intype1,
6046                      RegisterOperand intype2, string asm,
6047                      string outkind, string inkind1, string inkind2,
6048                      list<dag> pattern>
6049  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6050      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6051      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6052    Sched<[WriteV]> {
6053  bits<5> Rd;
6054  bits<5> Rn;
6055  bits<5> Rm;
6056  let Inst{31}    = 0;
6057  let Inst{30}    = size{0};
6058  let Inst{29}    = U;
6059  let Inst{28-24} = 0b01110;
6060  let Inst{23-22} = size{2-1};
6061  let Inst{21}    = 1;
6062  let Inst{20-16} = Rm;
6063  let Inst{15-12} = opcode;
6064  let Inst{11-10} = 0b00;
6065  let Inst{9-5}   = Rn;
6066  let Inst{4-0}   = Rd;
6067}
6068
6069let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6070class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6071                      RegisterOperand outtype, RegisterOperand intype1,
6072                      RegisterOperand intype2, string asm,
6073                      string outkind, string inkind1, string inkind2,
6074                      list<dag> pattern>
6075  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6076      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6077      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6078    Sched<[WriteV]> {
6079  bits<5> Rd;
6080  bits<5> Rn;
6081  bits<5> Rm;
6082  let Inst{31}    = 0;
6083  let Inst{30}    = size{0};
6084  let Inst{29}    = U;
6085  let Inst{28-24} = 0b01110;
6086  let Inst{23-22} = size{2-1};
6087  let Inst{21}    = 1;
6088  let Inst{20-16} = Rm;
6089  let Inst{15-12} = opcode;
6090  let Inst{11-10} = 0b00;
6091  let Inst{9-5}   = Rn;
6092  let Inst{4-0}   = Rd;
6093}
6094
6095// FIXME: TableGen doesn't know how to deal with expanded types that also
6096//        change the element count (in this case, placing the results in
6097//        the high elements of the result register rather than the low
6098//        elements). Until that's fixed, we can't code-gen those.
6099multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6100                                    Intrinsic IntOp> {
6101  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6102                                                  V64, V128, V128,
6103                                                  asm, ".8b", ".8h", ".8h",
6104     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6105  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6106                                                  V128, V128, V128,
6107                                                  asm#"2", ".16b", ".8h", ".8h",
6108     []>;
6109  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6110                                                  V64, V128, V128,
6111                                                  asm, ".4h", ".4s", ".4s",
6112     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6113  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6114                                                  V128, V128, V128,
6115                                                  asm#"2", ".8h", ".4s", ".4s",
6116     []>;
6117  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6118                                                  V64, V128, V128,
6119                                                  asm, ".2s", ".2d", ".2d",
6120     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6121  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6122                                                  V128, V128, V128,
6123                                                  asm#"2", ".4s", ".2d", ".2d",
6124     []>;
6125
6126
6127  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6128  // a version attached to an instruction.
6129  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6130                                                   (v8i16 V128:$Rm))),
6131            (!cast<Instruction>(NAME # "v8i16_v16i8")
6132                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6133                V128:$Rn, V128:$Rm)>;
6134  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6135                                                    (v4i32 V128:$Rm))),
6136            (!cast<Instruction>(NAME # "v4i32_v8i16")
6137                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6138                V128:$Rn, V128:$Rm)>;
6139  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6140                                                    (v2i64 V128:$Rm))),
6141            (!cast<Instruction>(NAME # "v2i64_v4i32")
6142                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6143                V128:$Rn, V128:$Rm)>;
6144}
6145
6146multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6147                                      Intrinsic IntOp> {
6148  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6149                                            V128, V64, V64,
6150                                            asm, ".8h", ".8b", ".8b",
6151      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6152  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6153                                            V128, V128, V128,
6154                                            asm#"2", ".8h", ".16b", ".16b", []>;
6155  let Predicates = [HasAES] in {
6156    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6157                                              V128, V64, V64,
6158                                              asm, ".1q", ".1d", ".1d", []>;
6159    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6160                                              V128, V128, V128,
6161                                              asm#"2", ".1q", ".2d", ".2d", []>;
6162  }
6163
6164  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
6165                          (v8i8 (extract_high_v16i8 V128:$Rm)))),
6166      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6167}
6168
6169multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6170                                 SDPatternOperator OpNode> {
6171  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6172                                                  V128, V64, V64,
6173                                                  asm, ".4s", ".4h", ".4h",
6174      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6175  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6176                                                  V128, V128, V128,
6177                                                  asm#"2", ".4s", ".8h", ".8h",
6178      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6179                                      (extract_high_v8i16 V128:$Rm)))]>;
6180  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6181                                                  V128, V64, V64,
6182                                                  asm, ".2d", ".2s", ".2s",
6183      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6184  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6185                                                  V128, V128, V128,
6186                                                  asm#"2", ".2d", ".4s", ".4s",
6187      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6188                                      (extract_high_v4i32 V128:$Rm)))]>;
6189}
6190
6191multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6192                                  SDPatternOperator OpNode = null_frag> {
6193  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6194                                                  V128, V64, V64,
6195                                                  asm, ".8h", ".8b", ".8b",
6196      [(set (v8i16 V128:$Rd),
6197            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6198  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6199                                                 V128, V128, V128,
6200                                                 asm#"2", ".8h", ".16b", ".16b",
6201      [(set (v8i16 V128:$Rd),
6202            (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6203                                (extract_high_v16i8 V128:$Rm)))))]>;
6204  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6205                                                  V128, V64, V64,
6206                                                  asm, ".4s", ".4h", ".4h",
6207      [(set (v4i32 V128:$Rd),
6208            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6209  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6210                                                  V128, V128, V128,
6211                                                  asm#"2", ".4s", ".8h", ".8h",
6212      [(set (v4i32 V128:$Rd),
6213            (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6214                                  (extract_high_v8i16 V128:$Rm)))))]>;
6215  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6216                                                  V128, V64, V64,
6217                                                  asm, ".2d", ".2s", ".2s",
6218      [(set (v2i64 V128:$Rd),
6219            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6220  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6221                                                  V128, V128, V128,
6222                                                  asm#"2", ".2d", ".4s", ".4s",
6223      [(set (v2i64 V128:$Rd),
6224            (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6225                                 (extract_high_v4i32 V128:$Rm)))))]>;
6226}
6227
6228multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6229                                          string asm,
6230                                          SDPatternOperator OpNode> {
6231  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6232                                                  V128, V64, V64,
6233                                                  asm, ".8h", ".8b", ".8b",
6234    [(set (v8i16 V128:$dst),
6235          (add (v8i16 V128:$Rd),
6236               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6237  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6238                                                 V128, V128, V128,
6239                                                 asm#"2", ".8h", ".16b", ".16b",
6240    [(set (v8i16 V128:$dst),
6241          (add (v8i16 V128:$Rd),
6242               (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6243                                   (extract_high_v16i8 V128:$Rm))))))]>;
6244  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6245                                                  V128, V64, V64,
6246                                                  asm, ".4s", ".4h", ".4h",
6247    [(set (v4i32 V128:$dst),
6248          (add (v4i32 V128:$Rd),
6249               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6250  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6251                                                  V128, V128, V128,
6252                                                  asm#"2", ".4s", ".8h", ".8h",
6253    [(set (v4i32 V128:$dst),
6254          (add (v4i32 V128:$Rd),
6255               (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6256                                    (extract_high_v8i16 V128:$Rm))))))]>;
6257  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6258                                                  V128, V64, V64,
6259                                                  asm, ".2d", ".2s", ".2s",
6260    [(set (v2i64 V128:$dst),
6261          (add (v2i64 V128:$Rd),
6262               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6263  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6264                                                  V128, V128, V128,
6265                                                  asm#"2", ".2d", ".4s", ".4s",
6266    [(set (v2i64 V128:$dst),
6267          (add (v2i64 V128:$Rd),
6268               (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6269                                    (extract_high_v4i32 V128:$Rm))))))]>;
6270}
6271
6272multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6273                                  SDPatternOperator OpNode = null_frag> {
6274  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6275                                                  V128, V64, V64,
6276                                                  asm, ".8h", ".8b", ".8b",
6277      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6278  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6279                                                 V128, V128, V128,
6280                                                 asm#"2", ".8h", ".16b", ".16b",
6281      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6282                                      (extract_high_v16i8 V128:$Rm)))]>;
6283  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6284                                                  V128, V64, V64,
6285                                                  asm, ".4s", ".4h", ".4h",
6286      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6287  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6288                                                  V128, V128, V128,
6289                                                  asm#"2", ".4s", ".8h", ".8h",
6290      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6291                                      (extract_high_v8i16 V128:$Rm)))]>;
6292  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6293                                                  V128, V64, V64,
6294                                                  asm, ".2d", ".2s", ".2s",
6295      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6296  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6297                                                  V128, V128, V128,
6298                                                  asm#"2", ".2d", ".4s", ".4s",
6299      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6300                                      (extract_high_v4i32 V128:$Rm)))]>;
6301}
6302
6303multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6304                                      string asm,
6305                                      SDPatternOperator OpNode> {
6306  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6307                                                  V128, V64, V64,
6308                                                  asm, ".8h", ".8b", ".8b",
6309    [(set (v8i16 V128:$dst),
6310          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6311  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6312                                                 V128, V128, V128,
6313                                                 asm#"2", ".8h", ".16b", ".16b",
6314    [(set (v8i16 V128:$dst),
6315          (OpNode (v8i16 V128:$Rd),
6316                  (extract_high_v16i8 V128:$Rn),
6317                  (extract_high_v16i8 V128:$Rm)))]>;
6318  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6319                                                  V128, V64, V64,
6320                                                  asm, ".4s", ".4h", ".4h",
6321    [(set (v4i32 V128:$dst),
6322          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6323  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6324                                                  V128, V128, V128,
6325                                                  asm#"2", ".4s", ".8h", ".8h",
6326    [(set (v4i32 V128:$dst),
6327          (OpNode (v4i32 V128:$Rd),
6328                  (extract_high_v8i16 V128:$Rn),
6329                  (extract_high_v8i16 V128:$Rm)))]>;
6330  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6331                                                  V128, V64, V64,
6332                                                  asm, ".2d", ".2s", ".2s",
6333    [(set (v2i64 V128:$dst),
6334          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6335  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6336                                                  V128, V128, V128,
6337                                                  asm#"2", ".2d", ".4s", ".4s",
6338    [(set (v2i64 V128:$dst),
6339          (OpNode (v2i64 V128:$Rd),
6340                  (extract_high_v4i32 V128:$Rn),
6341                  (extract_high_v4i32 V128:$Rm)))]>;
6342}
6343
6344multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6345                                           SDPatternOperator Accum> {
6346  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6347                                                  V128, V64, V64,
6348                                                  asm, ".4s", ".4h", ".4h",
6349    [(set (v4i32 V128:$dst),
6350          (Accum (v4i32 V128:$Rd),
6351                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6352                                                (v4i16 V64:$Rm)))))]>;
6353  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6354                                                  V128, V128, V128,
6355                                                  asm#"2", ".4s", ".8h", ".8h",
6356    [(set (v4i32 V128:$dst),
6357          (Accum (v4i32 V128:$Rd),
6358                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6359                                            (extract_high_v8i16 V128:$Rm)))))]>;
6360  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6361                                                  V128, V64, V64,
6362                                                  asm, ".2d", ".2s", ".2s",
6363    [(set (v2i64 V128:$dst),
6364          (Accum (v2i64 V128:$Rd),
6365                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6366                                                (v2i32 V64:$Rm)))))]>;
6367  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6368                                                  V128, V128, V128,
6369                                                  asm#"2", ".2d", ".4s", ".4s",
6370    [(set (v2i64 V128:$dst),
6371          (Accum (v2i64 V128:$Rd),
6372                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6373                                            (extract_high_v4i32 V128:$Rm)))))]>;
6374}
6375
6376multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6377                                  SDPatternOperator OpNode> {
6378  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6379                                                  V128, V128, V64,
6380                                                  asm, ".8h", ".8h", ".8b",
6381       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6382  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6383                                                  V128, V128, V128,
6384                                                  asm#"2", ".8h", ".8h", ".16b",
6385       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6386                                       (extract_high_v16i8 V128:$Rm)))]>;
6387  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6388                                                  V128, V128, V64,
6389                                                  asm, ".4s", ".4s", ".4h",
6390       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6391  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6392                                                  V128, V128, V128,
6393                                                  asm#"2", ".4s", ".4s", ".8h",
6394       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6395                                       (extract_high_v8i16 V128:$Rm)))]>;
6396  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6397                                                  V128, V128, V64,
6398                                                  asm, ".2d", ".2d", ".2s",
6399       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6400  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6401                                                  V128, V128, V128,
6402                                                  asm#"2", ".2d", ".2d", ".4s",
6403       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6404                                       (extract_high_v4i32 V128:$Rm)))]>;
6405}
6406
6407//----------------------------------------------------------------------------
6408// AdvSIMD bitwise extract from vector
6409//----------------------------------------------------------------------------
6410
6411class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6412                             string asm, string kind>
6413  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6414      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6415      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6416      [(set (vty regtype:$Rd),
6417            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6418    Sched<[WriteV]> {
6419  bits<5> Rd;
6420  bits<5> Rn;
6421  bits<5> Rm;
6422  bits<4> imm;
6423  let Inst{31}    = 0;
6424  let Inst{30}    = size;
6425  let Inst{29-21} = 0b101110000;
6426  let Inst{20-16} = Rm;
6427  let Inst{15}    = 0;
6428  let Inst{14-11} = imm;
6429  let Inst{10}    = 0;
6430  let Inst{9-5}   = Rn;
6431  let Inst{4-0}   = Rd;
6432}
6433
6434
6435multiclass SIMDBitwiseExtract<string asm> {
6436  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6437    let imm{3} = 0;
6438  }
6439  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6440}
6441
6442//----------------------------------------------------------------------------
6443// AdvSIMD zip vector
6444//----------------------------------------------------------------------------
6445
6446class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6447                        string asm, string kind, SDNode OpNode, ValueType valty>
6448  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6449      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6450      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6451      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6452    Sched<[WriteV]> {
6453  bits<5> Rd;
6454  bits<5> Rn;
6455  bits<5> Rm;
6456  let Inst{31}    = 0;
6457  let Inst{30}    = size{0};
6458  let Inst{29-24} = 0b001110;
6459  let Inst{23-22} = size{2-1};
6460  let Inst{21}    = 0;
6461  let Inst{20-16} = Rm;
6462  let Inst{15}    = 0;
6463  let Inst{14-12} = opc;
6464  let Inst{11-10} = 0b10;
6465  let Inst{9-5}   = Rn;
6466  let Inst{4-0}   = Rd;
6467}
6468
6469multiclass SIMDZipVector<bits<3>opc, string asm,
6470                         SDNode OpNode> {
6471  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6472      asm, ".8b", OpNode, v8i8>;
6473  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6474      asm, ".16b", OpNode, v16i8>;
6475  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6476      asm, ".4h", OpNode, v4i16>;
6477  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6478      asm, ".8h", OpNode, v8i16>;
6479  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6480      asm, ".2s", OpNode, v2i32>;
6481  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6482      asm, ".4s", OpNode, v4i32>;
6483  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6484      asm, ".2d", OpNode, v2i64>;
6485
6486  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6487        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6488  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6489        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6490  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6491        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6492  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6493        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6494  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6495        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6496}
6497
6498//----------------------------------------------------------------------------
6499// AdvSIMD three register scalar instructions
6500//----------------------------------------------------------------------------
6501
6502let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6503class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6504                        RegisterClass regtype, string asm,
6505                        list<dag> pattern>
6506  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6507      "\t$Rd, $Rn, $Rm", "", pattern>,
6508    Sched<[WriteV]> {
6509  bits<5> Rd;
6510  bits<5> Rn;
6511  bits<5> Rm;
6512  let Inst{31-30} = 0b01;
6513  let Inst{29}    = U;
6514  let Inst{28-24} = 0b11110;
6515  let Inst{23-21} = size;
6516  let Inst{20-16} = Rm;
6517  let Inst{15-11} = opcode;
6518  let Inst{10}    = 1;
6519  let Inst{9-5}   = Rn;
6520  let Inst{4-0}   = Rd;
6521}
6522
6523let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6524class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6525                        dag oops, dag iops, string asm,
6526            list<dag> pattern>
6527  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6528    Sched<[WriteV]> {
6529  bits<5> Rd;
6530  bits<5> Rn;
6531  bits<5> Rm;
6532  let Inst{31-30} = 0b01;
6533  let Inst{29}    = U;
6534  let Inst{28-24} = 0b11110;
6535  let Inst{23-22} = size;
6536  let Inst{21}    = R;
6537  let Inst{20-16} = Rm;
6538  let Inst{15-11} = opcode;
6539  let Inst{10}    = 1;
6540  let Inst{9-5}   = Rn;
6541  let Inst{4-0}   = Rd;
6542}
6543
6544multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6545                            SDPatternOperator OpNode> {
6546  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6547    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6548}
6549
6550multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6551                               SDPatternOperator OpNode> {
6552  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6553    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6554  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6555  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6556  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6557
6558  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6559            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6560  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6561            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6562}
6563
6564multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6565                             SDPatternOperator OpNode> {
6566  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6567                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6568  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6569}
6570
6571multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6572                                 SDPatternOperator OpNode = null_frag> {
6573  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6574                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6575                                     asm, []>;
6576  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6577                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6578                                     asm, []>;
6579}
6580
6581multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6582                             SDPatternOperator OpNode = null_frag> {
6583  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6584    def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6585      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6586    def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6587      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6588    let Predicates = [HasNEON, HasFullFP16] in {
6589    def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6590      [(set FPR16:$Rd, (OpNode FPR16:$Rn, FPR16:$Rm))]>;
6591    } // Predicates = [HasNEON, HasFullFP16]
6592  }
6593
6594  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6595            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6596}
6597
6598multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6599                                SDPatternOperator OpNode = null_frag> {
6600  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6601    def #NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6602      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6603    def #NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6604      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6605    let Predicates = [HasNEON, HasFullFP16] in {
6606    def #NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6607      []>;
6608    } // Predicates = [HasNEON, HasFullFP16]
6609  }
6610
6611  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6612            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6613}
6614
6615class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6616              dag oops, dag iops, string asm, string cstr, list<dag> pat>
6617  : I<oops, iops, asm,
6618      "\t$Rd, $Rn, $Rm", cstr, pat>,
6619    Sched<[WriteV]> {
6620  bits<5> Rd;
6621  bits<5> Rn;
6622  bits<5> Rm;
6623  let Inst{31-30} = 0b01;
6624  let Inst{29}    = U;
6625  let Inst{28-24} = 0b11110;
6626  let Inst{23-22} = size;
6627  let Inst{21}    = 1;
6628  let Inst{20-16} = Rm;
6629  let Inst{15-11} = opcode;
6630  let Inst{10}    = 0;
6631  let Inst{9-5}   = Rn;
6632  let Inst{4-0}   = Rd;
6633}
6634
6635let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6636multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6637                                  SDPatternOperator OpNode = null_frag> {
6638  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6639                                      (outs FPR32:$Rd),
6640                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6641  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6642                                      (outs FPR64:$Rd),
6643                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6644            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6645}
6646
6647let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6648multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6649                                  SDPatternOperator OpNode = null_frag> {
6650  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6651                                      (outs FPR32:$dst),
6652                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6653                                      asm, "$Rd = $dst", []>;
6654  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6655                                      (outs FPR64:$dst),
6656                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6657                                      asm, "$Rd = $dst",
6658            [(set (i64 FPR64:$dst),
6659                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6660}
6661
6662//----------------------------------------------------------------------------
6663// AdvSIMD two register scalar instructions
6664//----------------------------------------------------------------------------
6665
6666let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6667class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6668                        RegisterClass regtype, RegisterClass regtype2,
6669                        string asm, list<dag> pat>
6670  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6671      "\t$Rd, $Rn", "", pat>,
6672    Sched<[WriteV]> {
6673  bits<5> Rd;
6674  bits<5> Rn;
6675  let Inst{31-30} = 0b01;
6676  let Inst{29}    = U;
6677  let Inst{28-24} = 0b11110;
6678  let Inst{23-22} = size;
6679  let Inst{21} = 0b1;
6680  let Inst{20-19} = size2;
6681  let Inst{18-17} = 0b00;
6682  let Inst{16-12} = opcode;
6683  let Inst{11-10} = 0b10;
6684  let Inst{9-5}   = Rn;
6685  let Inst{4-0}   = Rd;
6686}
6687
6688let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6689class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6690                        RegisterClass regtype, RegisterClass regtype2,
6691                        string asm, list<dag> pat>
6692  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6693      "\t$Rd, $Rn", "$Rd = $dst", pat>,
6694    Sched<[WriteV]> {
6695  bits<5> Rd;
6696  bits<5> Rn;
6697  let Inst{31-30} = 0b01;
6698  let Inst{29}    = U;
6699  let Inst{28-24} = 0b11110;
6700  let Inst{23-22} = size;
6701  let Inst{21-17} = 0b10000;
6702  let Inst{16-12} = opcode;
6703  let Inst{11-10} = 0b10;
6704  let Inst{9-5}   = Rn;
6705  let Inst{4-0}   = Rd;
6706}
6707
6708
6709let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6710class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6711                        RegisterClass regtype, string asm, string zero>
6712  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6713      "\t$Rd, $Rn, #" # zero, "", []>,
6714    Sched<[WriteV]> {
6715  bits<5> Rd;
6716  bits<5> Rn;
6717  let Inst{31-30} = 0b01;
6718  let Inst{29}    = U;
6719  let Inst{28-24} = 0b11110;
6720  let Inst{23-22} = size;
6721  let Inst{21} = 0b1;
6722  let Inst{20-19} = size2;
6723  let Inst{18-17} = 0b00;
6724  let Inst{16-12} = opcode;
6725  let Inst{11-10} = 0b10;
6726  let Inst{9-5}   = Rn;
6727  let Inst{4-0}   = Rd;
6728}
6729
6730class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6731  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6732     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6733    Sched<[WriteV]> {
6734  bits<5> Rd;
6735  bits<5> Rn;
6736  let Inst{31-17} = 0b011111100110000;
6737  let Inst{16-12} = opcode;
6738  let Inst{11-10} = 0b10;
6739  let Inst{9-5}   = Rn;
6740  let Inst{4-0}   = Rd;
6741}
6742
6743multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6744                             SDPatternOperator OpNode> {
6745  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6746
6747  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6748            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6749}
6750
6751multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6752                              SDPatternOperator OpNode> {
6753  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6754  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6755  let Predicates = [HasNEON, HasFullFP16] in {
6756  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6757  }
6758
6759  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6760                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6761  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6762                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6763  let Predicates = [HasNEON, HasFullFP16] in {
6764  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6765                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6766  }
6767
6768  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
6769            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6770}
6771
6772multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
6773                          SDPatternOperator OpNode = null_frag> {
6774  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6775    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
6776
6777  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
6778            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
6779}
6780
6781multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
6782  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
6783  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
6784  let Predicates = [HasNEON, HasFullFP16] in {
6785  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
6786  }
6787}
6788
6789multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
6790                              SDPatternOperator OpNode> {
6791  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
6792                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
6793  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
6794                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
6795  let Predicates = [HasNEON, HasFullFP16] in {
6796  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
6797                                [(set FPR16:$Rd, (OpNode (f16 FPR16:$Rn)))]>;
6798  }
6799}
6800
6801multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
6802                             SDPatternOperator OpNode = null_frag> {
6803  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6804    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
6805           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6806    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
6807           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
6808    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
6809    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
6810  }
6811
6812  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
6813            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
6814}
6815
6816multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
6817                                 Intrinsic OpNode> {
6818  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6819    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
6820        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
6821    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
6822        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
6823    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
6824    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
6825  }
6826
6827  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
6828            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
6829}
6830
6831
6832
6833let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6834multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
6835                                 SDPatternOperator OpNode = null_frag> {
6836  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
6837        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
6838  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
6839  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
6840}
6841
6842//----------------------------------------------------------------------------
6843// AdvSIMD scalar pairwise instructions
6844//----------------------------------------------------------------------------
6845
6846let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6847class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
6848                        RegisterOperand regtype, RegisterOperand vectype,
6849                        string asm, string kind>
6850  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6851      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
6852    Sched<[WriteV]> {
6853  bits<5> Rd;
6854  bits<5> Rn;
6855  let Inst{31-30} = 0b01;
6856  let Inst{29}    = U;
6857  let Inst{28-24} = 0b11110;
6858  let Inst{23-22} = size;
6859  let Inst{21-17} = 0b11000;
6860  let Inst{16-12} = opcode;
6861  let Inst{11-10} = 0b10;
6862  let Inst{9-5}   = Rn;
6863  let Inst{4-0}   = Rd;
6864}
6865
6866multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
6867  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
6868                                      asm, ".2d">;
6869}
6870
6871multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
6872  let Predicates = [HasNEON, HasFullFP16] in {
6873  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
6874                                      asm, ".2h">;
6875  }
6876  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
6877                                      asm, ".2s">;
6878  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
6879                                      asm, ".2d">;
6880}
6881
6882//----------------------------------------------------------------------------
6883// AdvSIMD across lanes instructions
6884//----------------------------------------------------------------------------
6885
6886let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6887class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
6888                          RegisterClass regtype, RegisterOperand vectype,
6889                          string asm, string kind, list<dag> pattern>
6890  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
6891      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
6892    Sched<[WriteV]> {
6893  bits<5> Rd;
6894  bits<5> Rn;
6895  let Inst{31}    = 0;
6896  let Inst{30}    = Q;
6897  let Inst{29}    = U;
6898  let Inst{28-24} = 0b01110;
6899  let Inst{23-22} = size;
6900  let Inst{21-17} = 0b11000;
6901  let Inst{16-12} = opcode;
6902  let Inst{11-10} = 0b10;
6903  let Inst{9-5}   = Rn;
6904  let Inst{4-0}   = Rd;
6905}
6906
6907multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
6908                              string asm> {
6909  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
6910                                   asm, ".8b", []>;
6911  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
6912                                   asm, ".16b", []>;
6913  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
6914                                   asm, ".4h", []>;
6915  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
6916                                   asm, ".8h", []>;
6917  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
6918                                   asm, ".4s", []>;
6919}
6920
6921multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
6922  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
6923                                   asm, ".8b", []>;
6924  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
6925                                   asm, ".16b", []>;
6926  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
6927                                   asm, ".4h", []>;
6928  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
6929                                   asm, ".8h", []>;
6930  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
6931                                   asm, ".4s", []>;
6932}
6933
6934multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
6935                            Intrinsic intOp> {
6936  let Predicates = [HasNEON, HasFullFP16] in {
6937  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
6938                                   asm, ".4h",
6939        [(set FPR16:$Rd, (intOp (v4f16 V64:$Rn)))]>;
6940  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
6941                                   asm, ".8h",
6942        [(set FPR16:$Rd, (intOp (v8f16 V128:$Rn)))]>;
6943  } // Predicates = [HasNEON, HasFullFP16]
6944  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
6945                                   asm, ".4s",
6946        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
6947}
6948
6949//----------------------------------------------------------------------------
6950// AdvSIMD INS/DUP instructions
6951//----------------------------------------------------------------------------
6952
6953// FIXME: There has got to be a better way to factor these. ugh.
6954
6955class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
6956                     string operands, string constraints, list<dag> pattern>
6957  : I<outs, ins, asm, operands, constraints, pattern>,
6958    Sched<[WriteV]> {
6959  bits<5> Rd;
6960  bits<5> Rn;
6961  let Inst{31} = 0;
6962  let Inst{30} = Q;
6963  let Inst{29} = op;
6964  let Inst{28-21} = 0b01110000;
6965  let Inst{15} = 0;
6966  let Inst{10} = 1;
6967  let Inst{9-5} = Rn;
6968  let Inst{4-0} = Rd;
6969}
6970
6971class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
6972                      RegisterOperand vecreg, RegisterClass regtype>
6973  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
6974                   "{\t$Rd" # size # ", $Rn" #
6975                   "|" # size # "\t$Rd, $Rn}", "",
6976                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
6977  let Inst{20-16} = imm5;
6978  let Inst{14-11} = 0b0001;
6979}
6980
6981class SIMDDupFromElement<bit Q, string dstkind, string srckind,
6982                         ValueType vectype, ValueType insreg,
6983                         RegisterOperand vecreg, Operand idxtype,
6984                         ValueType elttype, SDNode OpNode>
6985  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
6986                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
6987                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
6988                 [(set (vectype vecreg:$Rd),
6989                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
6990  let Inst{14-11} = 0b0000;
6991}
6992
6993class SIMDDup64FromElement
6994  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
6995                       VectorIndexD, i64, AArch64duplane64> {
6996  bits<1> idx;
6997  let Inst{20} = idx;
6998  let Inst{19-16} = 0b1000;
6999}
7000
7001class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7002                           RegisterOperand vecreg>
7003  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7004                       VectorIndexS, i64, AArch64duplane32> {
7005  bits<2> idx;
7006  let Inst{20-19} = idx;
7007  let Inst{18-16} = 0b100;
7008}
7009
7010class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7011                           RegisterOperand vecreg>
7012  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7013                       VectorIndexH, i64, AArch64duplane16> {
7014  bits<3> idx;
7015  let Inst{20-18} = idx;
7016  let Inst{17-16} = 0b10;
7017}
7018
7019class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7020                          RegisterOperand vecreg>
7021  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7022                       VectorIndexB, i64, AArch64duplane8> {
7023  bits<4> idx;
7024  let Inst{20-17} = idx;
7025  let Inst{16} = 1;
7026}
7027
7028class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7029                  Operand idxtype, string asm, list<dag> pattern>
7030  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7031                   "{\t$Rd, $Rn" # size # "$idx" #
7032                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7033  let Inst{14-11} = imm4;
7034}
7035
7036class SIMDSMov<bit Q, string size, RegisterClass regtype,
7037               Operand idxtype>
7038  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7039class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7040               Operand idxtype>
7041  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7042      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7043
7044class SIMDMovAlias<string asm, string size, Instruction inst,
7045                   RegisterClass regtype, Operand idxtype>
7046    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7047                    "|" # size # "\t$dst, $src$idx}",
7048                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7049
7050multiclass SMov {
7051  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7052    bits<4> idx;
7053    let Inst{20-17} = idx;
7054    let Inst{16} = 1;
7055  }
7056  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7057    bits<4> idx;
7058    let Inst{20-17} = idx;
7059    let Inst{16} = 1;
7060  }
7061  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7062    bits<3> idx;
7063    let Inst{20-18} = idx;
7064    let Inst{17-16} = 0b10;
7065  }
7066  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7067    bits<3> idx;
7068    let Inst{20-18} = idx;
7069    let Inst{17-16} = 0b10;
7070  }
7071  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7072    bits<2> idx;
7073    let Inst{20-19} = idx;
7074    let Inst{18-16} = 0b100;
7075  }
7076}
7077
7078multiclass UMov {
7079  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7080    bits<4> idx;
7081    let Inst{20-17} = idx;
7082    let Inst{16} = 1;
7083  }
7084  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7085    bits<3> idx;
7086    let Inst{20-18} = idx;
7087    let Inst{17-16} = 0b10;
7088  }
7089  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7090    bits<2> idx;
7091    let Inst{20-19} = idx;
7092    let Inst{18-16} = 0b100;
7093  }
7094  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7095    bits<1> idx;
7096    let Inst{20} = idx;
7097    let Inst{19-16} = 0b1000;
7098  }
7099  def : SIMDMovAlias<"mov", ".s",
7100                     !cast<Instruction>(NAME#"vi32"),
7101                     GPR32, VectorIndexS>;
7102  def : SIMDMovAlias<"mov", ".d",
7103                     !cast<Instruction>(NAME#"vi64"),
7104                     GPR64, VectorIndexD>;
7105}
7106
7107class SIMDInsFromMain<string size, ValueType vectype,
7108                      RegisterClass regtype, Operand idxtype>
7109  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7110                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7111                   "{\t$Rd" # size # "$idx, $Rn" #
7112                   "|" # size # "\t$Rd$idx, $Rn}",
7113                   "$Rd = $dst",
7114            [(set V128:$dst,
7115              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7116  let Inst{14-11} = 0b0011;
7117}
7118
7119class SIMDInsFromElement<string size, ValueType vectype,
7120                         ValueType elttype, Operand idxtype>
7121  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7122                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7123                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7124                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7125                   "$Rd = $dst",
7126         [(set V128:$dst,
7127               (vector_insert
7128                 (vectype V128:$Rd),
7129                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7130                 idxtype:$idx))]>;
7131
7132class SIMDInsMainMovAlias<string size, Instruction inst,
7133                          RegisterClass regtype, Operand idxtype>
7134    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7135                        "|" # size #"\t$dst$idx, $src}",
7136                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7137class SIMDInsElementMovAlias<string size, Instruction inst,
7138                             Operand idxtype>
7139    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2" #
7140                      # "|" # size #"\t$dst$idx, $src$idx2}",
7141                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7142
7143
7144multiclass SIMDIns {
7145  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7146    bits<4> idx;
7147    let Inst{20-17} = idx;
7148    let Inst{16} = 1;
7149  }
7150  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7151    bits<3> idx;
7152    let Inst{20-18} = idx;
7153    let Inst{17-16} = 0b10;
7154  }
7155  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7156    bits<2> idx;
7157    let Inst{20-19} = idx;
7158    let Inst{18-16} = 0b100;
7159  }
7160  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7161    bits<1> idx;
7162    let Inst{20} = idx;
7163    let Inst{19-16} = 0b1000;
7164  }
7165
7166  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7167    bits<4> idx;
7168    bits<4> idx2;
7169    let Inst{20-17} = idx;
7170    let Inst{16} = 1;
7171    let Inst{14-11} = idx2;
7172  }
7173  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7174    bits<3> idx;
7175    bits<3> idx2;
7176    let Inst{20-18} = idx;
7177    let Inst{17-16} = 0b10;
7178    let Inst{14-12} = idx2;
7179    let Inst{11} = {?};
7180  }
7181  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7182    bits<2> idx;
7183    bits<2> idx2;
7184    let Inst{20-19} = idx;
7185    let Inst{18-16} = 0b100;
7186    let Inst{14-13} = idx2;
7187    let Inst{12-11} = {?,?};
7188  }
7189  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7190    bits<1> idx;
7191    bits<1> idx2;
7192    let Inst{20} = idx;
7193    let Inst{19-16} = 0b1000;
7194    let Inst{14} = idx2;
7195    let Inst{13-11} = {?,?,?};
7196  }
7197
7198  // For all forms of the INS instruction, the "mov" mnemonic is the
7199  // preferred alias. Why they didn't just call the instruction "mov" in
7200  // the first place is a very good question indeed...
7201  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7202                         GPR32, VectorIndexB>;
7203  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7204                         GPR32, VectorIndexH>;
7205  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7206                         GPR32, VectorIndexS>;
7207  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7208                         GPR64, VectorIndexD>;
7209
7210  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7211                         VectorIndexB>;
7212  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7213                         VectorIndexH>;
7214  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7215                         VectorIndexS>;
7216  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7217                         VectorIndexD>;
7218}
7219
7220//----------------------------------------------------------------------------
7221// AdvSIMD TBL/TBX
7222//----------------------------------------------------------------------------
7223
7224let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7225class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7226                          RegisterOperand listtype, string asm, string kind>
7227  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7228       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7229    Sched<[WriteV]> {
7230  bits<5> Vd;
7231  bits<5> Vn;
7232  bits<5> Vm;
7233  let Inst{31}    = 0;
7234  let Inst{30}    = Q;
7235  let Inst{29-21} = 0b001110000;
7236  let Inst{20-16} = Vm;
7237  let Inst{15}    = 0;
7238  let Inst{14-13} = len;
7239  let Inst{12}    = op;
7240  let Inst{11-10} = 0b00;
7241  let Inst{9-5}   = Vn;
7242  let Inst{4-0}   = Vd;
7243}
7244
7245let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7246class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7247                          RegisterOperand listtype, string asm, string kind>
7248  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7249       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7250    Sched<[WriteV]> {
7251  bits<5> Vd;
7252  bits<5> Vn;
7253  bits<5> Vm;
7254  let Inst{31}    = 0;
7255  let Inst{30}    = Q;
7256  let Inst{29-21} = 0b001110000;
7257  let Inst{20-16} = Vm;
7258  let Inst{15}    = 0;
7259  let Inst{14-13} = len;
7260  let Inst{12}    = op;
7261  let Inst{11-10} = 0b00;
7262  let Inst{9-5}   = Vn;
7263  let Inst{4-0}   = Vd;
7264}
7265
7266class SIMDTableLookupAlias<string asm, Instruction inst,
7267                          RegisterOperand vectype, RegisterOperand listtype>
7268    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7269                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7270
7271multiclass SIMDTableLookup<bit op, string asm> {
7272  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7273                                      asm, ".8b">;
7274  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7275                                      asm, ".8b">;
7276  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7277                                      asm, ".8b">;
7278  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7279                                      asm, ".8b">;
7280  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7281                                      asm, ".16b">;
7282  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7283                                      asm, ".16b">;
7284  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7285                                      asm, ".16b">;
7286  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7287                                      asm, ".16b">;
7288
7289  def : SIMDTableLookupAlias<asm # ".8b",
7290                         !cast<Instruction>(NAME#"v8i8One"),
7291                         V64, VecListOne128>;
7292  def : SIMDTableLookupAlias<asm # ".8b",
7293                         !cast<Instruction>(NAME#"v8i8Two"),
7294                         V64, VecListTwo128>;
7295  def : SIMDTableLookupAlias<asm # ".8b",
7296                         !cast<Instruction>(NAME#"v8i8Three"),
7297                         V64, VecListThree128>;
7298  def : SIMDTableLookupAlias<asm # ".8b",
7299                         !cast<Instruction>(NAME#"v8i8Four"),
7300                         V64, VecListFour128>;
7301  def : SIMDTableLookupAlias<asm # ".16b",
7302                         !cast<Instruction>(NAME#"v16i8One"),
7303                         V128, VecListOne128>;
7304  def : SIMDTableLookupAlias<asm # ".16b",
7305                         !cast<Instruction>(NAME#"v16i8Two"),
7306                         V128, VecListTwo128>;
7307  def : SIMDTableLookupAlias<asm # ".16b",
7308                         !cast<Instruction>(NAME#"v16i8Three"),
7309                         V128, VecListThree128>;
7310  def : SIMDTableLookupAlias<asm # ".16b",
7311                         !cast<Instruction>(NAME#"v16i8Four"),
7312                         V128, VecListFour128>;
7313}
7314
7315multiclass SIMDTableLookupTied<bit op, string asm> {
7316  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7317                                      asm, ".8b">;
7318  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7319                                      asm, ".8b">;
7320  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7321                                      asm, ".8b">;
7322  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7323                                      asm, ".8b">;
7324  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7325                                      asm, ".16b">;
7326  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7327                                      asm, ".16b">;
7328  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7329                                      asm, ".16b">;
7330  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7331                                      asm, ".16b">;
7332
7333  def : SIMDTableLookupAlias<asm # ".8b",
7334                         !cast<Instruction>(NAME#"v8i8One"),
7335                         V64, VecListOne128>;
7336  def : SIMDTableLookupAlias<asm # ".8b",
7337                         !cast<Instruction>(NAME#"v8i8Two"),
7338                         V64, VecListTwo128>;
7339  def : SIMDTableLookupAlias<asm # ".8b",
7340                         !cast<Instruction>(NAME#"v8i8Three"),
7341                         V64, VecListThree128>;
7342  def : SIMDTableLookupAlias<asm # ".8b",
7343                         !cast<Instruction>(NAME#"v8i8Four"),
7344                         V64, VecListFour128>;
7345  def : SIMDTableLookupAlias<asm # ".16b",
7346                         !cast<Instruction>(NAME#"v16i8One"),
7347                         V128, VecListOne128>;
7348  def : SIMDTableLookupAlias<asm # ".16b",
7349                         !cast<Instruction>(NAME#"v16i8Two"),
7350                         V128, VecListTwo128>;
7351  def : SIMDTableLookupAlias<asm # ".16b",
7352                         !cast<Instruction>(NAME#"v16i8Three"),
7353                         V128, VecListThree128>;
7354  def : SIMDTableLookupAlias<asm # ".16b",
7355                         !cast<Instruction>(NAME#"v16i8Four"),
7356                         V128, VecListFour128>;
7357}
7358
7359
7360//----------------------------------------------------------------------------
7361// AdvSIMD scalar CPY
7362//----------------------------------------------------------------------------
7363let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7364class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7365                        string kind, Operand idxtype>
7366  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7367       "{\t$dst, $src" # kind # "$idx" #
7368       "|\t$dst, $src$idx}", "", []>,
7369    Sched<[WriteV]> {
7370  bits<5> dst;
7371  bits<5> src;
7372  let Inst{31-21} = 0b01011110000;
7373  let Inst{15-10} = 0b000001;
7374  let Inst{9-5}   = src;
7375  let Inst{4-0}   = dst;
7376}
7377
7378class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7379      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7380    : InstAlias<asm # "{\t$dst, $src" # size # "$index" #
7381                    # "|\t$dst, $src$index}",
7382                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7383
7384
7385multiclass SIMDScalarCPY<string asm> {
7386  def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
7387    bits<4> idx;
7388    let Inst{20-17} = idx;
7389    let Inst{16} = 1;
7390  }
7391  def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7392    bits<3> idx;
7393    let Inst{20-18} = idx;
7394    let Inst{17-16} = 0b10;
7395  }
7396  def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7397    bits<2> idx;
7398    let Inst{20-19} = idx;
7399    let Inst{18-16} = 0b100;
7400  }
7401  def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7402    bits<1> idx;
7403    let Inst{20} = idx;
7404    let Inst{19-16} = 0b1000;
7405  }
7406
7407  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7408                                                          VectorIndexD:$idx)))),
7409            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7410
7411  // 'DUP' mnemonic aliases.
7412  def : SIMDScalarCPYAlias<"dup", ".b",
7413                           !cast<Instruction>(NAME#"i8"),
7414                           FPR8, V128, VectorIndexB>;
7415  def : SIMDScalarCPYAlias<"dup", ".h",
7416                           !cast<Instruction>(NAME#"i16"),
7417                           FPR16, V128, VectorIndexH>;
7418  def : SIMDScalarCPYAlias<"dup", ".s",
7419                           !cast<Instruction>(NAME#"i32"),
7420                           FPR32, V128, VectorIndexS>;
7421  def : SIMDScalarCPYAlias<"dup", ".d",
7422                           !cast<Instruction>(NAME#"i64"),
7423                           FPR64, V128, VectorIndexD>;
7424}
7425
7426//----------------------------------------------------------------------------
7427// AdvSIMD modified immediate instructions
7428//----------------------------------------------------------------------------
7429
7430class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7431                          string asm, string op_string,
7432                          string cstr, list<dag> pattern>
7433  : I<oops, iops, asm, op_string, cstr, pattern>,
7434    Sched<[WriteV]> {
7435  bits<5> Rd;
7436  bits<8> imm8;
7437  let Inst{31}    = 0;
7438  let Inst{30}    = Q;
7439  let Inst{29}    = op;
7440  let Inst{28-19} = 0b0111100000;
7441  let Inst{18-16} = imm8{7-5};
7442  let Inst{11} = op2;
7443  let Inst{10} = 1;
7444  let Inst{9-5}   = imm8{4-0};
7445  let Inst{4-0}   = Rd;
7446}
7447
7448class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7449                                Operand immtype, dag opt_shift_iop,
7450                                string opt_shift, string asm, string kind,
7451                                list<dag> pattern>
7452  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7453                        !con((ins immtype:$imm8), opt_shift_iop), asm,
7454                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
7455                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7456                        "", pattern> {
7457  let DecoderMethod = "DecodeModImmInstruction";
7458}
7459
7460class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7461                                Operand immtype, dag opt_shift_iop,
7462                                string opt_shift, string asm, string kind,
7463                                list<dag> pattern>
7464  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7465                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7466                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7467                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7468                        "$Rd = $dst", pattern> {
7469  let DecoderMethod = "DecodeModImmTiedInstruction";
7470}
7471
7472class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7473                                     RegisterOperand vectype, string asm,
7474                                     string kind, list<dag> pattern>
7475  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7476                              (ins logical_vec_shift:$shift),
7477                              "$shift", asm, kind, pattern> {
7478  bits<2> shift;
7479  let Inst{15}    = b15_b12{1};
7480  let Inst{14-13} = shift;
7481  let Inst{12}    = b15_b12{0};
7482}
7483
7484class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7485                                     RegisterOperand vectype, string asm,
7486                                     string kind, list<dag> pattern>
7487  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7488                              (ins logical_vec_shift:$shift),
7489                              "$shift", asm, kind, pattern> {
7490  bits<2> shift;
7491  let Inst{15}    = b15_b12{1};
7492  let Inst{14-13} = shift;
7493  let Inst{12}    = b15_b12{0};
7494}
7495
7496
7497class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7498                                         RegisterOperand vectype, string asm,
7499                                         string kind, list<dag> pattern>
7500  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7501                              (ins logical_vec_hw_shift:$shift),
7502                              "$shift", asm, kind, pattern> {
7503  bits<2> shift;
7504  let Inst{15} = b15_b12{1};
7505  let Inst{14} = 0;
7506  let Inst{13} = shift{0};
7507  let Inst{12} = b15_b12{0};
7508}
7509
7510class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7511                                         RegisterOperand vectype, string asm,
7512                                         string kind, list<dag> pattern>
7513  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7514                              (ins logical_vec_hw_shift:$shift),
7515                              "$shift", asm, kind, pattern> {
7516  bits<2> shift;
7517  let Inst{15} = b15_b12{1};
7518  let Inst{14} = 0;
7519  let Inst{13} = shift{0};
7520  let Inst{12} = b15_b12{0};
7521}
7522
7523multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7524                                      string asm> {
7525  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7526                                                 asm, ".4h", []>;
7527  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7528                                                 asm, ".8h", []>;
7529
7530  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7531                                             asm, ".2s", []>;
7532  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7533                                             asm, ".4s", []>;
7534}
7535
7536multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7537                                      bits<2> w_cmode, string asm,
7538                                      SDNode OpNode> {
7539  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7540                                                 asm, ".4h",
7541             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7542                                             imm0_255:$imm8,
7543                                             (i32 imm:$shift)))]>;
7544  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7545                                                 asm, ".8h",
7546             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7547                                              imm0_255:$imm8,
7548                                              (i32 imm:$shift)))]>;
7549
7550  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7551                                             asm, ".2s",
7552             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7553                                             imm0_255:$imm8,
7554                                             (i32 imm:$shift)))]>;
7555  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7556                                             asm, ".4s",
7557             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7558                                              imm0_255:$imm8,
7559                                              (i32 imm:$shift)))]>;
7560}
7561
7562class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7563                             RegisterOperand vectype, string asm,
7564                             string kind, list<dag> pattern>
7565  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7566                              (ins move_vec_shift:$shift),
7567                              "$shift", asm, kind, pattern> {
7568  bits<1> shift;
7569  let Inst{15-13} = cmode{3-1};
7570  let Inst{12}    = shift;
7571}
7572
7573class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7574                                   RegisterOperand vectype,
7575                                   Operand imm_type, string asm,
7576                                   string kind, list<dag> pattern>
7577  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7578                              asm, kind, pattern> {
7579  let Inst{15-12} = cmode;
7580}
7581
7582class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7583                                   list<dag> pattern>
7584  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7585                        "\t$Rd, $imm8", "", pattern> {
7586  let Inst{15-12} = cmode;
7587  let DecoderMethod = "DecodeModImmInstruction";
7588}
7589
7590//----------------------------------------------------------------------------
7591// AdvSIMD indexed element
7592//----------------------------------------------------------------------------
7593
7594let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7595class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7596                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7597                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7598                      string apple_kind, string dst_kind, string lhs_kind,
7599                      string rhs_kind, list<dag> pattern>
7600  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7601      asm,
7602      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7603      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7604    Sched<[WriteV]> {
7605  bits<5> Rd;
7606  bits<5> Rn;
7607  bits<5> Rm;
7608
7609  let Inst{31}    = 0;
7610  let Inst{30}    = Q;
7611  let Inst{29}    = U;
7612  let Inst{28}    = Scalar;
7613  let Inst{27-24} = 0b1111;
7614  let Inst{23-22} = size;
7615  // Bit 21 must be set by the derived class.
7616  let Inst{20-16} = Rm;
7617  let Inst{15-12} = opc;
7618  // Bit 11 must be set by the derived class.
7619  let Inst{10}    = 0;
7620  let Inst{9-5}   = Rn;
7621  let Inst{4-0}   = Rd;
7622}
7623
7624let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7625class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7626                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7627                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7628                      string apple_kind, string dst_kind, string lhs_kind,
7629                      string rhs_kind, list<dag> pattern>
7630  : I<(outs dst_reg:$dst),
7631      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7632      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7633      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7634    Sched<[WriteV]> {
7635  bits<5> Rd;
7636  bits<5> Rn;
7637  bits<5> Rm;
7638
7639  let Inst{31}    = 0;
7640  let Inst{30}    = Q;
7641  let Inst{29}    = U;
7642  let Inst{28}    = Scalar;
7643  let Inst{27-24} = 0b1111;
7644  let Inst{23-22} = size;
7645  // Bit 21 must be set by the derived class.
7646  let Inst{20-16} = Rm;
7647  let Inst{15-12} = opc;
7648  // Bit 11 must be set by the derived class.
7649  let Inst{10}    = 0;
7650  let Inst{9-5}   = Rn;
7651  let Inst{4-0}   = Rd;
7652}
7653
7654// ARMv8.2-A Dot Product Instructions (Indexed)
7655class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, string asm, string dst_kind,
7656                                      string lhs_kind, string rhs_kind,
7657                                      RegisterOperand RegType,
7658                                      ValueType AccumType, ValueType InputType,
7659                                      SDPatternOperator OpNode> :
7660        BaseSIMDIndexedTied<Q, U, 0b0, 0b10, 0b1110, RegType, RegType, V128,
7661                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
7662        [(set (AccumType RegType:$dst),
7663              (AccumType (OpNode (AccumType RegType:$Rd),
7664                                 (InputType RegType:$Rn),
7665                                 (InputType (bitconvert (AccumType
7666                                    (AArch64duplane32 (v4i32 V128:$Rm),
7667                                        VectorIndexS:$idx)))))))]> {
7668  bits<2> idx;
7669  let Inst{21}    = idx{0};  // L
7670  let Inst{11}    = idx{1};  // H
7671}
7672
7673multiclass SIMDThreeSameVectorDotIndex<bit U, string asm,
7674                                       SDPatternOperator OpNode> {
7675  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, asm, ".2s", ".8b", ".4b",
7676                                              V64, v2i32, v8i8, OpNode>;
7677  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, asm, ".4s", ".16b", ".4b",
7678                                              V128, v4i32, v16i8, OpNode>;
7679}
7680
7681// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
7682class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
7683                                      string dst_kind, string lhs_kind,
7684                                      string rhs_kind, RegisterOperand RegType,
7685                                      ValueType AccumType, ValueType InputType,
7686                                      SDPatternOperator OpNode> :
7687        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
7688                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
7689          [(set (AccumType RegType:$dst),
7690                (AccumType (OpNode (AccumType RegType:$Rd),
7691                                   (InputType RegType:$Rn),
7692                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
7693                                                VectorIndexH:$idx)))))]> {
7694  // idx = H:L:M
7695  bits<3> idx;
7696  let Inst{11} = idx{2}; // H
7697  let Inst{21} = idx{1}; // L
7698  let Inst{20} = idx{0}; // M
7699}
7700
7701multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
7702                                       SDPatternOperator OpNode> {
7703  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
7704                                              V64, v2f32, v4f16, OpNode>;
7705  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
7706                                              V128, v4f32, v8f16, OpNode>;
7707}
7708
7709multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
7710                         SDPatternOperator OpNode> {
7711  let Predicates = [HasNEON, HasFullFP16] in {
7712  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
7713                                      V64, V64,
7714                                      V128_lo, VectorIndexH,
7715                                      asm, ".4h", ".4h", ".4h", ".h",
7716    [(set (v4f16 V64:$Rd),
7717        (OpNode (v4f16 V64:$Rn),
7718         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7719    bits<3> idx;
7720    let Inst{11} = idx{2};
7721    let Inst{21} = idx{1};
7722    let Inst{20} = idx{0};
7723  }
7724
7725  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
7726                                      V128, V128,
7727                                      V128_lo, VectorIndexH,
7728                                      asm, ".8h", ".8h", ".8h", ".h",
7729    [(set (v8f16 V128:$Rd),
7730        (OpNode (v8f16 V128:$Rn),
7731         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7732    bits<3> idx;
7733    let Inst{11} = idx{2};
7734    let Inst{21} = idx{1};
7735    let Inst{20} = idx{0};
7736  }
7737  } // Predicates = [HasNEON, HasFullFP16]
7738
7739  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7740                                      V64, V64,
7741                                      V128, VectorIndexS,
7742                                      asm, ".2s", ".2s", ".2s", ".s",
7743    [(set (v2f32 V64:$Rd),
7744        (OpNode (v2f32 V64:$Rn),
7745         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7746    bits<2> idx;
7747    let Inst{11} = idx{1};
7748    let Inst{21} = idx{0};
7749  }
7750
7751  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7752                                      V128, V128,
7753                                      V128, VectorIndexS,
7754                                      asm, ".4s", ".4s", ".4s", ".s",
7755    [(set (v4f32 V128:$Rd),
7756        (OpNode (v4f32 V128:$Rn),
7757         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
7758    bits<2> idx;
7759    let Inst{11} = idx{1};
7760    let Inst{21} = idx{0};
7761  }
7762
7763  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
7764                                      V128, V128,
7765                                      V128, VectorIndexD,
7766                                      asm, ".2d", ".2d", ".2d", ".d",
7767    [(set (v2f64 V128:$Rd),
7768        (OpNode (v2f64 V128:$Rn),
7769         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
7770    bits<1> idx;
7771    let Inst{11} = idx{0};
7772    let Inst{21} = 0;
7773  }
7774
7775  let Predicates = [HasNEON, HasFullFP16] in {
7776  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
7777                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7778                                      asm, ".h", "", "", ".h",
7779    [(set (f16 FPR16Op:$Rd),
7780          (OpNode (f16 FPR16Op:$Rn),
7781                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
7782                                       VectorIndexH:$idx))))]> {
7783    bits<3> idx;
7784    let Inst{11} = idx{2};
7785    let Inst{21} = idx{1};
7786    let Inst{20} = idx{0};
7787  }
7788  } // Predicates = [HasNEON, HasFullFP16]
7789
7790  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
7791                                      FPR32Op, FPR32Op, V128, VectorIndexS,
7792                                      asm, ".s", "", "", ".s",
7793    [(set (f32 FPR32Op:$Rd),
7794          (OpNode (f32 FPR32Op:$Rn),
7795                  (f32 (vector_extract (v4f32 V128:$Rm),
7796                                       VectorIndexS:$idx))))]> {
7797    bits<2> idx;
7798    let Inst{11} = idx{1};
7799    let Inst{21} = idx{0};
7800  }
7801
7802  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
7803                                      FPR64Op, FPR64Op, V128, VectorIndexD,
7804                                      asm, ".d", "", "", ".d",
7805    [(set (f64 FPR64Op:$Rd),
7806          (OpNode (f64 FPR64Op:$Rn),
7807                  (f64 (vector_extract (v2f64 V128:$Rm),
7808                                       VectorIndexD:$idx))))]> {
7809    bits<1> idx;
7810    let Inst{11} = idx{0};
7811    let Inst{21} = 0;
7812  }
7813}
7814
7815multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
7816  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
7817  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7818                           (AArch64duplane32 (v4f32 V128:$Rm),
7819                                           VectorIndexS:$idx))),
7820            (!cast<Instruction>(INST # v2i32_indexed)
7821                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7822  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
7823                           (AArch64dup (f32 FPR32Op:$Rm)))),
7824            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
7825                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7826
7827
7828  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
7829  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7830                           (AArch64duplane32 (v4f32 V128:$Rm),
7831                                           VectorIndexS:$idx))),
7832            (!cast<Instruction>(INST # "v4i32_indexed")
7833                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7834  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
7835                           (AArch64dup (f32 FPR32Op:$Rm)))),
7836            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
7837                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
7838
7839  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
7840  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7841                           (AArch64duplane64 (v2f64 V128:$Rm),
7842                                           VectorIndexD:$idx))),
7843            (!cast<Instruction>(INST # "v2i64_indexed")
7844                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
7845  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
7846                           (AArch64dup (f64 FPR64Op:$Rm)))),
7847            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
7848                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
7849
7850  // 2 variants for 32-bit scalar version: extract from .2s or from .4s
7851  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7852                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
7853            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7854                V128:$Rm, VectorIndexS:$idx)>;
7855  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
7856                         (vector_extract (v2f32 V64:$Rm), VectorIndexS:$idx))),
7857            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
7858                (SUBREG_TO_REG (i32 0), V64:$Rm, dsub), VectorIndexS:$idx)>;
7859
7860  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
7861  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
7862                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
7863            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
7864                V128:$Rm, VectorIndexD:$idx)>;
7865}
7866
7867multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
7868  let Predicates = [HasNEON, HasFullFP16] in {
7869  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
7870                                          V128_lo, VectorIndexH,
7871                                          asm, ".4h", ".4h", ".4h", ".h", []> {
7872    bits<3> idx;
7873    let Inst{11} = idx{2};
7874    let Inst{21} = idx{1};
7875    let Inst{20} = idx{0};
7876  }
7877
7878  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
7879                                          V128, V128,
7880                                          V128_lo, VectorIndexH,
7881                                          asm, ".8h", ".8h", ".8h", ".h", []> {
7882    bits<3> idx;
7883    let Inst{11} = idx{2};
7884    let Inst{21} = idx{1};
7885    let Inst{20} = idx{0};
7886  }
7887  } // Predicates = [HasNEON, HasFullFP16]
7888
7889  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
7890                                          V128, VectorIndexS,
7891                                          asm, ".2s", ".2s", ".2s", ".s", []> {
7892    bits<2> idx;
7893    let Inst{11} = idx{1};
7894    let Inst{21} = idx{0};
7895  }
7896
7897  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
7898                                      V128, V128,
7899                                      V128, VectorIndexS,
7900                                      asm, ".4s", ".4s", ".4s", ".s", []> {
7901    bits<2> idx;
7902    let Inst{11} = idx{1};
7903    let Inst{21} = idx{0};
7904  }
7905
7906  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
7907                                      V128, V128,
7908                                      V128, VectorIndexD,
7909                                      asm, ".2d", ".2d", ".2d", ".d", []> {
7910    bits<1> idx;
7911    let Inst{11} = idx{0};
7912    let Inst{21} = 0;
7913  }
7914
7915  let Predicates = [HasNEON, HasFullFP16] in {
7916  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
7917                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7918                                      asm, ".h", "", "", ".h", []> {
7919    bits<3> idx;
7920    let Inst{11} = idx{2};
7921    let Inst{21} = idx{1};
7922    let Inst{20} = idx{0};
7923  }
7924  } // Predicates = [HasNEON, HasFullFP16]
7925
7926  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
7927                                      FPR32Op, FPR32Op, V128, VectorIndexS,
7928                                      asm, ".s", "", "", ".s", []> {
7929    bits<2> idx;
7930    let Inst{11} = idx{1};
7931    let Inst{21} = idx{0};
7932  }
7933
7934  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
7935                                      FPR64Op, FPR64Op, V128, VectorIndexD,
7936                                      asm, ".d", "", "", ".d", []> {
7937    bits<1> idx;
7938    let Inst{11} = idx{0};
7939    let Inst{21} = 0;
7940  }
7941}
7942
7943multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
7944                         SDPatternOperator OpNode> {
7945  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
7946                                      V128_lo, VectorIndexH,
7947                                      asm, ".4h", ".4h", ".4h", ".h",
7948    [(set (v4i16 V64:$Rd),
7949        (OpNode (v4i16 V64:$Rn),
7950         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7951    bits<3> idx;
7952    let Inst{11} = idx{2};
7953    let Inst{21} = idx{1};
7954    let Inst{20} = idx{0};
7955  }
7956
7957  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
7958                                      V128, V128,
7959                                      V128_lo, VectorIndexH,
7960                                      asm, ".8h", ".8h", ".8h", ".h",
7961    [(set (v8i16 V128:$Rd),
7962       (OpNode (v8i16 V128:$Rn),
7963         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
7964    bits<3> idx;
7965    let Inst{11} = idx{2};
7966    let Inst{21} = idx{1};
7967    let Inst{20} = idx{0};
7968  }
7969
7970  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
7971                                      V64, V64,
7972                                      V128, VectorIndexS,
7973                                      asm, ".2s", ".2s", ".2s",  ".s",
7974    [(set (v2i32 V64:$Rd),
7975       (OpNode (v2i32 V64:$Rn),
7976          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7977    bits<2> idx;
7978    let Inst{11} = idx{1};
7979    let Inst{21} = idx{0};
7980  }
7981
7982  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
7983                                      V128, V128,
7984                                      V128, VectorIndexS,
7985                                      asm, ".4s", ".4s", ".4s", ".s",
7986    [(set (v4i32 V128:$Rd),
7987       (OpNode (v4i32 V128:$Rn),
7988          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
7989    bits<2> idx;
7990    let Inst{11} = idx{1};
7991    let Inst{21} = idx{0};
7992  }
7993
7994  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
7995                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
7996                                      asm, ".h", "", "", ".h", []> {
7997    bits<3> idx;
7998    let Inst{11} = idx{2};
7999    let Inst{21} = idx{1};
8000    let Inst{20} = idx{0};
8001  }
8002
8003  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8004                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8005                                      asm, ".s", "", "", ".s",
8006      [(set (i32 FPR32Op:$Rd),
8007            (OpNode FPR32Op:$Rn,
8008                    (i32 (vector_extract (v4i32 V128:$Rm),
8009                                         VectorIndexS:$idx))))]> {
8010    bits<2> idx;
8011    let Inst{11} = idx{1};
8012    let Inst{21} = idx{0};
8013  }
8014}
8015
8016multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8017                               SDPatternOperator OpNode> {
8018  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8019                                      V64, V64,
8020                                      V128_lo, VectorIndexH,
8021                                      asm, ".4h", ".4h", ".4h", ".h",
8022    [(set (v4i16 V64:$Rd),
8023        (OpNode (v4i16 V64:$Rn),
8024         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8025    bits<3> idx;
8026    let Inst{11} = idx{2};
8027    let Inst{21} = idx{1};
8028    let Inst{20} = idx{0};
8029  }
8030
8031  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8032                                      V128, V128,
8033                                      V128_lo, VectorIndexH,
8034                                      asm, ".8h", ".8h", ".8h", ".h",
8035    [(set (v8i16 V128:$Rd),
8036       (OpNode (v8i16 V128:$Rn),
8037         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8038    bits<3> idx;
8039    let Inst{11} = idx{2};
8040    let Inst{21} = idx{1};
8041    let Inst{20} = idx{0};
8042  }
8043
8044  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8045                                      V64, V64,
8046                                      V128, VectorIndexS,
8047                                      asm, ".2s", ".2s", ".2s", ".s",
8048    [(set (v2i32 V64:$Rd),
8049       (OpNode (v2i32 V64:$Rn),
8050          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8051    bits<2> idx;
8052    let Inst{11} = idx{1};
8053    let Inst{21} = idx{0};
8054  }
8055
8056  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8057                                      V128, V128,
8058                                      V128, VectorIndexS,
8059                                      asm, ".4s", ".4s", ".4s", ".s",
8060    [(set (v4i32 V128:$Rd),
8061       (OpNode (v4i32 V128:$Rn),
8062          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8063    bits<2> idx;
8064    let Inst{11} = idx{1};
8065    let Inst{21} = idx{0};
8066  }
8067}
8068
8069multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8070                                   SDPatternOperator OpNode> {
8071  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8072                                          V128_lo, VectorIndexH,
8073                                          asm, ".4h", ".4h", ".4h", ".h",
8074    [(set (v4i16 V64:$dst),
8075        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8076         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8077    bits<3> idx;
8078    let Inst{11} = idx{2};
8079    let Inst{21} = idx{1};
8080    let Inst{20} = idx{0};
8081  }
8082
8083  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8084                                      V128, V128,
8085                                      V128_lo, VectorIndexH,
8086                                      asm, ".8h", ".8h", ".8h", ".h",
8087    [(set (v8i16 V128:$dst),
8088       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8089         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8090    bits<3> idx;
8091    let Inst{11} = idx{2};
8092    let Inst{21} = idx{1};
8093    let Inst{20} = idx{0};
8094  }
8095
8096  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8097                                      V64, V64,
8098                                      V128, VectorIndexS,
8099                                      asm, ".2s", ".2s", ".2s", ".s",
8100    [(set (v2i32 V64:$dst),
8101       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8102          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8103    bits<2> idx;
8104    let Inst{11} = idx{1};
8105    let Inst{21} = idx{0};
8106  }
8107
8108  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8109                                      V128, V128,
8110                                      V128, VectorIndexS,
8111                                      asm, ".4s", ".4s", ".4s", ".s",
8112    [(set (v4i32 V128:$dst),
8113       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8114          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8115    bits<2> idx;
8116    let Inst{11} = idx{1};
8117    let Inst{21} = idx{0};
8118  }
8119}
8120
8121multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8122                             SDPatternOperator OpNode> {
8123  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8124                                      V128, V64,
8125                                      V128_lo, VectorIndexH,
8126                                      asm, ".4s", ".4s", ".4h", ".h",
8127    [(set (v4i32 V128:$Rd),
8128        (OpNode (v4i16 V64:$Rn),
8129         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8130    bits<3> idx;
8131    let Inst{11} = idx{2};
8132    let Inst{21} = idx{1};
8133    let Inst{20} = idx{0};
8134  }
8135
8136  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8137                                      V128, V128,
8138                                      V128_lo, VectorIndexH,
8139                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8140    [(set (v4i32 V128:$Rd),
8141          (OpNode (extract_high_v8i16 V128:$Rn),
8142                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8143                                                      VectorIndexH:$idx))))]> {
8144
8145    bits<3> idx;
8146    let Inst{11} = idx{2};
8147    let Inst{21} = idx{1};
8148    let Inst{20} = idx{0};
8149  }
8150
8151  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8152                                      V128, V64,
8153                                      V128, VectorIndexS,
8154                                      asm, ".2d", ".2d", ".2s", ".s",
8155    [(set (v2i64 V128:$Rd),
8156        (OpNode (v2i32 V64:$Rn),
8157         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8158    bits<2> idx;
8159    let Inst{11} = idx{1};
8160    let Inst{21} = idx{0};
8161  }
8162
8163  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8164                                      V128, V128,
8165                                      V128, VectorIndexS,
8166                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8167    [(set (v2i64 V128:$Rd),
8168          (OpNode (extract_high_v4i32 V128:$Rn),
8169                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8170                                                      VectorIndexS:$idx))))]> {
8171    bits<2> idx;
8172    let Inst{11} = idx{1};
8173    let Inst{21} = idx{0};
8174  }
8175
8176  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8177                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8178                                      asm, ".h", "", "", ".h", []> {
8179    bits<3> idx;
8180    let Inst{11} = idx{2};
8181    let Inst{21} = idx{1};
8182    let Inst{20} = idx{0};
8183  }
8184
8185  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8186                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8187                                      asm, ".s", "", "", ".s", []> {
8188    bits<2> idx;
8189    let Inst{11} = idx{1};
8190    let Inst{21} = idx{0};
8191  }
8192}
8193
8194multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8195                                       SDPatternOperator Accum> {
8196  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8197                                      V128, V64,
8198                                      V128_lo, VectorIndexH,
8199                                      asm, ".4s", ".4s", ".4h", ".h",
8200    [(set (v4i32 V128:$dst),
8201          (Accum (v4i32 V128:$Rd),
8202                 (v4i32 (int_aarch64_neon_sqdmull
8203                             (v4i16 V64:$Rn),
8204                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8205                                                    VectorIndexH:$idx))))))]> {
8206    bits<3> idx;
8207    let Inst{11} = idx{2};
8208    let Inst{21} = idx{1};
8209    let Inst{20} = idx{0};
8210  }
8211
8212  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8213  // intermediate EXTRACT_SUBREG would be untyped.
8214  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8215                (i32 (vector_extract (v4i32
8216                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8217                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8218                                                    VectorIndexH:$idx)))),
8219                         (i64 0))))),
8220            (EXTRACT_SUBREG
8221                (!cast<Instruction>(NAME # v4i16_indexed)
8222                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8223                    V128_lo:$Rm, VectorIndexH:$idx),
8224                ssub)>;
8225
8226  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8227                                      V128, V128,
8228                                      V128_lo, VectorIndexH,
8229                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8230    [(set (v4i32 V128:$dst),
8231          (Accum (v4i32 V128:$Rd),
8232                 (v4i32 (int_aarch64_neon_sqdmull
8233                            (extract_high_v8i16 V128:$Rn),
8234                            (extract_high_v8i16
8235                                (AArch64duplane16 (v8i16 V128_lo:$Rm),
8236                                                VectorIndexH:$idx))))))]> {
8237    bits<3> idx;
8238    let Inst{11} = idx{2};
8239    let Inst{21} = idx{1};
8240    let Inst{20} = idx{0};
8241  }
8242
8243  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8244                                      V128, V64,
8245                                      V128, VectorIndexS,
8246                                      asm, ".2d", ".2d", ".2s", ".s",
8247    [(set (v2i64 V128:$dst),
8248        (Accum (v2i64 V128:$Rd),
8249               (v2i64 (int_aarch64_neon_sqdmull
8250                          (v2i32 V64:$Rn),
8251                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8252                                                 VectorIndexS:$idx))))))]> {
8253    bits<2> idx;
8254    let Inst{11} = idx{1};
8255    let Inst{21} = idx{0};
8256  }
8257
8258  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8259                                      V128, V128,
8260                                      V128, VectorIndexS,
8261                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8262    [(set (v2i64 V128:$dst),
8263          (Accum (v2i64 V128:$Rd),
8264                 (v2i64 (int_aarch64_neon_sqdmull
8265                            (extract_high_v4i32 V128:$Rn),
8266                            (extract_high_v4i32
8267                                (AArch64duplane32 (v4i32 V128:$Rm),
8268                                                VectorIndexS:$idx))))))]> {
8269    bits<2> idx;
8270    let Inst{11} = idx{1};
8271    let Inst{21} = idx{0};
8272  }
8273
8274  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8275                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8276                                      asm, ".h", "", "", ".h", []> {
8277    bits<3> idx;
8278    let Inst{11} = idx{2};
8279    let Inst{21} = idx{1};
8280    let Inst{20} = idx{0};
8281  }
8282
8283
8284  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8285                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8286                                      asm, ".s", "", "", ".s",
8287    [(set (i64 FPR64Op:$dst),
8288          (Accum (i64 FPR64Op:$Rd),
8289                 (i64 (int_aarch64_neon_sqdmulls_scalar
8290                            (i32 FPR32Op:$Rn),
8291                            (i32 (vector_extract (v4i32 V128:$Rm),
8292                                                 VectorIndexS:$idx))))))]> {
8293
8294    bits<2> idx;
8295    let Inst{11} = idx{1};
8296    let Inst{21} = idx{0};
8297  }
8298}
8299
8300multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8301                                   SDPatternOperator OpNode> {
8302  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8303  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8304                                      V128, V64,
8305                                      V128_lo, VectorIndexH,
8306                                      asm, ".4s", ".4s", ".4h", ".h",
8307    [(set (v4i32 V128:$Rd),
8308        (OpNode (v4i16 V64:$Rn),
8309         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8310    bits<3> idx;
8311    let Inst{11} = idx{2};
8312    let Inst{21} = idx{1};
8313    let Inst{20} = idx{0};
8314  }
8315
8316  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8317                                      V128, V128,
8318                                      V128_lo, VectorIndexH,
8319                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8320    [(set (v4i32 V128:$Rd),
8321          (OpNode (extract_high_v8i16 V128:$Rn),
8322                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8323                                                      VectorIndexH:$idx))))]> {
8324
8325    bits<3> idx;
8326    let Inst{11} = idx{2};
8327    let Inst{21} = idx{1};
8328    let Inst{20} = idx{0};
8329  }
8330
8331  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8332                                      V128, V64,
8333                                      V128, VectorIndexS,
8334                                      asm, ".2d", ".2d", ".2s", ".s",
8335    [(set (v2i64 V128:$Rd),
8336        (OpNode (v2i32 V64:$Rn),
8337         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8338    bits<2> idx;
8339    let Inst{11} = idx{1};
8340    let Inst{21} = idx{0};
8341  }
8342
8343  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8344                                      V128, V128,
8345                                      V128, VectorIndexS,
8346                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8347    [(set (v2i64 V128:$Rd),
8348          (OpNode (extract_high_v4i32 V128:$Rn),
8349                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8350                                                      VectorIndexS:$idx))))]> {
8351    bits<2> idx;
8352    let Inst{11} = idx{1};
8353    let Inst{21} = idx{0};
8354  }
8355  }
8356}
8357
8358multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8359                                       SDPatternOperator OpNode> {
8360  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8361  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8362                                      V128, V64,
8363                                      V128_lo, VectorIndexH,
8364                                      asm, ".4s", ".4s", ".4h", ".h",
8365    [(set (v4i32 V128:$dst),
8366        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8367         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8368    bits<3> idx;
8369    let Inst{11} = idx{2};
8370    let Inst{21} = idx{1};
8371    let Inst{20} = idx{0};
8372  }
8373
8374  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8375                                      V128, V128,
8376                                      V128_lo, VectorIndexH,
8377                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8378    [(set (v4i32 V128:$dst),
8379          (OpNode (v4i32 V128:$Rd),
8380                  (extract_high_v8i16 V128:$Rn),
8381                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8382                                                      VectorIndexH:$idx))))]> {
8383    bits<3> idx;
8384    let Inst{11} = idx{2};
8385    let Inst{21} = idx{1};
8386    let Inst{20} = idx{0};
8387  }
8388
8389  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8390                                      V128, V64,
8391                                      V128, VectorIndexS,
8392                                      asm, ".2d", ".2d", ".2s", ".s",
8393    [(set (v2i64 V128:$dst),
8394        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8395         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8396    bits<2> idx;
8397    let Inst{11} = idx{1};
8398    let Inst{21} = idx{0};
8399  }
8400
8401  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8402                                      V128, V128,
8403                                      V128, VectorIndexS,
8404                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8405    [(set (v2i64 V128:$dst),
8406          (OpNode (v2i64 V128:$Rd),
8407                  (extract_high_v4i32 V128:$Rn),
8408                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8409                                                      VectorIndexS:$idx))))]> {
8410    bits<2> idx;
8411    let Inst{11} = idx{1};
8412    let Inst{21} = idx{0};
8413  }
8414  }
8415}
8416
8417//----------------------------------------------------------------------------
8418// AdvSIMD scalar shift by immediate
8419//----------------------------------------------------------------------------
8420
8421let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8422class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8423                     RegisterClass regtype1, RegisterClass regtype2,
8424                     Operand immtype, string asm, list<dag> pattern>
8425  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8426      asm, "\t$Rd, $Rn, $imm", "", pattern>,
8427    Sched<[WriteV]> {
8428  bits<5> Rd;
8429  bits<5> Rn;
8430  bits<7> imm;
8431  let Inst{31-30} = 0b01;
8432  let Inst{29}    = U;
8433  let Inst{28-23} = 0b111110;
8434  let Inst{22-16} = fixed_imm;
8435  let Inst{15-11} = opc;
8436  let Inst{10}    = 1;
8437  let Inst{9-5} = Rn;
8438  let Inst{4-0} = Rd;
8439}
8440
8441let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8442class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8443                     RegisterClass regtype1, RegisterClass regtype2,
8444                     Operand immtype, string asm, list<dag> pattern>
8445  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8446      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8447    Sched<[WriteV]> {
8448  bits<5> Rd;
8449  bits<5> Rn;
8450  bits<7> imm;
8451  let Inst{31-30} = 0b01;
8452  let Inst{29}    = U;
8453  let Inst{28-23} = 0b111110;
8454  let Inst{22-16} = fixed_imm;
8455  let Inst{15-11} = opc;
8456  let Inst{10}    = 1;
8457  let Inst{9-5} = Rn;
8458  let Inst{4-0} = Rd;
8459}
8460
8461
8462multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8463  let Predicates = [HasNEON, HasFullFP16] in {
8464  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8465                              FPR16, FPR16, vecshiftR16, asm, []> {
8466    let Inst{19-16} = imm{3-0};
8467  }
8468  } // Predicates = [HasNEON, HasFullFP16]
8469  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8470                              FPR32, FPR32, vecshiftR32, asm, []> {
8471    let Inst{20-16} = imm{4-0};
8472  }
8473  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8474                              FPR64, FPR64, vecshiftR64, asm, []> {
8475    let Inst{21-16} = imm{5-0};
8476  }
8477}
8478
8479multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8480                             SDPatternOperator OpNode> {
8481  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8482                              FPR64, FPR64, vecshiftR64, asm,
8483  [(set (i64 FPR64:$Rd),
8484     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8485    let Inst{21-16} = imm{5-0};
8486  }
8487
8488  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8489            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8490}
8491
8492multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8493                                 SDPatternOperator OpNode = null_frag> {
8494  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8495                              FPR64, FPR64, vecshiftR64, asm,
8496  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8497                                                   (i32 vecshiftR64:$imm)))]> {
8498    let Inst{21-16} = imm{5-0};
8499  }
8500
8501  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8502                           (i32 vecshiftR64:$imm))),
8503            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8504                                            vecshiftR64:$imm)>;
8505}
8506
8507multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8508                             SDPatternOperator OpNode> {
8509  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8510                              FPR64, FPR64, vecshiftL64, asm,
8511    [(set (v1i64 FPR64:$Rd),
8512       (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8513    let Inst{21-16} = imm{5-0};
8514  }
8515}
8516
8517let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8518multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8519  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8520                              FPR64, FPR64, vecshiftL64, asm, []> {
8521    let Inst{21-16} = imm{5-0};
8522  }
8523}
8524
8525let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8526multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8527                               SDPatternOperator OpNode = null_frag> {
8528  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8529                              FPR8, FPR16, vecshiftR8, asm, []> {
8530    let Inst{18-16} = imm{2-0};
8531  }
8532
8533  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8534                              FPR16, FPR32, vecshiftR16, asm, []> {
8535    let Inst{19-16} = imm{3-0};
8536  }
8537
8538  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8539                              FPR32, FPR64, vecshiftR32, asm,
8540    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8541    let Inst{20-16} = imm{4-0};
8542  }
8543}
8544
8545multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
8546                                SDPatternOperator OpNode> {
8547  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8548                              FPR8, FPR8, vecshiftL8, asm, []> {
8549    let Inst{18-16} = imm{2-0};
8550  }
8551
8552  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8553                              FPR16, FPR16, vecshiftL16, asm, []> {
8554    let Inst{19-16} = imm{3-0};
8555  }
8556
8557  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8558                              FPR32, FPR32, vecshiftL32, asm,
8559    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
8560    let Inst{20-16} = imm{4-0};
8561  }
8562
8563  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8564                              FPR64, FPR64, vecshiftL64, asm,
8565    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8566    let Inst{21-16} = imm{5-0};
8567  }
8568
8569  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8570            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8571}
8572
8573multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
8574  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8575                              FPR8, FPR8, vecshiftR8, asm, []> {
8576    let Inst{18-16} = imm{2-0};
8577  }
8578
8579  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8580                              FPR16, FPR16, vecshiftR16, asm, []> {
8581    let Inst{19-16} = imm{3-0};
8582  }
8583
8584  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8585                              FPR32, FPR32, vecshiftR32, asm, []> {
8586    let Inst{20-16} = imm{4-0};
8587  }
8588
8589  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8590                              FPR64, FPR64, vecshiftR64, asm, []> {
8591    let Inst{21-16} = imm{5-0};
8592  }
8593}
8594
8595//----------------------------------------------------------------------------
8596// AdvSIMD vector x indexed element
8597//----------------------------------------------------------------------------
8598
8599let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8600class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8601                     RegisterOperand dst_reg, RegisterOperand src_reg,
8602                     Operand immtype,
8603                     string asm, string dst_kind, string src_kind,
8604                     list<dag> pattern>
8605  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
8606      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8607           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
8608    Sched<[WriteV]> {
8609  bits<5> Rd;
8610  bits<5> Rn;
8611  let Inst{31}    = 0;
8612  let Inst{30}    = Q;
8613  let Inst{29}    = U;
8614  let Inst{28-23} = 0b011110;
8615  let Inst{22-16} = fixed_imm;
8616  let Inst{15-11} = opc;
8617  let Inst{10}    = 1;
8618  let Inst{9-5}   = Rn;
8619  let Inst{4-0}   = Rd;
8620}
8621
8622let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8623class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
8624                     RegisterOperand vectype1, RegisterOperand vectype2,
8625                     Operand immtype,
8626                     string asm, string dst_kind, string src_kind,
8627                     list<dag> pattern>
8628  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
8629      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
8630           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
8631    Sched<[WriteV]> {
8632  bits<5> Rd;
8633  bits<5> Rn;
8634  let Inst{31}    = 0;
8635  let Inst{30}    = Q;
8636  let Inst{29}    = U;
8637  let Inst{28-23} = 0b011110;
8638  let Inst{22-16} = fixed_imm;
8639  let Inst{15-11} = opc;
8640  let Inst{10}    = 1;
8641  let Inst{9-5}   = Rn;
8642  let Inst{4-0}   = Rd;
8643}
8644
8645multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
8646                              Intrinsic OpNode> {
8647  let Predicates = [HasNEON, HasFullFP16] in {
8648  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8649                                  V64, V64, vecshiftR16,
8650                                  asm, ".4h", ".4h",
8651      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
8652    bits<4> imm;
8653    let Inst{19-16} = imm;
8654  }
8655
8656  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8657                                  V128, V128, vecshiftR16,
8658                                  asm, ".8h", ".8h",
8659      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
8660    bits<4> imm;
8661    let Inst{19-16} = imm;
8662  }
8663  } // Predicates = [HasNEON, HasFullFP16]
8664  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8665                                  V64, V64, vecshiftR32,
8666                                  asm, ".2s", ".2s",
8667      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
8668    bits<5> imm;
8669    let Inst{20-16} = imm;
8670  }
8671
8672  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8673                                  V128, V128, vecshiftR32,
8674                                  asm, ".4s", ".4s",
8675      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
8676    bits<5> imm;
8677    let Inst{20-16} = imm;
8678  }
8679
8680  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8681                                  V128, V128, vecshiftR64,
8682                                  asm, ".2d", ".2d",
8683      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
8684    bits<6> imm;
8685    let Inst{21-16} = imm;
8686  }
8687}
8688
8689multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
8690                                  Intrinsic OpNode> {
8691  let Predicates = [HasNEON, HasFullFP16] in {
8692  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8693                                  V64, V64, vecshiftR16,
8694                                  asm, ".4h", ".4h",
8695      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
8696    bits<4> imm;
8697    let Inst{19-16} = imm;
8698  }
8699
8700  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8701                                  V128, V128, vecshiftR16,
8702                                  asm, ".8h", ".8h",
8703      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
8704    bits<4> imm;
8705    let Inst{19-16} = imm;
8706  }
8707  } // Predicates = [HasNEON, HasFullFP16]
8708
8709  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8710                                  V64, V64, vecshiftR32,
8711                                  asm, ".2s", ".2s",
8712      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
8713    bits<5> imm;
8714    let Inst{20-16} = imm;
8715  }
8716
8717  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8718                                  V128, V128, vecshiftR32,
8719                                  asm, ".4s", ".4s",
8720      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
8721    bits<5> imm;
8722    let Inst{20-16} = imm;
8723  }
8724
8725  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8726                                  V128, V128, vecshiftR64,
8727                                  asm, ".2d", ".2d",
8728      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
8729    bits<6> imm;
8730    let Inst{21-16} = imm;
8731  }
8732}
8733
8734multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
8735                                     SDPatternOperator OpNode> {
8736  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8737                                  V64, V128, vecshiftR16Narrow,
8738                                  asm, ".8b", ".8h",
8739      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
8740    bits<3> imm;
8741    let Inst{18-16} = imm;
8742  }
8743
8744  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8745                                  V128, V128, vecshiftR16Narrow,
8746                                  asm#"2", ".16b", ".8h", []> {
8747    bits<3> imm;
8748    let Inst{18-16} = imm;
8749    let hasSideEffects = 0;
8750  }
8751
8752  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8753                                  V64, V128, vecshiftR32Narrow,
8754                                  asm, ".4h", ".4s",
8755      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
8756    bits<4> imm;
8757    let Inst{19-16} = imm;
8758  }
8759
8760  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8761                                  V128, V128, vecshiftR32Narrow,
8762                                  asm#"2", ".8h", ".4s", []> {
8763    bits<4> imm;
8764    let Inst{19-16} = imm;
8765    let hasSideEffects = 0;
8766  }
8767
8768  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8769                                  V64, V128, vecshiftR64Narrow,
8770                                  asm, ".2s", ".2d",
8771      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
8772    bits<5> imm;
8773    let Inst{20-16} = imm;
8774  }
8775
8776  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8777                                  V128, V128, vecshiftR64Narrow,
8778                                  asm#"2", ".4s", ".2d", []> {
8779    bits<5> imm;
8780    let Inst{20-16} = imm;
8781    let hasSideEffects = 0;
8782  }
8783
8784  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
8785  // themselves, so put them here instead.
8786
8787  // Patterns involving what's effectively an insert high and a normal
8788  // intrinsic, represented by CONCAT_VECTORS.
8789  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
8790                                                   vecshiftR16Narrow:$imm)),
8791            (!cast<Instruction>(NAME # "v16i8_shift")
8792                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8793                V128:$Rn, vecshiftR16Narrow:$imm)>;
8794  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
8795                                                     vecshiftR32Narrow:$imm)),
8796            (!cast<Instruction>(NAME # "v8i16_shift")
8797                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8798                V128:$Rn, vecshiftR32Narrow:$imm)>;
8799  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
8800                                                     vecshiftR64Narrow:$imm)),
8801            (!cast<Instruction>(NAME # "v4i32_shift")
8802                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
8803                V128:$Rn, vecshiftR64Narrow:$imm)>;
8804}
8805
8806multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
8807                                SDPatternOperator OpNode> {
8808  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8809                                  V64, V64, vecshiftL8,
8810                                  asm, ".8b", ".8b",
8811                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8812                       (i32 vecshiftL8:$imm)))]> {
8813    bits<3> imm;
8814    let Inst{18-16} = imm;
8815  }
8816
8817  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8818                                  V128, V128, vecshiftL8,
8819                                  asm, ".16b", ".16b",
8820             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8821                   (i32 vecshiftL8:$imm)))]> {
8822    bits<3> imm;
8823    let Inst{18-16} = imm;
8824  }
8825
8826  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8827                                  V64, V64, vecshiftL16,
8828                                  asm, ".4h", ".4h",
8829              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8830                    (i32 vecshiftL16:$imm)))]> {
8831    bits<4> imm;
8832    let Inst{19-16} = imm;
8833  }
8834
8835  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8836                                  V128, V128, vecshiftL16,
8837                                  asm, ".8h", ".8h",
8838            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8839                  (i32 vecshiftL16:$imm)))]> {
8840    bits<4> imm;
8841    let Inst{19-16} = imm;
8842  }
8843
8844  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8845                                  V64, V64, vecshiftL32,
8846                                  asm, ".2s", ".2s",
8847              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8848                    (i32 vecshiftL32:$imm)))]> {
8849    bits<5> imm;
8850    let Inst{20-16} = imm;
8851  }
8852
8853  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8854                                  V128, V128, vecshiftL32,
8855                                  asm, ".4s", ".4s",
8856            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8857                  (i32 vecshiftL32:$imm)))]> {
8858    bits<5> imm;
8859    let Inst{20-16} = imm;
8860  }
8861
8862  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8863                                  V128, V128, vecshiftL64,
8864                                  asm, ".2d", ".2d",
8865            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8866                  (i32 vecshiftL64:$imm)))]> {
8867    bits<6> imm;
8868    let Inst{21-16} = imm;
8869  }
8870}
8871
8872multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
8873                                SDPatternOperator OpNode> {
8874  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
8875                                  V64, V64, vecshiftR8,
8876                                  asm, ".8b", ".8b",
8877                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
8878                       (i32 vecshiftR8:$imm)))]> {
8879    bits<3> imm;
8880    let Inst{18-16} = imm;
8881  }
8882
8883  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
8884                                  V128, V128, vecshiftR8,
8885                                  asm, ".16b", ".16b",
8886             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
8887                   (i32 vecshiftR8:$imm)))]> {
8888    bits<3> imm;
8889    let Inst{18-16} = imm;
8890  }
8891
8892  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
8893                                  V64, V64, vecshiftR16,
8894                                  asm, ".4h", ".4h",
8895              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
8896                    (i32 vecshiftR16:$imm)))]> {
8897    bits<4> imm;
8898    let Inst{19-16} = imm;
8899  }
8900
8901  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
8902                                  V128, V128, vecshiftR16,
8903                                  asm, ".8h", ".8h",
8904            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
8905                  (i32 vecshiftR16:$imm)))]> {
8906    bits<4> imm;
8907    let Inst{19-16} = imm;
8908  }
8909
8910  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
8911                                  V64, V64, vecshiftR32,
8912                                  asm, ".2s", ".2s",
8913              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
8914                    (i32 vecshiftR32:$imm)))]> {
8915    bits<5> imm;
8916    let Inst{20-16} = imm;
8917  }
8918
8919  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
8920                                  V128, V128, vecshiftR32,
8921                                  asm, ".4s", ".4s",
8922            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
8923                  (i32 vecshiftR32:$imm)))]> {
8924    bits<5> imm;
8925    let Inst{20-16} = imm;
8926  }
8927
8928  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
8929                                  V128, V128, vecshiftR64,
8930                                  asm, ".2d", ".2d",
8931            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
8932                  (i32 vecshiftR64:$imm)))]> {
8933    bits<6> imm;
8934    let Inst{21-16} = imm;
8935  }
8936}
8937
8938let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8939multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
8940                                    SDPatternOperator OpNode = null_frag> {
8941  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
8942                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
8943                 [(set (v8i8 V64:$dst),
8944                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
8945                           (i32 vecshiftR8:$imm)))]> {
8946    bits<3> imm;
8947    let Inst{18-16} = imm;
8948  }
8949
8950  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
8951                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
8952             [(set (v16i8 V128:$dst),
8953               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
8954                       (i32 vecshiftR8:$imm)))]> {
8955    bits<3> imm;
8956    let Inst{18-16} = imm;
8957  }
8958
8959  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
8960                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
8961              [(set (v4i16 V64:$dst),
8962                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
8963                        (i32 vecshiftR16:$imm)))]> {
8964    bits<4> imm;
8965    let Inst{19-16} = imm;
8966  }
8967
8968  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
8969                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
8970            [(set (v8i16 V128:$dst),
8971              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8972                      (i32 vecshiftR16:$imm)))]> {
8973    bits<4> imm;
8974    let Inst{19-16} = imm;
8975  }
8976
8977  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
8978                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
8979              [(set (v2i32 V64:$dst),
8980                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8981                        (i32 vecshiftR32:$imm)))]> {
8982    bits<5> imm;
8983    let Inst{20-16} = imm;
8984  }
8985
8986  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
8987                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
8988            [(set (v4i32 V128:$dst),
8989              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8990                      (i32 vecshiftR32:$imm)))]> {
8991    bits<5> imm;
8992    let Inst{20-16} = imm;
8993  }
8994
8995  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
8996                                  V128, V128, vecshiftR64,
8997                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
8998              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
8999                      (i32 vecshiftR64:$imm)))]> {
9000    bits<6> imm;
9001    let Inst{21-16} = imm;
9002  }
9003}
9004
9005multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9006                                    SDPatternOperator OpNode = null_frag> {
9007  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9008                                  V64, V64, vecshiftL8,
9009                                  asm, ".8b", ".8b",
9010                    [(set (v8i8 V64:$dst),
9011                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9012                                  (i32 vecshiftL8:$imm)))]> {
9013    bits<3> imm;
9014    let Inst{18-16} = imm;
9015  }
9016
9017  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9018                                  V128, V128, vecshiftL8,
9019                                  asm, ".16b", ".16b",
9020                    [(set (v16i8 V128:$dst),
9021                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9022                                  (i32 vecshiftL8:$imm)))]> {
9023    bits<3> imm;
9024    let Inst{18-16} = imm;
9025  }
9026
9027  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9028                                  V64, V64, vecshiftL16,
9029                                  asm, ".4h", ".4h",
9030                    [(set (v4i16 V64:$dst),
9031                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9032                                   (i32 vecshiftL16:$imm)))]> {
9033    bits<4> imm;
9034    let Inst{19-16} = imm;
9035  }
9036
9037  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9038                                  V128, V128, vecshiftL16,
9039                                  asm, ".8h", ".8h",
9040                    [(set (v8i16 V128:$dst),
9041                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9042                                  (i32 vecshiftL16:$imm)))]> {
9043    bits<4> imm;
9044    let Inst{19-16} = imm;
9045  }
9046
9047  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9048                                  V64, V64, vecshiftL32,
9049                                  asm, ".2s", ".2s",
9050                    [(set (v2i32 V64:$dst),
9051                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9052                                  (i32 vecshiftL32:$imm)))]> {
9053    bits<5> imm;
9054    let Inst{20-16} = imm;
9055  }
9056
9057  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9058                                  V128, V128, vecshiftL32,
9059                                  asm, ".4s", ".4s",
9060                    [(set (v4i32 V128:$dst),
9061                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9062                                  (i32 vecshiftL32:$imm)))]> {
9063    bits<5> imm;
9064    let Inst{20-16} = imm;
9065  }
9066
9067  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9068                                  V128, V128, vecshiftL64,
9069                                  asm, ".2d", ".2d",
9070                    [(set (v2i64 V128:$dst),
9071                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9072                                  (i32 vecshiftL64:$imm)))]> {
9073    bits<6> imm;
9074    let Inst{21-16} = imm;
9075  }
9076}
9077
9078multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9079                                   SDPatternOperator OpNode> {
9080  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9081                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9082      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9083    bits<3> imm;
9084    let Inst{18-16} = imm;
9085  }
9086
9087  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9088                                  V128, V128, vecshiftL8,
9089                                  asm#"2", ".8h", ".16b",
9090      [(set (v8i16 V128:$Rd),
9091            (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
9092    bits<3> imm;
9093    let Inst{18-16} = imm;
9094  }
9095
9096  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9097                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9098      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9099    bits<4> imm;
9100    let Inst{19-16} = imm;
9101  }
9102
9103  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9104                                  V128, V128, vecshiftL16,
9105                                  asm#"2", ".4s", ".8h",
9106      [(set (v4i32 V128:$Rd),
9107            (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
9108
9109    bits<4> imm;
9110    let Inst{19-16} = imm;
9111  }
9112
9113  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9114                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9115      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9116    bits<5> imm;
9117    let Inst{20-16} = imm;
9118  }
9119
9120  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9121                                  V128, V128, vecshiftL32,
9122                                  asm#"2", ".2d", ".4s",
9123      [(set (v2i64 V128:$Rd),
9124            (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
9125    bits<5> imm;
9126    let Inst{20-16} = imm;
9127  }
9128}
9129
9130
9131//---
9132// Vector load/store
9133//---
9134// SIMD ldX/stX no-index memory references don't allow the optional
9135// ", #0" constant and handle post-indexing explicitly, so we use
9136// a more specialized parse method for them. Otherwise, it's the same as
9137// the general GPR64sp handling.
9138
9139class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9140                   string asm, dag oops, dag iops, list<dag> pattern>
9141  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9142  bits<5> Vt;
9143  bits<5> Rn;
9144  let Inst{31} = 0;
9145  let Inst{30} = Q;
9146  let Inst{29-23} = 0b0011000;
9147  let Inst{22} = L;
9148  let Inst{21-16} = 0b000000;
9149  let Inst{15-12} = opcode;
9150  let Inst{11-10} = size;
9151  let Inst{9-5} = Rn;
9152  let Inst{4-0} = Vt;
9153}
9154
9155class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9156                       string asm, dag oops, dag iops>
9157  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9158  bits<5> Vt;
9159  bits<5> Rn;
9160  bits<5> Xm;
9161  let Inst{31} = 0;
9162  let Inst{30} = Q;
9163  let Inst{29-23} = 0b0011001;
9164  let Inst{22} = L;
9165  let Inst{21} = 0;
9166  let Inst{20-16} = Xm;
9167  let Inst{15-12} = opcode;
9168  let Inst{11-10} = size;
9169  let Inst{9-5} = Rn;
9170  let Inst{4-0} = Vt;
9171}
9172
9173// The immediate form of AdvSIMD post-indexed addressing is encoded with
9174// register post-index addressing from the zero register.
9175multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9176                           int Offset, int Size> {
9177  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9178  //      "ld1\t$Vt, [$Rn], #16"
9179  // may get mapped to
9180  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9181  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9182                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9183                      GPR64sp:$Rn,
9184                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9185                      XZR), 1>;
9186
9187  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9188  //      "ld1.8b\t$Vt, [$Rn], #16"
9189  // may get mapped to
9190  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9191  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9192                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9193                      GPR64sp:$Rn,
9194                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9195                      XZR), 0>;
9196
9197  // E.g. "ld1.8b { v0, v1 }, [x1]"
9198  //      "ld1\t$Vt, [$Rn]"
9199  // may get mapped to
9200  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9201  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9202                  (!cast<Instruction>(BaseName # Count # "v" # layout)
9203                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9204                      GPR64sp:$Rn), 0>;
9205
9206  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9207  //      "ld1\t$Vt, [$Rn], $Xm"
9208  // may get mapped to
9209  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9210  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9211                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9212                      GPR64sp:$Rn,
9213                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9214                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9215}
9216
9217multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9218                       int Offset128, int Offset64, bits<4> opcode> {
9219  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9220    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9221                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9222                           (ins GPR64sp:$Rn), []>;
9223    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9224                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9225                           (ins GPR64sp:$Rn), []>;
9226    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9227                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9228                           (ins GPR64sp:$Rn), []>;
9229    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9230                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9231                           (ins GPR64sp:$Rn), []>;
9232    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9233                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9234                           (ins GPR64sp:$Rn), []>;
9235    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9236                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9237                           (ins GPR64sp:$Rn), []>;
9238    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9239                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9240                           (ins GPR64sp:$Rn), []>;
9241
9242
9243    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9244                       (outs GPR64sp:$wback,
9245                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
9246                       (ins GPR64sp:$Rn,
9247                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9248    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9249                       (outs GPR64sp:$wback,
9250                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
9251                       (ins GPR64sp:$Rn,
9252                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9253    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9254                       (outs GPR64sp:$wback,
9255                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
9256                       (ins GPR64sp:$Rn,
9257                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9258    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9259                       (outs GPR64sp:$wback,
9260                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
9261                       (ins GPR64sp:$Rn,
9262                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9263    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9264                       (outs GPR64sp:$wback,
9265                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
9266                       (ins GPR64sp:$Rn,
9267                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9268    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9269                       (outs GPR64sp:$wback,
9270                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
9271                       (ins GPR64sp:$Rn,
9272                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9273    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9274                       (outs GPR64sp:$wback,
9275                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
9276                       (ins GPR64sp:$Rn,
9277                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9278  }
9279
9280  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9281  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9282  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9283  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9284  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9285  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9286  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9287}
9288
9289// Only ld1/st1 has a v1d version.
9290multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9291                       int Offset128, int Offset64, bits<4> opcode> {
9292  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9293    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9294                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9295                                 GPR64sp:$Rn), []>;
9296    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9297                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9298                                GPR64sp:$Rn), []>;
9299    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9300                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9301                                GPR64sp:$Rn), []>;
9302    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9303                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9304                                GPR64sp:$Rn), []>;
9305    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9306                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9307                                GPR64sp:$Rn), []>;
9308    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9309                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9310                                GPR64sp:$Rn), []>;
9311    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9312                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9313                                GPR64sp:$Rn), []>;
9314
9315    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9316                       (outs GPR64sp:$wback),
9317                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9318                            GPR64sp:$Rn,
9319                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9320    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9321                       (outs GPR64sp:$wback),
9322                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9323                            GPR64sp:$Rn,
9324                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9325    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9326                       (outs GPR64sp:$wback),
9327                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9328                            GPR64sp:$Rn,
9329                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9330    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9331                       (outs GPR64sp:$wback),
9332                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9333                            GPR64sp:$Rn,
9334                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9335    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9336                       (outs GPR64sp:$wback),
9337                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9338                            GPR64sp:$Rn,
9339                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9340    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9341                       (outs GPR64sp:$wback),
9342                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9343                            GPR64sp:$Rn,
9344                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9345    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9346                       (outs GPR64sp:$wback),
9347                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9348                            GPR64sp:$Rn,
9349                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9350  }
9351
9352  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9353  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9354  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9355  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9356  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9357  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9358  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9359}
9360
9361multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9362                       int Offset128, int Offset64, bits<4> opcode>
9363  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9364
9365  // LD1 instructions have extra "1d" variants.
9366  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9367    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9368                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9369                           (ins GPR64sp:$Rn), []>;
9370
9371    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9372                       (outs GPR64sp:$wback,
9373                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
9374                       (ins GPR64sp:$Rn,
9375                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9376  }
9377
9378  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9379}
9380
9381multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9382                       int Offset128, int Offset64, bits<4> opcode>
9383  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9384
9385  // ST1 instructions have extra "1d" variants.
9386  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9387    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9388                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9389                                GPR64sp:$Rn), []>;
9390
9391    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9392                       (outs GPR64sp:$wback),
9393                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9394                            GPR64sp:$Rn,
9395                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9396  }
9397
9398  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9399}
9400
9401multiclass SIMDLd1Multiple<string asm> {
9402  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9403  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9404  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9405  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9406}
9407
9408multiclass SIMDSt1Multiple<string asm> {
9409  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9410  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9411  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9412  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9413}
9414
9415multiclass SIMDLd2Multiple<string asm> {
9416  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9417}
9418
9419multiclass SIMDSt2Multiple<string asm> {
9420  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9421}
9422
9423multiclass SIMDLd3Multiple<string asm> {
9424  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9425}
9426
9427multiclass SIMDSt3Multiple<string asm> {
9428  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9429}
9430
9431multiclass SIMDLd4Multiple<string asm> {
9432  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9433}
9434
9435multiclass SIMDSt4Multiple<string asm> {
9436  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9437}
9438
9439//---
9440// AdvSIMD Load/store single-element
9441//---
9442
9443class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9444                         string asm, string operands, string cst,
9445                         dag oops, dag iops, list<dag> pattern>
9446  : I<oops, iops, asm, operands, cst, pattern> {
9447  bits<5> Vt;
9448  bits<5> Rn;
9449  let Inst{31} = 0;
9450  let Inst{29-24} = 0b001101;
9451  let Inst{22} = L;
9452  let Inst{21} = R;
9453  let Inst{15-13} = opcode;
9454  let Inst{9-5} = Rn;
9455  let Inst{4-0} = Vt;
9456}
9457
9458class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9459                         string asm, string operands, string cst,
9460                         dag oops, dag iops, list<dag> pattern>
9461  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9462  bits<5> Vt;
9463  bits<5> Rn;
9464  let Inst{31} = 0;
9465  let Inst{29-24} = 0b001101;
9466  let Inst{22} = L;
9467  let Inst{21} = R;
9468  let Inst{15-13} = opcode;
9469  let Inst{9-5} = Rn;
9470  let Inst{4-0} = Vt;
9471}
9472
9473
9474let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9475class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9476                  DAGOperand listtype>
9477  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9478                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
9479                       []> {
9480  let Inst{30} = Q;
9481  let Inst{23} = 0;
9482  let Inst{20-16} = 0b00000;
9483  let Inst{12} = S;
9484  let Inst{11-10} = size;
9485}
9486let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9487class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9488                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
9489  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9490                       "$Rn = $wback",
9491                       (outs GPR64sp:$wback, listtype:$Vt),
9492                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9493  bits<5> Xm;
9494  let Inst{30} = Q;
9495  let Inst{23} = 1;
9496  let Inst{20-16} = Xm;
9497  let Inst{12} = S;
9498  let Inst{11-10} = size;
9499}
9500
9501multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9502                          int Offset, int Size> {
9503  // E.g. "ld1r { v0.8b }, [x1], #1"
9504  //      "ld1r.8b\t$Vt, [$Rn], #1"
9505  // may get mapped to
9506  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9507  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9508                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9509                      GPR64sp:$Rn,
9510                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9511                      XZR), 1>;
9512
9513  // E.g. "ld1r.8b { v0 }, [x1], #1"
9514  //      "ld1r.8b\t$Vt, [$Rn], #1"
9515  // may get mapped to
9516  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9517  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9518                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9519                      GPR64sp:$Rn,
9520                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9521                      XZR), 0>;
9522
9523  // E.g. "ld1r.8b { v0 }, [x1]"
9524  //      "ld1r.8b\t$Vt, [$Rn]"
9525  // may get mapped to
9526  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9527  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9528                  (!cast<Instruction>(BaseName # "v" # layout)
9529                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9530                      GPR64sp:$Rn), 0>;
9531
9532  // E.g. "ld1r.8b { v0 }, [x1], x2"
9533  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9534  // may get mapped to
9535  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9536  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9537                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9538                      GPR64sp:$Rn,
9539                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9540                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9541}
9542
9543multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9544  int Offset1, int Offset2, int Offset4, int Offset8> {
9545  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
9546                        !cast<DAGOperand>("VecList" # Count # "8b")>;
9547  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
9548                        !cast<DAGOperand>("VecList" # Count #"16b")>;
9549  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
9550                        !cast<DAGOperand>("VecList" # Count #"4h")>;
9551  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
9552                        !cast<DAGOperand>("VecList" # Count #"8h")>;
9553  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
9554                        !cast<DAGOperand>("VecList" # Count #"2s")>;
9555  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
9556                        !cast<DAGOperand>("VecList" # Count #"4s")>;
9557  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
9558                        !cast<DAGOperand>("VecList" # Count #"1d")>;
9559  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
9560                        !cast<DAGOperand>("VecList" # Count #"2d")>;
9561
9562  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
9563                                 !cast<DAGOperand>("VecList" # Count # "8b"),
9564                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9565  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
9566                                 !cast<DAGOperand>("VecList" # Count # "16b"),
9567                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
9568  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
9569                                 !cast<DAGOperand>("VecList" # Count # "4h"),
9570                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9571  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
9572                                 !cast<DAGOperand>("VecList" # Count # "8h"),
9573                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
9574  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
9575                                 !cast<DAGOperand>("VecList" # Count # "2s"),
9576                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9577  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
9578                                 !cast<DAGOperand>("VecList" # Count # "4s"),
9579                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
9580  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
9581                                 !cast<DAGOperand>("VecList" # Count # "1d"),
9582                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9583  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
9584                                 !cast<DAGOperand>("VecList" # Count # "2d"),
9585                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
9586
9587  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
9588  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
9589  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
9590  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
9591  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
9592  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
9593  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
9594  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
9595}
9596
9597class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
9598                      dag oops, dag iops, list<dag> pattern>
9599  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9600                       pattern> {
9601  // idx encoded in Q:S:size fields.
9602  bits<4> idx;
9603  let Inst{30} = idx{3};
9604  let Inst{23} = 0;
9605  let Inst{20-16} = 0b00000;
9606  let Inst{12} = idx{2};
9607  let Inst{11-10} = idx{1-0};
9608}
9609class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
9610                      dag oops, dag iops, list<dag> pattern>
9611  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9612                           oops, iops, pattern> {
9613  // idx encoded in Q:S:size fields.
9614  bits<4> idx;
9615  let Inst{30} = idx{3};
9616  let Inst{23} = 0;
9617  let Inst{20-16} = 0b00000;
9618  let Inst{12} = idx{2};
9619  let Inst{11-10} = idx{1-0};
9620}
9621class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
9622                          dag oops, dag iops>
9623  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9624                       "$Rn = $wback", oops, iops, []> {
9625  // idx encoded in Q:S:size fields.
9626  bits<4> idx;
9627  bits<5> Xm;
9628  let Inst{30} = idx{3};
9629  let Inst{23} = 1;
9630  let Inst{20-16} = Xm;
9631  let Inst{12} = idx{2};
9632  let Inst{11-10} = idx{1-0};
9633}
9634class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
9635                          dag oops, dag iops>
9636  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9637                           "$Rn = $wback", oops, iops, []> {
9638  // idx encoded in Q:S:size fields.
9639  bits<4> idx;
9640  bits<5> Xm;
9641  let Inst{30} = idx{3};
9642  let Inst{23} = 1;
9643  let Inst{20-16} = Xm;
9644  let Inst{12} = idx{2};
9645  let Inst{11-10} = idx{1-0};
9646}
9647
9648class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
9649                      dag oops, dag iops, list<dag> pattern>
9650  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9651                       pattern> {
9652  // idx encoded in Q:S:size<1> fields.
9653  bits<3> idx;
9654  let Inst{30} = idx{2};
9655  let Inst{23} = 0;
9656  let Inst{20-16} = 0b00000;
9657  let Inst{12} = idx{1};
9658  let Inst{11} = idx{0};
9659  let Inst{10} = size;
9660}
9661class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
9662                      dag oops, dag iops, list<dag> pattern>
9663  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9664                           oops, iops, pattern> {
9665  // idx encoded in Q:S:size<1> fields.
9666  bits<3> idx;
9667  let Inst{30} = idx{2};
9668  let Inst{23} = 0;
9669  let Inst{20-16} = 0b00000;
9670  let Inst{12} = idx{1};
9671  let Inst{11} = idx{0};
9672  let Inst{10} = size;
9673}
9674
9675class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9676                          dag oops, dag iops>
9677  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9678                       "$Rn = $wback", oops, iops, []> {
9679  // idx encoded in Q:S:size<1> fields.
9680  bits<3> idx;
9681  bits<5> Xm;
9682  let Inst{30} = idx{2};
9683  let Inst{23} = 1;
9684  let Inst{20-16} = Xm;
9685  let Inst{12} = idx{1};
9686  let Inst{11} = idx{0};
9687  let Inst{10} = size;
9688}
9689class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
9690                          dag oops, dag iops>
9691  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9692                           "$Rn = $wback", oops, iops, []> {
9693  // idx encoded in Q:S:size<1> fields.
9694  bits<3> idx;
9695  bits<5> Xm;
9696  let Inst{30} = idx{2};
9697  let Inst{23} = 1;
9698  let Inst{20-16} = Xm;
9699  let Inst{12} = idx{1};
9700  let Inst{11} = idx{0};
9701  let Inst{10} = size;
9702}
9703class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9704                      dag oops, dag iops, list<dag> pattern>
9705  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9706                       pattern> {
9707  // idx encoded in Q:S fields.
9708  bits<2> idx;
9709  let Inst{30} = idx{1};
9710  let Inst{23} = 0;
9711  let Inst{20-16} = 0b00000;
9712  let Inst{12} = idx{0};
9713  let Inst{11-10} = size;
9714}
9715class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9716                      dag oops, dag iops, list<dag> pattern>
9717  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9718                           oops, iops, pattern> {
9719  // idx encoded in Q:S fields.
9720  bits<2> idx;
9721  let Inst{30} = idx{1};
9722  let Inst{23} = 0;
9723  let Inst{20-16} = 0b00000;
9724  let Inst{12} = idx{0};
9725  let Inst{11-10} = size;
9726}
9727class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
9728                          string asm, dag oops, dag iops>
9729  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9730                       "$Rn = $wback", oops, iops, []> {
9731  // idx encoded in Q:S fields.
9732  bits<2> idx;
9733  bits<5> Xm;
9734  let Inst{30} = idx{1};
9735  let Inst{23} = 1;
9736  let Inst{20-16} = Xm;
9737  let Inst{12} = idx{0};
9738  let Inst{11-10} = size;
9739}
9740class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9741                          string asm, dag oops, dag iops>
9742  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9743                           "$Rn = $wback", oops, iops, []> {
9744  // idx encoded in Q:S fields.
9745  bits<2> idx;
9746  bits<5> Xm;
9747  let Inst{30} = idx{1};
9748  let Inst{23} = 1;
9749  let Inst{20-16} = Xm;
9750  let Inst{12} = idx{0};
9751  let Inst{11-10} = size;
9752}
9753class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9754                      dag oops, dag iops, list<dag> pattern>
9755  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
9756                       pattern> {
9757  // idx encoded in Q field.
9758  bits<1> idx;
9759  let Inst{30} = idx;
9760  let Inst{23} = 0;
9761  let Inst{20-16} = 0b00000;
9762  let Inst{12} = 0;
9763  let Inst{11-10} = size;
9764}
9765class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
9766                      dag oops, dag iops, list<dag> pattern>
9767  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
9768                           oops, iops, pattern> {
9769  // idx encoded in Q field.
9770  bits<1> idx;
9771  let Inst{30} = idx;
9772  let Inst{23} = 0;
9773  let Inst{20-16} = 0b00000;
9774  let Inst{12} = 0;
9775  let Inst{11-10} = size;
9776}
9777class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
9778                          string asm, dag oops, dag iops>
9779  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9780                       "$Rn = $wback", oops, iops, []> {
9781  // idx encoded in Q field.
9782  bits<1> idx;
9783  bits<5> Xm;
9784  let Inst{30} = idx;
9785  let Inst{23} = 1;
9786  let Inst{20-16} = Xm;
9787  let Inst{12} = 0;
9788  let Inst{11-10} = size;
9789}
9790class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
9791                          string asm, dag oops, dag iops>
9792  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
9793                           "$Rn = $wback", oops, iops, []> {
9794  // idx encoded in Q field.
9795  bits<1> idx;
9796  bits<5> Xm;
9797  let Inst{30} = idx;
9798  let Inst{23} = 1;
9799  let Inst{20-16} = Xm;
9800  let Inst{12} = 0;
9801  let Inst{11-10} = size;
9802}
9803
9804let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9805multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
9806                         RegisterOperand listtype,
9807                         RegisterOperand GPR64pi> {
9808  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
9809                           (outs listtype:$dst),
9810                           (ins listtype:$Vt, VectorIndexB:$idx,
9811                                GPR64sp:$Rn), []>;
9812
9813  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
9814                            (outs GPR64sp:$wback, listtype:$dst),
9815                            (ins listtype:$Vt, VectorIndexB:$idx,
9816                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
9817}
9818let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9819multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
9820                         RegisterOperand listtype,
9821                         RegisterOperand GPR64pi> {
9822  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
9823                            (outs listtype:$dst),
9824                            (ins listtype:$Vt, VectorIndexH:$idx,
9825                                 GPR64sp:$Rn), []>;
9826
9827  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
9828                            (outs GPR64sp:$wback, listtype:$dst),
9829                            (ins listtype:$Vt, VectorIndexH:$idx,
9830                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
9831}
9832let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9833multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
9834                         RegisterOperand listtype,
9835                         RegisterOperand GPR64pi> {
9836  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
9837                            (outs listtype:$dst),
9838                            (ins listtype:$Vt, VectorIndexS:$idx,
9839                                 GPR64sp:$Rn), []>;
9840
9841  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
9842                            (outs GPR64sp:$wback, listtype:$dst),
9843                            (ins listtype:$Vt, VectorIndexS:$idx,
9844                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
9845}
9846let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9847multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
9848                         RegisterOperand listtype, RegisterOperand GPR64pi> {
9849  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
9850                            (outs listtype:$dst),
9851                            (ins listtype:$Vt, VectorIndexD:$idx,
9852                                 GPR64sp:$Rn), []>;
9853
9854  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
9855                            (outs GPR64sp:$wback, listtype:$dst),
9856                            (ins listtype:$Vt, VectorIndexD:$idx,
9857                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
9858}
9859let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9860multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
9861                         RegisterOperand listtype, RegisterOperand GPR64pi> {
9862  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
9863                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
9864                                        GPR64sp:$Rn), []>;
9865
9866  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
9867                                    (outs GPR64sp:$wback),
9868                                    (ins listtype:$Vt, VectorIndexB:$idx,
9869                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
9870}
9871let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9872multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
9873                         RegisterOperand listtype, RegisterOperand GPR64pi> {
9874  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
9875                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
9876                                         GPR64sp:$Rn), []>;
9877
9878  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
9879                            (outs GPR64sp:$wback),
9880                            (ins listtype:$Vt, VectorIndexH:$idx,
9881                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
9882}
9883let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9884multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
9885                         RegisterOperand listtype, RegisterOperand GPR64pi> {
9886  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
9887                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
9888                                         GPR64sp:$Rn), []>;
9889
9890  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
9891                            (outs GPR64sp:$wback),
9892                            (ins listtype:$Vt, VectorIndexS:$idx,
9893                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
9894}
9895let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
9896multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
9897                         RegisterOperand listtype, RegisterOperand GPR64pi> {
9898  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
9899                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
9900                                         GPR64sp:$Rn), []>;
9901
9902  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
9903                            (outs GPR64sp:$wback),
9904                            (ins listtype:$Vt, VectorIndexD:$idx,
9905                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
9906}
9907
9908multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
9909                                 string Count, int Offset, Operand idxtype> {
9910  // E.g. "ld1 { v0.8b }[0], [x1], #1"
9911  //      "ld1\t$Vt, [$Rn], #1"
9912  // may get mapped to
9913  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9914  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
9915                  (!cast<Instruction>(NAME # Type  # "_POST")
9916                      GPR64sp:$Rn,
9917                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9918                      idxtype:$idx, XZR), 1>;
9919
9920  // E.g. "ld1.8b { v0 }[0], [x1], #1"
9921  //      "ld1.8b\t$Vt, [$Rn], #1"
9922  // may get mapped to
9923  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9924  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
9925                  (!cast<Instruction>(NAME # Type # "_POST")
9926                      GPR64sp:$Rn,
9927                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9928                      idxtype:$idx, XZR), 0>;
9929
9930  // E.g. "ld1.8b { v0 }[0], [x1]"
9931  //      "ld1.8b\t$Vt, [$Rn]"
9932  // may get mapped to
9933  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9934  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
9935                      (!cast<Instruction>(NAME # Type)
9936                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9937                         idxtype:$idx, GPR64sp:$Rn), 0>;
9938
9939  // E.g. "ld1.8b { v0 }[0], [x1], x2"
9940  //      "ld1.8b\t$Vt, [$Rn], $Xm"
9941  // may get mapped to
9942  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9943  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
9944                      (!cast<Instruction>(NAME # Type # "_POST")
9945                         GPR64sp:$Rn,
9946                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
9947                         idxtype:$idx,
9948                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9949}
9950
9951multiclass SIMDLdSt1SingleAliases<string asm> {
9952  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
9953  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
9954  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
9955  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
9956}
9957
9958multiclass SIMDLdSt2SingleAliases<string asm> {
9959  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
9960  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
9961  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
9962  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
9963}
9964
9965multiclass SIMDLdSt3SingleAliases<string asm> {
9966  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
9967  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
9968  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
9969  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
9970}
9971
9972multiclass SIMDLdSt4SingleAliases<string asm> {
9973  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
9974  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
9975  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
9976  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
9977}
9978} // end of 'let Predicates = [HasNEON]'
9979
9980//----------------------------------------------------------------------------
9981// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
9982//----------------------------------------------------------------------------
9983
9984let Predicates = [HasNEON, HasRDM] in {
9985
9986class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
9987                                    RegisterOperand regtype, string asm,
9988                                    string kind, list<dag> pattern>
9989  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
9990                                pattern> {
9991}
9992multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
9993                                             SDPatternOperator Accum> {
9994  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
9995    [(set (v4i16 V64:$dst),
9996          (Accum (v4i16 V64:$Rd),
9997                 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
9998                                                   (v4i16 V64:$Rm)))))]>;
9999  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10000    [(set (v8i16 V128:$dst),
10001          (Accum (v8i16 V128:$Rd),
10002                 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
10003                                                   (v8i16 V128:$Rm)))))]>;
10004  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10005    [(set (v2i32 V64:$dst),
10006          (Accum (v2i32 V64:$Rd),
10007                 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
10008                                                   (v2i32 V64:$Rm)))))]>;
10009  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10010    [(set (v4i32 V128:$dst),
10011          (Accum (v4i32 V128:$Rd),
10012                 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
10013                                                   (v4i32 V128:$Rm)))))]>;
10014}
10015
10016multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10017                                     SDPatternOperator Accum> {
10018  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10019                                          V64, V64, V128_lo, VectorIndexH,
10020                                          asm, ".4h", ".4h", ".4h", ".h",
10021    [(set (v4i16 V64:$dst),
10022          (Accum (v4i16 V64:$Rd),
10023                 (v4i16 (int_aarch64_neon_sqrdmulh
10024                          (v4i16 V64:$Rn),
10025                          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10026                                                    VectorIndexH:$idx))))))]> {
10027    bits<3> idx;
10028    let Inst{11} = idx{2};
10029    let Inst{21} = idx{1};
10030    let Inst{20} = idx{0};
10031  }
10032
10033  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10034                                          V128, V128, V128_lo, VectorIndexH,
10035                                          asm, ".8h", ".8h", ".8h", ".h",
10036    [(set (v8i16 V128:$dst),
10037          (Accum (v8i16 V128:$Rd),
10038                 (v8i16 (int_aarch64_neon_sqrdmulh
10039                          (v8i16 V128:$Rn),
10040                          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10041                                                   VectorIndexH:$idx))))))]> {
10042    bits<3> idx;
10043    let Inst{11} = idx{2};
10044    let Inst{21} = idx{1};
10045    let Inst{20} = idx{0};
10046  }
10047
10048  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10049                                          V64, V64, V128, VectorIndexS,
10050                                          asm, ".2s", ".2s", ".2s", ".s",
10051    [(set (v2i32 V64:$dst),
10052        (Accum (v2i32 V64:$Rd),
10053               (v2i32 (int_aarch64_neon_sqrdmulh
10054                        (v2i32 V64:$Rn),
10055                        (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10056                                                 VectorIndexS:$idx))))))]> {
10057    bits<2> idx;
10058    let Inst{11} = idx{1};
10059    let Inst{21} = idx{0};
10060  }
10061
10062  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10063  // an intermediate EXTRACT_SUBREG would be untyped.
10064  // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
10065  // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
10066  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10067                       (i32 (vector_extract
10068                               (v4i32 (insert_subvector
10069                                       (undef),
10070                                        (v2i32 (int_aarch64_neon_sqrdmulh
10071                                                 (v2i32 V64:$Rn),
10072                                                 (v2i32 (AArch64duplane32
10073                                                          (v4i32 V128:$Rm),
10074                                                          VectorIndexS:$idx)))),
10075                                      (i32 0))),
10076                               (i64 0))))),
10077            (EXTRACT_SUBREG
10078                (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
10079                          (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
10080                                                FPR32Op:$Rd,
10081                                                ssub)),
10082                          V64:$Rn,
10083                          V128:$Rm,
10084                          VectorIndexS:$idx)),
10085                ssub)>;
10086
10087  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10088                                          V128, V128, V128, VectorIndexS,
10089                                          asm, ".4s", ".4s", ".4s", ".s",
10090    [(set (v4i32 V128:$dst),
10091          (Accum (v4i32 V128:$Rd),
10092                 (v4i32 (int_aarch64_neon_sqrdmulh
10093                          (v4i32 V128:$Rn),
10094                          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10095                                                   VectorIndexS:$idx))))))]> {
10096    bits<2> idx;
10097    let Inst{11} = idx{1};
10098    let Inst{21} = idx{0};
10099  }
10100
10101  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10102  // an intermediate EXTRACT_SUBREG would be untyped.
10103  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10104                        (i32 (vector_extract
10105                               (v4i32 (int_aarch64_neon_sqrdmulh
10106                                        (v4i32 V128:$Rn),
10107                                        (v4i32 (AArch64duplane32
10108                                                 (v4i32 V128:$Rm),
10109                                                 VectorIndexS:$idx)))),
10110                               (i64 0))))),
10111            (EXTRACT_SUBREG
10112                (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
10113                         (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
10114                                               FPR32Op:$Rd,
10115                                               ssub)),
10116                         V128:$Rn,
10117                         V128:$Rm,
10118                         VectorIndexS:$idx)),
10119                ssub)>;
10120
10121  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10122                                        FPR16Op, FPR16Op, V128_lo,
10123                                        VectorIndexH, asm, ".h", "", "", ".h",
10124                                        []> {
10125    bits<3> idx;
10126    let Inst{11} = idx{2};
10127    let Inst{21} = idx{1};
10128    let Inst{20} = idx{0};
10129  }
10130
10131  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10132                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10133                                        asm, ".s", "", "", ".s",
10134    [(set (i32 FPR32Op:$dst),
10135          (Accum (i32 FPR32Op:$Rd),
10136                 (i32 (int_aarch64_neon_sqrdmulh
10137                        (i32 FPR32Op:$Rn),
10138                        (i32 (vector_extract (v4i32 V128:$Rm),
10139                                             VectorIndexS:$idx))))))]> {
10140    bits<2> idx;
10141    let Inst{11} = idx{1};
10142    let Inst{21} = idx{0};
10143  }
10144}
10145} // let Predicates = [HasNeon, HasRDM]
10146
10147//----------------------------------------------------------------------------
10148// ARMv8.3 Complex ADD/MLA instructions
10149//----------------------------------------------------------------------------
10150
10151class ComplexRotationOperand<int Angle, int Remainder, string Type>
10152  : AsmOperandClass {
10153  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10154  let DiagnosticType = "InvalidComplexRotation" # Type;
10155  let Name = "ComplexRotation" # Type;
10156}
10157def complexrotateop : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10158                                                 SDNodeXForm<imm, [{
10159  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10160}]>> {
10161  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10162  let PrintMethod = "printComplexRotationOp<90, 0>";
10163}
10164def complexrotateopodd : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10165                                                 SDNodeXForm<imm, [{
10166  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10167}]>> {
10168  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10169  let PrintMethod = "printComplexRotationOp<180, 90>";
10170}
10171let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10172class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10173                                     RegisterOperand regtype, Operand rottype,
10174                                     string asm, string kind, list<dag> pattern>
10175  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10176      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10177      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10178    Sched<[WriteV]> {
10179  bits<5> Rd;
10180  bits<5> Rn;
10181  bits<5> Rm;
10182  bits<1> rot;
10183  let Inst{31}    = 0;
10184  let Inst{30}    = Q;
10185  let Inst{29}    = U;
10186  let Inst{28-24} = 0b01110;
10187  let Inst{23-22} = size;
10188  let Inst{21}    = 0;
10189  let Inst{20-16} = Rm;
10190  let Inst{15-13} = opcode;
10191  // Non-tied version (FCADD) only has one rotation bit
10192  let Inst{12}    = rot;
10193  let Inst{11}    = 0;
10194  let Inst{10}    = 1;
10195  let Inst{9-5}   = Rn;
10196  let Inst{4-0}   = Rd;
10197}
10198
10199//8.3 CompNum - Floating-point complex number support
10200multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10201                                          string asm, SDPatternOperator OpNode>{
10202  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10203  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10204              asm, ".4h",
10205              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10206                                              (v4f16 V64:$Rn),
10207                                              (v4f16 V64:$Rm),
10208                                              (rottype i32:$rot)))]>;
10209
10210  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10211              asm, ".8h",
10212              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10213                                               (v8f16 V128:$Rn),
10214                                               (v8f16 V128:$Rm),
10215                                               (rottype i32:$rot)))]>;
10216  }
10217
10218  let Predicates = [HasComplxNum, HasNEON] in {
10219  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10220              asm, ".2s",
10221              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10222                                              (v2f32 V64:$Rn),
10223                                              (v2f32 V64:$Rm),
10224                                              (rottype i32:$rot)))]>;
10225
10226  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10227              asm, ".4s",
10228              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10229                                               (v4f32 V128:$Rn),
10230                                               (v4f32 V128:$Rm),
10231                                               (rottype i32:$rot)))]>;
10232
10233  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10234              asm, ".2d",
10235              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10236                                               (v2f64 V128:$Rn),
10237                                               (v2f64 V128:$Rm),
10238                                               (rottype i32:$rot)))]>;
10239  }
10240}
10241
10242let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10243class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10244                                         bits<3> opcode,
10245                                         RegisterOperand regtype,
10246                                         Operand rottype, string asm,
10247                                         string kind, list<dag> pattern>
10248  : I<(outs regtype:$dst),
10249      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10250      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10251      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10252    Sched<[WriteV]> {
10253  bits<5> Rd;
10254  bits<5> Rn;
10255  bits<5> Rm;
10256  bits<2> rot;
10257  let Inst{31}    = 0;
10258  let Inst{30}    = Q;
10259  let Inst{29}    = U;
10260  let Inst{28-24} = 0b01110;
10261  let Inst{23-22} = size;
10262  let Inst{21}    = 0;
10263  let Inst{20-16} = Rm;
10264  let Inst{15-13} = opcode;
10265  let Inst{12-11} = rot;
10266  let Inst{10}    = 1;
10267  let Inst{9-5}   = Rn;
10268  let Inst{4-0}   = Rd;
10269}
10270
10271multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10272                                             Operand rottype, string asm,
10273                                             SDPatternOperator OpNode> {
10274  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10275  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10276              rottype, asm, ".4h",
10277              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10278                                              (v4f16 V64:$Rn),
10279                                              (v4f16 V64:$Rm),
10280                                              (rottype i32:$rot)))]>;
10281
10282  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10283              rottype, asm, ".8h",
10284              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10285                                               (v8f16 V128:$Rn),
10286                                               (v8f16 V128:$Rm),
10287                                               (rottype i32:$rot)))]>;
10288  }
10289
10290  let Predicates = [HasComplxNum, HasNEON] in {
10291  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10292              rottype, asm, ".2s",
10293              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10294                                              (v2f32 V64:$Rn),
10295                                              (v2f32 V64:$Rm),
10296                                              (rottype i32:$rot)))]>;
10297
10298  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10299              rottype, asm, ".4s",
10300              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10301                                               (v4f32 V128:$Rn),
10302                                               (v4f32 V128:$Rm),
10303                                               (rottype i32:$rot)))]>;
10304
10305  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10306              rottype, asm, ".2d",
10307              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10308                                               (v2f64 V128:$Rn),
10309                                               (v2f64 V128:$Rm),
10310                                               (rottype i32:$rot)))]>;
10311  }
10312}
10313
10314let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10315class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10316                                 bit opc1, bit opc2, RegisterOperand dst_reg,
10317                                 RegisterOperand lhs_reg,
10318                                 RegisterOperand rhs_reg, Operand vec_idx,
10319                                 Operand rottype, string asm, string apple_kind,
10320                                 string dst_kind, string lhs_kind,
10321                                 string rhs_kind, list<dag> pattern>
10322  : I<(outs dst_reg:$dst),
10323      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10324      asm,
10325      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10326      "$idx, $rot" # "|" # apple_kind #
10327      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10328    Sched<[WriteV]> {
10329  bits<5> Rd;
10330  bits<5> Rn;
10331  bits<5> Rm;
10332  bits<2> rot;
10333
10334  let Inst{31}    = 0;
10335  let Inst{30}    = Q;
10336  let Inst{29}    = U;
10337  let Inst{28}    = Scalar;
10338  let Inst{27-24} = 0b1111;
10339  let Inst{23-22} = size;
10340  // Bit 21 must be set by the derived class.
10341  let Inst{20-16} = Rm;
10342  let Inst{15}    = opc1;
10343  let Inst{14-13} = rot;
10344  let Inst{12}    = opc2;
10345  // Bit 11 must be set by the derived class.
10346  let Inst{10}    = 0;
10347  let Inst{9-5}   = Rn;
10348  let Inst{4-0}   = Rd;
10349}
10350
10351// The complex instructions index by pairs of elements, so the VectorIndexes
10352// don't match the lane types, and the index bits are different to the other
10353// classes.
10354multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10355                                     string asm, SDPatternOperator OpNode> {
10356  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10357  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10358                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10359                      ".4h", ".h", []> {
10360    bits<1> idx;
10361    let Inst{11} = 0;
10362    let Inst{21} = idx{0};
10363  }
10364
10365  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10366                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10367                      ".8h", ".8h", ".h", []> {
10368    bits<2> idx;
10369    let Inst{11} = idx{1};
10370    let Inst{21} = idx{0};
10371  }
10372  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10373
10374  let Predicates = [HasComplxNum, HasNEON] in {
10375  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10376                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10377                      ".4s", ".4s", ".s", []> {
10378    bits<1> idx;
10379    let Inst{11} = idx{0};
10380    let Inst{21} = 0;
10381  }
10382  } // Predicates = [HasComplxNum, HasNEON]
10383}
10384
10385//----------------------------------------------------------------------------
10386// Crypto extensions
10387//----------------------------------------------------------------------------
10388
10389let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10390class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10391              list<dag> pat>
10392  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10393    Sched<[WriteV]>{
10394  bits<5> Rd;
10395  bits<5> Rn;
10396  let Inst{31-16} = 0b0100111000101000;
10397  let Inst{15-12} = opc;
10398  let Inst{11-10} = 0b10;
10399  let Inst{9-5}   = Rn;
10400  let Inst{4-0}   = Rd;
10401}
10402
10403class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10404  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10405            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10406
10407class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10408  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10409            "$Rd = $dst",
10410            [(set (v16i8 V128:$dst),
10411                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10412
10413let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10414class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10415                     dag oops, dag iops, list<dag> pat>
10416  : I<oops, iops, asm,
10417      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10418      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10419    Sched<[WriteV]>{
10420  bits<5> Rd;
10421  bits<5> Rn;
10422  bits<5> Rm;
10423  let Inst{31-21} = 0b01011110000;
10424  let Inst{20-16} = Rm;
10425  let Inst{15}    = 0;
10426  let Inst{14-12} = opc;
10427  let Inst{11-10} = 0b00;
10428  let Inst{9-5}   = Rn;
10429  let Inst{4-0}   = Rd;
10430}
10431
10432class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10433  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10434                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10435                   [(set (v4i32 FPR128:$dst),
10436                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10437                                 (v4i32 V128:$Rm)))]>;
10438
10439class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10440  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10441                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
10442                   [(set (v4i32 V128:$dst),
10443                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10444                                 (v4i32 V128:$Rm)))]>;
10445
10446class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10447  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10448                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10449                   [(set (v4i32 FPR128:$dst),
10450                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10451                                 (v4i32 V128:$Rm)))]>;
10452
10453let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10454class SHA2OpInst<bits<4> opc, string asm, string kind,
10455                 string cstr, dag oops, dag iops,
10456                 list<dag> pat>
10457  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10458                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10459    Sched<[WriteV]>{
10460  bits<5> Rd;
10461  bits<5> Rn;
10462  let Inst{31-16} = 0b0101111000101000;
10463  let Inst{15-12} = opc;
10464  let Inst{11-10} = 0b10;
10465  let Inst{9-5}   = Rn;
10466  let Inst{4-0}   = Rd;
10467}
10468
10469class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10470  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10471               (ins V128:$Rd, V128:$Rn),
10472               [(set (v4i32 V128:$dst),
10473                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10474
10475class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10476  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10477               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10478
10479// Armv8.2-A Crypto extensions
10480class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10481                    list<dag> pattern>
10482  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10483  bits<5> Vd;
10484  bits<5> Vn;
10485  let Inst{31-25} = 0b1100111;
10486  let Inst{9-5}   = Vn;
10487  let Inst{4-0}   = Vd;
10488}
10489
10490class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10491  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm, asmops,
10492                  "$Vm = $Vd", []> {
10493  let Inst{31-25} = 0b1100111;
10494  let Inst{24-21} = 0b0110;
10495  let Inst{20-15} = 0b000001;
10496  let Inst{14}    = op0;
10497  let Inst{13-12} = 0b00;
10498  let Inst{11-10} = op1;
10499}
10500class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10501  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
10502class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10503  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
10504
10505class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10506                string asmops, string cst>
10507  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10508  bits<5> Vm;
10509  let Inst{24-21} = 0b0011;
10510  let Inst{20-16} = Vm;
10511  let Inst{15}    = 0b1;
10512  let Inst{14}    = op0;
10513  let Inst{13-12} = 0b00;
10514  let Inst{11-10} = op1;
10515}
10516class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10517  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10518              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
10519class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10520  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10521              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10522class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10523  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10524              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
10525class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10526  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10527              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10528class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10529  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10530              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10531
10532class CryptoRRRR<bits<2>op0, string asm, string asmops>
10533  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10534                  asmops, "", []> {
10535  bits<5> Vm;
10536  bits<5> Va;
10537  let Inst{24-23} = 0b00;
10538  let Inst{22-21} = op0;
10539  let Inst{20-16} = Vm;
10540  let Inst{15}    = 0b0;
10541  let Inst{14-10} = Va;
10542}
10543class CryptoRRRR_16B<bits<2>op0, string asm>
10544 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
10545                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
10546}
10547class CryptoRRRR_4S<bits<2>op0, string asm>
10548 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
10549                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
10550}
10551
10552class CryptoRRRi6<string asm>
10553  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
10554                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
10555                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
10556  bits<6> imm;
10557  bits<5> Vm;
10558  let Inst{24-21} = 0b0100;
10559  let Inst{20-16} = Vm;
10560  let Inst{15-10} = imm;
10561  let Inst{9-5}   = Vn;
10562  let Inst{4-0}   = Vd;
10563}
10564
10565class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
10566  : BaseCryptoV82<(outs V128:$Vdst),
10567                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
10568                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
10569                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
10570  bits<2> imm;
10571  bits<5> Vm;
10572  let Inst{24-21} = 0b0010;
10573  let Inst{20-16} = Vm;
10574  let Inst{15}    = 0b1;
10575  let Inst{14}    = op0;
10576  let Inst{13-12} = imm;
10577  let Inst{11-10} = op1;
10578}
10579
10580//----------------------------------------------------------------------------
10581// v8.1 atomic instructions extension:
10582// * CAS
10583// * CASP
10584// * SWP
10585// * LDOPregister<OP>, and aliases STOPregister<OP>
10586
10587// Instruction encodings:
10588//
10589//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
10590// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
10591// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
10592// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
10593// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
10594// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
10595
10596// Instruction syntax:
10597//
10598// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10599// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
10600// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
10601// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
10602// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10603// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
10604// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
10605// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
10606// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
10607// ST<OP>{<order>} <Xs>, [<Xn|SP>]
10608
10609let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10610class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
10611                      string cstr, list<dag> pattern>
10612      : I<oops, iops, asm, operands, cstr, pattern> {
10613  bits<2> Sz;
10614  bit NP;
10615  bit Acq;
10616  bit Rel;
10617  bits<5> Rs;
10618  bits<5> Rn;
10619  bits<5> Rt;
10620  let Inst{31-30} = Sz;
10621  let Inst{29-24} = 0b001000;
10622  let Inst{23} = NP;
10623  let Inst{22} = Acq;
10624  let Inst{21} = 0b1;
10625  let Inst{20-16} = Rs;
10626  let Inst{15} = Rel;
10627  let Inst{14-10} = 0b11111;
10628  let Inst{9-5} = Rn;
10629  let Inst{4-0} = Rt;
10630  let Predicates = [HasLSE];
10631}
10632
10633class BaseCAS<string order, string size, RegisterClass RC>
10634      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10635                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
10636                        "$out = $Rs",[]>,
10637        Sched<[WriteAtomic]> {
10638  let NP = 1;
10639}
10640
10641multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
10642  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
10643  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
10644  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
10645  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
10646}
10647
10648class BaseCASP<string order, string size, RegisterOperand RC>
10649      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
10650                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
10651                        "$out = $Rs",[]>,
10652        Sched<[WriteAtomic]> {
10653  let NP = 0;
10654}
10655
10656multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
10657  let Sz = 0b00, Acq = Acq, Rel = Rel in
10658    def W : BaseCASP<order, "", WSeqPairClassOperand>;
10659  let Sz = 0b01, Acq = Acq, Rel = Rel in
10660    def X : BaseCASP<order, "", XSeqPairClassOperand>;
10661}
10662
10663let Predicates = [HasLSE] in
10664class BaseSWP<string order, string size, RegisterClass RC>
10665      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
10666          "\t$Rs, $Rt, [$Rn]","",[]>,
10667        Sched<[WriteAtomic]> {
10668  bits<2> Sz;
10669  bit Acq;
10670  bit Rel;
10671  bits<5> Rs;
10672  bits<3> opc = 0b000;
10673  bits<5> Rn;
10674  bits<5> Rt;
10675  let Inst{31-30} = Sz;
10676  let Inst{29-24} = 0b111000;
10677  let Inst{23} = Acq;
10678  let Inst{22} = Rel;
10679  let Inst{21} = 0b1;
10680  let Inst{20-16} = Rs;
10681  let Inst{15} = 0b1;
10682  let Inst{14-12} = opc;
10683  let Inst{11-10} = 0b00;
10684  let Inst{9-5} = Rn;
10685  let Inst{4-0} = Rt;
10686  let Predicates = [HasLSE];
10687}
10688
10689multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
10690  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
10691  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
10692  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
10693  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
10694}
10695
10696let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
10697class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
10698      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
10699          "\t$Rs, $Rt, [$Rn]","",[]>,
10700        Sched<[WriteAtomic]> {
10701  bits<2> Sz;
10702  bit Acq;
10703  bit Rel;
10704  bits<5> Rs;
10705  bits<3> opc;
10706  bits<5> Rn;
10707  bits<5> Rt;
10708  let Inst{31-30} = Sz;
10709  let Inst{29-24} = 0b111000;
10710  let Inst{23} = Acq;
10711  let Inst{22} = Rel;
10712  let Inst{21} = 0b1;
10713  let Inst{20-16} = Rs;
10714  let Inst{15} = 0b0;
10715  let Inst{14-12} = opc;
10716  let Inst{11-10} = 0b00;
10717  let Inst{9-5} = Rn;
10718  let Inst{4-0} = Rt;
10719  let Predicates = [HasLSE];
10720}
10721
10722multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
10723                        string order> {
10724  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
10725    def B : BaseLDOPregister<op, order, "b", GPR32>;
10726  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
10727    def H : BaseLDOPregister<op, order, "h", GPR32>;
10728  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
10729    def W : BaseLDOPregister<op, order, "", GPR32>;
10730  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
10731    def X : BaseLDOPregister<op, order, "", GPR64>;
10732}
10733
10734// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
10735// complex DAG for DstRHS.
10736let Predicates = [HasLSE] in
10737multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
10738                                         string size, dag SrcRHS, dag DstRHS> {
10739  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
10740            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
10741  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
10742            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
10743  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
10744            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
10745  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
10746            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10747  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
10748            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
10749}
10750
10751multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
10752                                     string size, dag RHS> {
10753  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
10754}
10755
10756multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
10757                                         string size, dag LHS, dag RHS> {
10758  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
10759}
10760
10761multiclass LDOPregister_patterns<string inst, string op> {
10762  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
10763  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
10764  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
10765  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
10766}
10767
10768multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
10769  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
10770                        (i64 GPR64:$Rm),
10771                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
10772  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
10773                        (i32 GPR32:$Rm),
10774                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10775  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
10776                        (i32 GPR32:$Rm),
10777                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10778  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
10779                        (i32 GPR32:$Rm),
10780                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
10781}
10782
10783let Predicates = [HasLSE] in
10784multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
10785                                        string size, dag OLD, dag NEW> {
10786  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
10787            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
10788  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
10789            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10790  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
10791            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10792  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
10793            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10794  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
10795            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
10796}
10797
10798multiclass CASregister_patterns_ord<string inst, string suffix, string op,
10799                                    string size, dag OLD, dag NEW> {
10800  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
10801}
10802
10803multiclass CASregister_patterns<string inst, string op> {
10804  defm : CASregister_patterns_ord<inst, "X", op, "64",
10805                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
10806  defm : CASregister_patterns_ord<inst, "W", op, "32",
10807                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10808  defm : CASregister_patterns_ord<inst, "H", op, "16",
10809                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10810  defm : CASregister_patterns_ord<inst, "B", op, "8",
10811                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
10812}
10813
10814let Predicates = [HasLSE] in
10815class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
10816                        Instruction inst> :
10817      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
10818
10819multiclass STOPregister<string asm, string instr> {
10820  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
10821                    !cast<Instruction>(instr # "LB")>;
10822  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
10823                    !cast<Instruction>(instr # "LH")>;
10824  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
10825                    !cast<Instruction>(instr # "LW")>;
10826  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
10827                    !cast<Instruction>(instr # "LX")>;
10828  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
10829                    !cast<Instruction>(instr # "B")>;
10830  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
10831                    !cast<Instruction>(instr # "H")>;
10832  def : BaseSTOPregister<asm,        GPR32, WZR,
10833                    !cast<Instruction>(instr # "W")>;
10834  def : BaseSTOPregister<asm,        GPR64, XZR,
10835                    !cast<Instruction>(instr # "X")>;
10836}
10837
10838//----------------------------------------------------------------------------
10839// Allow the size specifier tokens to be upper case, not just lower.
10840def : TokenAlias<".4B", ".4b">;  // Add dot product
10841def : TokenAlias<".8B", ".8b">;
10842def : TokenAlias<".4H", ".4h">;
10843def : TokenAlias<".2S", ".2s">;
10844def : TokenAlias<".1D", ".1d">;
10845def : TokenAlias<".16B", ".16b">;
10846def : TokenAlias<".8H", ".8h">;
10847def : TokenAlias<".4S", ".4s">;
10848def : TokenAlias<".2D", ".2d">;
10849def : TokenAlias<".1Q", ".1q">;
10850def : TokenAlias<".2H", ".2h">;
10851def : TokenAlias<".B", ".b">;
10852def : TokenAlias<".H", ".h">;
10853def : TokenAlias<".S", ".s">;
10854def : TokenAlias<".D", ".d">;
10855def : TokenAlias<".Q", ".q">;
10856