xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Target/AArch64/AArch64InstrFormats.td (revision 82d56013d7b633d116a93943de88e08335357a7c)
1//===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9//===----------------------------------------------------------------------===//
10//  Describe AArch64 instructions format here
11//
12
13// Format specifies the encoding used by the instruction.  This is part of the
14// ad-hoc solution used to emit machine instruction encodings by our machine
15// code emitter.
16class Format<bits<2> val> {
17  bits<2> Value = val;
18}
19
20def PseudoFrm   : Format<0>;
21def NormalFrm   : Format<1>; // Do we need any others?
22
23// Enum describing whether an instruction is
24// destructive in its first source operand.
25class DestructiveInstTypeEnum<bits<4> val> {
26  bits<4> Value = val;
27}
28def NotDestructive                : DestructiveInstTypeEnum<0>;
29// Destructive in its first operand and can be MOVPRFX'd, but has no other
30// special properties.
31def DestructiveOther              : DestructiveInstTypeEnum<1>;
32def DestructiveUnary              : DestructiveInstTypeEnum<2>;
33def DestructiveBinaryImm          : DestructiveInstTypeEnum<3>;
34def DestructiveBinaryShImmUnpred  : DestructiveInstTypeEnum<4>;
35def DestructiveBinary             : DestructiveInstTypeEnum<5>;
36def DestructiveBinaryComm         : DestructiveInstTypeEnum<6>;
37def DestructiveBinaryCommWithRev  : DestructiveInstTypeEnum<7>;
38def DestructiveTernaryCommWithRev : DestructiveInstTypeEnum<8>;
39
40class FalseLanesEnum<bits<2> val> {
41  bits<2> Value = val;
42}
43def FalseLanesNone  : FalseLanesEnum<0>;
44def FalseLanesZero  : FalseLanesEnum<1>;
45def FalseLanesUndef : FalseLanesEnum<2>;
46
47// AArch64 Instruction Format
48class AArch64Inst<Format f, string cstr> : Instruction {
49  field bits<32> Inst; // Instruction encoding.
50  // Mask of bits that cause an encoding to be UNPREDICTABLE.
51  // If a bit is set, then if the corresponding bit in the
52  // target encoding differs from its value in the "Inst" field,
53  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
54  field bits<32> Unpredictable = 0;
55  // SoftFail is the generic name for this field, but we alias it so
56  // as to make it more obvious what it means in ARM-land.
57  field bits<32> SoftFail = Unpredictable;
58  let Namespace   = "AArch64";
59  Format F        = f;
60  bits<2> Form    = F.Value;
61
62  // Defaults
63  bit isWhile = 0;
64  bit isPTestLike = 0;
65  FalseLanesEnum FalseLanes = FalseLanesNone;
66  DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
67  ElementSizeEnum ElementSize = ElementSizeNone;
68
69  let TSFlags{10}  = isPTestLike;
70  let TSFlags{9}   = isWhile;
71  let TSFlags{8-7} = FalseLanes.Value;
72  let TSFlags{6-3} = DestructiveInstType.Value;
73  let TSFlags{2-0} = ElementSize.Value;
74
75  let Pattern     = [];
76  let Constraints = cstr;
77}
78
79class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
80  : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
81
82// Pseudo instructions (don't have encoding information)
83class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
84    : AArch64Inst<PseudoFrm, cstr> {
85  dag OutOperandList = oops;
86  dag InOperandList  = iops;
87  let Pattern        = pattern;
88  let isCodeGenOnly  = 1;
89  let isPseudo       = 1;
90}
91
92// Real instructions (have encoding information)
93class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
94  let Pattern = pattern;
95  let Size = 4;
96}
97
98// Normal instructions
99class I<dag oops, dag iops, string asm, string operands, string cstr,
100        list<dag> pattern>
101    : EncodedI<cstr, pattern> {
102  dag OutOperandList = oops;
103  dag InOperandList  = iops;
104  let AsmString      = !strconcat(asm, operands);
105}
106
107class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
108class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
109class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
110
111// Helper fragment for an extract of the high portion of a 128-bit vector.
112def extract_high_v16i8 :
113   UnOpFrag<(extract_subvector (v16i8 node:$LHS), (i64 8))>;
114def extract_high_v8i16 :
115   UnOpFrag<(extract_subvector (v8i16 node:$LHS), (i64 4))>;
116def extract_high_v4i32 :
117   UnOpFrag<(extract_subvector (v4i32 node:$LHS), (i64 2))>;
118def extract_high_v2i64 :
119   UnOpFrag<(extract_subvector (v2i64 node:$LHS), (i64 1))>;
120
121//===----------------------------------------------------------------------===//
122// Asm Operand Classes.
123//
124
125// Shifter operand for arithmetic shifted encodings.
126def ShifterOperand : AsmOperandClass {
127  let Name = "Shifter";
128}
129
130// Shifter operand for mov immediate encodings.
131def MovImm32ShifterOperand : AsmOperandClass {
132  let SuperClasses = [ShifterOperand];
133  let Name = "MovImm32Shifter";
134  let RenderMethod = "addShifterOperands";
135  let DiagnosticType = "InvalidMovImm32Shift";
136}
137def MovImm64ShifterOperand : AsmOperandClass {
138  let SuperClasses = [ShifterOperand];
139  let Name = "MovImm64Shifter";
140  let RenderMethod = "addShifterOperands";
141  let DiagnosticType = "InvalidMovImm64Shift";
142}
143
144// Shifter operand for arithmetic register shifted encodings.
145class ArithmeticShifterOperand<int width> : AsmOperandClass {
146  let SuperClasses = [ShifterOperand];
147  let Name = "ArithmeticShifter" # width;
148  let PredicateMethod = "isArithmeticShifter<" # width # ">";
149  let RenderMethod = "addShifterOperands";
150  let DiagnosticType = "AddSubRegShift" # width;
151}
152
153def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
154def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
155
156// Shifter operand for logical register shifted encodings.
157class LogicalShifterOperand<int width> : AsmOperandClass {
158  let SuperClasses = [ShifterOperand];
159  let Name = "LogicalShifter" # width;
160  let PredicateMethod = "isLogicalShifter<" # width # ">";
161  let RenderMethod = "addShifterOperands";
162  let DiagnosticType = "AddSubRegShift" # width;
163}
164
165def LogicalShifterOperand32 : LogicalShifterOperand<32>;
166def LogicalShifterOperand64 : LogicalShifterOperand<64>;
167
168// Shifter operand for logical vector 128/64-bit shifted encodings.
169def LogicalVecShifterOperand : AsmOperandClass {
170  let SuperClasses = [ShifterOperand];
171  let Name = "LogicalVecShifter";
172  let RenderMethod = "addShifterOperands";
173}
174def LogicalVecHalfWordShifterOperand : AsmOperandClass {
175  let SuperClasses = [LogicalVecShifterOperand];
176  let Name = "LogicalVecHalfWordShifter";
177  let RenderMethod = "addShifterOperands";
178}
179
180// The "MSL" shifter on the vector MOVI instruction.
181def MoveVecShifterOperand : AsmOperandClass {
182  let SuperClasses = [ShifterOperand];
183  let Name = "MoveVecShifter";
184  let RenderMethod = "addShifterOperands";
185}
186
187// Extend operand for arithmetic encodings.
188def ExtendOperand : AsmOperandClass {
189  let Name = "Extend";
190  let DiagnosticType = "AddSubRegExtendLarge";
191}
192def ExtendOperand64 : AsmOperandClass {
193  let SuperClasses = [ExtendOperand];
194  let Name = "Extend64";
195  let DiagnosticType = "AddSubRegExtendSmall";
196}
197// 'extend' that's a lsl of a 64-bit register.
198def ExtendOperandLSL64 : AsmOperandClass {
199  let SuperClasses = [ExtendOperand];
200  let Name = "ExtendLSL64";
201  let RenderMethod = "addExtend64Operands";
202  let DiagnosticType = "AddSubRegExtendLarge";
203}
204
205// 8-bit floating-point immediate encodings.
206def FPImmOperand : AsmOperandClass {
207  let Name = "FPImm";
208  let ParserMethod = "tryParseFPImm<true>";
209  let DiagnosticType = "InvalidFPImm";
210}
211
212def CondCode : AsmOperandClass {
213  let Name = "CondCode";
214  let DiagnosticType = "InvalidCondCode";
215}
216
217// A 32-bit register pasrsed as 64-bit
218def GPR32as64Operand : AsmOperandClass {
219  let Name = "GPR32as64";
220  let ParserMethod =
221      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
222}
223def GPR32as64 : RegisterOperand<GPR32> {
224  let ParserMatchClass = GPR32as64Operand;
225}
226
227// A 64-bit register pasrsed as 32-bit
228def GPR64as32Operand : AsmOperandClass {
229  let Name = "GPR64as32";
230  let ParserMethod =
231      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
232}
233def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
234  let ParserMatchClass = GPR64as32Operand;
235}
236
237// 8-bit immediate for AdvSIMD where 64-bit values of the form:
238// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
239// are encoded as the eight bit value 'abcdefgh'.
240def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
241
242class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
243  let Name = "UImm" # Width # "s" # Scale;
244  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
245  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
246  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
247}
248
249class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
250  let Name = "SImm" # Width # "s" # Scale;
251  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
252  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
253  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
254}
255
256//===----------------------------------------------------------------------===//
257// Operand Definitions.
258//
259
260// ADR[P] instruction labels.
261def AdrpOperand : AsmOperandClass {
262  let Name = "AdrpLabel";
263  let ParserMethod = "tryParseAdrpLabel";
264  let DiagnosticType = "InvalidLabel";
265}
266def adrplabel : Operand<i64> {
267  let EncoderMethod = "getAdrLabelOpValue";
268  let PrintMethod = "printAdrpLabel";
269  let ParserMatchClass = AdrpOperand;
270  let OperandType = "OPERAND_PCREL";
271}
272
273def AdrOperand : AsmOperandClass {
274  let Name = "AdrLabel";
275  let ParserMethod = "tryParseAdrLabel";
276  let DiagnosticType = "InvalidLabel";
277}
278def adrlabel : Operand<i64> {
279  let EncoderMethod = "getAdrLabelOpValue";
280  let ParserMatchClass = AdrOperand;
281}
282
283class SImmOperand<int width> : AsmOperandClass {
284  let Name = "SImm" # width;
285  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
286  let RenderMethod = "addImmOperands";
287  let PredicateMethod = "isSImm<" # width # ">";
288}
289
290
291class AsmImmRange<int Low, int High> : AsmOperandClass {
292  let Name = "Imm" # Low # "_" # High;
293  let DiagnosticType = "InvalidImm" # Low # "_" # High;
294  let RenderMethod = "addImmOperands";
295  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
296}
297
298// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
299def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
300def simm10Scaled : Operand<i64> {
301  let ParserMatchClass = SImm10s8Operand;
302  let DecoderMethod = "DecodeSImm<10>";
303  let PrintMethod = "printImmScale<8>";
304}
305
306def simm9s16 : Operand<i64> {
307  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
308  let DecoderMethod = "DecodeSImm<9>";
309  let PrintMethod = "printImmScale<16>";
310}
311
312// uimm6 predicate - True if the immediate is in the range [0, 63].
313def UImm6Operand : AsmOperandClass {
314  let Name = "UImm6";
315  let DiagnosticType = "InvalidImm0_63";
316}
317
318def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
319  let ParserMatchClass = UImm6Operand;
320}
321
322def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
323  let ParserMatchClass = AsmImmRange<0, 65535>;
324}
325
326def SImm9Operand : SImmOperand<9>;
327def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
328  let ParserMatchClass = SImm9Operand;
329  let DecoderMethod = "DecodeSImm<9>";
330}
331
332def SImm8Operand : SImmOperand<8>;
333def simm8 : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
334  let ParserMatchClass = SImm8Operand;
335  let DecoderMethod = "DecodeSImm<8>";
336}
337
338def SImm6Operand : SImmOperand<6>;
339def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
340  let ParserMatchClass = SImm6Operand;
341  let DecoderMethod = "DecodeSImm<6>";
342}
343
344def SImm5Operand : SImmOperand<5>;
345def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
346  let ParserMatchClass = SImm5Operand;
347  let DecoderMethod = "DecodeSImm<5>";
348}
349
350def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
351  let ParserMatchClass = SImm5Operand;
352  let DecoderMethod = "DecodeSImm<5>";
353}
354
355def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
356  let ParserMatchClass = SImm5Operand;
357  let DecoderMethod = "DecodeSImm<5>";
358  let PrintMethod = "printSImm<8>";
359}
360
361def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
362  let ParserMatchClass = SImm5Operand;
363  let DecoderMethod = "DecodeSImm<5>";
364  let PrintMethod = "printSImm<16>";
365}
366
367// simm7sN predicate - True if the immediate is a multiple of N in the range
368// [-64 * N, 63 * N].
369
370def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
371def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
372def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
373
374def simm7s4 : Operand<i32> {
375  let ParserMatchClass = SImm7s4Operand;
376  let PrintMethod = "printImmScale<4>";
377}
378
379def simm7s8 : Operand<i32> {
380  let ParserMatchClass = SImm7s8Operand;
381  let PrintMethod = "printImmScale<8>";
382}
383
384def simm7s16 : Operand<i32> {
385  let ParserMatchClass = SImm7s16Operand;
386  let PrintMethod = "printImmScale<16>";
387}
388
389def am_sve_fi : ComplexPattern<i64, 2, "SelectAddrModeFrameIndexSVE", []>;
390
391def am_indexed7s8   : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S8", []>;
392def am_indexed7s16  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S16", []>;
393def am_indexed7s32  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S32", []>;
394def am_indexed7s64  : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S64", []>;
395def am_indexed7s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed7S128", []>;
396
397def am_indexedu6s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedU6S128", []>;
398def am_indexeds9s128 : ComplexPattern<i64, 2, "SelectAddrModeIndexedS9S128", []>;
399
400def UImmS1XForm : SDNodeXForm<imm, [{
401  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
402}]>;
403def UImmS2XForm : SDNodeXForm<imm, [{
404  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
405}]>;
406def UImmS4XForm : SDNodeXForm<imm, [{
407  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
408}]>;
409def UImmS8XForm : SDNodeXForm<imm, [{
410  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
411}]>;
412
413// uimm5sN predicate - True if the immediate is a multiple of N in the range
414// [0 * N, 32 * N].
415def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
416def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
417def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
418
419def uimm5s2 : Operand<i64>, ImmLeaf<i64,
420                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
421                UImmS2XForm> {
422  let ParserMatchClass = UImm5s2Operand;
423  let PrintMethod = "printImmScale<2>";
424}
425def uimm5s4 : Operand<i64>, ImmLeaf<i64,
426                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
427                UImmS4XForm> {
428  let ParserMatchClass = UImm5s4Operand;
429  let PrintMethod = "printImmScale<4>";
430}
431def uimm5s8 : Operand<i64>, ImmLeaf<i64,
432                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
433                UImmS8XForm> {
434  let ParserMatchClass = UImm5s8Operand;
435  let PrintMethod = "printImmScale<8>";
436}
437
438// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
439// instead of ImmLeaf (Constant)
440def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
441                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
442                UImmS2XForm> {
443  let ParserMatchClass = UImm5s2Operand;
444  let PrintMethod = "printImmScale<2>";
445}
446def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
447                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
448                UImmS4XForm> {
449  let ParserMatchClass = UImm5s4Operand;
450  let PrintMethod = "printImmScale<4>";
451}
452def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
453                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
454                UImmS8XForm> {
455  let ParserMatchClass = UImm5s8Operand;
456  let PrintMethod = "printImmScale<8>";
457}
458
459// uimm6sN predicate - True if the immediate is a multiple of N in the range
460// [0 * N, 64 * N].
461def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
462def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
463def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
464def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
465def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
466
467def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
468  let ParserMatchClass = UImm6s1Operand;
469}
470def uimm6s2 : Operand<i64>, ImmLeaf<i64,
471[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
472  let PrintMethod = "printImmScale<2>";
473  let ParserMatchClass = UImm6s2Operand;
474}
475def uimm6s4 : Operand<i64>, ImmLeaf<i64,
476[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
477  let PrintMethod = "printImmScale<4>";
478  let ParserMatchClass = UImm6s4Operand;
479}
480def uimm6s8 : Operand<i64>, ImmLeaf<i64,
481[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
482  let PrintMethod = "printImmScale<8>";
483  let ParserMatchClass = UImm6s8Operand;
484}
485def uimm6s16 : Operand<i64>, ImmLeaf<i64,
486[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
487  let PrintMethod = "printImmScale<16>";
488  let ParserMatchClass = UImm6s16Operand;
489}
490
491def SImmS2XForm : SDNodeXForm<imm, [{
492  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
493}]>;
494def SImmS3XForm : SDNodeXForm<imm, [{
495  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
496}]>;
497def SImmS4XForm : SDNodeXForm<imm, [{
498  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
499}]>;
500def SImmS16XForm : SDNodeXForm<imm, [{
501  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
502}]>;
503def SImmS32XForm : SDNodeXForm<imm, [{
504  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
505}]>;
506
507// simm6sN predicate - True if the immediate is a multiple of N in the range
508// [-32 * N, 31 * N].
509def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
510def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
511  let ParserMatchClass = SImm6s1Operand;
512  let DecoderMethod = "DecodeSImm<6>";
513}
514
515// simm4sN predicate - True if the immediate is a multiple of N in the range
516// [ -8* N, 7 * N].
517def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
518def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
519def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
520def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
521def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
522def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
523
524def simm4s1 : Operand<i64>, ImmLeaf<i64,
525[{ return Imm >=-8  && Imm <= 7; }]> {
526  let ParserMatchClass = SImm4s1Operand;
527  let DecoderMethod = "DecodeSImm<4>";
528}
529
530def simm4s2 : Operand<i64>, ImmLeaf<i64,
531[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
532  let PrintMethod = "printImmScale<2>";
533  let ParserMatchClass = SImm4s2Operand;
534  let DecoderMethod = "DecodeSImm<4>";
535}
536
537def simm4s3 : Operand<i64>, ImmLeaf<i64,
538[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
539  let PrintMethod = "printImmScale<3>";
540  let ParserMatchClass = SImm4s3Operand;
541  let DecoderMethod = "DecodeSImm<4>";
542}
543
544def simm4s4 : Operand<i64>, ImmLeaf<i64,
545[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
546  let PrintMethod = "printImmScale<4>";
547  let ParserMatchClass = SImm4s4Operand;
548  let DecoderMethod = "DecodeSImm<4>";
549}
550def simm4s16 : Operand<i64>, ImmLeaf<i64,
551[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
552  let PrintMethod = "printImmScale<16>";
553  let ParserMatchClass = SImm4s16Operand;
554  let DecoderMethod = "DecodeSImm<4>";
555}
556def simm4s32 : Operand<i64>, ImmLeaf<i64,
557[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
558  let PrintMethod = "printImmScale<32>";
559  let ParserMatchClass = SImm4s32Operand;
560  let DecoderMethod = "DecodeSImm<4>";
561}
562
563def Imm1_8Operand : AsmImmRange<1, 8>;
564def Imm1_16Operand : AsmImmRange<1, 16>;
565def Imm1_32Operand : AsmImmRange<1, 32>;
566def Imm1_64Operand : AsmImmRange<1, 64>;
567
568class BranchTarget<int N> : AsmOperandClass {
569  let Name = "BranchTarget" # N;
570  let DiagnosticType = "InvalidLabel";
571  let PredicateMethod = "isBranchTarget<" # N # ">";
572}
573
574class PCRelLabel<int N> : BranchTarget<N> {
575  let Name = "PCRelLabel" # N;
576}
577
578def BranchTarget14Operand : BranchTarget<14>;
579def BranchTarget26Operand : BranchTarget<26>;
580def PCRelLabel19Operand   : PCRelLabel<19>;
581
582def MovWSymbolG3AsmOperand : AsmOperandClass {
583  let Name = "MovWSymbolG3";
584  let RenderMethod = "addImmOperands";
585}
586
587def movw_symbol_g3 : Operand<i32> {
588  let ParserMatchClass = MovWSymbolG3AsmOperand;
589}
590
591def MovWSymbolG2AsmOperand : AsmOperandClass {
592  let Name = "MovWSymbolG2";
593  let RenderMethod = "addImmOperands";
594}
595
596def movw_symbol_g2 : Operand<i32> {
597  let ParserMatchClass = MovWSymbolG2AsmOperand;
598}
599
600def MovWSymbolG1AsmOperand : AsmOperandClass {
601  let Name = "MovWSymbolG1";
602  let RenderMethod = "addImmOperands";
603}
604
605def movw_symbol_g1 : Operand<i32> {
606  let ParserMatchClass = MovWSymbolG1AsmOperand;
607}
608
609def MovWSymbolG0AsmOperand : AsmOperandClass {
610  let Name = "MovWSymbolG0";
611  let RenderMethod = "addImmOperands";
612}
613
614def movw_symbol_g0 : Operand<i32> {
615  let ParserMatchClass = MovWSymbolG0AsmOperand;
616}
617
618class fixedpoint_i32<ValueType FloatVT>
619  : Operand<FloatVT>,
620    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
621  let EncoderMethod = "getFixedPointScaleOpValue";
622  let DecoderMethod = "DecodeFixedPointScaleImm32";
623  let ParserMatchClass = Imm1_32Operand;
624}
625
626class fixedpoint_i64<ValueType FloatVT>
627  : Operand<FloatVT>,
628    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
629  let EncoderMethod = "getFixedPointScaleOpValue";
630  let DecoderMethod = "DecodeFixedPointScaleImm64";
631  let ParserMatchClass = Imm1_64Operand;
632}
633
634def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
635def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
636def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
637
638def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
639def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
640def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
641
642def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
643  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
644}]> {
645  let EncoderMethod = "getVecShiftR8OpValue";
646  let DecoderMethod = "DecodeVecShiftR8Imm";
647  let ParserMatchClass = Imm1_8Operand;
648}
649def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
650  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
651}]> {
652  let EncoderMethod = "getVecShiftR16OpValue";
653  let DecoderMethod = "DecodeVecShiftR16Imm";
654  let ParserMatchClass = Imm1_16Operand;
655}
656def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
657  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
658}]> {
659  let EncoderMethod = "getVecShiftR16OpValue";
660  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
661  let ParserMatchClass = Imm1_8Operand;
662}
663def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
664  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
665}]> {
666  let EncoderMethod = "getVecShiftR32OpValue";
667  let DecoderMethod = "DecodeVecShiftR32Imm";
668  let ParserMatchClass = Imm1_32Operand;
669}
670def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
671  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
672}]> {
673  let EncoderMethod = "getVecShiftR32OpValue";
674  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
675  let ParserMatchClass = Imm1_16Operand;
676}
677def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
678  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
679}]> {
680  let EncoderMethod = "getVecShiftR64OpValue";
681  let DecoderMethod = "DecodeVecShiftR64Imm";
682  let ParserMatchClass = Imm1_64Operand;
683}
684def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
685  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
686}]> {
687  let EncoderMethod = "getVecShiftR64OpValue";
688  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
689  let ParserMatchClass = Imm1_32Operand;
690}
691
692// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
693// (ImmLeaf)
694def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
695  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
696}]> {
697  let EncoderMethod = "getVecShiftR8OpValue";
698  let DecoderMethod = "DecodeVecShiftR8Imm";
699  let ParserMatchClass = Imm1_8Operand;
700}
701def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
702  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
703}]> {
704  let EncoderMethod = "getVecShiftR16OpValue";
705  let DecoderMethod = "DecodeVecShiftR16Imm";
706  let ParserMatchClass = Imm1_16Operand;
707}
708def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
709  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
710}]> {
711  let EncoderMethod = "getVecShiftR32OpValue";
712  let DecoderMethod = "DecodeVecShiftR32Imm";
713  let ParserMatchClass = Imm1_32Operand;
714}
715def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
716  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
717}]> {
718  let EncoderMethod = "getVecShiftR64OpValue";
719  let DecoderMethod = "DecodeVecShiftR64Imm";
720  let ParserMatchClass = Imm1_64Operand;
721}
722
723def Imm0_1Operand : AsmImmRange<0, 1>;
724def Imm0_7Operand : AsmImmRange<0, 7>;
725def Imm0_15Operand : AsmImmRange<0, 15>;
726def Imm0_31Operand : AsmImmRange<0, 31>;
727def Imm0_63Operand : AsmImmRange<0, 63>;
728
729def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
730  return (((uint32_t)Imm) < 8);
731}]> {
732  let EncoderMethod = "getVecShiftL8OpValue";
733  let DecoderMethod = "DecodeVecShiftL8Imm";
734  let ParserMatchClass = Imm0_7Operand;
735}
736def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
737  return (((uint32_t)Imm) < 16);
738}]> {
739  let EncoderMethod = "getVecShiftL16OpValue";
740  let DecoderMethod = "DecodeVecShiftL16Imm";
741  let ParserMatchClass = Imm0_15Operand;
742}
743def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
744  return (((uint32_t)Imm) < 32);
745}]> {
746  let EncoderMethod = "getVecShiftL32OpValue";
747  let DecoderMethod = "DecodeVecShiftL32Imm";
748  let ParserMatchClass = Imm0_31Operand;
749}
750def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
751  return (((uint32_t)Imm) < 64);
752}]> {
753  let EncoderMethod = "getVecShiftL64OpValue";
754  let DecoderMethod = "DecodeVecShiftL64Imm";
755  let ParserMatchClass = Imm0_63Operand;
756}
757
758// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
759// (ImmLeaf)
760def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
761  return (((uint32_t)Imm) < 8);
762}]> {
763  let EncoderMethod = "getVecShiftL8OpValue";
764  let DecoderMethod = "DecodeVecShiftL8Imm";
765  let ParserMatchClass = Imm0_7Operand;
766}
767def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
768  return (((uint32_t)Imm) < 16);
769}]> {
770  let EncoderMethod = "getVecShiftL16OpValue";
771  let DecoderMethod = "DecodeVecShiftL16Imm";
772  let ParserMatchClass = Imm0_15Operand;
773}
774def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
775  return (((uint32_t)Imm) < 32);
776}]> {
777  let EncoderMethod = "getVecShiftL32OpValue";
778  let DecoderMethod = "DecodeVecShiftL32Imm";
779  let ParserMatchClass = Imm0_31Operand;
780}
781def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
782  return (((uint32_t)Imm) < 64);
783}]> {
784  let EncoderMethod = "getVecShiftL64OpValue";
785  let DecoderMethod = "DecodeVecShiftL64Imm";
786  let ParserMatchClass = Imm0_63Operand;
787}
788
789// Crazy immediate formats used by 32-bit and 64-bit logical immediate
790// instructions for splatting repeating bit patterns across the immediate.
791def logical_imm32_XFORM : SDNodeXForm<imm, [{
792  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
793  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
794}]>;
795def logical_imm64_XFORM : SDNodeXForm<imm, [{
796  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
797  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
798}]>;
799
800def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
801  GISDNodeXFormEquiv<logical_imm32_XFORM>;
802def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
803  GISDNodeXFormEquiv<logical_imm64_XFORM>;
804
805let DiagnosticType = "LogicalSecondSource" in {
806  def LogicalImm32Operand : AsmOperandClass {
807    let Name = "LogicalImm32";
808    let PredicateMethod = "isLogicalImm<int32_t>";
809    let RenderMethod = "addLogicalImmOperands<int32_t>";
810  }
811  def LogicalImm64Operand : AsmOperandClass {
812    let Name = "LogicalImm64";
813    let PredicateMethod = "isLogicalImm<int64_t>";
814    let RenderMethod = "addLogicalImmOperands<int64_t>";
815  }
816  def LogicalImm32NotOperand : AsmOperandClass {
817    let Name = "LogicalImm32Not";
818    let PredicateMethod = "isLogicalImm<int32_t>";
819    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
820  }
821  def LogicalImm64NotOperand : AsmOperandClass {
822    let Name = "LogicalImm64Not";
823    let PredicateMethod = "isLogicalImm<int64_t>";
824    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
825  }
826}
827def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
828  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
829}], logical_imm32_XFORM> {
830  let PrintMethod = "printLogicalImm<int32_t>";
831  let ParserMatchClass = LogicalImm32Operand;
832}
833def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
834  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
835}], logical_imm64_XFORM> {
836  let PrintMethod = "printLogicalImm<int64_t>";
837  let ParserMatchClass = LogicalImm64Operand;
838}
839def logical_imm32_not : Operand<i32> {
840  let ParserMatchClass = LogicalImm32NotOperand;
841}
842def logical_imm64_not : Operand<i64> {
843  let ParserMatchClass = LogicalImm64NotOperand;
844}
845
846// iXX_imm0_65535 predicates - True if the immediate is in the range [0,65535].
847let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
848def i32_imm0_65535 : Operand<i32>, TImmLeaf<i32, [{
849  return ((uint32_t)Imm) < 65536;
850}]>;
851
852def i64_imm0_65535 : Operand<i64>, TImmLeaf<i64, [{
853  return ((uint64_t)Imm) < 65536;
854}]>;
855}
856
857// imm0_255 predicate - True if the immediate is in the range [0,255].
858def Imm0_255Operand : AsmImmRange<0,255>;
859
860def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
861  return ((uint32_t)Imm) < 256;
862}]> {
863  let ParserMatchClass = Imm0_255Operand;
864  let PrintMethod = "printImm";
865}
866
867// imm0_127 predicate - True if the immediate is in the range [0,127]
868def Imm0_127Operand : AsmImmRange<0, 127>;
869def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
870  return ((uint32_t)Imm) < 128;
871}]> {
872  let ParserMatchClass = Imm0_127Operand;
873  let PrintMethod = "printImm";
874}
875
876def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
877  return ((uint64_t)Imm) < 128;
878}]> {
879  let ParserMatchClass = Imm0_127Operand;
880  let PrintMethod = "printImm";
881}
882
883// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
884// for all shift-amounts.
885
886// imm0_63 predicate - True if the immediate is in the range [0,63]
887def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
888  return ((uint64_t)Imm) < 64;
889}]> {
890  let ParserMatchClass = Imm0_63Operand;
891}
892
893def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
894  return ((uint64_t)Imm) < 64;
895}]> {
896  let ParserMatchClass = Imm0_63Operand;
897}
898
899// imm0_31 predicate - True if the immediate is in the range [0,31]
900def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
901  return ((uint64_t)Imm) < 32;
902}]> {
903  let ParserMatchClass = Imm0_31Operand;
904}
905
906// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
907// instead of Constant (ImmLeaf)
908def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
909  return ((uint64_t)Imm) < 32;
910}]> {
911  let ParserMatchClass = Imm0_31Operand;
912}
913
914// True if the 32-bit immediate is in the range [0,31]
915def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
916  return ((uint64_t)Imm) < 32;
917}]> {
918  let ParserMatchClass = Imm0_31Operand;
919}
920
921// imm0_1 predicate - True if the immediate is in the range [0,1]
922def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
923  return ((uint64_t)Imm) < 2;
924}]> {
925  let ParserMatchClass = Imm0_1Operand;
926}
927
928// timm0_1 - as above, but use TargetConstant (TImmLeaf)
929def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
930  return ((uint64_t)Imm) < 2;
931}]> {
932  let ParserMatchClass = Imm0_1Operand;
933}
934
935// imm0_15 predicate - True if the immediate is in the range [0,15]
936def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
937  return ((uint64_t)Imm) < 16;
938}]> {
939  let ParserMatchClass = Imm0_15Operand;
940}
941
942// imm0_7 predicate - True if the immediate is in the range [0,7]
943def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
944  return ((uint64_t)Imm) < 8;
945}]> {
946  let ParserMatchClass = Imm0_7Operand;
947}
948
949// imm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
950def imm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
951  return ((uint32_t)Imm) < 8;
952}]> {
953  let ParserMatchClass = Imm0_7Operand;
954}
955
956// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
957def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
958  return ((uint32_t)Imm) < 16;
959}]> {
960  let ParserMatchClass = Imm0_15Operand;
961}
962
963// An arithmetic shifter operand:
964//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
965//  {5-0} - imm6
966class arith_shift<ValueType Ty, int width> : Operand<Ty> {
967  let PrintMethod = "printShifter";
968  let ParserMatchClass = !cast<AsmOperandClass>(
969                         "ArithmeticShifterOperand" # width);
970}
971
972def arith_shift32 : arith_shift<i32, 32>;
973def arith_shift64 : arith_shift<i64, 64>;
974
975class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
976    : Operand<Ty>,
977      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
978  let PrintMethod = "printShiftedRegister";
979  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
980}
981
982def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
983def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
984
985def gi_arith_shifted_reg32 :
986  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
987  GIComplexPatternEquiv<arith_shifted_reg32>;
988
989def gi_arith_shifted_reg64 :
990  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
991  GIComplexPatternEquiv<arith_shifted_reg64>;
992
993// An arithmetic shifter operand:
994//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
995//  {5-0} - imm6
996class logical_shift<int width> : Operand<i32> {
997  let PrintMethod = "printShifter";
998  let ParserMatchClass = !cast<AsmOperandClass>(
999                         "LogicalShifterOperand" # width);
1000}
1001
1002def logical_shift32 : logical_shift<32>;
1003def logical_shift64 : logical_shift<64>;
1004
1005class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1006    : Operand<Ty>,
1007      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1008  let PrintMethod = "printShiftedRegister";
1009  let MIOperandInfo = (ops regclass, shiftop);
1010}
1011
1012def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1013def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1014
1015def gi_logical_shifted_reg32 :
1016  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1017  GIComplexPatternEquiv<logical_shifted_reg32>;
1018
1019def gi_logical_shifted_reg64 :
1020  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1021  GIComplexPatternEquiv<logical_shifted_reg64>;
1022
1023// A logical vector shifter operand:
1024//  {7-6} - shift type: 00 = lsl
1025//  {5-0} - imm6: #0, #8, #16, or #24
1026def logical_vec_shift : Operand<i32> {
1027  let PrintMethod = "printShifter";
1028  let EncoderMethod = "getVecShifterOpValue";
1029  let ParserMatchClass = LogicalVecShifterOperand;
1030}
1031
1032// A logical vector half-word shifter operand:
1033//  {7-6} - shift type: 00 = lsl
1034//  {5-0} - imm6: #0 or #8
1035def logical_vec_hw_shift : Operand<i32> {
1036  let PrintMethod = "printShifter";
1037  let EncoderMethod = "getVecShifterOpValue";
1038  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1039}
1040
1041// A vector move shifter operand:
1042//  {0} - imm1: #8 or #16
1043def move_vec_shift : Operand<i32> {
1044  let PrintMethod = "printShifter";
1045  let EncoderMethod = "getMoveVecShifterOpValue";
1046  let ParserMatchClass = MoveVecShifterOperand;
1047}
1048
1049let DiagnosticType = "AddSubSecondSource" in {
1050  def AddSubImmOperand : AsmOperandClass {
1051    let Name = "AddSubImm";
1052    let ParserMethod = "tryParseImmWithOptionalShift";
1053    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1054  }
1055  def AddSubImmNegOperand : AsmOperandClass {
1056    let Name = "AddSubImmNeg";
1057    let ParserMethod = "tryParseImmWithOptionalShift";
1058    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1059  }
1060}
1061// An ADD/SUB immediate shifter operand:
1062//  second operand:
1063//  {7-6} - shift type: 00 = lsl
1064//  {5-0} - imm6: #0 or #12
1065class addsub_shifted_imm<ValueType Ty>
1066    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1067  let PrintMethod = "printAddSubImm";
1068  let EncoderMethod = "getAddSubImmOpValue";
1069  let ParserMatchClass = AddSubImmOperand;
1070  let MIOperandInfo = (ops i32imm, i32imm);
1071}
1072
1073class addsub_shifted_imm_neg<ValueType Ty>
1074    : Operand<Ty> {
1075  let EncoderMethod = "getAddSubImmOpValue";
1076  let ParserMatchClass = AddSubImmNegOperand;
1077  let MIOperandInfo = (ops i32imm, i32imm);
1078}
1079
1080def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1081def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1082def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1083def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1084
1085def gi_addsub_shifted_imm32 :
1086    GIComplexOperandMatcher<s32, "selectArithImmed">,
1087    GIComplexPatternEquiv<addsub_shifted_imm32>;
1088
1089def gi_addsub_shifted_imm64 :
1090    GIComplexOperandMatcher<s64, "selectArithImmed">,
1091    GIComplexPatternEquiv<addsub_shifted_imm64>;
1092
1093class neg_addsub_shifted_imm<ValueType Ty>
1094    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1095  let PrintMethod = "printAddSubImm";
1096  let EncoderMethod = "getAddSubImmOpValue";
1097  let ParserMatchClass = AddSubImmOperand;
1098  let MIOperandInfo = (ops i32imm, i32imm);
1099}
1100
1101def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1102def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1103
1104def gi_neg_addsub_shifted_imm32 :
1105    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1106    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1107
1108def gi_neg_addsub_shifted_imm64 :
1109    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1110    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1111
1112// An extend operand:
1113//  {5-3} - extend type
1114//  {2-0} - imm3
1115def arith_extend : Operand<i32> {
1116  let PrintMethod = "printArithExtend";
1117  let ParserMatchClass = ExtendOperand;
1118}
1119def arith_extend64 : Operand<i32> {
1120  let PrintMethod = "printArithExtend";
1121  let ParserMatchClass = ExtendOperand64;
1122}
1123
1124// 'extend' that's a lsl of a 64-bit register.
1125def arith_extendlsl64 : Operand<i32> {
1126  let PrintMethod = "printArithExtend";
1127  let ParserMatchClass = ExtendOperandLSL64;
1128}
1129
1130class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1131                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1132  let PrintMethod = "printExtendedRegister";
1133  let MIOperandInfo = (ops GPR32, arith_extend);
1134}
1135
1136class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1137                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1138  let PrintMethod = "printExtendedRegister";
1139  let MIOperandInfo = (ops GPR32, arith_extend64);
1140}
1141
1142def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1143def gi_arith_extended_reg32_i32 :
1144    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1145    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1146
1147def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1148def gi_arith_extended_reg32_i64 :
1149    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1150    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1151
1152def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1153def gi_arith_extended_reg32to64_i64 :
1154    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1155    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1156
1157// Floating-point immediate.
1158
1159def fpimm16XForm : SDNodeXForm<fpimm, [{
1160      APFloat InVal = N->getValueAPF();
1161      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1162      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1163    }]>;
1164
1165def fpimm32XForm : SDNodeXForm<fpimm, [{
1166      APFloat InVal = N->getValueAPF();
1167      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1168      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1169    }]>;
1170
1171def fpimm64XForm : SDNodeXForm<fpimm, [{
1172      APFloat InVal = N->getValueAPF();
1173      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1174      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1175    }]>;
1176
1177def fpimm16 : Operand<f16>,
1178              FPImmLeaf<f16, [{
1179      return AArch64_AM::getFP16Imm(Imm) != -1;
1180    }], fpimm16XForm> {
1181  let ParserMatchClass = FPImmOperand;
1182  let PrintMethod = "printFPImmOperand";
1183}
1184
1185def fpimm32 : Operand<f32>,
1186              FPImmLeaf<f32, [{
1187      return AArch64_AM::getFP32Imm(Imm) != -1;
1188    }], fpimm32XForm> {
1189  let ParserMatchClass = FPImmOperand;
1190  let PrintMethod = "printFPImmOperand";
1191}
1192def fpimm64 : Operand<f64>,
1193              FPImmLeaf<f64, [{
1194      return AArch64_AM::getFP64Imm(Imm) != -1;
1195    }], fpimm64XForm> {
1196  let ParserMatchClass = FPImmOperand;
1197  let PrintMethod = "printFPImmOperand";
1198}
1199
1200def fpimm8 : Operand<i32> {
1201  let ParserMatchClass = FPImmOperand;
1202  let PrintMethod = "printFPImmOperand";
1203}
1204
1205def fpimm0 : FPImmLeaf<fAny, [{
1206  return Imm.isExactlyValue(+0.0);
1207}]>;
1208
1209def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1210  GISDNodeXFormEquiv<fpimm16XForm>;
1211def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1212  GISDNodeXFormEquiv<fpimm32XForm>;
1213def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1214  GISDNodeXFormEquiv<fpimm64XForm>;
1215
1216// Vector lane operands
1217class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1218  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1219  let DiagnosticType = "Invalid" # Name;
1220  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1221  let RenderMethod = "addVectorIndexOperands";
1222}
1223
1224class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1225    : Operand<ty> {
1226  let ParserMatchClass = mc;
1227  let PrintMethod = "printVectorIndex";
1228}
1229
1230multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1231  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1232  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1233}
1234
1235def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1236def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1237def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1238def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1239def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1240
1241defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1242                                [{ return ((uint64_t)Imm) == 1; }]>;
1243defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1244                                [{ return ((uint64_t)Imm) < 16; }]>;
1245defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1246                                [{ return ((uint64_t)Imm) < 8; }]>;
1247defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1248                                [{ return ((uint64_t)Imm) < 4; }]>;
1249defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1250                                [{ return ((uint64_t)Imm) < 2; }]>;
1251
1252defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1253                                   [{ return ((uint64_t)Imm) == 1; }]>;
1254defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1255                                   [{ return ((uint64_t)Imm) < 16; }]>;
1256defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1257                                   [{ return ((uint64_t)Imm) < 8; }]>;
1258defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1259                                   [{ return ((uint64_t)Imm) < 4; }]>;
1260defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1261                                   [{ return ((uint64_t)Imm) < 2; }]>;
1262
1263def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1264def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1265def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1266def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1267def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1268
1269defm sve_elm_idx_extdup_b
1270  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1271                [{ return ((uint64_t)Imm) < 64; }]>;
1272defm sve_elm_idx_extdup_h
1273  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1274                [{ return ((uint64_t)Imm) < 32; }]>;
1275defm sve_elm_idx_extdup_s
1276  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1277                [{ return ((uint64_t)Imm) < 16; }]>;
1278defm sve_elm_idx_extdup_d
1279  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1280                [{ return ((uint64_t)Imm) < 8; }]>;
1281defm sve_elm_idx_extdup_q
1282  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1283                [{ return ((uint64_t)Imm) < 4; }]>;
1284
1285// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1286// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1287// are encoded as the eight bit value 'abcdefgh'.
1288def simdimmtype10 : Operand<i32>,
1289                    FPImmLeaf<f64, [{
1290      return AArch64_AM::isAdvSIMDModImmType10(
1291                 Imm.bitcastToAPInt().getZExtValue());
1292    }], SDNodeXForm<fpimm, [{
1293      APFloat InVal = N->getValueAPF();
1294      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1295                                                           .bitcastToAPInt()
1296                                                           .getZExtValue());
1297      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1298    }]>> {
1299  let ParserMatchClass = SIMDImmType10Operand;
1300  let PrintMethod = "printSIMDType10Operand";
1301}
1302
1303
1304//---
1305// System management
1306//---
1307
1308// Base encoding for system instruction operands.
1309let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1310class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1311                  list<dag> pattern = []>
1312    : I<oops, iops, asm, operands, "", pattern> {
1313  let Inst{31-22} = 0b1101010100;
1314  let Inst{21}    = L;
1315}
1316
1317// System instructions which do not have an Rt register.
1318class SimpleSystemI<bit L, dag iops, string asm, string operands,
1319                    list<dag> pattern = []>
1320    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1321  let Inst{4-0} = 0b11111;
1322}
1323
1324// System instructions which have an Rt register.
1325class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1326                list<dag> pattern = []>
1327    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1328      Sched<[WriteSys]> {
1329  bits<5> Rt;
1330  let Inst{4-0} = Rt;
1331}
1332
1333// System instructions for transactional memory extension
1334class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1335                    string asm, string operands, list<dag> pattern>
1336    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1337      Sched<[WriteSys]> {
1338  let Inst{20-12} = 0b000110011;
1339  let Inst{11-8} = CRm;
1340  let Inst{7-5} = op2;
1341  let DecoderMethod = "";
1342
1343  let mayLoad = 1;
1344  let mayStore = 1;
1345}
1346
1347// System instructions for transactional memory - single input operand
1348class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1349    : TMBaseSystemI<0b1, CRm, 0b011,
1350                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1351  bits<5> Rt;
1352  let Inst{4-0} = Rt;
1353}
1354
1355// System instructions that pass a register argument
1356// This class assumes the register is for input rather than output.
1357class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1358                      list<dag> pattern = []>
1359    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1360  let Inst{20-12} = 0b000110001;
1361  let Inst{11-8} = CRm;
1362  let Inst{7-5} = Op2;
1363}
1364
1365// System instructions for transactional memory - no operand
1366class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1367    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1368  let Inst{4-0} = 0b11111;
1369}
1370
1371// System instructions for exit from transactions
1372class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1373    : I<(outs), (ins i64_imm0_65535:$imm), asm, "\t$imm", "", pattern>,
1374      Sched<[WriteSys]> {
1375  bits<16> imm;
1376  let Inst{31-24} = 0b11010100;
1377  let Inst{23-21} = op1;
1378  let Inst{20-5}  = imm;
1379  let Inst{4-0}   = 0b00000;
1380}
1381
1382// Hint instructions that take both a CRm and a 3-bit immediate.
1383// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1384// model patterns with sufficiently fine granularity
1385let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1386  class HintI<string mnemonic>
1387      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1388                      [(int_aarch64_hint imm0_127:$imm)]>,
1389        Sched<[WriteHint]> {
1390    bits <7> imm;
1391    let Inst{20-12} = 0b000110010;
1392    let Inst{11-5} = imm;
1393  }
1394
1395// System instructions taking a single literal operand which encodes into
1396// CRm. op2 differentiates the opcodes.
1397def BarrierAsmOperand : AsmOperandClass {
1398  let Name = "Barrier";
1399  let ParserMethod = "tryParseBarrierOperand";
1400}
1401def barrier_op : Operand<i32> {
1402  let PrintMethod = "printBarrierOption";
1403  let ParserMatchClass = BarrierAsmOperand;
1404}
1405def BarriernXSAsmOperand : AsmOperandClass {
1406  let Name = "BarriernXS";
1407  let ParserMethod = "tryParseBarriernXSOperand";
1408}
1409def barrier_nxs_op : Operand<i32> {
1410  let PrintMethod = "printBarriernXSOption";
1411  let ParserMatchClass = BarriernXSAsmOperand;
1412}
1413class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1414                 list<dag> pattern = []>
1415    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1416      Sched<[WriteBarrier]> {
1417  bits<4> CRm;
1418  let Inst{20-12} = 0b000110011;
1419  let Inst{11-8} = CRm;
1420  let Inst{7-5} = opc;
1421}
1422
1423class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1424    : SimpleSystemI<0, (ins), asm, "", pattern>,
1425      Sched<[]> {
1426  bits<4> CRm;
1427  let CRm = 0b0011;
1428  let Inst{31-12} = 0b11010101000000110010;
1429  let Inst{11-8} = CRm;
1430  let Inst{7-5} = op2;
1431  let Inst{4-0} = 0b11111;
1432}
1433
1434// MRS/MSR system instructions. These have different operand classes because
1435// a different subset of registers can be accessed through each instruction.
1436def MRSSystemRegisterOperand : AsmOperandClass {
1437  let Name = "MRSSystemRegister";
1438  let ParserMethod = "tryParseSysReg";
1439  let DiagnosticType = "MRS";
1440}
1441// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1442def mrs_sysreg_op : Operand<i32> {
1443  let ParserMatchClass = MRSSystemRegisterOperand;
1444  let DecoderMethod = "DecodeMRSSystemRegister";
1445  let PrintMethod = "printMRSSystemRegister";
1446}
1447
1448def MSRSystemRegisterOperand : AsmOperandClass {
1449  let Name = "MSRSystemRegister";
1450  let ParserMethod = "tryParseSysReg";
1451  let DiagnosticType = "MSR";
1452}
1453def msr_sysreg_op : Operand<i32> {
1454  let ParserMatchClass = MSRSystemRegisterOperand;
1455  let DecoderMethod = "DecodeMSRSystemRegister";
1456  let PrintMethod = "printMSRSystemRegister";
1457}
1458
1459def PSBHintOperand : AsmOperandClass {
1460  let Name = "PSBHint";
1461  let ParserMethod = "tryParsePSBHint";
1462}
1463def psbhint_op : Operand<i32> {
1464  let ParserMatchClass = PSBHintOperand;
1465  let PrintMethod = "printPSBHintOp";
1466  let MCOperandPredicate = [{
1467    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1468    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1469    if (!MCOp.isImm())
1470      return false;
1471    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1472  }];
1473}
1474
1475def BTIHintOperand : AsmOperandClass {
1476  let Name = "BTIHint";
1477  let ParserMethod = "tryParseBTIHint";
1478}
1479def btihint_op : Operand<i32> {
1480  let ParserMatchClass = BTIHintOperand;
1481  let PrintMethod = "printBTIHintOp";
1482  let MCOperandPredicate = [{
1483    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1484    if (!MCOp.isImm())
1485      return false;
1486    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1487  }];
1488}
1489
1490class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1491                       "mrs", "\t$Rt, $systemreg"> {
1492  bits<16> systemreg;
1493  let Inst{20-5} = systemreg;
1494  let DecoderNamespace = "Fallback";
1495  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1496  // require doing this. The alternative was to explicitly model each one, but
1497  // it feels like it is unnecessary because it seems there are no negative
1498  // consequences setting these flags for all.
1499  let Defs = [NZCV];
1500}
1501
1502// FIXME: Some of these def NZCV, others don't. Best way to model that?
1503// Explicitly modeling each of the system register as a register class
1504// would do it, but feels like overkill at this point.
1505class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1506                       "msr", "\t$systemreg, $Rt"> {
1507  bits<16> systemreg;
1508  let Inst{20-5} = systemreg;
1509  let DecoderNamespace = "Fallback";
1510}
1511
1512def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1513  let Name = "SystemPStateFieldWithImm0_15";
1514  let ParserMethod = "tryParseSysReg";
1515}
1516def pstatefield4_op : Operand<i32> {
1517  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1518  let PrintMethod = "printSystemPStateField";
1519}
1520
1521// Instructions to modify PSTATE, no input reg
1522let Defs = [NZCV] in
1523class PstateWriteSimple<dag iops, string asm, string operands>
1524  : SimpleSystemI<0, iops, asm, operands> {
1525
1526  let Inst{20-19} = 0b00;
1527  let Inst{15-12} = 0b0100;
1528}
1529
1530class MSRpstateImm0_15
1531  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1532                  "\t$pstatefield, $imm">,
1533    Sched<[WriteSys]> {
1534
1535  bits<6> pstatefield;
1536  bits<4> imm;
1537  let Inst{18-16} = pstatefield{5-3};
1538  let Inst{11-8} = imm;
1539  let Inst{7-5} = pstatefield{2-0};
1540
1541  let DecoderMethod = "DecodeSystemPStateInstruction";
1542  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1543  // Fail the decoder should attempt to decode the instruction as MSRI.
1544  let hasCompleteDecoder = 0;
1545}
1546
1547def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1548  let Name = "SystemPStateFieldWithImm0_1";
1549  let ParserMethod = "tryParseSysReg";
1550}
1551def pstatefield1_op : Operand<i32> {
1552  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1553  let PrintMethod = "printSystemPStateField";
1554}
1555
1556class MSRpstateImm0_1
1557  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1558                 "\t$pstatefield, $imm">,
1559    Sched<[WriteSys]> {
1560
1561  bits<6> pstatefield;
1562  bit imm;
1563  let Inst{18-16} = pstatefield{5-3};
1564  let Inst{11-9} = 0b000;
1565  let Inst{8} = imm;
1566  let Inst{7-5} = pstatefield{2-0};
1567
1568  let DecoderMethod = "DecodeSystemPStateInstruction";
1569  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1570  // Fail the decoder should attempt to decode the instruction as MSRI.
1571  let hasCompleteDecoder = 0;
1572}
1573
1574// SYS and SYSL generic system instructions.
1575def SysCRAsmOperand : AsmOperandClass {
1576  let Name = "SysCR";
1577  let ParserMethod = "tryParseSysCROperand";
1578}
1579
1580def sys_cr_op : Operand<i32> {
1581  let PrintMethod = "printSysCROperand";
1582  let ParserMatchClass = SysCRAsmOperand;
1583}
1584
1585class SystemXtI<bit L, string asm>
1586  : RtSystemI<L, (outs),
1587       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1588       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1589  bits<3> op1;
1590  bits<4> Cn;
1591  bits<4> Cm;
1592  bits<3> op2;
1593  let Inst{20-19} = 0b01;
1594  let Inst{18-16} = op1;
1595  let Inst{15-12} = Cn;
1596  let Inst{11-8}  = Cm;
1597  let Inst{7-5}   = op2;
1598}
1599
1600class SystemLXtI<bit L, string asm>
1601  : RtSystemI<L, (outs),
1602       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1603       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1604  bits<3> op1;
1605  bits<4> Cn;
1606  bits<4> Cm;
1607  bits<3> op2;
1608  let Inst{20-19} = 0b01;
1609  let Inst{18-16} = op1;
1610  let Inst{15-12} = Cn;
1611  let Inst{11-8}  = Cm;
1612  let Inst{7-5}   = op2;
1613}
1614
1615
1616// Branch (register) instructions:
1617//
1618//  case opc of
1619//    0001 blr
1620//    0000 br
1621//    0101 dret
1622//    0100 eret
1623//    0010 ret
1624//    otherwise UNDEFINED
1625class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1626                    string operands, list<dag> pattern>
1627    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1628  let Inst{31-25} = 0b1101011;
1629  let Inst{24-21} = opc;
1630  let Inst{20-16} = 0b11111;
1631  let Inst{15-10} = 0b000000;
1632  let Inst{4-0}   = 0b00000;
1633}
1634
1635class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1636    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1637  bits<5> Rn;
1638  let Inst{9-5} = Rn;
1639}
1640
1641let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
1642class SpecialReturn<bits<4> opc, string asm>
1643    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
1644  let Inst{9-5} = 0b11111;
1645}
1646
1647let mayLoad = 1 in
1648class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
1649  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
1650  Sched<[]> {
1651  bits<5> Rn;
1652  bits<5> Rt;
1653  let Inst{31-30} = sz;
1654  let Inst{29-10} = 0b11100010111111110000;
1655  let Inst{9-5} = Rn;
1656  let Inst{4-0} = Rt;
1657}
1658
1659class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
1660               list<dag> pattern>
1661  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
1662  let isAuthenticated = 1;
1663  let Inst{31-25} = 0b1101011;
1664  let Inst{20-11} = 0b1111100001;
1665  let Inst{10} = M;
1666  let Inst{4-0} = 0b11111;
1667}
1668
1669class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
1670  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
1671  bits<5> Rn;
1672  bits<5> Rm;
1673  let Inst{24-22} = 0b100;
1674  let Inst{21} = op;
1675  let Inst{9-5} = Rn;
1676  let Inst{4-0} = Rm;
1677}
1678
1679class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
1680  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
1681  bits<5> Rn;
1682  let Inst{24} = 0;
1683  let Inst{23-21} = opc;
1684  let Inst{9-5} = Rn;
1685}
1686
1687let Uses = [LR,SP] in
1688class AuthReturn<bits<3> op, bits<1> M, string asm>
1689  : AuthBase<M, (outs), (ins), asm, "", []> {
1690  let Inst{24} = 0;
1691  let Inst{23-21} = op;
1692  let Inst{9-0} = 0b1111111111;
1693}
1694
1695let mayLoad = 1 in
1696class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
1697                   string operands, string cstr, Operand opr>
1698  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
1699  bits<10> offset;
1700  bits<5> Rn;
1701  bits<5> Rt;
1702  let isAuthenticated = 1;
1703  let Inst{31-24} = 0b11111000;
1704  let Inst{23} = M;
1705  let Inst{22} = offset{9};
1706  let Inst{21} = 1;
1707  let Inst{20-12} = offset{8-0};
1708  let Inst{11} = W;
1709  let Inst{10} = 1;
1710  let Inst{9-5} = Rn;
1711  let Inst{4-0} = Rt;
1712
1713  let DecoderMethod = "DecodeAuthLoadInstruction";
1714}
1715
1716multiclass AuthLoad<bit M, string asm, Operand opr> {
1717  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
1718                               (ins GPR64sp:$Rn, opr:$offset),
1719                               asm, "\t$Rt, [$Rn, $offset]", "", opr>;
1720  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
1721                               (ins GPR64sp:$Rn, opr:$offset),
1722                               asm, "\t$Rt, [$Rn, $offset]!",
1723                               "$Rn = $wback,@earlyclobber $wback", opr>;
1724
1725  def : InstAlias<asm # "\t$Rt, [$Rn]",
1726                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
1727
1728  def : InstAlias<asm # "\t$Rt, [$wback]!",
1729                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
1730}
1731
1732//---
1733// Conditional branch instruction.
1734//---
1735
1736// Condition code.
1737// 4-bit immediate. Pretty-printed as <cc>
1738def ccode : Operand<i32> {
1739  let PrintMethod = "printCondCode";
1740  let ParserMatchClass = CondCode;
1741}
1742def inv_ccode : Operand<i32> {
1743  // AL and NV are invalid in the aliases which use inv_ccode
1744  let PrintMethod = "printInverseCondCode";
1745  let ParserMatchClass = CondCode;
1746  let MCOperandPredicate = [{
1747    return MCOp.isImm() &&
1748           MCOp.getImm() != AArch64CC::AL &&
1749           MCOp.getImm() != AArch64CC::NV;
1750  }];
1751}
1752
1753// Conditional branch target. 19-bit immediate. The low two bits of the target
1754// offset are implied zero and so are not part of the immediate.
1755def am_brcond : Operand<OtherVT> {
1756  let EncoderMethod = "getCondBranchTargetOpValue";
1757  let DecoderMethod = "DecodePCRelLabel19";
1758  let PrintMethod = "printAlignedLabel";
1759  let ParserMatchClass = PCRelLabel19Operand;
1760  let OperandType = "OPERAND_PCREL";
1761}
1762
1763class BranchCond : I<(outs), (ins ccode:$cond, am_brcond:$target),
1764                     "b", ".$cond\t$target", "",
1765                     [(AArch64brcond bb:$target, imm:$cond, NZCV)]>,
1766                   Sched<[WriteBr]> {
1767  let isBranch = 1;
1768  let isTerminator = 1;
1769  let Uses = [NZCV];
1770
1771  bits<4> cond;
1772  bits<19> target;
1773  let Inst{31-24} = 0b01010100;
1774  let Inst{23-5} = target;
1775  let Inst{4} = 0;
1776  let Inst{3-0} = cond;
1777}
1778
1779//---
1780// Compare-and-branch instructions.
1781//---
1782class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
1783    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
1784         asm, "\t$Rt, $target", "",
1785         [(node regtype:$Rt, bb:$target)]>,
1786      Sched<[WriteBr]> {
1787  let isBranch = 1;
1788  let isTerminator = 1;
1789
1790  bits<5> Rt;
1791  bits<19> target;
1792  let Inst{30-25} = 0b011010;
1793  let Inst{24}    = op;
1794  let Inst{23-5}  = target;
1795  let Inst{4-0}   = Rt;
1796}
1797
1798multiclass CmpBranch<bit op, string asm, SDNode node> {
1799  def W : BaseCmpBranch<GPR32, op, asm, node> {
1800    let Inst{31} = 0;
1801  }
1802  def X : BaseCmpBranch<GPR64, op, asm, node> {
1803    let Inst{31} = 1;
1804  }
1805}
1806
1807//---
1808// Test-bit-and-branch instructions.
1809//---
1810// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
1811// the target offset are implied zero and so are not part of the immediate.
1812def am_tbrcond : Operand<OtherVT> {
1813  let EncoderMethod = "getTestBranchTargetOpValue";
1814  let PrintMethod = "printAlignedLabel";
1815  let ParserMatchClass = BranchTarget14Operand;
1816  let OperandType = "OPERAND_PCREL";
1817}
1818
1819// AsmOperand classes to emit (or not) special diagnostics
1820def TBZImm0_31Operand : AsmOperandClass {
1821  let Name = "TBZImm0_31";
1822  let PredicateMethod = "isImmInRange<0,31>";
1823  let RenderMethod = "addImmOperands";
1824}
1825def TBZImm32_63Operand : AsmOperandClass {
1826  let Name = "Imm32_63";
1827  let PredicateMethod = "isImmInRange<32,63>";
1828  let DiagnosticType = "InvalidImm0_63";
1829  let RenderMethod = "addImmOperands";
1830}
1831
1832class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
1833  return (((uint32_t)Imm) < 32);
1834}]> {
1835  let ParserMatchClass = matcher;
1836}
1837
1838def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
1839def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
1840
1841def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
1842  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
1843}]> {
1844  let ParserMatchClass = TBZImm32_63Operand;
1845}
1846
1847class BaseTestBranch<RegisterClass regtype, Operand immtype,
1848                     bit op, string asm, SDNode node>
1849    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
1850       asm, "\t$Rt, $bit_off, $target", "",
1851       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
1852      Sched<[WriteBr]> {
1853  let isBranch = 1;
1854  let isTerminator = 1;
1855
1856  bits<5> Rt;
1857  bits<6> bit_off;
1858  bits<14> target;
1859
1860  let Inst{30-25} = 0b011011;
1861  let Inst{24}    = op;
1862  let Inst{23-19} = bit_off{4-0};
1863  let Inst{18-5}  = target;
1864  let Inst{4-0}   = Rt;
1865
1866  let DecoderMethod = "DecodeTestAndBranch";
1867}
1868
1869multiclass TestBranch<bit op, string asm, SDNode node> {
1870  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
1871    let Inst{31} = 0;
1872  }
1873
1874  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
1875    let Inst{31} = 1;
1876  }
1877
1878  // Alias X-reg with 0-31 imm to W-Reg.
1879  def : InstAlias<asm # "\t$Rd, $imm, $target",
1880                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
1881                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
1882  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
1883            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
1884            tbz_imm0_31_diag:$imm, bb:$target)>;
1885}
1886
1887//---
1888// Unconditional branch (immediate) instructions.
1889//---
1890def am_b_target : Operand<OtherVT> {
1891  let EncoderMethod = "getBranchTargetOpValue";
1892  let PrintMethod = "printAlignedLabel";
1893  let ParserMatchClass = BranchTarget26Operand;
1894  let OperandType = "OPERAND_PCREL";
1895}
1896def am_bl_target : Operand<i64> {
1897  let EncoderMethod = "getBranchTargetOpValue";
1898  let PrintMethod = "printAlignedLabel";
1899  let ParserMatchClass = BranchTarget26Operand;
1900  let OperandType = "OPERAND_PCREL";
1901}
1902
1903class BImm<bit op, dag iops, string asm, list<dag> pattern>
1904    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
1905  bits<26> addr;
1906  let Inst{31}    = op;
1907  let Inst{30-26} = 0b00101;
1908  let Inst{25-0}  = addr;
1909
1910  let DecoderMethod = "DecodeUnconditionalBranch";
1911}
1912
1913class BranchImm<bit op, string asm, list<dag> pattern>
1914    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
1915class CallImm<bit op, string asm, list<dag> pattern>
1916    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
1917
1918//---
1919// Basic one-operand data processing instructions.
1920//---
1921
1922let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1923class BaseOneOperandData<bits<3> opc, RegisterClass regtype, string asm,
1924                         SDPatternOperator node>
1925  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
1926      [(set regtype:$Rd, (node regtype:$Rn))]>,
1927    Sched<[WriteI, ReadI]> {
1928  bits<5> Rd;
1929  bits<5> Rn;
1930
1931  let Inst{30-13} = 0b101101011000000000;
1932  let Inst{12-10} = opc;
1933  let Inst{9-5}   = Rn;
1934  let Inst{4-0}   = Rd;
1935}
1936
1937let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
1938multiclass OneOperandData<bits<3> opc, string asm,
1939                          SDPatternOperator node = null_frag> {
1940  def Wr : BaseOneOperandData<opc, GPR32, asm, node> {
1941    let Inst{31} = 0;
1942  }
1943
1944  def Xr : BaseOneOperandData<opc, GPR64, asm, node> {
1945    let Inst{31} = 1;
1946  }
1947}
1948
1949class OneWRegData<bits<3> opc, string asm, SDPatternOperator node>
1950    : BaseOneOperandData<opc, GPR32, asm, node> {
1951  let Inst{31} = 0;
1952}
1953
1954class OneXRegData<bits<3> opc, string asm, SDPatternOperator node>
1955    : BaseOneOperandData<opc, GPR64, asm, node> {
1956  let Inst{31} = 1;
1957}
1958
1959class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm>
1960  : I<(outs GPR64:$Rd), (ins GPR64:$src, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
1961      "$Rd = $src",
1962      []>,
1963    Sched<[WriteI, ReadI]> {
1964  bits<5> Rd;
1965  bits<5> Rn;
1966  let Inst{31-15} = 0b11011010110000010;
1967  let Inst{14-12} = opcode_prefix;
1968  let Inst{11-10} = opcode;
1969  let Inst{9-5} = Rn;
1970  let Inst{4-0} = Rd;
1971}
1972
1973class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm>
1974  : I<(outs GPR64:$Rd), (ins GPR64:$src), asm, "\t$Rd", "$Rd = $src",
1975      []>, Sched<[]> {
1976  bits<5> Rd;
1977  let Inst{31-15} = 0b11011010110000010;
1978  let Inst{14-12} = opcode_prefix;
1979  let Inst{11-10} = opcode;
1980  let Inst{9-5} = 0b11111;
1981  let Inst{4-0} = Rd;
1982}
1983
1984class SignAuthTwoOperand<bits<4> opc, string asm,
1985                         SDPatternOperator OpNode>
1986  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
1987      asm, "\t$Rd, $Rn, $Rm", "",
1988      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
1989    Sched<[WriteI, ReadI, ReadI]> {
1990  bits<5> Rd;
1991  bits<5> Rn;
1992  bits<5> Rm;
1993  let Inst{31-21} = 0b10011010110;
1994  let Inst{20-16} = Rm;
1995  let Inst{15-14} = 0b00;
1996  let Inst{13-10} = opc;
1997  let Inst{9-5}   = Rn;
1998  let Inst{4-0}   = Rd;
1999}
2000
2001class ClearAuth<bits<1> data, string asm>
2002  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2003  bits<5> Rd;
2004  let Inst{31-11} = 0b110110101100000101000;
2005  let Inst{10} = data;
2006  let Inst{9-5} = 0b11111;
2007  let Inst{4-0} = Rd;
2008}
2009
2010// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2011class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2012    : I<(outs), iops, asm, ops, "", []>,
2013      Sched<[WriteI, ReadI, ReadI]> {
2014  let Uses = [NZCV];
2015  let Defs = [NZCV];
2016  bits<5> Rn;
2017  let Inst{31}    = sf;
2018  let Inst{30-15} = 0b0111010000000000;
2019  let Inst{14}    = sz;
2020  let Inst{13-10} = 0b0010;
2021  let Inst{9-5}   = Rn;
2022  let Inst{4-0}   = 0b01101;
2023}
2024
2025class FlagRotate<dag iops, string asm, string ops>
2026    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2027  bits<6> imm;
2028  bits<4> mask;
2029  let Inst{20-15} = imm;
2030  let Inst{13-10} = 0b0001;
2031  let Inst{4}     = 0b0;
2032  let Inst{3-0}   = mask;
2033}
2034
2035//---
2036// Basic two-operand data processing instructions.
2037//---
2038class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2039                          list<dag> pattern>
2040    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2041        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2042      Sched<[WriteI, ReadI, ReadI]> {
2043  let Uses = [NZCV];
2044  bits<5> Rd;
2045  bits<5> Rn;
2046  bits<5> Rm;
2047  let Inst{30}    = isSub;
2048  let Inst{28-21} = 0b11010000;
2049  let Inst{20-16} = Rm;
2050  let Inst{15-10} = 0;
2051  let Inst{9-5}   = Rn;
2052  let Inst{4-0}   = Rd;
2053}
2054
2055class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2056                      SDNode OpNode>
2057    : BaseBaseAddSubCarry<isSub, regtype, asm,
2058        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2059
2060class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2061                              SDNode OpNode>
2062    : BaseBaseAddSubCarry<isSub, regtype, asm,
2063        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2064         (implicit NZCV)]> {
2065  let Defs = [NZCV];
2066}
2067
2068multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2069                       SDNode OpNode, SDNode OpNode_setflags> {
2070  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2071    let Inst{31} = 0;
2072    let Inst{29} = 0;
2073  }
2074  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2075    let Inst{31} = 1;
2076    let Inst{29} = 0;
2077  }
2078
2079  // Sets flags.
2080  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2081                                    OpNode_setflags> {
2082    let Inst{31} = 0;
2083    let Inst{29} = 1;
2084  }
2085  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2086                                    OpNode_setflags> {
2087    let Inst{31} = 1;
2088    let Inst{29} = 1;
2089  }
2090}
2091
2092class BaseTwoOperand<bits<4> opc, RegisterClass regtype, string asm,
2093                     SDPatternOperator OpNode,
2094                     RegisterClass in1regtype = regtype,
2095                     RegisterClass in2regtype = regtype>
2096  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2097      asm, "\t$Rd, $Rn, $Rm", "",
2098      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2099  bits<5> Rd;
2100  bits<5> Rn;
2101  bits<5> Rm;
2102  let Inst{30-21} = 0b0011010110;
2103  let Inst{20-16} = Rm;
2104  let Inst{15-14} = 0b00;
2105  let Inst{13-10} = opc;
2106  let Inst{9-5}   = Rn;
2107  let Inst{4-0}   = Rd;
2108}
2109
2110class BaseDiv<bit isSigned, RegisterClass regtype, string asm,
2111              SDPatternOperator OpNode>
2112    : BaseTwoOperand<{0,0,1,?}, regtype, asm, OpNode> {
2113  let Inst{10}    = isSigned;
2114}
2115
2116multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2117  def Wr : BaseDiv<isSigned, GPR32, asm, OpNode>,
2118           Sched<[WriteID32, ReadID, ReadID]> {
2119    let Inst{31} = 0;
2120  }
2121  def Xr : BaseDiv<isSigned, GPR64, asm, OpNode>,
2122           Sched<[WriteID64, ReadID, ReadID]> {
2123    let Inst{31} = 1;
2124  }
2125}
2126
2127class BaseShift<bits<2> shift_type, RegisterClass regtype, string asm,
2128                SDPatternOperator OpNode = null_frag>
2129  : BaseTwoOperand<{1,0,?,?}, regtype, asm, OpNode>,
2130    Sched<[WriteIS, ReadI]> {
2131  let Inst{11-10} = shift_type;
2132}
2133
2134multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2135  def Wr : BaseShift<shift_type, GPR32, asm> {
2136    let Inst{31} = 0;
2137  }
2138
2139  def Xr : BaseShift<shift_type, GPR64, asm, OpNode> {
2140    let Inst{31} = 1;
2141  }
2142
2143  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2144            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2145                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2146
2147  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2148            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2149
2150  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2151            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2152
2153  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2154            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2155
2156  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2157            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2158                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2159
2160  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2161            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2162                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2163}
2164
2165class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2166    : InstAlias<asm#"\t$dst, $src1, $src2",
2167                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2168
2169class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2170                       RegisterClass addtype, string asm,
2171                       list<dag> pattern>
2172  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2173      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2174  bits<5> Rd;
2175  bits<5> Rn;
2176  bits<5> Rm;
2177  bits<5> Ra;
2178  let Inst{30-24} = 0b0011011;
2179  let Inst{23-21} = opc;
2180  let Inst{20-16} = Rm;
2181  let Inst{15}    = isSub;
2182  let Inst{14-10} = Ra;
2183  let Inst{9-5}   = Rn;
2184  let Inst{4-0}   = Rd;
2185}
2186
2187multiclass MulAccum<bit isSub, string asm, SDNode AccNode> {
2188  // MADD/MSUB generation is decided by MachineCombiner.cpp
2189  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm,
2190      [/*(set GPR32:$Rd, (AccNode GPR32:$Ra, (mul GPR32:$Rn, GPR32:$Rm)))*/]>,
2191      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2192    let Inst{31} = 0;
2193  }
2194
2195  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm,
2196      [/*(set GPR64:$Rd, (AccNode GPR64:$Ra, (mul GPR64:$Rn, GPR64:$Rm)))*/]>,
2197      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2198    let Inst{31} = 1;
2199  }
2200}
2201
2202class WideMulAccum<bit isSub, bits<3> opc, string asm,
2203                   SDNode AccNode, SDNode ExtNode>
2204  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2205    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2206                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2207    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2208  let Inst{31} = 1;
2209}
2210
2211class MulHi<bits<3> opc, string asm, SDNode OpNode>
2212  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2213      asm, "\t$Rd, $Rn, $Rm", "",
2214      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2215    Sched<[WriteIM64, ReadIM, ReadIM]> {
2216  bits<5> Rd;
2217  bits<5> Rn;
2218  bits<5> Rm;
2219  let Inst{31-24} = 0b10011011;
2220  let Inst{23-21} = opc;
2221  let Inst{20-16} = Rm;
2222  let Inst{15}    = 0;
2223  let Inst{9-5}   = Rn;
2224  let Inst{4-0}   = Rd;
2225
2226  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2227  // (i.e. all bits 1) but is ignored by the processor.
2228  let PostEncoderMethod = "fixMulHigh";
2229}
2230
2231class MulAccumWAlias<string asm, Instruction inst>
2232    : InstAlias<asm#"\t$dst, $src1, $src2",
2233                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2234class MulAccumXAlias<string asm, Instruction inst>
2235    : InstAlias<asm#"\t$dst, $src1, $src2",
2236                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2237class WideMulAccumAlias<string asm, Instruction inst>
2238    : InstAlias<asm#"\t$dst, $src1, $src2",
2239                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2240
2241class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2242              SDPatternOperator OpNode, string asm>
2243  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2244      asm, "\t$Rd, $Rn, $Rm", "",
2245      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2246    Sched<[WriteISReg, ReadI, ReadISReg]> {
2247  bits<5> Rd;
2248  bits<5> Rn;
2249  bits<5> Rm;
2250
2251  let Inst{31} = sf;
2252  let Inst{30-21} = 0b0011010110;
2253  let Inst{20-16} = Rm;
2254  let Inst{15-13} = 0b010;
2255  let Inst{12} = C;
2256  let Inst{11-10} = sz;
2257  let Inst{9-5} = Rn;
2258  let Inst{4-0} = Rd;
2259  let Predicates = [HasCRC];
2260}
2261
2262//---
2263// Address generation.
2264//---
2265
2266class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2267    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2268        pattern>,
2269      Sched<[WriteI]> {
2270  bits<5>  Xd;
2271  bits<21> label;
2272  let Inst{31}    = page;
2273  let Inst{30-29} = label{1-0};
2274  let Inst{28-24} = 0b10000;
2275  let Inst{23-5}  = label{20-2};
2276  let Inst{4-0}   = Xd;
2277
2278  let DecoderMethod = "DecodeAdrInstruction";
2279}
2280
2281//---
2282// Move immediate.
2283//---
2284
2285def movimm32_imm : Operand<i32> {
2286  let ParserMatchClass = AsmImmRange<0, 65535>;
2287  let EncoderMethod = "getMoveWideImmOpValue";
2288  let PrintMethod = "printImm";
2289}
2290def movimm32_shift : Operand<i32> {
2291  let PrintMethod = "printShifter";
2292  let ParserMatchClass = MovImm32ShifterOperand;
2293}
2294def movimm64_shift : Operand<i32> {
2295  let PrintMethod = "printShifter";
2296  let ParserMatchClass = MovImm64ShifterOperand;
2297}
2298
2299let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2300class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2301                        string asm>
2302  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2303       asm, "\t$Rd, $imm$shift", "", []>,
2304    Sched<[WriteImm]> {
2305  bits<5> Rd;
2306  bits<16> imm;
2307  bits<6> shift;
2308  let Inst{30-29} = opc;
2309  let Inst{28-23} = 0b100101;
2310  let Inst{22-21} = shift{5-4};
2311  let Inst{20-5}  = imm;
2312  let Inst{4-0}   = Rd;
2313
2314  let DecoderMethod = "DecodeMoveImmInstruction";
2315}
2316
2317multiclass MoveImmediate<bits<2> opc, string asm> {
2318  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2319    let Inst{31} = 0;
2320  }
2321
2322  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2323    let Inst{31} = 1;
2324  }
2325}
2326
2327let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2328class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2329                          string asm>
2330  : I<(outs regtype:$Rd),
2331      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2332       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2333    Sched<[WriteI, ReadI]> {
2334  bits<5> Rd;
2335  bits<16> imm;
2336  bits<6> shift;
2337  let Inst{30-29} = opc;
2338  let Inst{28-23} = 0b100101;
2339  let Inst{22-21} = shift{5-4};
2340  let Inst{20-5}  = imm;
2341  let Inst{4-0}   = Rd;
2342
2343  let DecoderMethod = "DecodeMoveImmInstruction";
2344}
2345
2346multiclass InsertImmediate<bits<2> opc, string asm> {
2347  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2348    let Inst{31} = 0;
2349  }
2350
2351  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2352    let Inst{31} = 1;
2353  }
2354}
2355
2356//---
2357// Add/Subtract
2358//---
2359
2360class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2361                    string asm_inst, string asm_ops,
2362                    dag inputs, dag pattern>
2363    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2364      Sched<[WriteI, ReadI]> {
2365  bits<5>  Rd;
2366  bits<5>  Rn;
2367  let Inst{30}    = isSub;
2368  let Inst{29}    = setFlags;
2369  let Inst{28-24} = 0b10001;
2370  let Inst{9-5}   = Rn;
2371  let Inst{4-0}   = Rd;
2372}
2373
2374class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2375                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2376                     string asm_inst, SDPatternOperator OpNode>
2377    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2378                    (ins srcRegtype:$Rn, immtype:$imm),
2379                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2380  bits<14> imm;
2381  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2382  let Inst{21-10} = imm{11-0};
2383  let DecoderMethod = "DecodeAddSubImmShift";
2384}
2385
2386class BaseAddSubRegPseudo<RegisterClass regtype,
2387                          SDPatternOperator OpNode>
2388    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2389             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2390      Sched<[WriteI, ReadI, ReadI]>;
2391
2392class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2393                     arith_shifted_reg shifted_regtype, string asm,
2394                     SDPatternOperator OpNode>
2395    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2396        asm, "\t$Rd, $Rn, $Rm", "",
2397        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm))]>,
2398      Sched<[WriteISReg, ReadI, ReadISReg]> {
2399  // The operands are in order to match the 'addr' MI operands, so we
2400  // don't need an encoder method and by-name matching. Just use the default
2401  // in-order handling. Since we're using by-order, make sure the names
2402  // do not match.
2403  bits<5> dst;
2404  bits<5> src1;
2405  bits<5> src2;
2406  bits<8> shift;
2407  let Inst{30}    = isSub;
2408  let Inst{29}    = setFlags;
2409  let Inst{28-24} = 0b01011;
2410  let Inst{23-22} = shift{7-6};
2411  let Inst{21}    = 0;
2412  let Inst{20-16} = src2;
2413  let Inst{15-10} = shift{5-0};
2414  let Inst{9-5}   = src1;
2415  let Inst{4-0}   = dst;
2416
2417  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2418}
2419
2420class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2421                     RegisterClass src1Regtype, Operand src2Regtype,
2422                     string asm, SDPatternOperator OpNode>
2423    : I<(outs dstRegtype:$R1),
2424        (ins src1Regtype:$R2, src2Regtype:$R3),
2425        asm, "\t$R1, $R2, $R3", "",
2426        [(set dstRegtype:$R1, (OpNode src1Regtype:$R2, src2Regtype:$R3))]>,
2427      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2428  bits<5> Rd;
2429  bits<5> Rn;
2430  bits<5> Rm;
2431  bits<6> ext;
2432  let Inst{30}    = isSub;
2433  let Inst{29}    = setFlags;
2434  let Inst{28-24} = 0b01011;
2435  let Inst{23-21} = 0b001;
2436  let Inst{20-16} = Rm;
2437  let Inst{15-13} = ext{5-3};
2438  let Inst{12-10} = ext{2-0};
2439  let Inst{9-5}   = Rn;
2440  let Inst{4-0}   = Rd;
2441
2442  let DecoderMethod = "DecodeAddSubERegInstruction";
2443}
2444
2445let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2446class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2447                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2448                       Operand ext_op, string asm>
2449    : I<(outs dstRegtype:$Rd),
2450        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2451        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2452      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2453  bits<5> Rd;
2454  bits<5> Rn;
2455  bits<5> Rm;
2456  bits<6> ext;
2457  let Inst{30}    = isSub;
2458  let Inst{29}    = setFlags;
2459  let Inst{28-24} = 0b01011;
2460  let Inst{23-21} = 0b001;
2461  let Inst{20-16} = Rm;
2462  let Inst{15}    = ext{5};
2463  let Inst{12-10} = ext{2-0};
2464  let Inst{9-5}   = Rn;
2465  let Inst{4-0}   = Rd;
2466
2467  let DecoderMethod = "DecodeAddSubERegInstruction";
2468}
2469
2470// Aliases for register+register add/subtract.
2471class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2472                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2473                     int shiftExt>
2474    : InstAlias<asm#"\t$dst, $src1, $src2",
2475                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2476                      shiftExt)>;
2477
2478multiclass AddSub<bit isSub, string mnemonic, string alias,
2479                  SDPatternOperator OpNode = null_frag> {
2480  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2481  // Add/Subtract immediate
2482  // Increase the weight of the immediate variant to try to match it before
2483  // the extended register variant.
2484  // We used to match the register variant before the immediate when the
2485  // register argument could be implicitly zero-extended.
2486  let AddedComplexity = 6 in
2487  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2488                           mnemonic, OpNode> {
2489    let Inst{31} = 0;
2490  }
2491  let AddedComplexity = 6 in
2492  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2493                           mnemonic, OpNode> {
2494    let Inst{31} = 1;
2495  }
2496
2497  // Add/Subtract register - Only used for CodeGen
2498  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2499  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2500
2501  // Add/Subtract shifted register
2502  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2503                           OpNode> {
2504    let Inst{31} = 0;
2505  }
2506  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2507                           OpNode> {
2508    let Inst{31} = 1;
2509  }
2510  }
2511
2512  // Add/Subtract extended register
2513  let AddedComplexity = 1, hasSideEffects = 0 in {
2514  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2515                           arith_extended_reg32_i32, mnemonic, OpNode> {
2516    let Inst{31} = 0;
2517  }
2518  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2519                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2520    let Inst{31} = 1;
2521  }
2522  }
2523
2524  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2525                               arith_extendlsl64, mnemonic> {
2526    // UXTX and SXTX only.
2527    let Inst{14-13} = 0b11;
2528    let Inst{31} = 1;
2529  }
2530
2531  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2532  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2533                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2534                      addsub_shifted_imm32_neg:$imm), 0>;
2535  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2536                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2537                       addsub_shifted_imm64_neg:$imm), 0>;
2538
2539  // Register/register aliases with no shift when SP is not used.
2540  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2541                       GPR32, GPR32, GPR32, 0>;
2542  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2543                       GPR64, GPR64, GPR64, 0>;
2544
2545  // Register/register aliases with no shift when either the destination or
2546  // first source register is SP.
2547  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2548                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2549  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2550                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2551  def : AddSubRegAlias<mnemonic,
2552                       !cast<Instruction>(NAME#"Xrx64"),
2553                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2554  def : AddSubRegAlias<mnemonic,
2555                       !cast<Instruction>(NAME#"Xrx64"),
2556                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2557}
2558
2559multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2560                   string alias, string cmpAlias> {
2561  let isCompare = 1, Defs = [NZCV] in {
2562  // Add/Subtract immediate
2563  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2564                           mnemonic, OpNode> {
2565    let Inst{31} = 0;
2566  }
2567  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2568                           mnemonic, OpNode> {
2569    let Inst{31} = 1;
2570  }
2571
2572  // Add/Subtract register
2573  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2574  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2575
2576  // Add/Subtract shifted register
2577  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
2578                           OpNode> {
2579    let Inst{31} = 0;
2580  }
2581  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
2582                           OpNode> {
2583    let Inst{31} = 1;
2584  }
2585
2586  // Add/Subtract extended register
2587  let AddedComplexity = 1 in {
2588  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
2589                           arith_extended_reg32_i32, mnemonic, OpNode> {
2590    let Inst{31} = 0;
2591  }
2592  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
2593                           arith_extended_reg32_i64, mnemonic, OpNode> {
2594    let Inst{31} = 1;
2595  }
2596  }
2597
2598  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
2599                               arith_extendlsl64, mnemonic> {
2600    // UXTX and SXTX only.
2601    let Inst{14-13} = 0b11;
2602    let Inst{31} = 1;
2603  }
2604  } // Defs = [NZCV]
2605
2606  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
2607  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2608                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
2609                      addsub_shifted_imm32_neg:$imm), 0>;
2610  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2611                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
2612                       addsub_shifted_imm64_neg:$imm), 0>;
2613
2614  // Compare aliases
2615  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2616                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
2617  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2618                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
2619  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
2620                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2621  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
2622                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
2623  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
2624                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
2625  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
2626                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
2627  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
2628                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
2629
2630  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
2631  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
2632                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
2633  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
2634                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
2635
2636  // Compare shorthands
2637  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
2638                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
2639  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
2640                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
2641  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
2642                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
2643  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
2644                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
2645
2646  // Register/register aliases with no shift when SP is not used.
2647  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2648                       GPR32, GPR32, GPR32, 0>;
2649  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2650                       GPR64, GPR64, GPR64, 0>;
2651
2652  // Register/register aliases with no shift when the first source register
2653  // is SP.
2654  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2655                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
2656  def : AddSubRegAlias<mnemonic,
2657                       !cast<Instruction>(NAME#"Xrx64"),
2658                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
2659}
2660
2661class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
2662      : BaseAddSubImm<
2663          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
2664          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
2665          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
2666  bits<6> imm6;
2667  bits<4> imm4;
2668  let Inst{31} = 1;
2669  let Inst{23-22} = 0b10;
2670  let Inst{21-16} = imm6;
2671  let Inst{15-14} = 0b00;
2672  let Inst{13-10} = imm4;
2673  let Unpredictable{15-14} = 0b11;
2674}
2675
2676class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
2677      : BaseTwoOperand<0b0000, GPR64, asm_instr, OpNode, GPR64sp, GPR64sp> {
2678  let Inst{31} = 1;
2679  let Inst{29} = setsFlags;
2680}
2681
2682//---
2683// Extract
2684//---
2685def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
2686                                      SDTCisPtrTy<3>]>;
2687def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
2688
2689class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
2690                     list<dag> patterns>
2691    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
2692         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
2693      Sched<[WriteExtr, ReadExtrHi]> {
2694  bits<5> Rd;
2695  bits<5> Rn;
2696  bits<5> Rm;
2697  bits<6> imm;
2698
2699  let Inst{30-23} = 0b00100111;
2700  let Inst{21}    = 0;
2701  let Inst{20-16} = Rm;
2702  let Inst{15-10} = imm;
2703  let Inst{9-5}   = Rn;
2704  let Inst{4-0}   = Rd;
2705}
2706
2707multiclass ExtractImm<string asm> {
2708  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
2709                      [(set GPR32:$Rd,
2710                        (AArch64Extr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
2711    let Inst{31} = 0;
2712    let Inst{22} = 0;
2713    // imm<5> must be zero.
2714    let imm{5}   = 0;
2715  }
2716  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
2717                      [(set GPR64:$Rd,
2718                        (AArch64Extr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
2719
2720    let Inst{31} = 1;
2721    let Inst{22} = 1;
2722  }
2723}
2724
2725//---
2726// Bitfield
2727//---
2728
2729let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2730class BaseBitfieldImm<bits<2> opc,
2731                      RegisterClass regtype, Operand imm_type, string asm>
2732    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
2733         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
2734      Sched<[WriteIS, ReadI]> {
2735  bits<5> Rd;
2736  bits<5> Rn;
2737  bits<6> immr;
2738  bits<6> imms;
2739
2740  let Inst{30-29} = opc;
2741  let Inst{28-23} = 0b100110;
2742  let Inst{21-16} = immr;
2743  let Inst{15-10} = imms;
2744  let Inst{9-5}   = Rn;
2745  let Inst{4-0}   = Rd;
2746}
2747
2748multiclass BitfieldImm<bits<2> opc, string asm> {
2749  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
2750    let Inst{31} = 0;
2751    let Inst{22} = 0;
2752    // imms<5> and immr<5> must be zero, else ReservedValue().
2753    let Inst{21} = 0;
2754    let Inst{15} = 0;
2755  }
2756  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
2757    let Inst{31} = 1;
2758    let Inst{22} = 1;
2759  }
2760}
2761
2762let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2763class BaseBitfieldImmWith2RegArgs<bits<2> opc,
2764                      RegisterClass regtype, Operand imm_type, string asm>
2765    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
2766                             imm_type:$imms),
2767         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
2768      Sched<[WriteIS, ReadI]> {
2769  bits<5> Rd;
2770  bits<5> Rn;
2771  bits<6> immr;
2772  bits<6> imms;
2773
2774  let Inst{30-29} = opc;
2775  let Inst{28-23} = 0b100110;
2776  let Inst{21-16} = immr;
2777  let Inst{15-10} = imms;
2778  let Inst{9-5}   = Rn;
2779  let Inst{4-0}   = Rd;
2780}
2781
2782multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
2783  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
2784    let Inst{31} = 0;
2785    let Inst{22} = 0;
2786    // imms<5> and immr<5> must be zero, else ReservedValue().
2787    let Inst{21} = 0;
2788    let Inst{15} = 0;
2789  }
2790  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
2791    let Inst{31} = 1;
2792    let Inst{22} = 1;
2793  }
2794}
2795
2796//---
2797// Logical
2798//---
2799
2800// Logical (immediate)
2801class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
2802                     RegisterClass sregtype, Operand imm_type, string asm,
2803                     list<dag> pattern>
2804    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
2805         asm, "\t$Rd, $Rn, $imm", "", pattern>,
2806      Sched<[WriteI, ReadI]> {
2807  bits<5>  Rd;
2808  bits<5>  Rn;
2809  bits<13> imm;
2810  let Inst{30-29} = opc;
2811  let Inst{28-23} = 0b100100;
2812  let Inst{22}    = imm{12};
2813  let Inst{21-16} = imm{11-6};
2814  let Inst{15-10} = imm{5-0};
2815  let Inst{9-5}   = Rn;
2816  let Inst{4-0}   = Rd;
2817
2818  let DecoderMethod = "DecodeLogicalImmInstruction";
2819}
2820
2821// Logical (shifted register)
2822class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
2823                      logical_shifted_reg shifted_regtype, string asm,
2824                      list<dag> pattern>
2825    : I<(outs regtype:$Rd), (ins regtype:$Rn, shifted_regtype:$Rm),
2826        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2827      Sched<[WriteISReg, ReadI, ReadISReg]> {
2828  // The operands are in order to match the 'addr' MI operands, so we
2829  // don't need an encoder method and by-name matching. Just use the default
2830  // in-order handling. Since we're using by-order, make sure the names
2831  // do not match.
2832  bits<5> dst;
2833  bits<5> src1;
2834  bits<5> src2;
2835  bits<8> shift;
2836  let Inst{30-29} = opc;
2837  let Inst{28-24} = 0b01010;
2838  let Inst{23-22} = shift{7-6};
2839  let Inst{21}    = N;
2840  let Inst{20-16} = src2;
2841  let Inst{15-10} = shift{5-0};
2842  let Inst{9-5}   = src1;
2843  let Inst{4-0}   = dst;
2844
2845  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2846}
2847
2848// Aliases for register+register logical instructions.
2849class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
2850    : InstAlias<asm#"\t$dst, $src1, $src2",
2851                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
2852
2853multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
2854                      string Alias> {
2855  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2856  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
2857                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
2858                                               logical_imm32:$imm))]> {
2859    let Inst{31} = 0;
2860    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2861  }
2862  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
2863  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
2864                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
2865                                               logical_imm64:$imm))]> {
2866    let Inst{31} = 1;
2867  }
2868
2869  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2870                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
2871                      logical_imm32_not:$imm), 0>;
2872  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2873                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
2874                       logical_imm64_not:$imm), 0>;
2875}
2876
2877multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
2878                       string Alias> {
2879  let isCompare = 1, Defs = [NZCV] in {
2880  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
2881      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
2882    let Inst{31} = 0;
2883    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
2884  }
2885  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
2886      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
2887    let Inst{31} = 1;
2888  }
2889  } // end Defs = [NZCV]
2890
2891  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2892                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
2893                      logical_imm32_not:$imm), 0>;
2894  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
2895                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
2896                       logical_imm64_not:$imm), 0>;
2897}
2898
2899class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
2900    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2901             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2902      Sched<[WriteI, ReadI, ReadI]>;
2903
2904// Split from LogicalImm as not all instructions have both.
2905multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
2906                      SDPatternOperator OpNode> {
2907  let isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2908  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2909  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2910  }
2911
2912  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2913                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
2914                                                 logical_shifted_reg32:$Rm))]> {
2915    let Inst{31} = 0;
2916  }
2917  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2918                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
2919                                                 logical_shifted_reg64:$Rm))]> {
2920    let Inst{31} = 1;
2921  }
2922
2923  def : LogicalRegAlias<mnemonic,
2924                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2925  def : LogicalRegAlias<mnemonic,
2926                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2927}
2928
2929// Split from LogicalReg to allow setting NZCV Defs
2930multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
2931                       SDPatternOperator OpNode = null_frag> {
2932  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
2933  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
2934  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
2935
2936  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
2937            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm))]> {
2938    let Inst{31} = 0;
2939  }
2940  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
2941            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm))]> {
2942    let Inst{31} = 1;
2943  }
2944  } // Defs = [NZCV]
2945
2946  def : LogicalRegAlias<mnemonic,
2947                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
2948  def : LogicalRegAlias<mnemonic,
2949                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
2950}
2951
2952//---
2953// Conditionally set flags
2954//---
2955
2956let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2957class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
2958                            string mnemonic, SDNode OpNode>
2959    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
2960         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
2961         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
2962                             (i32 imm:$cond), NZCV))]>,
2963      Sched<[WriteI, ReadI]> {
2964  let Uses = [NZCV];
2965  let Defs = [NZCV];
2966
2967  bits<5> Rn;
2968  bits<5> imm;
2969  bits<4> nzcv;
2970  bits<4> cond;
2971
2972  let Inst{30}    = op;
2973  let Inst{29-21} = 0b111010010;
2974  let Inst{20-16} = imm;
2975  let Inst{15-12} = cond;
2976  let Inst{11-10} = 0b10;
2977  let Inst{9-5}   = Rn;
2978  let Inst{4}     = 0b0;
2979  let Inst{3-0}   = nzcv;
2980}
2981
2982let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2983class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
2984                            SDNode OpNode>
2985    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
2986         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
2987         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
2988                             (i32 imm:$cond), NZCV))]>,
2989      Sched<[WriteI, ReadI, ReadI]> {
2990  let Uses = [NZCV];
2991  let Defs = [NZCV];
2992
2993  bits<5> Rn;
2994  bits<5> Rm;
2995  bits<4> nzcv;
2996  bits<4> cond;
2997
2998  let Inst{30}    = op;
2999  let Inst{29-21} = 0b111010010;
3000  let Inst{20-16} = Rm;
3001  let Inst{15-12} = cond;
3002  let Inst{11-10} = 0b00;
3003  let Inst{9-5}   = Rn;
3004  let Inst{4}     = 0b0;
3005  let Inst{3-0}   = nzcv;
3006}
3007
3008multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3009  // immediate operand variants
3010  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3011    let Inst{31} = 0;
3012  }
3013  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3014    let Inst{31} = 1;
3015  }
3016  // register operand variants
3017  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3018    let Inst{31} = 0;
3019  }
3020  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3021    let Inst{31} = 1;
3022  }
3023}
3024
3025//---
3026// Conditional select
3027//---
3028
3029class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3030    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3031         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3032         [(set regtype:$Rd,
3033               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3034      Sched<[WriteI, ReadI, ReadI]> {
3035  let Uses = [NZCV];
3036
3037  bits<5> Rd;
3038  bits<5> Rn;
3039  bits<5> Rm;
3040  bits<4> cond;
3041
3042  let Inst{30}    = op;
3043  let Inst{29-21} = 0b011010100;
3044  let Inst{20-16} = Rm;
3045  let Inst{15-12} = cond;
3046  let Inst{11-10} = op2;
3047  let Inst{9-5}   = Rn;
3048  let Inst{4-0}   = Rd;
3049}
3050
3051multiclass CondSelect<bit op, bits<2> op2, string asm> {
3052  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3053    let Inst{31} = 0;
3054  }
3055  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3056    let Inst{31} = 1;
3057  }
3058}
3059
3060class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3061                       PatFrag frag>
3062    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3063         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3064         [(set regtype:$Rd,
3065               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3066               (i32 imm:$cond), NZCV))]>,
3067      Sched<[WriteI, ReadI, ReadI]> {
3068  let Uses = [NZCV];
3069
3070  bits<5> Rd;
3071  bits<5> Rn;
3072  bits<5> Rm;
3073  bits<4> cond;
3074
3075  let Inst{30}    = op;
3076  let Inst{29-21} = 0b011010100;
3077  let Inst{20-16} = Rm;
3078  let Inst{15-12} = cond;
3079  let Inst{11-10} = op2;
3080  let Inst{9-5}   = Rn;
3081  let Inst{4-0}   = Rd;
3082}
3083
3084def inv_cond_XFORM : SDNodeXForm<imm, [{
3085  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3086  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3087                                   MVT::i32);
3088}]>;
3089
3090multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3091  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3092    let Inst{31} = 0;
3093  }
3094  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3095    let Inst{31} = 1;
3096  }
3097
3098  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3099            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3100                                           (inv_cond_XFORM imm:$cond))>;
3101
3102  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3103            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3104                                           (inv_cond_XFORM imm:$cond))>;
3105}
3106
3107//---
3108// Special Mask Value
3109//---
3110def maski8_or_more : Operand<i32>,
3111  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3112}
3113def maski16_or_more : Operand<i32>,
3114  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3115}
3116
3117
3118//---
3119// Load/store
3120//---
3121
3122// (unsigned immediate)
3123// Indexed for 8-bit registers. offset is in range [0,4095].
3124def am_indexed8 : ComplexPattern<i64, 2, "SelectAddrModeIndexed8", []>;
3125def am_indexed16 : ComplexPattern<i64, 2, "SelectAddrModeIndexed16", []>;
3126def am_indexed32 : ComplexPattern<i64, 2, "SelectAddrModeIndexed32", []>;
3127def am_indexed64 : ComplexPattern<i64, 2, "SelectAddrModeIndexed64", []>;
3128def am_indexed128 : ComplexPattern<i64, 2, "SelectAddrModeIndexed128", []>;
3129
3130def gi_am_indexed8 :
3131    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3132    GIComplexPatternEquiv<am_indexed8>;
3133def gi_am_indexed16 :
3134    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3135    GIComplexPatternEquiv<am_indexed16>;
3136def gi_am_indexed32 :
3137    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3138    GIComplexPatternEquiv<am_indexed32>;
3139def gi_am_indexed64 :
3140    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3141    GIComplexPatternEquiv<am_indexed64>;
3142def gi_am_indexed128 :
3143    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3144    GIComplexPatternEquiv<am_indexed128>;
3145
3146class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3147  let Name = "UImm12Offset" # Scale;
3148  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3149  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3150  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3151}
3152
3153def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3154def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3155def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3156def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3157def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3158
3159class uimm12_scaled<int Scale> : Operand<i64> {
3160  let ParserMatchClass
3161   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3162  let EncoderMethod
3163   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3164  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3165}
3166
3167def uimm12s1 : uimm12_scaled<1>;
3168def uimm12s2 : uimm12_scaled<2>;
3169def uimm12s4 : uimm12_scaled<4>;
3170def uimm12s8 : uimm12_scaled<8>;
3171def uimm12s16 : uimm12_scaled<16>;
3172
3173class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3174                      string asm, list<dag> pattern>
3175    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3176  bits<5> Rt;
3177
3178  bits<5> Rn;
3179  bits<12> offset;
3180
3181  let Inst{31-30} = sz;
3182  let Inst{29-27} = 0b111;
3183  let Inst{26}    = V;
3184  let Inst{25-24} = 0b01;
3185  let Inst{23-22} = opc;
3186  let Inst{21-10} = offset;
3187  let Inst{9-5}   = Rn;
3188  let Inst{4-0}   = Rt;
3189
3190  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3191}
3192
3193multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3194                  Operand indextype, string asm, list<dag> pattern> {
3195  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3196  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3197                           (ins GPR64sp:$Rn, indextype:$offset),
3198                           asm, pattern>,
3199           Sched<[WriteLD]>;
3200
3201  def : InstAlias<asm # "\t$Rt, [$Rn]",
3202                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3203}
3204
3205multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3206             Operand indextype, string asm, list<dag> pattern> {
3207  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3208  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3209                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3210                           asm, pattern>,
3211           Sched<[WriteST]>;
3212
3213  def : InstAlias<asm # "\t$Rt, [$Rn]",
3214                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3215}
3216
3217// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3218// substitute zero-registers automatically.
3219//
3220// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3221//       into StoreUI.
3222multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3223             Operand indextype, string asm, list<dag> pattern> {
3224  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3225  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3226                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3227                           asm, pattern>,
3228           Sched<[WriteST]>;
3229
3230  def : InstAlias<asm # "\t$Rt, [$Rn]",
3231                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3232}
3233
3234def PrefetchOperand : AsmOperandClass {
3235  let Name = "Prefetch";
3236  let ParserMethod = "tryParsePrefetch";
3237}
3238def prfop : Operand<i32> {
3239  let PrintMethod = "printPrefetchOp";
3240  let ParserMatchClass = PrefetchOperand;
3241}
3242
3243let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3244class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3245    : BaseLoadStoreUI<sz, V, opc,
3246                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3247                      asm, pat>,
3248      Sched<[WriteLD]>;
3249
3250//---
3251// Load literal
3252//---
3253
3254// Load literal address: 19-bit immediate. The low two bits of the target
3255// offset are implied zero and so are not part of the immediate.
3256def am_ldrlit : Operand<iPTR> {
3257  let EncoderMethod = "getLoadLiteralOpValue";
3258  let DecoderMethod = "DecodePCRelLabel19";
3259  let PrintMethod = "printAlignedLabel";
3260  let ParserMatchClass = PCRelLabel19Operand;
3261  let OperandType = "OPERAND_PCREL";
3262}
3263
3264let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3265class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3266    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3267        asm, "\t$Rt, $label", "", pat>,
3268      Sched<[WriteLD]> {
3269  bits<5> Rt;
3270  bits<19> label;
3271  let Inst{31-30} = opc;
3272  let Inst{29-27} = 0b011;
3273  let Inst{26}    = V;
3274  let Inst{25-24} = 0b00;
3275  let Inst{23-5}  = label;
3276  let Inst{4-0}   = Rt;
3277}
3278
3279let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3280class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3281    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3282        asm, "\t$Rt, $label", "", pat>,
3283      Sched<[WriteLD]> {
3284  bits<5> Rt;
3285  bits<19> label;
3286  let Inst{31-30} = opc;
3287  let Inst{29-27} = 0b011;
3288  let Inst{26}    = V;
3289  let Inst{25-24} = 0b00;
3290  let Inst{23-5}  = label;
3291  let Inst{4-0}   = Rt;
3292}
3293
3294//---
3295// Load/store register offset
3296//---
3297
3298def ro_Xindexed8 : ComplexPattern<i64, 4, "SelectAddrModeXRO<8>", []>;
3299def ro_Xindexed16 : ComplexPattern<i64, 4, "SelectAddrModeXRO<16>", []>;
3300def ro_Xindexed32 : ComplexPattern<i64, 4, "SelectAddrModeXRO<32>", []>;
3301def ro_Xindexed64 : ComplexPattern<i64, 4, "SelectAddrModeXRO<64>", []>;
3302def ro_Xindexed128 : ComplexPattern<i64, 4, "SelectAddrModeXRO<128>", []>;
3303
3304def gi_ro_Xindexed8 :
3305    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3306    GIComplexPatternEquiv<ro_Xindexed8>;
3307def gi_ro_Xindexed16 :
3308    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3309    GIComplexPatternEquiv<ro_Xindexed16>;
3310def gi_ro_Xindexed32 :
3311    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3312    GIComplexPatternEquiv<ro_Xindexed32>;
3313def gi_ro_Xindexed64 :
3314    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3315    GIComplexPatternEquiv<ro_Xindexed64>;
3316def gi_ro_Xindexed128 :
3317    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3318    GIComplexPatternEquiv<ro_Xindexed128>;
3319
3320def ro_Windexed8 : ComplexPattern<i64, 4, "SelectAddrModeWRO<8>", []>;
3321def ro_Windexed16 : ComplexPattern<i64, 4, "SelectAddrModeWRO<16>", []>;
3322def ro_Windexed32 : ComplexPattern<i64, 4, "SelectAddrModeWRO<32>", []>;
3323def ro_Windexed64 : ComplexPattern<i64, 4, "SelectAddrModeWRO<64>", []>;
3324def ro_Windexed128 : ComplexPattern<i64, 4, "SelectAddrModeWRO<128>", []>;
3325
3326def gi_ro_Windexed8 :
3327    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3328    GIComplexPatternEquiv<ro_Windexed8>;
3329def gi_ro_Windexed16 :
3330    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3331    GIComplexPatternEquiv<ro_Windexed16>;
3332def gi_ro_Windexed32 :
3333    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3334    GIComplexPatternEquiv<ro_Windexed32>;
3335def gi_ro_Windexed64 :
3336    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3337    GIComplexPatternEquiv<ro_Windexed64>;
3338def gi_ro_Windexed128 :
3339    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3340    GIComplexPatternEquiv<ro_Windexed128>;
3341
3342class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3343  let Name = "Mem" # Reg # "Extend" # Width;
3344  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3345  let RenderMethod = "addMemExtendOperands";
3346  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3347}
3348
3349def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3350  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3351  // the trivial shift.
3352  let RenderMethod = "addMemExtend8Operands";
3353}
3354def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3355def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3356def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3357def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3358
3359def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3360  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3361  // the trivial shift.
3362  let RenderMethod = "addMemExtend8Operands";
3363}
3364def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3365def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3366def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3367def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3368
3369class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3370        : Operand<i32> {
3371  let ParserMatchClass = ParserClass;
3372  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3373  let DecoderMethod = "DecodeMemExtend";
3374  let EncoderMethod = "getMemExtendOpValue";
3375  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3376}
3377
3378def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3379def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3380def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3381def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3382def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3383
3384def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3385def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3386def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3387def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3388def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3389
3390class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3391                  Operand wextend, Operand xextend>  {
3392  // CodeGen-level pattern covering the entire addressing mode.
3393  ComplexPattern Wpat = windex;
3394  ComplexPattern Xpat = xindex;
3395
3396  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3397  Operand Wext = wextend;
3398  Operand Xext = xextend;
3399}
3400
3401def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3402def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3403def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3404def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3405def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3406                       ro_Xextend128>;
3407
3408class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3409                      string asm, dag ins, dag outs, list<dag> pat>
3410    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3411  bits<5> Rt;
3412  bits<5> Rn;
3413  bits<5> Rm;
3414  bits<2> extend;
3415  let Inst{31-30} = sz;
3416  let Inst{29-27} = 0b111;
3417  let Inst{26}    = V;
3418  let Inst{25-24} = 0b00;
3419  let Inst{23-22} = opc;
3420  let Inst{21}    = 1;
3421  let Inst{20-16} = Rm;
3422  let Inst{15}    = extend{1}; // sign extend Rm?
3423  let Inst{14}    = 1;
3424  let Inst{12}    = extend{0}; // do shift?
3425  let Inst{11-10} = 0b10;
3426  let Inst{9-5}   = Rn;
3427  let Inst{4-0}   = Rt;
3428}
3429
3430class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3431  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3432              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3433
3434multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3435                   string asm, ValueType Ty, SDPatternOperator loadop> {
3436  let AddedComplexity = 10 in
3437  def roW : LoadStore8RO<sz, V, opc, regtype, asm,
3438                 (outs regtype:$Rt),
3439                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3440                 [(set (Ty regtype:$Rt),
3441                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3442                                             ro_Wextend8:$extend)))]>,
3443           Sched<[WriteLDIdx, ReadAdrBase]> {
3444    let Inst{13} = 0b0;
3445  }
3446
3447  let AddedComplexity = 10 in
3448  def roX : LoadStore8RO<sz, V, opc, regtype, asm,
3449                 (outs regtype:$Rt),
3450                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3451                 [(set (Ty regtype:$Rt),
3452                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3453                                             ro_Xextend8:$extend)))]>,
3454           Sched<[WriteLDIdx, ReadAdrBase]> {
3455    let Inst{13} = 0b1;
3456  }
3457
3458  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3459}
3460
3461multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3462                    string asm, ValueType Ty, SDPatternOperator storeop> {
3463  let AddedComplexity = 10 in
3464  def roW : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3465                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3466                 [(storeop (Ty regtype:$Rt),
3467                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3468                                         ro_Wextend8:$extend))]>,
3469            Sched<[WriteSTIdx, ReadAdrBase]> {
3470    let Inst{13} = 0b0;
3471  }
3472
3473  let AddedComplexity = 10 in
3474  def roX : LoadStore8RO<sz, V, opc, regtype, asm, (outs),
3475                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3476                 [(storeop (Ty regtype:$Rt),
3477                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3478                                         ro_Xextend8:$extend))]>,
3479            Sched<[WriteSTIdx, ReadAdrBase]> {
3480    let Inst{13} = 0b1;
3481  }
3482
3483  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3484}
3485
3486class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3487                      string asm, dag ins, dag outs, list<dag> pat>
3488    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3489  bits<5> Rt;
3490  bits<5> Rn;
3491  bits<5> Rm;
3492  bits<2> extend;
3493  let Inst{31-30} = sz;
3494  let Inst{29-27} = 0b111;
3495  let Inst{26}    = V;
3496  let Inst{25-24} = 0b00;
3497  let Inst{23-22} = opc;
3498  let Inst{21}    = 1;
3499  let Inst{20-16} = Rm;
3500  let Inst{15}    = extend{1}; // sign extend Rm?
3501  let Inst{14}    = 1;
3502  let Inst{12}    = extend{0}; // do shift?
3503  let Inst{11-10} = 0b10;
3504  let Inst{9-5}   = Rn;
3505  let Inst{4-0}   = Rt;
3506}
3507
3508multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3509                    string asm, ValueType Ty, SDPatternOperator loadop> {
3510  let AddedComplexity = 10 in
3511  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3512                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3513                 [(set (Ty regtype:$Rt),
3514                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3515                                              ro_Wextend16:$extend)))]>,
3516            Sched<[WriteLDIdx, ReadAdrBase]> {
3517    let Inst{13} = 0b0;
3518  }
3519
3520  let AddedComplexity = 10 in
3521  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3522                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3523                 [(set (Ty regtype:$Rt),
3524                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3525                                             ro_Xextend16:$extend)))]>,
3526            Sched<[WriteLDIdx, ReadAdrBase]> {
3527    let Inst{13} = 0b1;
3528  }
3529
3530  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3531}
3532
3533multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3534                     string asm, ValueType Ty, SDPatternOperator storeop> {
3535  let AddedComplexity = 10 in
3536  def roW : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3537                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3538                [(storeop (Ty regtype:$Rt),
3539                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3540                                         ro_Wextend16:$extend))]>,
3541           Sched<[WriteSTIdx, ReadAdrBase]> {
3542    let Inst{13} = 0b0;
3543  }
3544
3545  let AddedComplexity = 10 in
3546  def roX : LoadStore16RO<sz, V, opc, regtype, asm, (outs),
3547                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3548                [(storeop (Ty regtype:$Rt),
3549                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3550                                         ro_Xextend16:$extend))]>,
3551           Sched<[WriteSTIdx, ReadAdrBase]> {
3552    let Inst{13} = 0b1;
3553  }
3554
3555  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3556}
3557
3558class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3559                      string asm, dag ins, dag outs, list<dag> pat>
3560    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3561  bits<5> Rt;
3562  bits<5> Rn;
3563  bits<5> Rm;
3564  bits<2> extend;
3565  let Inst{31-30} = sz;
3566  let Inst{29-27} = 0b111;
3567  let Inst{26}    = V;
3568  let Inst{25-24} = 0b00;
3569  let Inst{23-22} = opc;
3570  let Inst{21}    = 1;
3571  let Inst{20-16} = Rm;
3572  let Inst{15}    = extend{1}; // sign extend Rm?
3573  let Inst{14}    = 1;
3574  let Inst{12}    = extend{0}; // do shift?
3575  let Inst{11-10} = 0b10;
3576  let Inst{9-5}   = Rn;
3577  let Inst{4-0}   = Rt;
3578}
3579
3580multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3581                    string asm, ValueType Ty, SDPatternOperator loadop> {
3582  let AddedComplexity = 10 in
3583  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3584                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3585                 [(set (Ty regtype:$Rt),
3586                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3587                                              ro_Wextend32:$extend)))]>,
3588           Sched<[WriteLDIdx, ReadAdrBase]> {
3589    let Inst{13} = 0b0;
3590  }
3591
3592  let AddedComplexity = 10 in
3593  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3594                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3595                 [(set (Ty regtype:$Rt),
3596                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3597                                              ro_Xextend32:$extend)))]>,
3598           Sched<[WriteLDIdx, ReadAdrBase]> {
3599    let Inst{13} = 0b1;
3600  }
3601
3602  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3603}
3604
3605multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3606                     string asm, ValueType Ty, SDPatternOperator storeop> {
3607  let AddedComplexity = 10 in
3608  def roW : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3609                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
3610                [(storeop (Ty regtype:$Rt),
3611                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
3612                                         ro_Wextend32:$extend))]>,
3613            Sched<[WriteSTIdx, ReadAdrBase]> {
3614    let Inst{13} = 0b0;
3615  }
3616
3617  let AddedComplexity = 10 in
3618  def roX : LoadStore32RO<sz, V, opc, regtype, asm, (outs),
3619                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
3620                [(storeop (Ty regtype:$Rt),
3621                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
3622                                        ro_Xextend32:$extend))]>,
3623            Sched<[WriteSTIdx, ReadAdrBase]> {
3624    let Inst{13} = 0b1;
3625  }
3626
3627  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3628}
3629
3630class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3631                      string asm, dag ins, dag outs, list<dag> pat>
3632    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3633  bits<5> Rt;
3634  bits<5> Rn;
3635  bits<5> Rm;
3636  bits<2> extend;
3637  let Inst{31-30} = sz;
3638  let Inst{29-27} = 0b111;
3639  let Inst{26}    = V;
3640  let Inst{25-24} = 0b00;
3641  let Inst{23-22} = opc;
3642  let Inst{21}    = 1;
3643  let Inst{20-16} = Rm;
3644  let Inst{15}    = extend{1}; // sign extend Rm?
3645  let Inst{14}    = 1;
3646  let Inst{12}    = extend{0}; // do shift?
3647  let Inst{11-10} = 0b10;
3648  let Inst{9-5}   = Rn;
3649  let Inst{4-0}   = Rt;
3650}
3651
3652multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3653                    string asm, ValueType Ty, SDPatternOperator loadop> {
3654  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3655  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3656                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3657                [(set (Ty regtype:$Rt),
3658                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3659                                             ro_Wextend64:$extend)))]>,
3660           Sched<[WriteLDIdx, ReadAdrBase]> {
3661    let Inst{13} = 0b0;
3662  }
3663
3664  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3665  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3666                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3667                 [(set (Ty regtype:$Rt),
3668                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3669                                              ro_Xextend64:$extend)))]>,
3670           Sched<[WriteLDIdx, ReadAdrBase]> {
3671    let Inst{13} = 0b1;
3672  }
3673
3674  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3675}
3676
3677multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3678                     string asm, ValueType Ty, SDPatternOperator storeop> {
3679  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3680  def roW : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3681                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3682                [(storeop (Ty regtype:$Rt),
3683                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3684                                         ro_Wextend64:$extend))]>,
3685            Sched<[WriteSTIdx, ReadAdrBase]> {
3686    let Inst{13} = 0b0;
3687  }
3688
3689  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3690  def roX : LoadStore64RO<sz, V, opc, regtype, asm, (outs),
3691                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3692                [(storeop (Ty regtype:$Rt),
3693                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3694                                         ro_Xextend64:$extend))]>,
3695            Sched<[WriteSTIdx, ReadAdrBase]> {
3696    let Inst{13} = 0b1;
3697  }
3698
3699  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3700}
3701
3702class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3703                      string asm, dag ins, dag outs, list<dag> pat>
3704    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3705  bits<5> Rt;
3706  bits<5> Rn;
3707  bits<5> Rm;
3708  bits<2> extend;
3709  let Inst{31-30} = sz;
3710  let Inst{29-27} = 0b111;
3711  let Inst{26}    = V;
3712  let Inst{25-24} = 0b00;
3713  let Inst{23-22} = opc;
3714  let Inst{21}    = 1;
3715  let Inst{20-16} = Rm;
3716  let Inst{15}    = extend{1}; // sign extend Rm?
3717  let Inst{14}    = 1;
3718  let Inst{12}    = extend{0}; // do shift?
3719  let Inst{11-10} = 0b10;
3720  let Inst{9-5}   = Rn;
3721  let Inst{4-0}   = Rt;
3722}
3723
3724multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3725                     string asm, ValueType Ty, SDPatternOperator loadop> {
3726  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3727  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3728                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3729                 [(set (Ty regtype:$Rt),
3730                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
3731                                               ro_Wextend128:$extend)))]>,
3732            Sched<[WriteLDIdx, ReadAdrBase]> {
3733    let Inst{13} = 0b0;
3734  }
3735
3736  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3737  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs regtype:$Rt),
3738                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3739                 [(set (Ty regtype:$Rt),
3740                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
3741                                               ro_Xextend128:$extend)))]>,
3742            Sched<[WriteLDIdx, ReadAdrBase]> {
3743    let Inst{13} = 0b1;
3744  }
3745
3746  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3747}
3748
3749multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3750                      string asm, ValueType Ty, SDPatternOperator storeop> {
3751  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3752  def roW : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3753               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
3754                []>,
3755            Sched<[WriteSTIdx, ReadAdrBase]> {
3756    let Inst{13} = 0b0;
3757  }
3758
3759  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3760  def roX : LoadStore128RO<sz, V, opc, regtype, asm, (outs),
3761               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
3762                []>,
3763            Sched<[WriteSTIdx, ReadAdrBase]> {
3764    let Inst{13} = 0b1;
3765  }
3766
3767  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3768}
3769
3770let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3771class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
3772                     string asm, list<dag> pat>
3773    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
3774      Sched<[WriteLD]> {
3775  bits<5> Rt;
3776  bits<5> Rn;
3777  bits<5> Rm;
3778  bits<2> extend;
3779  let Inst{31-30} = sz;
3780  let Inst{29-27} = 0b111;
3781  let Inst{26}    = V;
3782  let Inst{25-24} = 0b00;
3783  let Inst{23-22} = opc;
3784  let Inst{21}    = 1;
3785  let Inst{20-16} = Rm;
3786  let Inst{15}    = extend{1}; // sign extend Rm?
3787  let Inst{14}    = 1;
3788  let Inst{12}    = extend{0}; // do shift?
3789  let Inst{11-10} = 0b10;
3790  let Inst{9-5}   = Rn;
3791  let Inst{4-0}   = Rt;
3792}
3793
3794multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
3795  def roW : BasePrefetchRO<sz, V, opc, (outs),
3796                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
3797                asm, [(AArch64Prefetch imm:$Rt,
3798                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
3799                                                    ro_Wextend64:$extend))]> {
3800    let Inst{13} = 0b0;
3801  }
3802
3803  def roX : BasePrefetchRO<sz, V, opc, (outs),
3804                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
3805                asm,  [(AArch64Prefetch imm:$Rt,
3806                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
3807                                                     ro_Xextend64:$extend))]> {
3808    let Inst{13} = 0b1;
3809  }
3810
3811  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
3812               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
3813                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3814}
3815
3816//---
3817// Load/store unscaled immediate
3818//---
3819
3820def am_unscaled8 :  ComplexPattern<i64, 2, "SelectAddrModeUnscaled8", []>;
3821def am_unscaled16 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled16", []>;
3822def am_unscaled32 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled32", []>;
3823def am_unscaled64 : ComplexPattern<i64, 2, "SelectAddrModeUnscaled64", []>;
3824def am_unscaled128 :ComplexPattern<i64, 2, "SelectAddrModeUnscaled128", []>;
3825
3826def gi_am_unscaled8 :
3827    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
3828    GIComplexPatternEquiv<am_unscaled8>;
3829def gi_am_unscaled16 :
3830    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
3831    GIComplexPatternEquiv<am_unscaled16>;
3832def gi_am_unscaled32 :
3833    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
3834    GIComplexPatternEquiv<am_unscaled32>;
3835def gi_am_unscaled64 :
3836    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
3837    GIComplexPatternEquiv<am_unscaled64>;
3838def gi_am_unscaled128 :
3839    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
3840    GIComplexPatternEquiv<am_unscaled128>;
3841
3842
3843class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3844                           string asm, list<dag> pattern>
3845    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3846  bits<5> Rt;
3847  bits<5> Rn;
3848  bits<9> offset;
3849  let Inst{31-30} = sz;
3850  let Inst{29-27} = 0b111;
3851  let Inst{26}    = V;
3852  let Inst{25-24} = 0b00;
3853  let Inst{23-22} = opc;
3854  let Inst{21}    = 0;
3855  let Inst{20-12} = offset;
3856  let Inst{11-10} = 0b00;
3857  let Inst{9-5}   = Rn;
3858  let Inst{4-0}   = Rt;
3859
3860  let DecoderMethod = "DecodeSignedLdStInstruction";
3861}
3862
3863// Armv8.4 LDAPR & STLR with Immediate Offset instruction
3864multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3865                              DAGOperand regtype > {
3866  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
3867                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
3868          Sched<[WriteST]> {
3869    let Inst{29} = 0;
3870    let Inst{24} = 1;
3871  }
3872  def : InstAlias<asm # "\t$Rt, [$Rn]",
3873                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3874}
3875
3876multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
3877                               DAGOperand regtype > {
3878  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
3879                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3880                               asm, []>,
3881          Sched<[WriteST]> {
3882    let Inst{29} = 0;
3883    let Inst{24} = 1;
3884  }
3885  def : InstAlias<asm # "\t$Rt, [$Rn]",
3886                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3887}
3888
3889multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3890                   string asm, list<dag> pattern> {
3891  let AddedComplexity = 1 in // try this before LoadUI
3892  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
3893                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
3894          Sched<[WriteLD]>;
3895
3896  def : InstAlias<asm # "\t$Rt, [$Rn]",
3897                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3898}
3899
3900multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3901                         string asm, list<dag> pattern> {
3902  let AddedComplexity = 1 in // try this before StoreUI
3903  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3904                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3905                               asm, pattern>,
3906          Sched<[WriteST]>;
3907
3908  def : InstAlias<asm # "\t$Rt, [$Rn]",
3909                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3910}
3911
3912multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
3913                            list<dag> pat> {
3914  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3915  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
3916                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
3917                               asm, pat>,
3918          Sched<[WriteLD]>;
3919
3920  def : InstAlias<asm # "\t$Rt, [$Rn]",
3921                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
3922}
3923
3924//---
3925// Load/store unscaled immediate, unprivileged
3926//---
3927
3928class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3929                                dag oops, dag iops, string asm>
3930    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
3931  bits<5> Rt;
3932  bits<5> Rn;
3933  bits<9> offset;
3934  let Inst{31-30} = sz;
3935  let Inst{29-27} = 0b111;
3936  let Inst{26}    = V;
3937  let Inst{25-24} = 0b00;
3938  let Inst{23-22} = opc;
3939  let Inst{21}    = 0;
3940  let Inst{20-12} = offset;
3941  let Inst{11-10} = 0b10;
3942  let Inst{9-5}   = Rn;
3943  let Inst{4-0}   = Rt;
3944
3945  let DecoderMethod = "DecodeSignedLdStInstruction";
3946}
3947
3948multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
3949                            RegisterClass regtype, string asm> {
3950  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
3951  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
3952                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
3953          Sched<[WriteLD]>;
3954
3955  def : InstAlias<asm # "\t$Rt, [$Rn]",
3956                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3957}
3958
3959multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
3960                             RegisterClass regtype, string asm> {
3961  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
3962  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
3963                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
3964                                 asm>,
3965          Sched<[WriteST]>;
3966
3967  def : InstAlias<asm # "\t$Rt, [$Rn]",
3968                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
3969}
3970
3971//---
3972// Load/store pre-indexed
3973//---
3974
3975class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3976                          string asm, string cstr, list<dag> pat>
3977    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
3978  bits<5> Rt;
3979  bits<5> Rn;
3980  bits<9> offset;
3981  let Inst{31-30} = sz;
3982  let Inst{29-27} = 0b111;
3983  let Inst{26}    = V;
3984  let Inst{25-24} = 0;
3985  let Inst{23-22} = opc;
3986  let Inst{21}    = 0;
3987  let Inst{20-12} = offset;
3988  let Inst{11-10} = 0b11;
3989  let Inst{9-5}   = Rn;
3990  let Inst{4-0}   = Rt;
3991
3992  let DecoderMethod = "DecodeSignedLdStInstruction";
3993}
3994
3995let hasSideEffects = 0 in {
3996let mayStore = 0, mayLoad = 1 in
3997class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3998             string asm>
3999    : BaseLoadStorePreIdx<sz, V, opc,
4000                     (outs GPR64sp:$wback, regtype:$Rt),
4001                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4002                     "$Rn = $wback,@earlyclobber $wback", []>,
4003      Sched<[WriteAdr, WriteLD]>;
4004
4005let mayStore = 1, mayLoad = 0 in
4006class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4007                  string asm, SDPatternOperator storeop, ValueType Ty>
4008    : BaseLoadStorePreIdx<sz, V, opc,
4009                      (outs GPR64sp:$wback),
4010                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4011                      asm, "$Rn = $wback,@earlyclobber $wback",
4012      [(set GPR64sp:$wback,
4013            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4014      Sched<[WriteAdr, WriteST]>;
4015} // hasSideEffects = 0
4016
4017//---
4018// Load/store post-indexed
4019//---
4020
4021class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4022                          string asm, string cstr, list<dag> pat>
4023    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4024  bits<5> Rt;
4025  bits<5> Rn;
4026  bits<9> offset;
4027  let Inst{31-30} = sz;
4028  let Inst{29-27} = 0b111;
4029  let Inst{26}    = V;
4030  let Inst{25-24} = 0b00;
4031  let Inst{23-22} = opc;
4032  let Inst{21}    = 0b0;
4033  let Inst{20-12} = offset;
4034  let Inst{11-10} = 0b01;
4035  let Inst{9-5}   = Rn;
4036  let Inst{4-0}   = Rt;
4037
4038  let DecoderMethod = "DecodeSignedLdStInstruction";
4039}
4040
4041let hasSideEffects = 0 in {
4042let mayStore = 0, mayLoad = 1 in
4043class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4044             string asm>
4045    : BaseLoadStorePostIdx<sz, V, opc,
4046                      (outs GPR64sp:$wback, regtype:$Rt),
4047                      (ins GPR64sp:$Rn, simm9:$offset),
4048                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4049      Sched<[WriteAdr, WriteLD]>;
4050
4051let mayStore = 1, mayLoad = 0 in
4052class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4053                   string asm, SDPatternOperator storeop, ValueType Ty>
4054    : BaseLoadStorePostIdx<sz, V, opc,
4055                      (outs GPR64sp:$wback),
4056                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4057                       asm, "$Rn = $wback,@earlyclobber $wback",
4058      [(set GPR64sp:$wback,
4059            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4060    Sched<[WriteAdr, WriteST]>;
4061} // hasSideEffects = 0
4062
4063
4064//---
4065// Load/store pair
4066//---
4067
4068// (indexed, offset)
4069
4070class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4071                              string asm>
4072    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4073  bits<5> Rt;
4074  bits<5> Rt2;
4075  bits<5> Rn;
4076  bits<7> offset;
4077  let Inst{31-30} = opc;
4078  let Inst{29-27} = 0b101;
4079  let Inst{26}    = V;
4080  let Inst{25-23} = 0b010;
4081  let Inst{22}    = L;
4082  let Inst{21-15} = offset;
4083  let Inst{14-10} = Rt2;
4084  let Inst{9-5}   = Rn;
4085  let Inst{4-0}   = Rt;
4086
4087  let DecoderMethod = "DecodePairLdStInstruction";
4088}
4089
4090multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4091                          Operand indextype, string asm> {
4092  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4093  def i : BaseLoadStorePairOffset<opc, V, 1,
4094                                  (outs regtype:$Rt, regtype:$Rt2),
4095                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4096          Sched<[WriteLD, WriteLDHi]>;
4097
4098  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4099                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4100                                                  GPR64sp:$Rn, 0)>;
4101}
4102
4103
4104multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4105                           Operand indextype, string asm> {
4106  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4107  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4108                                  (ins regtype:$Rt, regtype:$Rt2,
4109                                       GPR64sp:$Rn, indextype:$offset),
4110                                  asm>,
4111          Sched<[WriteSTP]>;
4112
4113  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4114                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4115                                                  GPR64sp:$Rn, 0)>;
4116}
4117
4118// (pre-indexed)
4119class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4120                              string asm>
4121    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4122  bits<5> Rt;
4123  bits<5> Rt2;
4124  bits<5> Rn;
4125  bits<7> offset;
4126  let Inst{31-30} = opc;
4127  let Inst{29-27} = 0b101;
4128  let Inst{26}    = V;
4129  let Inst{25-23} = 0b011;
4130  let Inst{22}    = L;
4131  let Inst{21-15} = offset;
4132  let Inst{14-10} = Rt2;
4133  let Inst{9-5}   = Rn;
4134  let Inst{4-0}   = Rt;
4135
4136  let DecoderMethod = "DecodePairLdStInstruction";
4137}
4138
4139let hasSideEffects = 0 in {
4140let mayStore = 0, mayLoad = 1 in
4141class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4142                     Operand indextype, string asm>
4143    : BaseLoadStorePairPreIdx<opc, V, 1,
4144                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4145                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4146      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4147
4148let mayStore = 1, mayLoad = 0 in
4149class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4150                      Operand indextype, string asm>
4151    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4152                             (ins regtype:$Rt, regtype:$Rt2,
4153                                  GPR64sp:$Rn, indextype:$offset),
4154                             asm>,
4155      Sched<[WriteAdr, WriteSTP]>;
4156} // hasSideEffects = 0
4157
4158// (post-indexed)
4159
4160class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4161                              string asm>
4162    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4163  bits<5> Rt;
4164  bits<5> Rt2;
4165  bits<5> Rn;
4166  bits<7> offset;
4167  let Inst{31-30} = opc;
4168  let Inst{29-27} = 0b101;
4169  let Inst{26}    = V;
4170  let Inst{25-23} = 0b001;
4171  let Inst{22}    = L;
4172  let Inst{21-15} = offset;
4173  let Inst{14-10} = Rt2;
4174  let Inst{9-5}   = Rn;
4175  let Inst{4-0}   = Rt;
4176
4177  let DecoderMethod = "DecodePairLdStInstruction";
4178}
4179
4180let hasSideEffects = 0 in {
4181let mayStore = 0, mayLoad = 1 in
4182class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4183                      Operand idxtype, string asm>
4184    : BaseLoadStorePairPostIdx<opc, V, 1,
4185                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4186                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4187      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4188
4189let mayStore = 1, mayLoad = 0 in
4190class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4191                       Operand idxtype, string asm>
4192    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4193                             (ins regtype:$Rt, regtype:$Rt2,
4194                                  GPR64sp:$Rn, idxtype:$offset),
4195                             asm>,
4196      Sched<[WriteAdr, WriteSTP]>;
4197} // hasSideEffects = 0
4198
4199//  (no-allocate)
4200
4201class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4202                              string asm>
4203    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4204  bits<5> Rt;
4205  bits<5> Rt2;
4206  bits<5> Rn;
4207  bits<7> offset;
4208  let Inst{31-30} = opc;
4209  let Inst{29-27} = 0b101;
4210  let Inst{26}    = V;
4211  let Inst{25-23} = 0b000;
4212  let Inst{22}    = L;
4213  let Inst{21-15} = offset;
4214  let Inst{14-10} = Rt2;
4215  let Inst{9-5}   = Rn;
4216  let Inst{4-0}   = Rt;
4217
4218  let DecoderMethod = "DecodePairLdStInstruction";
4219}
4220
4221multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4222                           Operand indextype, string asm> {
4223  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4224  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4225                                   (outs regtype:$Rt, regtype:$Rt2),
4226                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4227          Sched<[WriteLD, WriteLDHi]>;
4228
4229
4230  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4231                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4232                                                  GPR64sp:$Rn, 0)>;
4233}
4234
4235multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4236                      Operand indextype, string asm> {
4237  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4238  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4239                                   (ins regtype:$Rt, regtype:$Rt2,
4240                                        GPR64sp:$Rn, indextype:$offset),
4241                                   asm>,
4242          Sched<[WriteSTP]>;
4243
4244  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4245                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4246                                                  GPR64sp:$Rn, 0)>;
4247}
4248
4249//---
4250// Load/store exclusive
4251//---
4252
4253// True exclusive operations write to and/or read from the system's exclusive
4254// monitors, which as far as a compiler is concerned can be modelled as a
4255// random shared memory address. Hence LoadExclusive mayStore.
4256//
4257// Since these instructions have the undefined register bits set to 1 in
4258// their canonical form, we need a post encoder method to set those bits
4259// to 1 when encoding these instructions. We do this using the
4260// fixLoadStoreExclusive function. This function has template parameters:
4261//
4262// fixLoadStoreExclusive<int hasRs, int hasRt2>
4263//
4264// hasRs indicates that the instruction uses the Rs field, so we won't set
4265// it to 1 (and the same for Rt2). We don't need template parameters for
4266// the other register fields since Rt and Rn are always used.
4267//
4268let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4269class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4270                             dag oops, dag iops, string asm, string operands>
4271    : I<oops, iops, asm, operands, "", []> {
4272  let Inst{31-30} = sz;
4273  let Inst{29-24} = 0b001000;
4274  let Inst{23}    = o2;
4275  let Inst{22}    = L;
4276  let Inst{21}    = o1;
4277  let Inst{15}    = o0;
4278
4279  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4280}
4281
4282// Neither Rs nor Rt2 operands.
4283class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4284                               dag oops, dag iops, string asm, string operands>
4285    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4286  bits<5> Rt;
4287  bits<5> Rn;
4288  let Inst{20-16} = 0b11111;
4289  let Unpredictable{20-16} = 0b11111;
4290  let Inst{14-10} = 0b11111;
4291  let Unpredictable{14-10} = 0b11111;
4292  let Inst{9-5} = Rn;
4293  let Inst{4-0} = Rt;
4294
4295  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4296}
4297
4298// Simple load acquires don't set the exclusive monitor
4299let mayLoad = 1, mayStore = 0 in
4300class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4301                  RegisterClass regtype, string asm>
4302    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4303                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4304      Sched<[WriteLD]>;
4305
4306class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4307                    RegisterClass regtype, string asm>
4308    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4309                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4310      Sched<[WriteLD]>;
4311
4312class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4313                       RegisterClass regtype, string asm>
4314    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4315                             (outs regtype:$Rt, regtype:$Rt2),
4316                             (ins GPR64sp0:$Rn), asm,
4317                             "\t$Rt, $Rt2, [$Rn]">,
4318      Sched<[WriteLD, WriteLDHi]> {
4319  bits<5> Rt;
4320  bits<5> Rt2;
4321  bits<5> Rn;
4322  let Inst{14-10} = Rt2;
4323  let Inst{9-5} = Rn;
4324  let Inst{4-0} = Rt;
4325
4326  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4327}
4328
4329// Simple store release operations do not check the exclusive monitor.
4330let mayLoad = 0, mayStore = 1 in
4331class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4332                   RegisterClass regtype, string asm>
4333    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4334                               (ins regtype:$Rt, GPR64sp0:$Rn),
4335                               asm, "\t$Rt, [$Rn]">,
4336      Sched<[WriteST]>;
4337
4338let mayLoad = 1, mayStore = 1 in
4339class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4340                     RegisterClass regtype, string asm>
4341    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4342                             (ins regtype:$Rt, GPR64sp0:$Rn),
4343                             asm, "\t$Ws, $Rt, [$Rn]">,
4344      Sched<[WriteSTX]> {
4345  bits<5> Ws;
4346  bits<5> Rt;
4347  bits<5> Rn;
4348  let Inst{20-16} = Ws;
4349  let Inst{9-5} = Rn;
4350  let Inst{4-0} = Rt;
4351
4352  let Constraints = "@earlyclobber $Ws";
4353  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4354}
4355
4356class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4357                         RegisterClass regtype, string asm>
4358    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4359                             (outs GPR32:$Ws),
4360                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4361                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4362      Sched<[WriteSTX]> {
4363  bits<5> Ws;
4364  bits<5> Rt;
4365  bits<5> Rt2;
4366  bits<5> Rn;
4367  let Inst{20-16} = Ws;
4368  let Inst{14-10} = Rt2;
4369  let Inst{9-5} = Rn;
4370  let Inst{4-0} = Rt;
4371
4372  let Constraints = "@earlyclobber $Ws";
4373}
4374
4375// Armv8.5-A Memory Tagging Extension
4376class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4377                 string asm_opnds, string cstr, dag oops, dag iops>
4378    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4379      Sched<[]> {
4380  bits<5> Rn;
4381
4382  let Inst{31-24} = 0b11011001;
4383  let Inst{23-22} = opc1;
4384  let Inst{21}    = 1;
4385  // Inst{20-12} defined by subclass
4386  let Inst{11-10} = opc2;
4387  let Inst{9-5}   = Rn;
4388  // Inst{4-0} defined by subclass
4389}
4390
4391class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4392                   dag oops, dag iops>
4393    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4394                  "", oops, iops> {
4395  bits<5> Rt;
4396
4397  let Inst{20-12} = 0b000000000;
4398  let Inst{4-0}   = Rt;
4399
4400  let mayLoad = Load;
4401}
4402
4403class MemTagLoad<string asm_insn, string asm_opnds>
4404    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4405                 (outs GPR64:$wback),
4406                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4407  bits<5> Rt;
4408  bits<9> offset;
4409
4410  let Inst{20-12} = offset;
4411  let Inst{4-0}   = Rt;
4412
4413  let mayLoad = 1;
4414}
4415
4416class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4417                     string asm_opnds, string cstr, dag oops, dag iops>
4418    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4419  bits<5> Rt;
4420  bits<9> offset;
4421
4422  let Inst{20-12} = offset;
4423  let Inst{4-0}   = Rt;
4424
4425  let mayStore = 1;
4426}
4427
4428multiclass MemTagStore<bits<2> opc1, string insn> {
4429  def Offset :
4430    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4431                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4432  def PreIndex :
4433    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4434                    "$Rn = $wback",
4435                    (outs GPR64sp:$wback),
4436                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4437  def PostIndex :
4438    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4439                    "$Rn = $wback",
4440                    (outs GPR64sp:$wback),
4441                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4442
4443  def : InstAlias<insn # "\t$Rt, [$Rn]",
4444                  (!cast<Instruction>(NAME # "Offset") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4445}
4446
4447//---
4448// Exception generation
4449//---
4450
4451let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4452class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm>
4453    : I<(outs), (ins i32_imm0_65535:$imm), asm, "\t$imm", "", []>,
4454      Sched<[WriteSys]> {
4455  bits<16> imm;
4456  let Inst{31-24} = 0b11010100;
4457  let Inst{23-21} = op1;
4458  let Inst{20-5}  = imm;
4459  let Inst{4-2}   = 0b000;
4460  let Inst{1-0}   = ll;
4461}
4462
4463//---
4464// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4465//--
4466let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4467class UDFType<bits<16> opc, string asm>
4468  : I<(outs), (ins uimm16:$imm),
4469       asm, "\t$imm", "", []>,
4470    Sched<[]> {
4471  bits<16> imm;
4472  let Inst{31-16} = opc;
4473  let Inst{15-0} = imm;
4474}
4475}
4476let Predicates = [HasFPARMv8] in {
4477
4478//---
4479// Floating point to integer conversion
4480//---
4481
4482class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4483                      RegisterClass srcType, RegisterClass dstType,
4484                      string asm, list<dag> pattern>
4485    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4486         asm, "\t$Rd, $Rn", "", pattern>,
4487      Sched<[WriteFCvt]> {
4488  bits<5> Rd;
4489  bits<5> Rn;
4490  let Inst{30-29} = 0b00;
4491  let Inst{28-24} = 0b11110;
4492  let Inst{23-22} = type;
4493  let Inst{21}    = 1;
4494  let Inst{20-19} = rmode;
4495  let Inst{18-16} = opcode;
4496  let Inst{15-10} = 0;
4497  let Inst{9-5}   = Rn;
4498  let Inst{4-0}   = Rd;
4499}
4500
4501let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4502class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4503                      RegisterClass srcType, RegisterClass dstType,
4504                      Operand immType, string asm, list<dag> pattern>
4505    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4506         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4507      Sched<[WriteFCvt]> {
4508  bits<5> Rd;
4509  bits<5> Rn;
4510  bits<6> scale;
4511  let Inst{30-29} = 0b00;
4512  let Inst{28-24} = 0b11110;
4513  let Inst{23-22} = type;
4514  let Inst{21}    = 0;
4515  let Inst{20-19} = rmode;
4516  let Inst{18-16} = opcode;
4517  let Inst{15-10} = scale;
4518  let Inst{9-5}   = Rn;
4519  let Inst{4-0}   = Rd;
4520}
4521
4522multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4523           SDPatternOperator OpN> {
4524  // Unscaled half-precision to 32-bit
4525  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4526                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4527    let Inst{31} = 0; // 32-bit GPR flag
4528    let Predicates = [HasFullFP16];
4529  }
4530
4531  // Unscaled half-precision to 64-bit
4532  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4533                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4534    let Inst{31} = 1; // 64-bit GPR flag
4535    let Predicates = [HasFullFP16];
4536  }
4537
4538  // Unscaled single-precision to 32-bit
4539  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4540                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4541    let Inst{31} = 0; // 32-bit GPR flag
4542  }
4543
4544  // Unscaled single-precision to 64-bit
4545  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4546                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4547    let Inst{31} = 1; // 64-bit GPR flag
4548  }
4549
4550  // Unscaled double-precision to 32-bit
4551  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4552                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4553    let Inst{31} = 0; // 32-bit GPR flag
4554  }
4555
4556  // Unscaled double-precision to 64-bit
4557  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4558                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4559    let Inst{31} = 1; // 64-bit GPR flag
4560  }
4561}
4562
4563multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4564                             SDPatternOperator OpN> {
4565  // Scaled half-precision to 32-bit
4566  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4567                              fixedpoint_f16_i32, asm,
4568              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4569                                          fixedpoint_f16_i32:$scale)))]> {
4570    let Inst{31} = 0; // 32-bit GPR flag
4571    let scale{5} = 1;
4572    let Predicates = [HasFullFP16];
4573  }
4574
4575  // Scaled half-precision to 64-bit
4576  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
4577                              fixedpoint_f16_i64, asm,
4578              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
4579                                          fixedpoint_f16_i64:$scale)))]> {
4580    let Inst{31} = 1; // 64-bit GPR flag
4581    let Predicates = [HasFullFP16];
4582  }
4583
4584  // Scaled single-precision to 32-bit
4585  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
4586                              fixedpoint_f32_i32, asm,
4587              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
4588                                          fixedpoint_f32_i32:$scale)))]> {
4589    let Inst{31} = 0; // 32-bit GPR flag
4590    let scale{5} = 1;
4591  }
4592
4593  // Scaled single-precision to 64-bit
4594  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
4595                              fixedpoint_f32_i64, asm,
4596              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
4597                                          fixedpoint_f32_i64:$scale)))]> {
4598    let Inst{31} = 1; // 64-bit GPR flag
4599  }
4600
4601  // Scaled double-precision to 32-bit
4602  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
4603                              fixedpoint_f64_i32, asm,
4604              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
4605                                          fixedpoint_f64_i32:$scale)))]> {
4606    let Inst{31} = 0; // 32-bit GPR flag
4607    let scale{5} = 1;
4608  }
4609
4610  // Scaled double-precision to 64-bit
4611  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
4612                              fixedpoint_f64_i64, asm,
4613              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
4614                                          fixedpoint_f64_i64:$scale)))]> {
4615    let Inst{31} = 1; // 64-bit GPR flag
4616  }
4617}
4618
4619//---
4620// Integer to floating point conversion
4621//---
4622
4623let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
4624class BaseIntegerToFP<bit isUnsigned,
4625                      RegisterClass srcType, RegisterClass dstType,
4626                      Operand immType, string asm, list<dag> pattern>
4627    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4628         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4629      Sched<[WriteFCvt]> {
4630  bits<5> Rd;
4631  bits<5> Rn;
4632  bits<6> scale;
4633  let Inst{30-24} = 0b0011110;
4634  let Inst{21-17} = 0b00001;
4635  let Inst{16}    = isUnsigned;
4636  let Inst{15-10} = scale;
4637  let Inst{9-5}   = Rn;
4638  let Inst{4-0}   = Rd;
4639}
4640
4641class BaseIntegerToFPUnscaled<bit isUnsigned,
4642                      RegisterClass srcType, RegisterClass dstType,
4643                      ValueType dvt, string asm, SDPatternOperator node>
4644    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4645         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
4646      Sched<[WriteFCvt]> {
4647  bits<5> Rd;
4648  bits<5> Rn;
4649  bits<6> scale;
4650  let Inst{30-24} = 0b0011110;
4651  let Inst{21-17} = 0b10001;
4652  let Inst{16}    = isUnsigned;
4653  let Inst{15-10} = 0b000000;
4654  let Inst{9-5}   = Rn;
4655  let Inst{4-0}   = Rd;
4656}
4657
4658multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
4659  // Unscaled
4660  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
4661    let Inst{31} = 0; // 32-bit GPR flag
4662    let Inst{23-22} = 0b11; // 16-bit FPR flag
4663    let Predicates = [HasFullFP16];
4664  }
4665
4666  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
4667    let Inst{31} = 0; // 32-bit GPR flag
4668    let Inst{23-22} = 0b00; // 32-bit FPR flag
4669  }
4670
4671  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
4672    let Inst{31} = 0; // 32-bit GPR flag
4673    let Inst{23-22} = 0b01; // 64-bit FPR flag
4674  }
4675
4676  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
4677    let Inst{31} = 1; // 64-bit GPR flag
4678    let Inst{23-22} = 0b11; // 16-bit FPR flag
4679    let Predicates = [HasFullFP16];
4680  }
4681
4682  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
4683    let Inst{31} = 1; // 64-bit GPR flag
4684    let Inst{23-22} = 0b00; // 32-bit FPR flag
4685  }
4686
4687  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
4688    let Inst{31} = 1; // 64-bit GPR flag
4689    let Inst{23-22} = 0b01; // 64-bit FPR flag
4690  }
4691
4692  // Scaled
4693  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_f16_i32, asm,
4694                             [(set (f16 FPR16:$Rd),
4695                                   (fdiv (node GPR32:$Rn),
4696                                         fixedpoint_f16_i32:$scale))]> {
4697    let Inst{31} = 0; // 32-bit GPR flag
4698    let Inst{23-22} = 0b11; // 16-bit FPR flag
4699    let scale{5} = 1;
4700    let Predicates = [HasFullFP16];
4701  }
4702
4703  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_f32_i32, asm,
4704                             [(set FPR32:$Rd,
4705                                   (fdiv (node GPR32:$Rn),
4706                                         fixedpoint_f32_i32:$scale))]> {
4707    let Inst{31} = 0; // 32-bit GPR flag
4708    let Inst{23-22} = 0b00; // 32-bit FPR flag
4709    let scale{5} = 1;
4710  }
4711
4712  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_f64_i32, asm,
4713                             [(set FPR64:$Rd,
4714                                   (fdiv (node GPR32:$Rn),
4715                                         fixedpoint_f64_i32:$scale))]> {
4716    let Inst{31} = 0; // 32-bit GPR flag
4717    let Inst{23-22} = 0b01; // 64-bit FPR flag
4718    let scale{5} = 1;
4719  }
4720
4721  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_f16_i64, asm,
4722                             [(set (f16 FPR16:$Rd),
4723                                   (fdiv (node GPR64:$Rn),
4724                                         fixedpoint_f16_i64:$scale))]> {
4725    let Inst{31} = 1; // 64-bit GPR flag
4726    let Inst{23-22} = 0b11; // 16-bit FPR flag
4727    let Predicates = [HasFullFP16];
4728  }
4729
4730  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_f32_i64, asm,
4731                             [(set FPR32:$Rd,
4732                                   (fdiv (node GPR64:$Rn),
4733                                         fixedpoint_f32_i64:$scale))]> {
4734    let Inst{31} = 1; // 64-bit GPR flag
4735    let Inst{23-22} = 0b00; // 32-bit FPR flag
4736  }
4737
4738  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_f64_i64, asm,
4739                             [(set FPR64:$Rd,
4740                                   (fdiv (node GPR64:$Rn),
4741                                         fixedpoint_f64_i64:$scale))]> {
4742    let Inst{31} = 1; // 64-bit GPR flag
4743    let Inst{23-22} = 0b01; // 64-bit FPR flag
4744  }
4745}
4746
4747//---
4748// Unscaled integer <-> floating point conversion (i.e. FMOV)
4749//---
4750
4751let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4752class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
4753                      RegisterClass srcType, RegisterClass dstType,
4754                      string asm>
4755    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
4756        // We use COPY_TO_REGCLASS for these bitconvert operations.
4757        // copyPhysReg() expands the resultant COPY instructions after
4758        // regalloc is done. This gives greater freedom for the allocator
4759        // and related passes (coalescing, copy propagation, et. al.) to
4760        // be more effective.
4761        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
4762      Sched<[WriteFCopy]> {
4763  bits<5> Rd;
4764  bits<5> Rn;
4765  let Inst{30-24} = 0b0011110;
4766  let Inst{21}    = 1;
4767  let Inst{20-19} = rmode;
4768  let Inst{18-16} = opcode;
4769  let Inst{15-10} = 0b000000;
4770  let Inst{9-5}   = Rn;
4771  let Inst{4-0}   = Rd;
4772}
4773
4774let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4775class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
4776                     RegisterClass srcType, RegisterOperand dstType, string asm,
4777                     string kind>
4778    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4779        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
4780      Sched<[WriteFCopy]> {
4781  bits<5> Rd;
4782  bits<5> Rn;
4783  let Inst{30-23} = 0b00111101;
4784  let Inst{21}    = 1;
4785  let Inst{20-19} = rmode;
4786  let Inst{18-16} = opcode;
4787  let Inst{15-10} = 0b000000;
4788  let Inst{9-5}   = Rn;
4789  let Inst{4-0}   = Rd;
4790
4791  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4792}
4793
4794let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4795class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
4796                     RegisterOperand srcType, RegisterClass dstType, string asm,
4797                     string kind>
4798    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
4799        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
4800      Sched<[WriteFCopy]> {
4801  bits<5> Rd;
4802  bits<5> Rn;
4803  let Inst{30-23} = 0b00111101;
4804  let Inst{21}    = 1;
4805  let Inst{20-19} = rmode;
4806  let Inst{18-16} = opcode;
4807  let Inst{15-10} = 0b000000;
4808  let Inst{9-5}   = Rn;
4809  let Inst{4-0}   = Rd;
4810
4811  let DecoderMethod =  "DecodeFMOVLaneInstruction";
4812}
4813
4814
4815multiclass UnscaledConversion<string asm> {
4816  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
4817    let Inst{31} = 0; // 32-bit GPR flag
4818    let Inst{23-22} = 0b11; // 16-bit FPR flag
4819    let Predicates = [HasFullFP16];
4820  }
4821
4822  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
4823    let Inst{31} = 1; // 64-bit GPR flag
4824    let Inst{23-22} = 0b11; // 16-bit FPR flag
4825    let Predicates = [HasFullFP16];
4826  }
4827
4828  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
4829    let Inst{31} = 0; // 32-bit GPR flag
4830    let Inst{23-22} = 0b00; // 32-bit FPR flag
4831  }
4832
4833  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
4834    let Inst{31} = 1; // 64-bit GPR flag
4835    let Inst{23-22} = 0b01; // 64-bit FPR flag
4836  }
4837
4838  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
4839    let Inst{31} = 0; // 32-bit GPR flag
4840    let Inst{23-22} = 0b11; // 16-bit FPR flag
4841    let Predicates = [HasFullFP16];
4842  }
4843
4844  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
4845    let Inst{31} = 1; // 64-bit GPR flag
4846    let Inst{23-22} = 0b11; // 16-bit FPR flag
4847    let Predicates = [HasFullFP16];
4848  }
4849
4850  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
4851    let Inst{31} = 0; // 32-bit GPR flag
4852    let Inst{23-22} = 0b00; // 32-bit FPR flag
4853  }
4854
4855  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
4856    let Inst{31} = 1; // 64-bit GPR flag
4857    let Inst{23-22} = 0b01; // 64-bit FPR flag
4858  }
4859
4860  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
4861                                             asm, ".d"> {
4862    let Inst{31} = 1;
4863    let Inst{22} = 0;
4864  }
4865
4866  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
4867                                               asm, ".d"> {
4868    let Inst{31} = 1;
4869    let Inst{22} = 0;
4870  }
4871}
4872
4873//---
4874// Floating point conversion
4875//---
4876
4877class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
4878                       RegisterClass srcType, string asm, list<dag> pattern>
4879    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
4880      Sched<[WriteFCvt]> {
4881  bits<5> Rd;
4882  bits<5> Rn;
4883  let Inst{31-24} = 0b00011110;
4884  let Inst{23-22} = type;
4885  let Inst{21-17} = 0b10001;
4886  let Inst{16-15} = opcode;
4887  let Inst{14-10} = 0b10000;
4888  let Inst{9-5}   = Rn;
4889  let Inst{4-0}   = Rd;
4890}
4891
4892multiclass FPConversion<string asm> {
4893  // Double-precision to Half-precision
4894  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
4895                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
4896
4897  // Double-precision to Single-precision
4898  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
4899                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
4900
4901  // Half-precision to Double-precision
4902  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
4903                             [(set FPR64:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4904
4905  // Half-precision to Single-precision
4906  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
4907                             [(set FPR32:$Rd, (fpextend (f16 FPR16:$Rn)))]>;
4908
4909  // Single-precision to Double-precision
4910  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
4911                             [(set FPR64:$Rd, (fpextend FPR32:$Rn))]>;
4912
4913  // Single-precision to Half-precision
4914  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
4915                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
4916}
4917
4918//---
4919// Single operand floating point data processing
4920//---
4921
4922let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4923class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
4924                              ValueType vt, string asm, SDPatternOperator node>
4925    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
4926         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
4927      Sched<[WriteF]> {
4928  bits<5> Rd;
4929  bits<5> Rn;
4930  let Inst{31-24} = 0b00011110;
4931  let Inst{21}    = 0b1;
4932  let Inst{20-15} = opcode;
4933  let Inst{14-10} = 0b10000;
4934  let Inst{9-5}   = Rn;
4935  let Inst{4-0}   = Rd;
4936}
4937
4938multiclass SingleOperandFPData<bits<4> opcode, string asm,
4939                               SDPatternOperator node = null_frag> {
4940
4941  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
4942    let Inst{23-22} = 0b11; // 16-bit size flag
4943    let Predicates = [HasFullFP16];
4944  }
4945
4946  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
4947    let Inst{23-22} = 0b00; // 32-bit size flag
4948  }
4949
4950  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
4951    let Inst{23-22} = 0b01; // 64-bit size flag
4952  }
4953}
4954
4955multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
4956                  SDPatternOperator node = null_frag>{
4957
4958  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
4959    let Inst{23-22} = 0b00; // 32-bit registers
4960  }
4961
4962  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
4963    let Inst{23-22} = 0b01; // 64-bit registers
4964  }
4965}
4966
4967// FRInt[32|64][Z|N] instructions
4968multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
4969      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
4970
4971//---
4972// Two operand floating point data processing
4973//---
4974
4975let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
4976class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
4977                           string asm, list<dag> pat>
4978    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
4979         asm, "\t$Rd, $Rn, $Rm", "", pat>,
4980      Sched<[WriteF]> {
4981  bits<5> Rd;
4982  bits<5> Rn;
4983  bits<5> Rm;
4984  let Inst{31-24} = 0b00011110;
4985  let Inst{21}    = 1;
4986  let Inst{20-16} = Rm;
4987  let Inst{15-12} = opcode;
4988  let Inst{11-10} = 0b10;
4989  let Inst{9-5}   = Rn;
4990  let Inst{4-0}   = Rd;
4991}
4992
4993multiclass TwoOperandFPData<bits<4> opcode, string asm,
4994                            SDPatternOperator node = null_frag> {
4995  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
4996                         [(set (f16 FPR16:$Rd),
4997                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
4998    let Inst{23-22} = 0b11; // 16-bit size flag
4999    let Predicates = [HasFullFP16];
5000  }
5001
5002  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5003                         [(set (f32 FPR32:$Rd),
5004                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5005    let Inst{23-22} = 0b00; // 32-bit size flag
5006  }
5007
5008  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5009                         [(set (f64 FPR64:$Rd),
5010                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5011    let Inst{23-22} = 0b01; // 64-bit size flag
5012  }
5013}
5014
5015multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm, SDNode node> {
5016  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5017                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5018    let Inst{23-22} = 0b11; // 16-bit size flag
5019    let Predicates = [HasFullFP16];
5020  }
5021
5022  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5023                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5024    let Inst{23-22} = 0b00; // 32-bit size flag
5025  }
5026
5027  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5028                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5029    let Inst{23-22} = 0b01; // 64-bit size flag
5030  }
5031}
5032
5033
5034//---
5035// Three operand floating point data processing
5036//---
5037
5038class BaseThreeOperandFPData<bit isNegated, bit isSub,
5039                             RegisterClass regtype, string asm, list<dag> pat>
5040    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5041         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5042      Sched<[WriteFMul]> {
5043  bits<5> Rd;
5044  bits<5> Rn;
5045  bits<5> Rm;
5046  bits<5> Ra;
5047  let Inst{31-24} = 0b00011111;
5048  let Inst{21}    = isNegated;
5049  let Inst{20-16} = Rm;
5050  let Inst{15}    = isSub;
5051  let Inst{14-10} = Ra;
5052  let Inst{9-5}   = Rn;
5053  let Inst{4-0}   = Rd;
5054}
5055
5056multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5057                              SDPatternOperator node> {
5058  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5059            [(set (f16 FPR16:$Rd),
5060                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5061    let Inst{23-22} = 0b11; // 16-bit size flag
5062    let Predicates = [HasFullFP16];
5063  }
5064
5065  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5066            [(set FPR32:$Rd,
5067                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5068    let Inst{23-22} = 0b00; // 32-bit size flag
5069  }
5070
5071  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5072            [(set FPR64:$Rd,
5073                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5074    let Inst{23-22} = 0b01; // 64-bit size flag
5075  }
5076}
5077
5078//---
5079// Floating point data comparisons
5080//---
5081
5082let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5083class BaseOneOperandFPComparison<bit signalAllNans,
5084                                 RegisterClass regtype, string asm,
5085                                 list<dag> pat>
5086    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5087      Sched<[WriteFCmp]> {
5088  bits<5> Rn;
5089  let Inst{31-24} = 0b00011110;
5090  let Inst{21}    = 1;
5091
5092  let Inst{15-10} = 0b001000;
5093  let Inst{9-5}   = Rn;
5094  let Inst{4}     = signalAllNans;
5095  let Inst{3-0}   = 0b1000;
5096
5097  // Rm should be 0b00000 canonically, but we need to accept any value.
5098  let PostEncoderMethod = "fixOneOperandFPComparison";
5099}
5100
5101let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5102class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5103                                string asm, list<dag> pat>
5104    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5105      Sched<[WriteFCmp]> {
5106  bits<5> Rm;
5107  bits<5> Rn;
5108  let Inst{31-24} = 0b00011110;
5109  let Inst{21}    = 1;
5110  let Inst{20-16} = Rm;
5111  let Inst{15-10} = 0b001000;
5112  let Inst{9-5}   = Rn;
5113  let Inst{4}     = signalAllNans;
5114  let Inst{3-0}   = 0b0000;
5115}
5116
5117multiclass FPComparison<bit signalAllNans, string asm,
5118                        SDPatternOperator OpNode = null_frag> {
5119  let Defs = [NZCV] in {
5120  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5121      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5122    let Inst{23-22} = 0b11;
5123    let Predicates = [HasFullFP16];
5124  }
5125
5126  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5127      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5128    let Inst{23-22} = 0b11;
5129    let Predicates = [HasFullFP16];
5130  }
5131
5132  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5133      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5134    let Inst{23-22} = 0b00;
5135  }
5136
5137  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5138      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5139    let Inst{23-22} = 0b00;
5140  }
5141
5142  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5143      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5144    let Inst{23-22} = 0b01;
5145  }
5146
5147  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5148      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5149    let Inst{23-22} = 0b01;
5150  }
5151  } // Defs = [NZCV]
5152}
5153
5154//---
5155// Floating point conditional comparisons
5156//---
5157
5158let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5159class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5160                           string mnemonic, list<dag> pat>
5161    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5162         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5163      Sched<[WriteFCmp]> {
5164  let Uses = [NZCV];
5165  let Defs = [NZCV];
5166
5167  bits<5> Rn;
5168  bits<5> Rm;
5169  bits<4> nzcv;
5170  bits<4> cond;
5171
5172  let Inst{31-24} = 0b00011110;
5173  let Inst{21}    = 1;
5174  let Inst{20-16} = Rm;
5175  let Inst{15-12} = cond;
5176  let Inst{11-10} = 0b01;
5177  let Inst{9-5}   = Rn;
5178  let Inst{4}     = signalAllNans;
5179  let Inst{3-0}   = nzcv;
5180}
5181
5182multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5183                            SDPatternOperator OpNode = null_frag> {
5184  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5185      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5186                          (i32 imm:$cond), NZCV))]> {
5187    let Inst{23-22} = 0b11;
5188    let Predicates = [HasFullFP16];
5189  }
5190
5191  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5192      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5193                          (i32 imm:$cond), NZCV))]> {
5194    let Inst{23-22} = 0b00;
5195  }
5196
5197  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5198      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5199                          (i32 imm:$cond), NZCV))]> {
5200    let Inst{23-22} = 0b01;
5201  }
5202}
5203
5204//---
5205// Floating point conditional select
5206//---
5207
5208class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5209    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5210         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5211         [(set regtype:$Rd,
5212               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5213                          (i32 imm:$cond), NZCV))]>,
5214      Sched<[WriteF]> {
5215  bits<5> Rd;
5216  bits<5> Rn;
5217  bits<5> Rm;
5218  bits<4> cond;
5219
5220  let Inst{31-24} = 0b00011110;
5221  let Inst{21}    = 1;
5222  let Inst{20-16} = Rm;
5223  let Inst{15-12} = cond;
5224  let Inst{11-10} = 0b11;
5225  let Inst{9-5}   = Rn;
5226  let Inst{4-0}   = Rd;
5227}
5228
5229multiclass FPCondSelect<string asm> {
5230  let Uses = [NZCV] in {
5231  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5232    let Inst{23-22} = 0b11;
5233    let Predicates = [HasFullFP16];
5234  }
5235
5236  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5237    let Inst{23-22} = 0b00;
5238  }
5239
5240  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5241    let Inst{23-22} = 0b01;
5242  }
5243  } // Uses = [NZCV]
5244}
5245
5246//---
5247// Floating move immediate
5248//---
5249
5250class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5251  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5252      [(set regtype:$Rd, fpimmtype:$imm)]>,
5253    Sched<[WriteFImm]> {
5254  bits<5> Rd;
5255  bits<8> imm;
5256  let Inst{31-24} = 0b00011110;
5257  let Inst{21}    = 1;
5258  let Inst{20-13} = imm;
5259  let Inst{12-5}  = 0b10000000;
5260  let Inst{4-0}   = Rd;
5261}
5262
5263multiclass FPMoveImmediate<string asm> {
5264  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5265    let Inst{23-22} = 0b11;
5266    let Predicates = [HasFullFP16];
5267  }
5268
5269  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5270    let Inst{23-22} = 0b00;
5271  }
5272
5273  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5274    let Inst{23-22} = 0b01;
5275  }
5276}
5277} // end of 'let Predicates = [HasFPARMv8]'
5278
5279//----------------------------------------------------------------------------
5280// AdvSIMD
5281//----------------------------------------------------------------------------
5282
5283let Predicates = [HasNEON] in {
5284
5285//----------------------------------------------------------------------------
5286// AdvSIMD three register vector instructions
5287//----------------------------------------------------------------------------
5288
5289let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5290class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5291                        RegisterOperand regtype, string asm, string kind,
5292                        list<dag> pattern>
5293  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5294      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5295      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5296    Sched<[WriteV]> {
5297  bits<5> Rd;
5298  bits<5> Rn;
5299  bits<5> Rm;
5300  let Inst{31}    = 0;
5301  let Inst{30}    = Q;
5302  let Inst{29}    = U;
5303  let Inst{28-24} = 0b01110;
5304  let Inst{23-21} = size;
5305  let Inst{20-16} = Rm;
5306  let Inst{15-11} = opcode;
5307  let Inst{10}    = 1;
5308  let Inst{9-5}   = Rn;
5309  let Inst{4-0}   = Rd;
5310}
5311
5312let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5313class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5314                        RegisterOperand regtype, string asm, string kind,
5315                        list<dag> pattern>
5316  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5317      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5318      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5319    Sched<[WriteV]> {
5320  bits<5> Rd;
5321  bits<5> Rn;
5322  bits<5> Rm;
5323  let Inst{31}    = 0;
5324  let Inst{30}    = Q;
5325  let Inst{29}    = U;
5326  let Inst{28-24} = 0b01110;
5327  let Inst{23-21} = size;
5328  let Inst{20-16} = Rm;
5329  let Inst{15-11} = opcode;
5330  let Inst{10}    = 1;
5331  let Inst{9-5}   = Rn;
5332  let Inst{4-0}   = Rd;
5333}
5334
5335let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5336class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5337  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5338    Sched<[WriteV]>;
5339
5340multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5341  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5342             [(set (v8i8 V64:$dst),
5343                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5344  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5345             [(set (v16i8 V128:$dst),
5346                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5347                           (v16i8 V128:$Rm)))]>;
5348
5349  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5350                           (v4i16 V64:$RHS))),
5351          (!cast<Instruction>(NAME#"v8i8")
5352            V64:$LHS, V64:$MHS, V64:$RHS)>;
5353  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5354                           (v2i32 V64:$RHS))),
5355          (!cast<Instruction>(NAME#"v8i8")
5356            V64:$LHS, V64:$MHS, V64:$RHS)>;
5357  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5358                           (v1i64 V64:$RHS))),
5359          (!cast<Instruction>(NAME#"v8i8")
5360            V64:$LHS, V64:$MHS, V64:$RHS)>;
5361
5362  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5363                           (v8i16 V128:$RHS))),
5364      (!cast<Instruction>(NAME#"v16i8")
5365        V128:$LHS, V128:$MHS, V128:$RHS)>;
5366  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5367                           (v4i32 V128:$RHS))),
5368      (!cast<Instruction>(NAME#"v16i8")
5369        V128:$LHS, V128:$MHS, V128:$RHS)>;
5370  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5371                           (v2i64 V128:$RHS))),
5372      (!cast<Instruction>(NAME#"v16i8")
5373        V128:$LHS, V128:$MHS, V128:$RHS)>;
5374}
5375
5376// All operand sizes distinguished in the encoding.
5377multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5378                               SDPatternOperator OpNode> {
5379  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5380                                      asm, ".8b",
5381         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5382  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5383                                      asm, ".16b",
5384         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5385  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5386                                      asm, ".4h",
5387         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5388  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5389                                      asm, ".8h",
5390         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5391  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5392                                      asm, ".2s",
5393         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5394  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5395                                      asm, ".4s",
5396         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5397  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5398                                      asm, ".2d",
5399         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5400}
5401
5402multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5403  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5404          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5405  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5406          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5407  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5408          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5409
5410  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5411          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5412  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5413          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5414  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5415          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5416  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5417          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5418}
5419
5420// As above, but D sized elements unsupported.
5421multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5422                                  SDPatternOperator OpNode> {
5423  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5424                                      asm, ".8b",
5425        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5426  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5427                                      asm, ".16b",
5428        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5429  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5430                                      asm, ".4h",
5431        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5432  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5433                                      asm, ".8h",
5434        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5435  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5436                                      asm, ".2s",
5437        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5438  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5439                                      asm, ".4s",
5440        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5441}
5442
5443multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5444                                  SDPatternOperator OpNode> {
5445  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5446                                      asm, ".8b",
5447      [(set (v8i8 V64:$dst),
5448            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5449  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5450                                      asm, ".16b",
5451      [(set (v16i8 V128:$dst),
5452            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5453  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5454                                      asm, ".4h",
5455      [(set (v4i16 V64:$dst),
5456            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5457  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5458                                      asm, ".8h",
5459      [(set (v8i16 V128:$dst),
5460            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5461  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5462                                      asm, ".2s",
5463      [(set (v2i32 V64:$dst),
5464            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5465  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5466                                      asm, ".4s",
5467      [(set (v4i32 V128:$dst),
5468            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5469}
5470
5471// As above, but only B sized elements supported.
5472multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5473                                SDPatternOperator OpNode> {
5474  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5475                                      asm, ".8b",
5476    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5477  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5478                                      asm, ".16b",
5479    [(set (v16i8 V128:$Rd),
5480          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5481}
5482
5483// As above, but only floating point elements supported.
5484multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5485                                 string asm, SDPatternOperator OpNode> {
5486  let Predicates = [HasNEON, HasFullFP16] in {
5487  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5488                                      asm, ".4h",
5489        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5490  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5491                                      asm, ".8h",
5492        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5493  } // Predicates = [HasNEON, HasFullFP16]
5494  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5495                                      asm, ".2s",
5496        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5497  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5498                                      asm, ".4s",
5499        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5500  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5501                                      asm, ".2d",
5502        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5503}
5504
5505multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5506                                    string asm,
5507                                    SDPatternOperator OpNode> {
5508  let Predicates = [HasNEON, HasFullFP16] in {
5509  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5510                                      asm, ".4h",
5511        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5512  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5513                                      asm, ".8h",
5514        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5515  } // Predicates = [HasNEON, HasFullFP16]
5516  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5517                                      asm, ".2s",
5518        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5519  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5520                                      asm, ".4s",
5521        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5522  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5523                                      asm, ".2d",
5524        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5525}
5526
5527multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
5528                                 string asm, SDPatternOperator OpNode> {
5529  let Predicates = [HasNEON, HasFullFP16] in {
5530  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
5531                                      asm, ".4h",
5532     [(set (v4f16 V64:$dst),
5533           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5534  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
5535                                      asm, ".8h",
5536     [(set (v8f16 V128:$dst),
5537           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5538  } // Predicates = [HasNEON, HasFullFP16]
5539  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
5540                                      asm, ".2s",
5541     [(set (v2f32 V64:$dst),
5542           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5543  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
5544                                      asm, ".4s",
5545     [(set (v4f32 V128:$dst),
5546           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5547  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
5548                                      asm, ".2d",
5549     [(set (v2f64 V128:$dst),
5550           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5551}
5552
5553// As above, but D and B sized elements unsupported.
5554multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
5555                                SDPatternOperator OpNode> {
5556  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5557                                      asm, ".4h",
5558        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5559  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5560                                      asm, ".8h",
5561        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5562  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5563                                      asm, ".2s",
5564        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5565  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5566                                      asm, ".4s",
5567        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5568}
5569
5570// Logical three vector ops share opcode bits, and only use B sized elements.
5571multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
5572                                  SDPatternOperator OpNode = null_frag> {
5573  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
5574                                     asm, ".8b",
5575                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
5576  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
5577                                     asm, ".16b",
5578                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
5579
5580  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5581          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5582  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5583          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5584  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
5585          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
5586
5587  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5588      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5589  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5590      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5591  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5592      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
5593}
5594
5595multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
5596                                  string asm, SDPatternOperator OpNode = null_frag> {
5597  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
5598                                     asm, ".8b",
5599             [(set (v8i8 V64:$dst),
5600                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5601  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
5602                                     asm, ".16b",
5603             [(set (v16i8 V128:$dst),
5604                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5605                           (v16i8 V128:$Rm)))]>;
5606
5607  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5608                           (v4i16 V64:$RHS))),
5609          (!cast<Instruction>(NAME#"v8i8")
5610            V64:$LHS, V64:$MHS, V64:$RHS)>;
5611  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5612                           (v2i32 V64:$RHS))),
5613          (!cast<Instruction>(NAME#"v8i8")
5614            V64:$LHS, V64:$MHS, V64:$RHS)>;
5615  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5616                           (v1i64 V64:$RHS))),
5617          (!cast<Instruction>(NAME#"v8i8")
5618            V64:$LHS, V64:$MHS, V64:$RHS)>;
5619
5620  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5621                           (v8i16 V128:$RHS))),
5622      (!cast<Instruction>(NAME#"v16i8")
5623        V128:$LHS, V128:$MHS, V128:$RHS)>;
5624  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5625                           (v4i32 V128:$RHS))),
5626      (!cast<Instruction>(NAME#"v16i8")
5627        V128:$LHS, V128:$MHS, V128:$RHS)>;
5628  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5629                           (v2i64 V128:$RHS))),
5630      (!cast<Instruction>(NAME#"v16i8")
5631        V128:$LHS, V128:$MHS, V128:$RHS)>;
5632}
5633
5634// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
5635// bytes from S-sized elements.
5636class BaseSIMDThreeSameVectorDot<bit Q, bit U, bit Mixed, string asm, string kind1,
5637                                 string kind2, RegisterOperand RegType,
5638                                 ValueType AccumType, ValueType InputType,
5639                                 SDPatternOperator OpNode> :
5640        BaseSIMDThreeSameVectorTied<Q, U, 0b100, {0b1001, Mixed}, RegType, asm, kind1,
5641        [(set (AccumType RegType:$dst),
5642              (OpNode (AccumType RegType:$Rd),
5643                      (InputType RegType:$Rn),
5644                      (InputType RegType:$Rm)))]> {
5645  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5646}
5647
5648multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
5649  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, Mixed, asm, ".2s", ".8b", V64,
5650                                         v2i32, v8i8, OpNode>;
5651  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, Mixed, asm, ".4s", ".16b", V128,
5652                                         v4i32, v16i8, OpNode>;
5653}
5654
5655// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
5656// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
5657// 8H to 4S, when Q=1).
5658class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
5659                                 string kind2, RegisterOperand RegType,
5660                                 ValueType AccumType, ValueType InputType,
5661                                 SDPatternOperator OpNode> :
5662        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
5663		[(set (AccumType RegType:$dst),
5664              (OpNode (AccumType RegType:$Rd),
5665                      (InputType RegType:$Rn),
5666                      (InputType RegType:$Rm)))]> {
5667  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
5668  let Inst{13} = b13;
5669}
5670
5671multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
5672                                  SDPatternOperator OpNode> {
5673  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
5674                                         v2f32, v4f16, OpNode>;
5675  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
5676                                         v4f32, v8f16, OpNode>;
5677}
5678
5679
5680//----------------------------------------------------------------------------
5681// AdvSIMD two register vector instructions.
5682//----------------------------------------------------------------------------
5683
5684let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5685class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
5686                            bits<2> size2, RegisterOperand regtype, string asm,
5687                            string dstkind, string srckind, list<dag> pattern>
5688  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
5689      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5690      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
5691    Sched<[WriteV]> {
5692  bits<5> Rd;
5693  bits<5> Rn;
5694  let Inst{31}    = 0;
5695  let Inst{30}    = Q;
5696  let Inst{29}    = U;
5697  let Inst{28-24} = 0b01110;
5698  let Inst{23-22} = size;
5699  let Inst{21} = 0b1;
5700  let Inst{20-19} = size2;
5701  let Inst{18-17} = 0b00;
5702  let Inst{16-12} = opcode;
5703  let Inst{11-10} = 0b10;
5704  let Inst{9-5}   = Rn;
5705  let Inst{4-0}   = Rd;
5706}
5707
5708let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5709class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
5710                                bits<2> size2, RegisterOperand regtype,
5711                                string asm, string dstkind, string srckind,
5712                                list<dag> pattern>
5713  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
5714      "{\t$Rd" # dstkind # ", $Rn" # srckind #
5715      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
5716    Sched<[WriteV]> {
5717  bits<5> Rd;
5718  bits<5> Rn;
5719  let Inst{31}    = 0;
5720  let Inst{30}    = Q;
5721  let Inst{29}    = U;
5722  let Inst{28-24} = 0b01110;
5723  let Inst{23-22} = size;
5724  let Inst{21} = 0b1;
5725  let Inst{20-19} = size2;
5726  let Inst{18-17} = 0b00;
5727  let Inst{16-12} = opcode;
5728  let Inst{11-10} = 0b10;
5729  let Inst{9-5}   = Rn;
5730  let Inst{4-0}   = Rd;
5731}
5732
5733// Supports B, H, and S element sizes.
5734multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
5735                            SDPatternOperator OpNode> {
5736  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5737                                      asm, ".8b", ".8b",
5738                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5739  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5740                                      asm, ".16b", ".16b",
5741                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5742  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5743                                      asm, ".4h", ".4h",
5744                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5745  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5746                                      asm, ".8h", ".8h",
5747                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5748  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5749                                      asm, ".2s", ".2s",
5750                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5751  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5752                                      asm, ".4s", ".4s",
5753                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5754}
5755
5756class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
5757                            RegisterOperand regtype, string asm, string dstkind,
5758                            string srckind, string amount>
5759  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
5760      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
5761      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
5762    Sched<[WriteV]> {
5763  bits<5> Rd;
5764  bits<5> Rn;
5765  let Inst{31}    = 0;
5766  let Inst{30}    = Q;
5767  let Inst{29-24} = 0b101110;
5768  let Inst{23-22} = size;
5769  let Inst{21-10} = 0b100001001110;
5770  let Inst{9-5}   = Rn;
5771  let Inst{4-0}   = Rd;
5772}
5773
5774multiclass SIMDVectorLShiftLongBySizeBHS {
5775  let hasSideEffects = 0 in {
5776  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
5777                                             "shll", ".8h",  ".8b", "8">;
5778  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
5779                                             "shll2", ".8h", ".16b", "8">;
5780  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
5781                                             "shll", ".4s",  ".4h", "16">;
5782  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
5783                                             "shll2", ".4s", ".8h", "16">;
5784  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
5785                                             "shll", ".2d",  ".2s", "32">;
5786  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
5787                                             "shll2", ".2d", ".4s", "32">;
5788  }
5789}
5790
5791// Supports all element sizes.
5792multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
5793                             SDPatternOperator OpNode> {
5794  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5795                                      asm, ".4h", ".8b",
5796               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5797  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5798                                      asm, ".8h", ".16b",
5799               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5800  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5801                                      asm, ".2s", ".4h",
5802               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5803  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5804                                      asm, ".4s", ".8h",
5805               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5806  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5807                                      asm, ".1d", ".2s",
5808               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5809  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5810                                      asm, ".2d", ".4s",
5811               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5812}
5813
5814multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
5815                                 SDPatternOperator OpNode> {
5816  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5817                                          asm, ".4h", ".8b",
5818      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
5819                                      (v8i8 V64:$Rn)))]>;
5820  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5821                                          asm, ".8h", ".16b",
5822      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
5823                                      (v16i8 V128:$Rn)))]>;
5824  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5825                                          asm, ".2s", ".4h",
5826      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
5827                                      (v4i16 V64:$Rn)))]>;
5828  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5829                                          asm, ".4s", ".8h",
5830      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
5831                                      (v8i16 V128:$Rn)))]>;
5832  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5833                                          asm, ".1d", ".2s",
5834      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
5835                                      (v2i32 V64:$Rn)))]>;
5836  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5837                                          asm, ".2d", ".4s",
5838      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
5839                                      (v4i32 V128:$Rn)))]>;
5840}
5841
5842// Supports all element sizes, except 1xD.
5843multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
5844                                  SDPatternOperator OpNode> {
5845  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
5846                                    asm, ".8b", ".8b",
5847    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
5848  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
5849                                    asm, ".16b", ".16b",
5850    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
5851  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
5852                                    asm, ".4h", ".4h",
5853    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
5854  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
5855                                    asm, ".8h", ".8h",
5856    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
5857  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
5858                                    asm, ".2s", ".2s",
5859    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
5860  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
5861                                    asm, ".4s", ".4s",
5862    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
5863  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
5864                                    asm, ".2d", ".2d",
5865    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
5866}
5867
5868multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
5869                             SDPatternOperator OpNode = null_frag> {
5870  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5871                                asm, ".8b", ".8b",
5872    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5873  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5874                                asm, ".16b", ".16b",
5875    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5876  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5877                                asm, ".4h", ".4h",
5878    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
5879  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5880                                asm, ".8h", ".8h",
5881    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
5882  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
5883                                asm, ".2s", ".2s",
5884    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5885  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
5886                                asm, ".4s", ".4s",
5887    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5888  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
5889                                asm, ".2d", ".2d",
5890    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
5891}
5892
5893
5894// Supports only B element sizes.
5895multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
5896                          SDPatternOperator OpNode> {
5897  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
5898                                asm, ".8b", ".8b",
5899                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
5900  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
5901                                asm, ".16b", ".16b",
5902                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
5903
5904}
5905
5906// Supports only B and H element sizes.
5907multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
5908                                SDPatternOperator OpNode> {
5909  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
5910                                asm, ".8b", ".8b",
5911                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
5912  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
5913                                asm, ".16b", ".16b",
5914                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
5915  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
5916                                asm, ".4h", ".4h",
5917                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
5918  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
5919                                asm, ".8h", ".8h",
5920                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
5921}
5922
5923// Supports H, S and D element sizes, uses high bit of the size field
5924// as an extra opcode bit.
5925multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
5926                           SDPatternOperator OpNode> {
5927  let Predicates = [HasNEON, HasFullFP16] in {
5928  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5929                                asm, ".4h", ".4h",
5930                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5931  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5932                                asm, ".8h", ".8h",
5933                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5934  } // Predicates = [HasNEON, HasFullFP16]
5935  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5936                                asm, ".2s", ".2s",
5937                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5938  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5939                                asm, ".4s", ".4s",
5940                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5941  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5942                                asm, ".2d", ".2d",
5943                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5944}
5945
5946// Supports only S and D element sizes
5947multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
5948                           SDPatternOperator OpNode = null_frag> {
5949
5950  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
5951                                asm, ".2s", ".2s",
5952                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5953  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
5954                                asm, ".4s", ".4s",
5955                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5956  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
5957                                asm, ".2d", ".2d",
5958                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5959}
5960
5961multiclass FRIntNNTVector<bit U, bit op, string asm,
5962                          SDPatternOperator OpNode = null_frag> :
5963           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
5964
5965// Supports only S element size.
5966multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
5967                           SDPatternOperator OpNode> {
5968  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5969                                asm, ".2s", ".2s",
5970                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
5971  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5972                                asm, ".4s", ".4s",
5973                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
5974}
5975
5976
5977multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
5978                           SDPatternOperator OpNode> {
5979  let Predicates = [HasNEON, HasFullFP16] in {
5980  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
5981                                asm, ".4h", ".4h",
5982                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
5983  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
5984                                asm, ".8h", ".8h",
5985                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
5986  } // Predicates = [HasNEON, HasFullFP16]
5987  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
5988                                asm, ".2s", ".2s",
5989                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
5990  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
5991                                asm, ".4s", ".4s",
5992                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
5993  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
5994                                asm, ".2d", ".2d",
5995                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
5996}
5997
5998multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
5999                           SDPatternOperator OpNode> {
6000  let Predicates = [HasNEON, HasFullFP16] in {
6001  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6002                                asm, ".4h", ".4h",
6003                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6004  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6005                                asm, ".8h", ".8h",
6006                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6007  } // Predicates = [HasNEON, HasFullFP16]
6008  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6009                                asm, ".2s", ".2s",
6010                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6011  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6012                                asm, ".4s", ".4s",
6013                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6014  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6015                                asm, ".2d", ".2d",
6016                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6017}
6018
6019
6020class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6021                           RegisterOperand inreg, RegisterOperand outreg,
6022                           string asm, string outkind, string inkind,
6023                           list<dag> pattern>
6024  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6025      "{\t$Rd" # outkind # ", $Rn" # inkind #
6026      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6027    Sched<[WriteV]> {
6028  bits<5> Rd;
6029  bits<5> Rn;
6030  let Inst{31}    = 0;
6031  let Inst{30}    = Q;
6032  let Inst{29}    = U;
6033  let Inst{28-24} = 0b01110;
6034  let Inst{23-22} = size;
6035  let Inst{21-17} = 0b10000;
6036  let Inst{16-12} = opcode;
6037  let Inst{11-10} = 0b10;
6038  let Inst{9-5}   = Rn;
6039  let Inst{4-0}   = Rd;
6040}
6041
6042class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6043                           RegisterOperand inreg, RegisterOperand outreg,
6044                           string asm, string outkind, string inkind,
6045                           list<dag> pattern>
6046  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6047      "{\t$Rd" # outkind # ", $Rn" # inkind #
6048      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6049    Sched<[WriteV]> {
6050  bits<5> Rd;
6051  bits<5> Rn;
6052  let Inst{31}    = 0;
6053  let Inst{30}    = Q;
6054  let Inst{29}    = U;
6055  let Inst{28-24} = 0b01110;
6056  let Inst{23-22} = size;
6057  let Inst{21-17} = 0b10000;
6058  let Inst{16-12} = opcode;
6059  let Inst{11-10} = 0b10;
6060  let Inst{9-5}   = Rn;
6061  let Inst{4-0}   = Rd;
6062}
6063
6064multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6065                              SDPatternOperator OpNode> {
6066  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6067                                      asm, ".8b", ".8h",
6068        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6069  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6070                                      asm#"2", ".16b", ".8h", []>;
6071  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6072                                      asm, ".4h", ".4s",
6073        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6074  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6075                                      asm#"2", ".8h", ".4s", []>;
6076  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6077                                      asm, ".2s", ".2d",
6078        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6079  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6080                                      asm#"2", ".4s", ".2d", []>;
6081
6082  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6083            (!cast<Instruction>(NAME # "v16i8")
6084                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6085  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6086            (!cast<Instruction>(NAME # "v8i16")
6087                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6088  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6089            (!cast<Instruction>(NAME # "v4i32")
6090                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6091}
6092
6093class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6094                           bits<5> opcode, RegisterOperand regtype, string asm,
6095                           string kind, string zero, ValueType dty,
6096                           ValueType sty, SDNode OpNode>
6097  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6098      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6099      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6100      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6101    Sched<[WriteV]> {
6102  bits<5> Rd;
6103  bits<5> Rn;
6104  let Inst{31}    = 0;
6105  let Inst{30}    = Q;
6106  let Inst{29}    = U;
6107  let Inst{28-24} = 0b01110;
6108  let Inst{23-22} = size;
6109  let Inst{21} = 0b1;
6110  let Inst{20-19} = size2;
6111  let Inst{18-17} = 0b00;
6112  let Inst{16-12} = opcode;
6113  let Inst{11-10} = 0b10;
6114  let Inst{9-5}   = Rn;
6115  let Inst{4-0}   = Rd;
6116}
6117
6118// Comparisons support all element sizes, except 1xD.
6119multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6120                            SDNode OpNode> {
6121  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6122                                     asm, ".8b", "0",
6123                                     v8i8, v8i8, OpNode>;
6124  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6125                                     asm, ".16b", "0",
6126                                     v16i8, v16i8, OpNode>;
6127  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6128                                     asm, ".4h", "0",
6129                                     v4i16, v4i16, OpNode>;
6130  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6131                                     asm, ".8h", "0",
6132                                     v8i16, v8i16, OpNode>;
6133  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6134                                     asm, ".2s", "0",
6135                                     v2i32, v2i32, OpNode>;
6136  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6137                                     asm, ".4s", "0",
6138                                     v4i32, v4i32, OpNode>;
6139  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6140                                     asm, ".2d", "0",
6141                                     v2i64, v2i64, OpNode>;
6142}
6143
6144// FP Comparisons support only S and D element sizes (and H for v8.2a).
6145multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6146                              string asm, SDNode OpNode> {
6147
6148  let Predicates = [HasNEON, HasFullFP16] in {
6149  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6150                                     asm, ".4h", "0.0",
6151                                     v4i16, v4f16, OpNode>;
6152  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6153                                     asm, ".8h", "0.0",
6154                                     v8i16, v8f16, OpNode>;
6155  } // Predicates = [HasNEON, HasFullFP16]
6156  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6157                                     asm, ".2s", "0.0",
6158                                     v2i32, v2f32, OpNode>;
6159  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6160                                     asm, ".4s", "0.0",
6161                                     v4i32, v4f32, OpNode>;
6162  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6163                                     asm, ".2d", "0.0",
6164                                     v2i64, v2f64, OpNode>;
6165
6166  let Predicates = [HasNEON, HasFullFP16] in {
6167  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6168                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6169  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6170                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6171  }
6172  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6173                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6174  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6175                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6176  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6177                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6178  let Predicates = [HasNEON, HasFullFP16] in {
6179  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6180                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6181  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6182                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6183  }
6184  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6185                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6186  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6187                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6188  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6189                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6190}
6191
6192let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6193class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6194                             RegisterOperand outtype, RegisterOperand intype,
6195                             string asm, string VdTy, string VnTy,
6196                             list<dag> pattern>
6197  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6198      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6199    Sched<[WriteV]> {
6200  bits<5> Rd;
6201  bits<5> Rn;
6202  let Inst{31}    = 0;
6203  let Inst{30}    = Q;
6204  let Inst{29}    = U;
6205  let Inst{28-24} = 0b01110;
6206  let Inst{23-22} = size;
6207  let Inst{21-17} = 0b10000;
6208  let Inst{16-12} = opcode;
6209  let Inst{11-10} = 0b10;
6210  let Inst{9-5}   = Rn;
6211  let Inst{4-0}   = Rd;
6212}
6213
6214class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6215                             RegisterOperand outtype, RegisterOperand intype,
6216                             string asm, string VdTy, string VnTy,
6217                             list<dag> pattern>
6218  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6219      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6220    Sched<[WriteV]> {
6221  bits<5> Rd;
6222  bits<5> Rn;
6223  let Inst{31}    = 0;
6224  let Inst{30}    = Q;
6225  let Inst{29}    = U;
6226  let Inst{28-24} = 0b01110;
6227  let Inst{23-22} = size;
6228  let Inst{21-17} = 0b10000;
6229  let Inst{16-12} = opcode;
6230  let Inst{11-10} = 0b10;
6231  let Inst{9-5}   = Rn;
6232  let Inst{4-0}   = Rd;
6233}
6234
6235multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6236  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6237                                    asm, ".4s", ".4h", []>;
6238  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6239                                    asm#"2", ".4s", ".8h", []>;
6240  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6241                                    asm, ".2d", ".2s", []>;
6242  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6243                                    asm#"2", ".2d", ".4s", []>;
6244}
6245
6246multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6247  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6248                                    asm, ".4h", ".4s", []>;
6249  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6250                                    asm#"2", ".8h", ".4s", []>;
6251  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6252                                    asm, ".2s", ".2d", []>;
6253  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6254                                    asm#"2", ".4s", ".2d", []>;
6255}
6256
6257multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6258                                     Intrinsic OpNode> {
6259  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6260                                     asm, ".2s", ".2d",
6261                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6262  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6263                                    asm#"2", ".4s", ".2d", []>;
6264
6265  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6266            (!cast<Instruction>(NAME # "v4f32")
6267                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6268}
6269
6270//----------------------------------------------------------------------------
6271// AdvSIMD three register different-size vector instructions.
6272//----------------------------------------------------------------------------
6273
6274let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6275class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6276                      RegisterOperand outtype, RegisterOperand intype1,
6277                      RegisterOperand intype2, string asm,
6278                      string outkind, string inkind1, string inkind2,
6279                      list<dag> pattern>
6280  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6281      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6282      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6283    Sched<[WriteV]> {
6284  bits<5> Rd;
6285  bits<5> Rn;
6286  bits<5> Rm;
6287  let Inst{31}    = 0;
6288  let Inst{30}    = size{0};
6289  let Inst{29}    = U;
6290  let Inst{28-24} = 0b01110;
6291  let Inst{23-22} = size{2-1};
6292  let Inst{21}    = 1;
6293  let Inst{20-16} = Rm;
6294  let Inst{15-12} = opcode;
6295  let Inst{11-10} = 0b00;
6296  let Inst{9-5}   = Rn;
6297  let Inst{4-0}   = Rd;
6298}
6299
6300let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6301class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6302                      RegisterOperand outtype, RegisterOperand intype1,
6303                      RegisterOperand intype2, string asm,
6304                      string outkind, string inkind1, string inkind2,
6305                      list<dag> pattern>
6306  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6307      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6308      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6309    Sched<[WriteV]> {
6310  bits<5> Rd;
6311  bits<5> Rn;
6312  bits<5> Rm;
6313  let Inst{31}    = 0;
6314  let Inst{30}    = size{0};
6315  let Inst{29}    = U;
6316  let Inst{28-24} = 0b01110;
6317  let Inst{23-22} = size{2-1};
6318  let Inst{21}    = 1;
6319  let Inst{20-16} = Rm;
6320  let Inst{15-12} = opcode;
6321  let Inst{11-10} = 0b00;
6322  let Inst{9-5}   = Rn;
6323  let Inst{4-0}   = Rd;
6324}
6325
6326// FIXME: TableGen doesn't know how to deal with expanded types that also
6327//        change the element count (in this case, placing the results in
6328//        the high elements of the result register rather than the low
6329//        elements). Until that's fixed, we can't code-gen those.
6330multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6331                                    Intrinsic IntOp> {
6332  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6333                                                  V64, V128, V128,
6334                                                  asm, ".8b", ".8h", ".8h",
6335     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6336  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6337                                                  V128, V128, V128,
6338                                                  asm#"2", ".16b", ".8h", ".8h",
6339     []>;
6340  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6341                                                  V64, V128, V128,
6342                                                  asm, ".4h", ".4s", ".4s",
6343     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6344  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6345                                                  V128, V128, V128,
6346                                                  asm#"2", ".8h", ".4s", ".4s",
6347     []>;
6348  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6349                                                  V64, V128, V128,
6350                                                  asm, ".2s", ".2d", ".2d",
6351     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6352  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6353                                                  V128, V128, V128,
6354                                                  asm#"2", ".4s", ".2d", ".2d",
6355     []>;
6356
6357
6358  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6359  // a version attached to an instruction.
6360  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6361                                                   (v8i16 V128:$Rm))),
6362            (!cast<Instruction>(NAME # "v8i16_v16i8")
6363                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6364                V128:$Rn, V128:$Rm)>;
6365  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6366                                                    (v4i32 V128:$Rm))),
6367            (!cast<Instruction>(NAME # "v4i32_v8i16")
6368                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6369                V128:$Rn, V128:$Rm)>;
6370  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6371                                                    (v2i64 V128:$Rm))),
6372            (!cast<Instruction>(NAME # "v2i64_v4i32")
6373                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6374                V128:$Rn, V128:$Rm)>;
6375}
6376
6377multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6378                                      Intrinsic IntOp> {
6379  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6380                                            V128, V64, V64,
6381                                            asm, ".8h", ".8b", ".8b",
6382      [(set (v8i16 V128:$Rd), (IntOp (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6383  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6384                                            V128, V128, V128,
6385                                            asm#"2", ".8h", ".16b", ".16b", []>;
6386  let Predicates = [HasAES] in {
6387    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6388                                              V128, V64, V64,
6389                                              asm, ".1q", ".1d", ".1d", []>;
6390    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6391                                              V128, V128, V128,
6392                                              asm#"2", ".1q", ".2d", ".2d", []>;
6393  }
6394
6395  def : Pat<(v8i16 (IntOp (v8i8 (extract_high_v16i8 V128:$Rn)),
6396                          (v8i8 (extract_high_v16i8 V128:$Rm)))),
6397      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6398}
6399
6400multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6401                                 SDPatternOperator OpNode> {
6402  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6403                                                  V128, V64, V64,
6404                                                  asm, ".4s", ".4h", ".4h",
6405      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6406  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6407                                                  V128, V128, V128,
6408                                                  asm#"2", ".4s", ".8h", ".8h",
6409      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6410                                      (extract_high_v8i16 V128:$Rm)))]>;
6411  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6412                                                  V128, V64, V64,
6413                                                  asm, ".2d", ".2s", ".2s",
6414      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6415  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6416                                                  V128, V128, V128,
6417                                                  asm#"2", ".2d", ".4s", ".4s",
6418      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6419                                      (extract_high_v4i32 V128:$Rm)))]>;
6420}
6421
6422multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
6423                                  SDPatternOperator OpNode = null_frag> {
6424  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6425                                                  V128, V64, V64,
6426                                                  asm, ".8h", ".8b", ".8b",
6427      [(set (v8i16 V128:$Rd),
6428            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
6429  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6430                                                 V128, V128, V128,
6431                                                 asm#"2", ".8h", ".16b", ".16b",
6432      [(set (v8i16 V128:$Rd),
6433            (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6434                                (extract_high_v16i8 V128:$Rm)))))]>;
6435  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6436                                                  V128, V64, V64,
6437                                                  asm, ".4s", ".4h", ".4h",
6438      [(set (v4i32 V128:$Rd),
6439            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
6440  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6441                                                  V128, V128, V128,
6442                                                  asm#"2", ".4s", ".8h", ".8h",
6443      [(set (v4i32 V128:$Rd),
6444            (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6445                                  (extract_high_v8i16 V128:$Rm)))))]>;
6446  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6447                                                  V128, V64, V64,
6448                                                  asm, ".2d", ".2s", ".2s",
6449      [(set (v2i64 V128:$Rd),
6450            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
6451  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6452                                                  V128, V128, V128,
6453                                                  asm#"2", ".2d", ".4s", ".4s",
6454      [(set (v2i64 V128:$Rd),
6455            (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6456                                 (extract_high_v4i32 V128:$Rm)))))]>;
6457}
6458
6459multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
6460                                          string asm,
6461                                          SDPatternOperator OpNode> {
6462  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6463                                                  V128, V64, V64,
6464                                                  asm, ".8h", ".8b", ".8b",
6465    [(set (v8i16 V128:$dst),
6466          (add (v8i16 V128:$Rd),
6467               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
6468  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6469                                                 V128, V128, V128,
6470                                                 asm#"2", ".8h", ".16b", ".16b",
6471    [(set (v8i16 V128:$dst),
6472          (add (v8i16 V128:$Rd),
6473               (zext (v8i8 (OpNode (extract_high_v16i8 V128:$Rn),
6474                                   (extract_high_v16i8 V128:$Rm))))))]>;
6475  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6476                                                  V128, V64, V64,
6477                                                  asm, ".4s", ".4h", ".4h",
6478    [(set (v4i32 V128:$dst),
6479          (add (v4i32 V128:$Rd),
6480               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
6481  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6482                                                  V128, V128, V128,
6483                                                  asm#"2", ".4s", ".8h", ".8h",
6484    [(set (v4i32 V128:$dst),
6485          (add (v4i32 V128:$Rd),
6486               (zext (v4i16 (OpNode (extract_high_v8i16 V128:$Rn),
6487                                    (extract_high_v8i16 V128:$Rm))))))]>;
6488  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6489                                                  V128, V64, V64,
6490                                                  asm, ".2d", ".2s", ".2s",
6491    [(set (v2i64 V128:$dst),
6492          (add (v2i64 V128:$Rd),
6493               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
6494  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6495                                                  V128, V128, V128,
6496                                                  asm#"2", ".2d", ".4s", ".4s",
6497    [(set (v2i64 V128:$dst),
6498          (add (v2i64 V128:$Rd),
6499               (zext (v2i32 (OpNode (extract_high_v4i32 V128:$Rn),
6500                                    (extract_high_v4i32 V128:$Rm))))))]>;
6501}
6502
6503multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
6504                                  SDPatternOperator OpNode = null_frag> {
6505  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6506                                                  V128, V64, V64,
6507                                                  asm, ".8h", ".8b", ".8b",
6508      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6509  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6510                                                 V128, V128, V128,
6511                                                 asm#"2", ".8h", ".16b", ".16b",
6512      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 V128:$Rn),
6513                                      (extract_high_v16i8 V128:$Rm)))]>;
6514  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6515                                                  V128, V64, V64,
6516                                                  asm, ".4s", ".4h", ".4h",
6517      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6518  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6519                                                  V128, V128, V128,
6520                                                  asm#"2", ".4s", ".8h", ".8h",
6521      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 V128:$Rn),
6522                                      (extract_high_v8i16 V128:$Rm)))]>;
6523  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6524                                                  V128, V64, V64,
6525                                                  asm, ".2d", ".2s", ".2s",
6526      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6527  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6528                                                  V128, V128, V128,
6529                                                  asm#"2", ".2d", ".4s", ".4s",
6530      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 V128:$Rn),
6531                                      (extract_high_v4i32 V128:$Rm)))]>;
6532}
6533
6534multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
6535                                      string asm,
6536                                      SDPatternOperator OpNode> {
6537  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
6538                                                  V128, V64, V64,
6539                                                  asm, ".8h", ".8b", ".8b",
6540    [(set (v8i16 V128:$dst),
6541          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6542  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6543                                                 V128, V128, V128,
6544                                                 asm#"2", ".8h", ".16b", ".16b",
6545    [(set (v8i16 V128:$dst),
6546          (OpNode (v8i16 V128:$Rd),
6547                  (extract_high_v16i8 V128:$Rn),
6548                  (extract_high_v16i8 V128:$Rm)))]>;
6549  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6550                                                  V128, V64, V64,
6551                                                  asm, ".4s", ".4h", ".4h",
6552    [(set (v4i32 V128:$dst),
6553          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6554  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6555                                                  V128, V128, V128,
6556                                                  asm#"2", ".4s", ".8h", ".8h",
6557    [(set (v4i32 V128:$dst),
6558          (OpNode (v4i32 V128:$Rd),
6559                  (extract_high_v8i16 V128:$Rn),
6560                  (extract_high_v8i16 V128:$Rm)))]>;
6561  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6562                                                  V128, V64, V64,
6563                                                  asm, ".2d", ".2s", ".2s",
6564    [(set (v2i64 V128:$dst),
6565          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6566  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6567                                                  V128, V128, V128,
6568                                                  asm#"2", ".2d", ".4s", ".4s",
6569    [(set (v2i64 V128:$dst),
6570          (OpNode (v2i64 V128:$Rd),
6571                  (extract_high_v4i32 V128:$Rn),
6572                  (extract_high_v4i32 V128:$Rm)))]>;
6573}
6574
6575multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
6576                                           SDPatternOperator Accum> {
6577  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
6578                                                  V128, V64, V64,
6579                                                  asm, ".4s", ".4h", ".4h",
6580    [(set (v4i32 V128:$dst),
6581          (Accum (v4i32 V128:$Rd),
6582                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
6583                                                (v4i16 V64:$Rm)))))]>;
6584  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6585                                                  V128, V128, V128,
6586                                                  asm#"2", ".4s", ".8h", ".8h",
6587    [(set (v4i32 V128:$dst),
6588          (Accum (v4i32 V128:$Rd),
6589                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 V128:$Rn),
6590                                            (extract_high_v8i16 V128:$Rm)))))]>;
6591  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
6592                                                  V128, V64, V64,
6593                                                  asm, ".2d", ".2s", ".2s",
6594    [(set (v2i64 V128:$dst),
6595          (Accum (v2i64 V128:$Rd),
6596                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
6597                                                (v2i32 V64:$Rm)))))]>;
6598  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6599                                                  V128, V128, V128,
6600                                                  asm#"2", ".2d", ".4s", ".4s",
6601    [(set (v2i64 V128:$dst),
6602          (Accum (v2i64 V128:$Rd),
6603                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 V128:$Rn),
6604                                            (extract_high_v4i32 V128:$Rm)))))]>;
6605}
6606
6607multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
6608                                  SDPatternOperator OpNode> {
6609  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6610                                                  V128, V128, V64,
6611                                                  asm, ".8h", ".8h", ".8b",
6612       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
6613  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6614                                                  V128, V128, V128,
6615                                                  asm#"2", ".8h", ".8h", ".16b",
6616       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
6617                                       (extract_high_v16i8 V128:$Rm)))]>;
6618  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6619                                                  V128, V128, V64,
6620                                                  asm, ".4s", ".4s", ".4h",
6621       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
6622  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6623                                                  V128, V128, V128,
6624                                                  asm#"2", ".4s", ".4s", ".8h",
6625       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
6626                                       (extract_high_v8i16 V128:$Rm)))]>;
6627  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6628                                                  V128, V128, V64,
6629                                                  asm, ".2d", ".2d", ".2s",
6630       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
6631  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6632                                                  V128, V128, V128,
6633                                                  asm#"2", ".2d", ".2d", ".4s",
6634       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
6635                                       (extract_high_v4i32 V128:$Rm)))]>;
6636}
6637
6638//----------------------------------------------------------------------------
6639// AdvSIMD bitwise extract from vector
6640//----------------------------------------------------------------------------
6641
6642class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
6643                             string asm, string kind>
6644  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
6645      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
6646      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
6647      [(set (vty regtype:$Rd),
6648            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
6649    Sched<[WriteV]> {
6650  bits<5> Rd;
6651  bits<5> Rn;
6652  bits<5> Rm;
6653  bits<4> imm;
6654  let Inst{31}    = 0;
6655  let Inst{30}    = size;
6656  let Inst{29-21} = 0b101110000;
6657  let Inst{20-16} = Rm;
6658  let Inst{15}    = 0;
6659  let Inst{14-11} = imm;
6660  let Inst{10}    = 0;
6661  let Inst{9-5}   = Rn;
6662  let Inst{4-0}   = Rd;
6663}
6664
6665
6666multiclass SIMDBitwiseExtract<string asm> {
6667  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
6668    let imm{3} = 0;
6669  }
6670  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
6671}
6672
6673//----------------------------------------------------------------------------
6674// AdvSIMD zip vector
6675//----------------------------------------------------------------------------
6676
6677class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
6678                        string asm, string kind, SDNode OpNode, ValueType valty>
6679  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6680      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
6681      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
6682      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
6683    Sched<[WriteV]> {
6684  bits<5> Rd;
6685  bits<5> Rn;
6686  bits<5> Rm;
6687  let Inst{31}    = 0;
6688  let Inst{30}    = size{0};
6689  let Inst{29-24} = 0b001110;
6690  let Inst{23-22} = size{2-1};
6691  let Inst{21}    = 0;
6692  let Inst{20-16} = Rm;
6693  let Inst{15}    = 0;
6694  let Inst{14-12} = opc;
6695  let Inst{11-10} = 0b10;
6696  let Inst{9-5}   = Rn;
6697  let Inst{4-0}   = Rd;
6698}
6699
6700multiclass SIMDZipVector<bits<3>opc, string asm,
6701                         SDNode OpNode> {
6702  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
6703      asm, ".8b", OpNode, v8i8>;
6704  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
6705      asm, ".16b", OpNode, v16i8>;
6706  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
6707      asm, ".4h", OpNode, v4i16>;
6708  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
6709      asm, ".8h", OpNode, v8i16>;
6710  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
6711      asm, ".2s", OpNode, v2i32>;
6712  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
6713      asm, ".4s", OpNode, v4i32>;
6714  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
6715      asm, ".2d", OpNode, v2i64>;
6716
6717  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
6718        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
6719  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
6720        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
6721  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
6722        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
6723  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
6724        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
6725  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
6726        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
6727}
6728
6729//----------------------------------------------------------------------------
6730// AdvSIMD three register scalar instructions
6731//----------------------------------------------------------------------------
6732
6733let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6734class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
6735                        RegisterClass regtype, string asm,
6736                        list<dag> pattern>
6737  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
6738      "\t$Rd, $Rn, $Rm", "", pattern>,
6739    Sched<[WriteV]> {
6740  bits<5> Rd;
6741  bits<5> Rn;
6742  bits<5> Rm;
6743  let Inst{31-30} = 0b01;
6744  let Inst{29}    = U;
6745  let Inst{28-24} = 0b11110;
6746  let Inst{23-21} = size;
6747  let Inst{20-16} = Rm;
6748  let Inst{15-11} = opcode;
6749  let Inst{10}    = 1;
6750  let Inst{9-5}   = Rn;
6751  let Inst{4-0}   = Rd;
6752}
6753
6754let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
6755class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
6756                        dag oops, dag iops, string asm,
6757            list<dag> pattern>
6758  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
6759    Sched<[WriteV]> {
6760  bits<5> Rd;
6761  bits<5> Rn;
6762  bits<5> Rm;
6763  let Inst{31-30} = 0b01;
6764  let Inst{29}    = U;
6765  let Inst{28-24} = 0b11110;
6766  let Inst{23-22} = size;
6767  let Inst{21}    = R;
6768  let Inst{20-16} = Rm;
6769  let Inst{15-11} = opcode;
6770  let Inst{10}    = 1;
6771  let Inst{9-5}   = Rn;
6772  let Inst{4-0}   = Rd;
6773}
6774
6775multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
6776                            SDPatternOperator OpNode> {
6777  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6778    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6779}
6780
6781multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
6782                               SDPatternOperator OpNode> {
6783  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
6784    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
6785  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
6786  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6787  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
6788
6789  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
6790            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
6791  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
6792            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
6793}
6794
6795multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
6796                             SDPatternOperator OpNode> {
6797  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
6798                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6799  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
6800}
6801
6802multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm,
6803                                 SDPatternOperator OpNode = null_frag> {
6804  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
6805                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
6806                                     asm, []>;
6807  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
6808                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
6809                                     asm, []>;
6810}
6811
6812multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
6813                             SDPatternOperator OpNode = null_frag> {
6814  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6815    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6816      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6817    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6818      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
6819    let Predicates = [HasNEON, HasFullFP16] in {
6820    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6821      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
6822    } // Predicates = [HasNEON, HasFullFP16]
6823  }
6824
6825  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6826            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6827}
6828
6829multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
6830                                SDPatternOperator OpNode = null_frag> {
6831  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
6832    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
6833      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
6834    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
6835      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
6836    let Predicates = [HasNEON, HasFullFP16] in {
6837    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
6838      []>;
6839    } // Predicates = [HasNEON, HasFullFP16]
6840  }
6841
6842  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
6843            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
6844}
6845
6846class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
6847              dag oops, dag iops, string asm, string cstr, list<dag> pat>
6848  : I<oops, iops, asm,
6849      "\t$Rd, $Rn, $Rm", cstr, pat>,
6850    Sched<[WriteV]> {
6851  bits<5> Rd;
6852  bits<5> Rn;
6853  bits<5> Rm;
6854  let Inst{31-30} = 0b01;
6855  let Inst{29}    = U;
6856  let Inst{28-24} = 0b11110;
6857  let Inst{23-22} = size;
6858  let Inst{21}    = 1;
6859  let Inst{20-16} = Rm;
6860  let Inst{15-11} = opcode;
6861  let Inst{10}    = 0;
6862  let Inst{9-5}   = Rn;
6863  let Inst{4-0}   = Rd;
6864}
6865
6866let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6867multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
6868                                  SDPatternOperator OpNode = null_frag> {
6869  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6870                                      (outs FPR32:$Rd),
6871                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
6872  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6873                                      (outs FPR64:$Rd),
6874                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
6875            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6876}
6877
6878let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6879multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
6880                                  SDPatternOperator OpNode = null_frag> {
6881  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
6882                                      (outs FPR32:$dst),
6883                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
6884                                      asm, "$Rd = $dst", []>;
6885  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
6886                                      (outs FPR64:$dst),
6887                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
6888                                      asm, "$Rd = $dst",
6889            [(set (i64 FPR64:$dst),
6890                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
6891}
6892
6893//----------------------------------------------------------------------------
6894// AdvSIMD two register scalar instructions
6895//----------------------------------------------------------------------------
6896
6897let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6898class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6899                        RegisterClass regtype, RegisterClass regtype2,
6900                        string asm, list<dag> pat>
6901  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
6902      "\t$Rd, $Rn", "", pat>,
6903    Sched<[WriteV]> {
6904  bits<5> Rd;
6905  bits<5> Rn;
6906  let Inst{31-30} = 0b01;
6907  let Inst{29}    = U;
6908  let Inst{28-24} = 0b11110;
6909  let Inst{23-22} = size;
6910  let Inst{21} = 0b1;
6911  let Inst{20-19} = size2;
6912  let Inst{18-17} = 0b00;
6913  let Inst{16-12} = opcode;
6914  let Inst{11-10} = 0b10;
6915  let Inst{9-5}   = Rn;
6916  let Inst{4-0}   = Rd;
6917}
6918
6919let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6920class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
6921                        RegisterClass regtype, RegisterClass regtype2,
6922                        string asm, list<dag> pat>
6923  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
6924      "\t$Rd, $Rn", "$Rd = $dst", pat>,
6925    Sched<[WriteV]> {
6926  bits<5> Rd;
6927  bits<5> Rn;
6928  let Inst{31-30} = 0b01;
6929  let Inst{29}    = U;
6930  let Inst{28-24} = 0b11110;
6931  let Inst{23-22} = size;
6932  let Inst{21-17} = 0b10000;
6933  let Inst{16-12} = opcode;
6934  let Inst{11-10} = 0b10;
6935  let Inst{9-5}   = Rn;
6936  let Inst{4-0}   = Rd;
6937}
6938
6939
6940let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6941class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
6942                        RegisterClass regtype, string asm, string zero>
6943  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6944      "\t$Rd, $Rn, #" # zero, "", []>,
6945    Sched<[WriteV]> {
6946  bits<5> Rd;
6947  bits<5> Rn;
6948  let Inst{31-30} = 0b01;
6949  let Inst{29}    = U;
6950  let Inst{28-24} = 0b11110;
6951  let Inst{23-22} = size;
6952  let Inst{21} = 0b1;
6953  let Inst{20-19} = size2;
6954  let Inst{18-17} = 0b00;
6955  let Inst{16-12} = opcode;
6956  let Inst{11-10} = 0b10;
6957  let Inst{9-5}   = Rn;
6958  let Inst{4-0}   = Rd;
6959}
6960
6961class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
6962  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
6963     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
6964    Sched<[WriteV]> {
6965  bits<5> Rd;
6966  bits<5> Rn;
6967  let Inst{31-17} = 0b011111100110000;
6968  let Inst{16-12} = opcode;
6969  let Inst{11-10} = 0b10;
6970  let Inst{9-5}   = Rn;
6971  let Inst{4-0}   = Rd;
6972}
6973
6974multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
6975                             SDPatternOperator OpNode> {
6976  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
6977
6978  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
6979            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
6980}
6981
6982multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
6983                              SDPatternOperator OpNode> {
6984  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
6985  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
6986  let Predicates = [HasNEON, HasFullFP16] in {
6987  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
6988  }
6989
6990  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6991                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
6992  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6993                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
6994  let Predicates = [HasNEON, HasFullFP16] in {
6995  def : InstAlias<asm # "\t$Rd, $Rn, #0",
6996                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
6997  }
6998
6999  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7000            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7001}
7002
7003multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7004                          SDPatternOperator OpNode = null_frag> {
7005  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7006    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7007
7008  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7009            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7010}
7011
7012multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
7013  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7014  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7015  let Predicates = [HasNEON, HasFullFP16] in {
7016  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7017  }
7018}
7019
7020multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7021                              SDPatternOperator OpNode> {
7022  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7023                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7024  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7025                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7026  let Predicates = [HasNEON, HasFullFP16] in {
7027  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7028                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7029  }
7030}
7031
7032multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7033                             SDPatternOperator OpNode = null_frag> {
7034  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7035    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7036           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7037    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7038           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7039    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7040    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7041  }
7042
7043  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7044            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7045}
7046
7047multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7048                                 Intrinsic OpNode> {
7049  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7050    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7051        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7052    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7053        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7054    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7055    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7056  }
7057
7058  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7059            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7060}
7061
7062
7063
7064let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7065multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7066                                 SDPatternOperator OpNode = null_frag> {
7067  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7068        [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7069  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7070  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7071}
7072
7073//----------------------------------------------------------------------------
7074// AdvSIMD scalar pairwise instructions
7075//----------------------------------------------------------------------------
7076
7077let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7078class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7079                        RegisterOperand regtype, RegisterOperand vectype,
7080                        string asm, string kind>
7081  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7082      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7083    Sched<[WriteV]> {
7084  bits<5> Rd;
7085  bits<5> Rn;
7086  let Inst{31-30} = 0b01;
7087  let Inst{29}    = U;
7088  let Inst{28-24} = 0b11110;
7089  let Inst{23-22} = size;
7090  let Inst{21-17} = 0b11000;
7091  let Inst{16-12} = opcode;
7092  let Inst{11-10} = 0b10;
7093  let Inst{9-5}   = Rn;
7094  let Inst{4-0}   = Rd;
7095}
7096
7097multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7098  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7099                                      asm, ".2d">;
7100}
7101
7102multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7103  let Predicates = [HasNEON, HasFullFP16] in {
7104  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7105                                      asm, ".2h">;
7106  }
7107  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7108                                      asm, ".2s">;
7109  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7110                                      asm, ".2d">;
7111}
7112
7113//----------------------------------------------------------------------------
7114// AdvSIMD across lanes instructions
7115//----------------------------------------------------------------------------
7116
7117let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7118class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7119                          RegisterClass regtype, RegisterOperand vectype,
7120                          string asm, string kind, list<dag> pattern>
7121  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7122      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7123    Sched<[WriteV]> {
7124  bits<5> Rd;
7125  bits<5> Rn;
7126  let Inst{31}    = 0;
7127  let Inst{30}    = Q;
7128  let Inst{29}    = U;
7129  let Inst{28-24} = 0b01110;
7130  let Inst{23-22} = size;
7131  let Inst{21-17} = 0b11000;
7132  let Inst{16-12} = opcode;
7133  let Inst{11-10} = 0b10;
7134  let Inst{9-5}   = Rn;
7135  let Inst{4-0}   = Rd;
7136}
7137
7138multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7139                              string asm> {
7140  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7141                                   asm, ".8b", []>;
7142  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7143                                   asm, ".16b", []>;
7144  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7145                                   asm, ".4h", []>;
7146  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7147                                   asm, ".8h", []>;
7148  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7149                                   asm, ".4s", []>;
7150}
7151
7152multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7153  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7154                                   asm, ".8b", []>;
7155  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7156                                   asm, ".16b", []>;
7157  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7158                                   asm, ".4h", []>;
7159  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7160                                   asm, ".8h", []>;
7161  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7162                                   asm, ".4s", []>;
7163}
7164
7165multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7166                            Intrinsic intOp> {
7167  let Predicates = [HasNEON, HasFullFP16] in {
7168  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7169                                   asm, ".4h",
7170        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7171  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7172                                   asm, ".8h",
7173        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7174  } // Predicates = [HasNEON, HasFullFP16]
7175  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7176                                   asm, ".4s",
7177        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7178}
7179
7180//----------------------------------------------------------------------------
7181// AdvSIMD INS/DUP instructions
7182//----------------------------------------------------------------------------
7183
7184// FIXME: There has got to be a better way to factor these. ugh.
7185
7186class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7187                     string operands, string constraints, list<dag> pattern>
7188  : I<outs, ins, asm, operands, constraints, pattern>,
7189    Sched<[WriteV]> {
7190  bits<5> Rd;
7191  bits<5> Rn;
7192  let Inst{31} = 0;
7193  let Inst{30} = Q;
7194  let Inst{29} = op;
7195  let Inst{28-21} = 0b01110000;
7196  let Inst{15} = 0;
7197  let Inst{10} = 1;
7198  let Inst{9-5} = Rn;
7199  let Inst{4-0} = Rd;
7200}
7201
7202class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7203                      RegisterOperand vecreg, RegisterClass regtype>
7204  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7205                   "{\t$Rd" # size # ", $Rn" #
7206                   "|" # size # "\t$Rd, $Rn}", "",
7207                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7208  let Inst{20-16} = imm5;
7209  let Inst{14-11} = 0b0001;
7210}
7211
7212class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7213                         ValueType vectype, ValueType insreg,
7214                         RegisterOperand vecreg, Operand idxtype,
7215                         ValueType elttype, SDNode OpNode>
7216  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7217                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7218                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7219                 [(set (vectype vecreg:$Rd),
7220                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7221  let Inst{14-11} = 0b0000;
7222}
7223
7224class SIMDDup64FromElement
7225  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7226                       VectorIndexD, i64, AArch64duplane64> {
7227  bits<1> idx;
7228  let Inst{20} = idx;
7229  let Inst{19-16} = 0b1000;
7230}
7231
7232class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7233                           RegisterOperand vecreg>
7234  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7235                       VectorIndexS, i64, AArch64duplane32> {
7236  bits<2> idx;
7237  let Inst{20-19} = idx;
7238  let Inst{18-16} = 0b100;
7239}
7240
7241class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7242                           RegisterOperand vecreg>
7243  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7244                       VectorIndexH, i64, AArch64duplane16> {
7245  bits<3> idx;
7246  let Inst{20-18} = idx;
7247  let Inst{17-16} = 0b10;
7248}
7249
7250class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7251                          RegisterOperand vecreg>
7252  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7253                       VectorIndexB, i64, AArch64duplane8> {
7254  bits<4> idx;
7255  let Inst{20-17} = idx;
7256  let Inst{16} = 1;
7257}
7258
7259class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7260                  Operand idxtype, string asm, list<dag> pattern>
7261  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7262                   "{\t$Rd, $Rn" # size # "$idx" #
7263                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7264  let Inst{14-11} = imm4;
7265}
7266
7267class SIMDSMov<bit Q, string size, RegisterClass regtype,
7268               Operand idxtype>
7269  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7270class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7271               Operand idxtype>
7272  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7273      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7274
7275class SIMDMovAlias<string asm, string size, Instruction inst,
7276                   RegisterClass regtype, Operand idxtype>
7277    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7278                    "|" # size # "\t$dst, $src$idx}",
7279                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7280
7281multiclass SMov {
7282  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7283    bits<4> idx;
7284    let Inst{20-17} = idx;
7285    let Inst{16} = 1;
7286  }
7287  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7288    bits<4> idx;
7289    let Inst{20-17} = idx;
7290    let Inst{16} = 1;
7291  }
7292  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7293    bits<3> idx;
7294    let Inst{20-18} = idx;
7295    let Inst{17-16} = 0b10;
7296  }
7297  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7298    bits<3> idx;
7299    let Inst{20-18} = idx;
7300    let Inst{17-16} = 0b10;
7301  }
7302  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7303    bits<2> idx;
7304    let Inst{20-19} = idx;
7305    let Inst{18-16} = 0b100;
7306  }
7307}
7308
7309multiclass UMov {
7310  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7311    bits<4> idx;
7312    let Inst{20-17} = idx;
7313    let Inst{16} = 1;
7314  }
7315  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7316    bits<3> idx;
7317    let Inst{20-18} = idx;
7318    let Inst{17-16} = 0b10;
7319  }
7320  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7321    bits<2> idx;
7322    let Inst{20-19} = idx;
7323    let Inst{18-16} = 0b100;
7324  }
7325  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7326    bits<1> idx;
7327    let Inst{20} = idx;
7328    let Inst{19-16} = 0b1000;
7329  }
7330  def : SIMDMovAlias<"mov", ".s",
7331                     !cast<Instruction>(NAME#"vi32"),
7332                     GPR32, VectorIndexS>;
7333  def : SIMDMovAlias<"mov", ".d",
7334                     !cast<Instruction>(NAME#"vi64"),
7335                     GPR64, VectorIndexD>;
7336}
7337
7338class SIMDInsFromMain<string size, ValueType vectype,
7339                      RegisterClass regtype, Operand idxtype>
7340  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7341                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7342                   "{\t$Rd" # size # "$idx, $Rn" #
7343                   "|" # size # "\t$Rd$idx, $Rn}",
7344                   "$Rd = $dst",
7345            [(set V128:$dst,
7346              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7347  let Inst{14-11} = 0b0011;
7348}
7349
7350class SIMDInsFromElement<string size, ValueType vectype,
7351                         ValueType elttype, Operand idxtype>
7352  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7353                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7354                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7355                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7356                   "$Rd = $dst",
7357         [(set V128:$dst,
7358               (vector_insert
7359                 (vectype V128:$Rd),
7360                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
7361                 idxtype:$idx))]>;
7362
7363class SIMDInsMainMovAlias<string size, Instruction inst,
7364                          RegisterClass regtype, Operand idxtype>
7365    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
7366                        "|" # size #"\t$dst$idx, $src}",
7367                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
7368class SIMDInsElementMovAlias<string size, Instruction inst,
7369                             Operand idxtype>
7370    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
7371                      # "|" # size #"\t$dst$idx, $src$idx2}",
7372                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
7373
7374
7375multiclass SIMDIns {
7376  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
7377    bits<4> idx;
7378    let Inst{20-17} = idx;
7379    let Inst{16} = 1;
7380  }
7381  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
7382    bits<3> idx;
7383    let Inst{20-18} = idx;
7384    let Inst{17-16} = 0b10;
7385  }
7386  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
7387    bits<2> idx;
7388    let Inst{20-19} = idx;
7389    let Inst{18-16} = 0b100;
7390  }
7391  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
7392    bits<1> idx;
7393    let Inst{20} = idx;
7394    let Inst{19-16} = 0b1000;
7395  }
7396
7397  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
7398    bits<4> idx;
7399    bits<4> idx2;
7400    let Inst{20-17} = idx;
7401    let Inst{16} = 1;
7402    let Inst{14-11} = idx2;
7403  }
7404  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
7405    bits<3> idx;
7406    bits<3> idx2;
7407    let Inst{20-18} = idx;
7408    let Inst{17-16} = 0b10;
7409    let Inst{14-12} = idx2;
7410    let Inst{11} = {?};
7411  }
7412  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
7413    bits<2> idx;
7414    bits<2> idx2;
7415    let Inst{20-19} = idx;
7416    let Inst{18-16} = 0b100;
7417    let Inst{14-13} = idx2;
7418    let Inst{12-11} = {?,?};
7419  }
7420  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
7421    bits<1> idx;
7422    bits<1> idx2;
7423    let Inst{20} = idx;
7424    let Inst{19-16} = 0b1000;
7425    let Inst{14} = idx2;
7426    let Inst{13-11} = {?,?,?};
7427  }
7428
7429  // For all forms of the INS instruction, the "mov" mnemonic is the
7430  // preferred alias. Why they didn't just call the instruction "mov" in
7431  // the first place is a very good question indeed...
7432  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
7433                         GPR32, VectorIndexB>;
7434  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
7435                         GPR32, VectorIndexH>;
7436  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
7437                         GPR32, VectorIndexS>;
7438  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
7439                         GPR64, VectorIndexD>;
7440
7441  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
7442                         VectorIndexB>;
7443  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
7444                         VectorIndexH>;
7445  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
7446                         VectorIndexS>;
7447  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
7448                         VectorIndexD>;
7449}
7450
7451//----------------------------------------------------------------------------
7452// AdvSIMD TBL/TBX
7453//----------------------------------------------------------------------------
7454
7455let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7456class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7457                          RegisterOperand listtype, string asm, string kind>
7458  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
7459       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
7460    Sched<[WriteV]> {
7461  bits<5> Vd;
7462  bits<5> Vn;
7463  bits<5> Vm;
7464  let Inst{31}    = 0;
7465  let Inst{30}    = Q;
7466  let Inst{29-21} = 0b001110000;
7467  let Inst{20-16} = Vm;
7468  let Inst{15}    = 0;
7469  let Inst{14-13} = len;
7470  let Inst{12}    = op;
7471  let Inst{11-10} = 0b00;
7472  let Inst{9-5}   = Vn;
7473  let Inst{4-0}   = Vd;
7474}
7475
7476let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7477class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
7478                          RegisterOperand listtype, string asm, string kind>
7479  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
7480       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
7481    Sched<[WriteV]> {
7482  bits<5> Vd;
7483  bits<5> Vn;
7484  bits<5> Vm;
7485  let Inst{31}    = 0;
7486  let Inst{30}    = Q;
7487  let Inst{29-21} = 0b001110000;
7488  let Inst{20-16} = Vm;
7489  let Inst{15}    = 0;
7490  let Inst{14-13} = len;
7491  let Inst{12}    = op;
7492  let Inst{11-10} = 0b00;
7493  let Inst{9-5}   = Vn;
7494  let Inst{4-0}   = Vd;
7495}
7496
7497class SIMDTableLookupAlias<string asm, Instruction inst,
7498                          RegisterOperand vectype, RegisterOperand listtype>
7499    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
7500                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
7501
7502multiclass SIMDTableLookup<bit op, string asm> {
7503  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
7504                                      asm, ".8b">;
7505  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
7506                                      asm, ".8b">;
7507  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
7508                                      asm, ".8b">;
7509  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
7510                                      asm, ".8b">;
7511  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
7512                                      asm, ".16b">;
7513  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
7514                                      asm, ".16b">;
7515  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
7516                                      asm, ".16b">;
7517  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
7518                                      asm, ".16b">;
7519
7520  def : SIMDTableLookupAlias<asm # ".8b",
7521                         !cast<Instruction>(NAME#"v8i8One"),
7522                         V64, VecListOne128>;
7523  def : SIMDTableLookupAlias<asm # ".8b",
7524                         !cast<Instruction>(NAME#"v8i8Two"),
7525                         V64, VecListTwo128>;
7526  def : SIMDTableLookupAlias<asm # ".8b",
7527                         !cast<Instruction>(NAME#"v8i8Three"),
7528                         V64, VecListThree128>;
7529  def : SIMDTableLookupAlias<asm # ".8b",
7530                         !cast<Instruction>(NAME#"v8i8Four"),
7531                         V64, VecListFour128>;
7532  def : SIMDTableLookupAlias<asm # ".16b",
7533                         !cast<Instruction>(NAME#"v16i8One"),
7534                         V128, VecListOne128>;
7535  def : SIMDTableLookupAlias<asm # ".16b",
7536                         !cast<Instruction>(NAME#"v16i8Two"),
7537                         V128, VecListTwo128>;
7538  def : SIMDTableLookupAlias<asm # ".16b",
7539                         !cast<Instruction>(NAME#"v16i8Three"),
7540                         V128, VecListThree128>;
7541  def : SIMDTableLookupAlias<asm # ".16b",
7542                         !cast<Instruction>(NAME#"v16i8Four"),
7543                         V128, VecListFour128>;
7544}
7545
7546multiclass SIMDTableLookupTied<bit op, string asm> {
7547  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
7548                                      asm, ".8b">;
7549  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
7550                                      asm, ".8b">;
7551  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
7552                                      asm, ".8b">;
7553  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
7554                                      asm, ".8b">;
7555  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
7556                                      asm, ".16b">;
7557  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
7558                                      asm, ".16b">;
7559  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
7560                                      asm, ".16b">;
7561  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
7562                                      asm, ".16b">;
7563
7564  def : SIMDTableLookupAlias<asm # ".8b",
7565                         !cast<Instruction>(NAME#"v8i8One"),
7566                         V64, VecListOne128>;
7567  def : SIMDTableLookupAlias<asm # ".8b",
7568                         !cast<Instruction>(NAME#"v8i8Two"),
7569                         V64, VecListTwo128>;
7570  def : SIMDTableLookupAlias<asm # ".8b",
7571                         !cast<Instruction>(NAME#"v8i8Three"),
7572                         V64, VecListThree128>;
7573  def : SIMDTableLookupAlias<asm # ".8b",
7574                         !cast<Instruction>(NAME#"v8i8Four"),
7575                         V64, VecListFour128>;
7576  def : SIMDTableLookupAlias<asm # ".16b",
7577                         !cast<Instruction>(NAME#"v16i8One"),
7578                         V128, VecListOne128>;
7579  def : SIMDTableLookupAlias<asm # ".16b",
7580                         !cast<Instruction>(NAME#"v16i8Two"),
7581                         V128, VecListTwo128>;
7582  def : SIMDTableLookupAlias<asm # ".16b",
7583                         !cast<Instruction>(NAME#"v16i8Three"),
7584                         V128, VecListThree128>;
7585  def : SIMDTableLookupAlias<asm # ".16b",
7586                         !cast<Instruction>(NAME#"v16i8Four"),
7587                         V128, VecListFour128>;
7588}
7589
7590
7591//----------------------------------------------------------------------------
7592// AdvSIMD scalar CPY
7593//----------------------------------------------------------------------------
7594let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7595class BaseSIMDScalarCPY<RegisterClass regtype, RegisterOperand vectype,
7596                        string kind, Operand idxtype>
7597  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), "mov",
7598       "{\t$dst, $src" # kind # "$idx" #
7599       "|\t$dst, $src$idx}", "", []>,
7600    Sched<[WriteV]> {
7601  bits<5> dst;
7602  bits<5> src;
7603  let Inst{31-21} = 0b01011110000;
7604  let Inst{15-10} = 0b000001;
7605  let Inst{9-5}   = src;
7606  let Inst{4-0}   = dst;
7607}
7608
7609class SIMDScalarCPYAlias<string asm, string size, Instruction inst,
7610      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
7611    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
7612                    # "|\t$dst, $src$index}",
7613                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
7614
7615
7616multiclass SIMDScalarCPY<string asm> {
7617  def i8  : BaseSIMDScalarCPY<FPR8,  V128, ".b", VectorIndexB> {
7618    bits<4> idx;
7619    let Inst{20-17} = idx;
7620    let Inst{16} = 1;
7621  }
7622  def i16 : BaseSIMDScalarCPY<FPR16, V128, ".h", VectorIndexH> {
7623    bits<3> idx;
7624    let Inst{20-18} = idx;
7625    let Inst{17-16} = 0b10;
7626  }
7627  def i32 : BaseSIMDScalarCPY<FPR32, V128, ".s", VectorIndexS> {
7628    bits<2> idx;
7629    let Inst{20-19} = idx;
7630    let Inst{18-16} = 0b100;
7631  }
7632  def i64 : BaseSIMDScalarCPY<FPR64, V128, ".d", VectorIndexD> {
7633    bits<1> idx;
7634    let Inst{20} = idx;
7635    let Inst{19-16} = 0b1000;
7636  }
7637
7638  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
7639                                                          VectorIndexD:$idx)))),
7640            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
7641
7642  // 'DUP' mnemonic aliases.
7643  def : SIMDScalarCPYAlias<"dup", ".b",
7644                           !cast<Instruction>(NAME#"i8"),
7645                           FPR8, V128, VectorIndexB>;
7646  def : SIMDScalarCPYAlias<"dup", ".h",
7647                           !cast<Instruction>(NAME#"i16"),
7648                           FPR16, V128, VectorIndexH>;
7649  def : SIMDScalarCPYAlias<"dup", ".s",
7650                           !cast<Instruction>(NAME#"i32"),
7651                           FPR32, V128, VectorIndexS>;
7652  def : SIMDScalarCPYAlias<"dup", ".d",
7653                           !cast<Instruction>(NAME#"i64"),
7654                           FPR64, V128, VectorIndexD>;
7655}
7656
7657//----------------------------------------------------------------------------
7658// AdvSIMD modified immediate instructions
7659//----------------------------------------------------------------------------
7660
7661class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
7662                          string asm, string op_string,
7663                          string cstr, list<dag> pattern>
7664  : I<oops, iops, asm, op_string, cstr, pattern>,
7665    Sched<[WriteV]> {
7666  bits<5> Rd;
7667  bits<8> imm8;
7668  let Inst{31}    = 0;
7669  let Inst{30}    = Q;
7670  let Inst{29}    = op;
7671  let Inst{28-19} = 0b0111100000;
7672  let Inst{18-16} = imm8{7-5};
7673  let Inst{11} = op2;
7674  let Inst{10} = 1;
7675  let Inst{9-5}   = imm8{4-0};
7676  let Inst{4-0}   = Rd;
7677}
7678
7679class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
7680                                Operand immtype, dag opt_shift_iop,
7681                                string opt_shift, string asm, string kind,
7682                                list<dag> pattern>
7683  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
7684                        !con((ins immtype:$imm8), opt_shift_iop), asm,
7685                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
7686                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7687                        "", pattern> {
7688  let DecoderMethod = "DecodeModImmInstruction";
7689}
7690
7691class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
7692                                Operand immtype, dag opt_shift_iop,
7693                                string opt_shift, string asm, string kind,
7694                                list<dag> pattern>
7695  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
7696                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
7697                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
7698                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
7699                        "$Rd = $dst", pattern> {
7700  let DecoderMethod = "DecodeModImmTiedInstruction";
7701}
7702
7703class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
7704                                     RegisterOperand vectype, string asm,
7705                                     string kind, list<dag> pattern>
7706  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7707                              (ins logical_vec_shift:$shift),
7708                              "$shift", asm, kind, pattern> {
7709  bits<2> shift;
7710  let Inst{15}    = b15_b12{1};
7711  let Inst{14-13} = shift;
7712  let Inst{12}    = b15_b12{0};
7713}
7714
7715class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
7716                                     RegisterOperand vectype, string asm,
7717                                     string kind, list<dag> pattern>
7718  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7719                              (ins logical_vec_shift:$shift),
7720                              "$shift", asm, kind, pattern> {
7721  bits<2> shift;
7722  let Inst{15}    = b15_b12{1};
7723  let Inst{14-13} = shift;
7724  let Inst{12}    = b15_b12{0};
7725}
7726
7727
7728class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
7729                                         RegisterOperand vectype, string asm,
7730                                         string kind, list<dag> pattern>
7731  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7732                              (ins logical_vec_hw_shift:$shift),
7733                              "$shift", asm, kind, pattern> {
7734  bits<2> shift;
7735  let Inst{15} = b15_b12{1};
7736  let Inst{14} = 0;
7737  let Inst{13} = shift{0};
7738  let Inst{12} = b15_b12{0};
7739}
7740
7741class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
7742                                         RegisterOperand vectype, string asm,
7743                                         string kind, list<dag> pattern>
7744  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
7745                              (ins logical_vec_hw_shift:$shift),
7746                              "$shift", asm, kind, pattern> {
7747  bits<2> shift;
7748  let Inst{15} = b15_b12{1};
7749  let Inst{14} = 0;
7750  let Inst{13} = shift{0};
7751  let Inst{12} = b15_b12{0};
7752}
7753
7754multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
7755                                      string asm> {
7756  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
7757                                                 asm, ".4h", []>;
7758  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
7759                                                 asm, ".8h", []>;
7760
7761  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
7762                                             asm, ".2s", []>;
7763  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
7764                                             asm, ".4s", []>;
7765}
7766
7767multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
7768                                      bits<2> w_cmode, string asm,
7769                                      SDNode OpNode> {
7770  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
7771                                                 asm, ".4h",
7772             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
7773                                             imm0_255:$imm8,
7774                                             (i32 imm:$shift)))]>;
7775  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
7776                                                 asm, ".8h",
7777             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
7778                                              imm0_255:$imm8,
7779                                              (i32 imm:$shift)))]>;
7780
7781  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
7782                                             asm, ".2s",
7783             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
7784                                             imm0_255:$imm8,
7785                                             (i32 imm:$shift)))]>;
7786  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
7787                                             asm, ".4s",
7788             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
7789                                              imm0_255:$imm8,
7790                                              (i32 imm:$shift)))]>;
7791}
7792
7793class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
7794                             RegisterOperand vectype, string asm,
7795                             string kind, list<dag> pattern>
7796  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
7797                              (ins move_vec_shift:$shift),
7798                              "$shift", asm, kind, pattern> {
7799  bits<1> shift;
7800  let Inst{15-13} = cmode{3-1};
7801  let Inst{12}    = shift;
7802}
7803
7804class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
7805                                   RegisterOperand vectype,
7806                                   Operand imm_type, string asm,
7807                                   string kind, list<dag> pattern>
7808  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
7809                              asm, kind, pattern> {
7810  let Inst{15-12} = cmode;
7811}
7812
7813class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
7814                                   list<dag> pattern>
7815  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
7816                        "\t$Rd, $imm8", "", pattern> {
7817  let Inst{15-12} = cmode;
7818  let DecoderMethod = "DecodeModImmInstruction";
7819}
7820
7821//----------------------------------------------------------------------------
7822// AdvSIMD indexed element
7823//----------------------------------------------------------------------------
7824
7825let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7826class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7827                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7828                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7829                      string apple_kind, string dst_kind, string lhs_kind,
7830                      string rhs_kind, list<dag> pattern>
7831  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
7832      asm,
7833      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7834      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
7835    Sched<[WriteV]> {
7836  bits<5> Rd;
7837  bits<5> Rn;
7838  bits<5> Rm;
7839
7840  let Inst{31}    = 0;
7841  let Inst{30}    = Q;
7842  let Inst{29}    = U;
7843  let Inst{28}    = Scalar;
7844  let Inst{27-24} = 0b1111;
7845  let Inst{23-22} = size;
7846  // Bit 21 must be set by the derived class.
7847  let Inst{20-16} = Rm;
7848  let Inst{15-12} = opc;
7849  // Bit 11 must be set by the derived class.
7850  let Inst{10}    = 0;
7851  let Inst{9-5}   = Rn;
7852  let Inst{4-0}   = Rd;
7853}
7854
7855let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7856class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
7857                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
7858                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
7859                      string apple_kind, string dst_kind, string lhs_kind,
7860                      string rhs_kind, list<dag> pattern>
7861  : I<(outs dst_reg:$dst),
7862      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
7863      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
7864      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
7865    Sched<[WriteV]> {
7866  bits<5> Rd;
7867  bits<5> Rn;
7868  bits<5> Rm;
7869
7870  let Inst{31}    = 0;
7871  let Inst{30}    = Q;
7872  let Inst{29}    = U;
7873  let Inst{28}    = Scalar;
7874  let Inst{27-24} = 0b1111;
7875  let Inst{23-22} = size;
7876  // Bit 21 must be set by the derived class.
7877  let Inst{20-16} = Rm;
7878  let Inst{15-12} = opc;
7879  // Bit 11 must be set by the derived class.
7880  let Inst{10}    = 0;
7881  let Inst{9-5}   = Rn;
7882  let Inst{4-0}   = Rd;
7883}
7884
7885
7886//----------------------------------------------------------------------------
7887// Armv8.6 BFloat16 Extension
7888//----------------------------------------------------------------------------
7889let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
7890
7891class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
7892                                   string kind2, RegisterOperand RegType,
7893                                   ValueType AccumType, ValueType InputType>
7894  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
7895                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
7896                                            (InputType RegType:$Rn),
7897                                            (InputType RegType:$Rm)))]> {
7898  let AsmString = !strconcat(asm,
7899                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
7900                               ", $Rm" # kind2 # "}");
7901}
7902
7903multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
7904  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
7905                                           v2f32, v4bf16>;
7906  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
7907                                           v4f32, v8bf16>;
7908}
7909
7910class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
7911                                      string dst_kind, string lhs_kind,
7912                                      string rhs_kind,
7913                                      RegisterOperand RegType,
7914                                      ValueType AccumType,
7915                                      ValueType InputType>
7916  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
7917                        RegType, RegType, V128, VectorIndexS,
7918                        asm, "", dst_kind, lhs_kind, rhs_kind,
7919        [(set (AccumType RegType:$dst),
7920              (AccumType (int_aarch64_neon_bfdot
7921                                 (AccumType RegType:$Rd),
7922                                 (InputType RegType:$Rn),
7923                                 (InputType (bitconvert (AccumType
7924                                    (AArch64duplane32 (v4f32 V128:$Rm),
7925                                        VectorIndexS:$idx)))))))]> {
7926
7927  bits<2> idx;
7928  let Inst{21}    = idx{0};  // L
7929  let Inst{11}    = idx{1};  // H
7930}
7931
7932multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
7933
7934  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
7935                                               ".2h", V64, v2f32, v4bf16>;
7936  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
7937                                              ".2h", V128, v4f32, v8bf16>;
7938}
7939
7940class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
7941  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
7942              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
7943                                               (v8bf16 V128:$Rn),
7944                                               (v8bf16 V128:$Rm)))]> {
7945  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
7946}
7947
7948class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
7949  : I<(outs V128:$dst),
7950      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
7951      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
7952          [(set (v4f32 V128:$dst),
7953                (v4f32 (OpNode (v4f32 V128:$Rd),
7954                               (v8bf16 V128:$Rn),
7955                               (v8bf16
7956                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
7957                                      VectorIndexH:$idx)))))]>,
7958    Sched<[WriteV]> {
7959  bits<5> Rd;
7960  bits<5> Rn;
7961  bits<4> Rm;
7962  bits<3> idx;
7963
7964  let Inst{31}    = 0;
7965  let Inst{30}    = Q;
7966  let Inst{29-22} = 0b00111111;
7967  let Inst{21-20} = idx{1-0};
7968  let Inst{19-16} = Rm;
7969  let Inst{15-12} = 0b1111;
7970  let Inst{11}    = idx{2};   // H
7971  let Inst{10}    = 0;
7972  let Inst{9-5}   = Rn;
7973  let Inst{4-0}   = Rd;
7974}
7975
7976class SIMDThreeSameVectorBF16MatrixMul<string asm>
7977  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
7978                                V128, asm, ".4s",
7979                          [(set (v4f32 V128:$dst),
7980                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
7981                                                         (v8bf16 V128:$Rn),
7982                                                         (v8bf16 V128:$Rm)))]> {
7983  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
7984                                    ", $Rm", ".8h", "}");
7985}
7986
7987class SIMD_BFCVTN
7988  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
7989                           "bfcvtn", ".4h", ".4s",
7990    [(set (v8bf16 V128:$Rd),
7991          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
7992
7993class SIMD_BFCVTN2
7994  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
7995                           "bfcvtn2", ".8h", ".4s",
7996    [(set (v8bf16 V128:$dst),
7997          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
7998
7999class BF16ToSinglePrecision<string asm>
8000  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8001    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8002    Sched<[WriteFCvt]> {
8003  bits<5> Rd;
8004  bits<5> Rn;
8005  let Inst{31-10} = 0b0001111001100011010000;
8006  let Inst{9-5}   = Rn;
8007  let Inst{4-0}   = Rd;
8008}
8009} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8010
8011//----------------------------------------------------------------------------
8012// Armv8.6 Matrix Multiply Extension
8013//----------------------------------------------------------------------------
8014
8015class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8016  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8017              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8018                                               (v16i8 V128:$Rn),
8019                                               (v16i8 V128:$Rm)))]> {
8020  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8021}
8022
8023//----------------------------------------------------------------------------
8024// ARMv8.2-A Dot Product Instructions (Indexed)
8025class BaseSIMDThreeSameVectorDotIndex<bit Q, bit U, bit Mixed, bits<2> size, string asm,
8026                                      string dst_kind, string lhs_kind, string rhs_kind,
8027                                      RegisterOperand RegType,
8028                                      ValueType AccumType, ValueType InputType,
8029                                      SDPatternOperator OpNode> :
8030        BaseSIMDIndexedTied<Q, U, 0b0, size, {0b111, Mixed}, RegType, RegType, V128,
8031                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8032        [(set (AccumType RegType:$dst),
8033              (AccumType (OpNode (AccumType RegType:$Rd),
8034                                 (InputType RegType:$Rn),
8035                                 (InputType (bitconvert (AccumType
8036                                    (AArch64duplane32 (v4i32 V128:$Rm),
8037                                        VectorIndexS:$idx)))))))]> {
8038  bits<2> idx;
8039  let Inst{21}    = idx{0};  // L
8040  let Inst{11}    = idx{1};  // H
8041}
8042
8043multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8044                                       SDPatternOperator OpNode> {
8045  def v8i8  : BaseSIMDThreeSameVectorDotIndex<0, U, Mixed, size, asm, ".2s", ".8b", ".4b",
8046                                              V64, v2i32, v8i8, OpNode>;
8047  def v16i8 : BaseSIMDThreeSameVectorDotIndex<1, U, Mixed, size, asm, ".4s", ".16b", ".4b",
8048                                              V128, v4i32, v16i8, OpNode>;
8049}
8050
8051// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8052class BaseSIMDThreeSameVectorFMLIndex<bit Q, bit U, bits<4> opc, string asm,
8053                                      string dst_kind, string lhs_kind,
8054                                      string rhs_kind, RegisterOperand RegType,
8055                                      ValueType AccumType, ValueType InputType,
8056                                      SDPatternOperator OpNode> :
8057        BaseSIMDIndexedTied<Q, U, 0, 0b10, opc, RegType, RegType, V128,
8058                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8059          [(set (AccumType RegType:$dst),
8060                (AccumType (OpNode (AccumType RegType:$Rd),
8061                                   (InputType RegType:$Rn),
8062                                   (InputType (AArch64duplane16 (v8f16 V128:$Rm),
8063                                                VectorIndexH:$idx)))))]> {
8064  // idx = H:L:M
8065  bits<3> idx;
8066  let Inst{11} = idx{2}; // H
8067  let Inst{21} = idx{1}; // L
8068  let Inst{20} = idx{0}; // M
8069}
8070
8071multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8072                                       SDPatternOperator OpNode> {
8073  def v4f16 : BaseSIMDThreeSameVectorFMLIndex<0, U, opc, asm, ".2s", ".2h", ".h",
8074                                              V64, v2f32, v4f16, OpNode>;
8075  def v8f16 : BaseSIMDThreeSameVectorFMLIndex<1, U, opc, asm, ".4s", ".4h", ".h",
8076                                              V128, v4f32, v8f16, OpNode>;
8077}
8078
8079multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8080                         SDPatternOperator OpNode> {
8081  let Predicates = [HasNEON, HasFullFP16] in {
8082  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8083                                      V64, V64,
8084                                      V128_lo, VectorIndexH,
8085                                      asm, ".4h", ".4h", ".4h", ".h",
8086    [(set (v4f16 V64:$Rd),
8087        (OpNode (v4f16 V64:$Rn),
8088         (v4f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8089    bits<3> idx;
8090    let Inst{11} = idx{2};
8091    let Inst{21} = idx{1};
8092    let Inst{20} = idx{0};
8093  }
8094
8095  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8096                                      V128, V128,
8097                                      V128_lo, VectorIndexH,
8098                                      asm, ".8h", ".8h", ".8h", ".h",
8099    [(set (v8f16 V128:$Rd),
8100        (OpNode (v8f16 V128:$Rn),
8101         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8102    bits<3> idx;
8103    let Inst{11} = idx{2};
8104    let Inst{21} = idx{1};
8105    let Inst{20} = idx{0};
8106  }
8107  } // Predicates = [HasNEON, HasFullFP16]
8108
8109  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8110                                      V64, V64,
8111                                      V128, VectorIndexS,
8112                                      asm, ".2s", ".2s", ".2s", ".s",
8113    [(set (v2f32 V64:$Rd),
8114        (OpNode (v2f32 V64:$Rn),
8115         (v2f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8116    bits<2> idx;
8117    let Inst{11} = idx{1};
8118    let Inst{21} = idx{0};
8119  }
8120
8121  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8122                                      V128, V128,
8123                                      V128, VectorIndexS,
8124                                      asm, ".4s", ".4s", ".4s", ".s",
8125    [(set (v4f32 V128:$Rd),
8126        (OpNode (v4f32 V128:$Rn),
8127         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8128    bits<2> idx;
8129    let Inst{11} = idx{1};
8130    let Inst{21} = idx{0};
8131  }
8132
8133  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8134                                      V128, V128,
8135                                      V128, VectorIndexD,
8136                                      asm, ".2d", ".2d", ".2d", ".d",
8137    [(set (v2f64 V128:$Rd),
8138        (OpNode (v2f64 V128:$Rn),
8139         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8140    bits<1> idx;
8141    let Inst{11} = idx{0};
8142    let Inst{21} = 0;
8143  }
8144
8145  let Predicates = [HasNEON, HasFullFP16] in {
8146  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8147                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8148                                      asm, ".h", "", "", ".h",
8149    [(set (f16 FPR16Op:$Rd),
8150          (OpNode (f16 FPR16Op:$Rn),
8151                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8152                                       VectorIndexH:$idx))))]> {
8153    bits<3> idx;
8154    let Inst{11} = idx{2};
8155    let Inst{21} = idx{1};
8156    let Inst{20} = idx{0};
8157  }
8158  } // Predicates = [HasNEON, HasFullFP16]
8159
8160  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8161                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8162                                      asm, ".s", "", "", ".s",
8163    [(set (f32 FPR32Op:$Rd),
8164          (OpNode (f32 FPR32Op:$Rn),
8165                  (f32 (vector_extract (v4f32 V128:$Rm),
8166                                       VectorIndexS:$idx))))]> {
8167    bits<2> idx;
8168    let Inst{11} = idx{1};
8169    let Inst{21} = idx{0};
8170  }
8171
8172  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8173                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8174                                      asm, ".d", "", "", ".d",
8175    [(set (f64 FPR64Op:$Rd),
8176          (OpNode (f64 FPR64Op:$Rn),
8177                  (f64 (vector_extract (v2f64 V128:$Rm),
8178                                       VectorIndexD:$idx))))]> {
8179    bits<1> idx;
8180    let Inst{11} = idx{0};
8181    let Inst{21} = 0;
8182  }
8183}
8184
8185multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8186  let Predicates = [HasNEON, HasFullFP16] in {
8187  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8188  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8189                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8190                                           VectorIndexH:$idx))),
8191            (!cast<Instruction>(INST # "v8i16_indexed")
8192                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8193  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8194                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8195            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8196                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8197
8198  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8199                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8200                                           VectorIndexH:$idx))),
8201            (!cast<Instruction>(INST # "v4i16_indexed")
8202                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8203  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8204                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8205            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8206                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8207
8208  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8209                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8210            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8211                V128_lo:$Rm, VectorIndexH:$idx)>;
8212  } // Predicates = [HasNEON, HasFullFP16]
8213
8214  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8215  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8216                           (AArch64duplane32 (v4f32 V128:$Rm),
8217                                           VectorIndexS:$idx))),
8218            (!cast<Instruction>(INST # v2i32_indexed)
8219                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8220  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8221                           (AArch64dup (f32 FPR32Op:$Rm)))),
8222            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8223                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8224
8225
8226  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8227  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8228                           (AArch64duplane32 (v4f32 V128:$Rm),
8229                                           VectorIndexS:$idx))),
8230            (!cast<Instruction>(INST # "v4i32_indexed")
8231                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8232  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8233                           (AArch64dup (f32 FPR32Op:$Rm)))),
8234            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8235                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8236
8237  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8238  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8239                           (AArch64duplane64 (v2f64 V128:$Rm),
8240                                           VectorIndexD:$idx))),
8241            (!cast<Instruction>(INST # "v2i64_indexed")
8242                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8243  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8244                           (AArch64dup (f64 FPR64Op:$Rm)))),
8245            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
8246                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
8247
8248  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
8249  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
8250                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
8251            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
8252                V128:$Rm, VectorIndexS:$idx)>;
8253
8254  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
8255  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
8256                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
8257            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
8258                V128:$Rm, VectorIndexD:$idx)>;
8259}
8260
8261multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
8262  let Predicates = [HasNEON, HasFullFP16] in {
8263  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
8264                                          V128_lo, VectorIndexH,
8265                                          asm, ".4h", ".4h", ".4h", ".h", []> {
8266    bits<3> idx;
8267    let Inst{11} = idx{2};
8268    let Inst{21} = idx{1};
8269    let Inst{20} = idx{0};
8270  }
8271
8272  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
8273                                          V128, V128,
8274                                          V128_lo, VectorIndexH,
8275                                          asm, ".8h", ".8h", ".8h", ".h", []> {
8276    bits<3> idx;
8277    let Inst{11} = idx{2};
8278    let Inst{21} = idx{1};
8279    let Inst{20} = idx{0};
8280  }
8281  } // Predicates = [HasNEON, HasFullFP16]
8282
8283  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
8284                                          V128, VectorIndexS,
8285                                          asm, ".2s", ".2s", ".2s", ".s", []> {
8286    bits<2> idx;
8287    let Inst{11} = idx{1};
8288    let Inst{21} = idx{0};
8289  }
8290
8291  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8292                                      V128, V128,
8293                                      V128, VectorIndexS,
8294                                      asm, ".4s", ".4s", ".4s", ".s", []> {
8295    bits<2> idx;
8296    let Inst{11} = idx{1};
8297    let Inst{21} = idx{0};
8298  }
8299
8300  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
8301                                      V128, V128,
8302                                      V128, VectorIndexD,
8303                                      asm, ".2d", ".2d", ".2d", ".d", []> {
8304    bits<1> idx;
8305    let Inst{11} = idx{0};
8306    let Inst{21} = 0;
8307  }
8308
8309  let Predicates = [HasNEON, HasFullFP16] in {
8310  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
8311                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8312                                      asm, ".h", "", "", ".h", []> {
8313    bits<3> idx;
8314    let Inst{11} = idx{2};
8315    let Inst{21} = idx{1};
8316    let Inst{20} = idx{0};
8317  }
8318  } // Predicates = [HasNEON, HasFullFP16]
8319
8320  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8321                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8322                                      asm, ".s", "", "", ".s", []> {
8323    bits<2> idx;
8324    let Inst{11} = idx{1};
8325    let Inst{21} = idx{0};
8326  }
8327
8328  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
8329                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8330                                      asm, ".d", "", "", ".d", []> {
8331    bits<1> idx;
8332    let Inst{11} = idx{0};
8333    let Inst{21} = 0;
8334  }
8335}
8336
8337multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
8338                                 SDPatternOperator OpNodeLaneQ> {
8339
8340  def : Pat<(v4i16 (OpNodeLane
8341                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
8342                     VectorIndexS32b:$idx)),
8343            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
8344              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
8345              (UImmS1XForm $idx))>;
8346
8347  def : Pat<(v4i16 (OpNodeLaneQ
8348                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
8349                     VectorIndexH32b:$idx)),
8350            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
8351              (UImmS1XForm $idx))>;
8352
8353  def : Pat<(v8i16 (OpNodeLane
8354                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
8355                     VectorIndexS32b:$idx)),
8356            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
8357              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8358              (UImmS1XForm $idx))>;
8359
8360  def : Pat<(v8i16 (OpNodeLaneQ
8361                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
8362                     VectorIndexH32b:$idx)),
8363            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
8364              (UImmS1XForm $idx))>;
8365
8366  def : Pat<(v2i32 (OpNodeLane
8367                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
8368                     VectorIndexD32b:$idx)),
8369            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
8370              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
8371              (UImmS1XForm $idx))>;
8372
8373  def : Pat<(v2i32 (OpNodeLaneQ
8374                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
8375                     VectorIndexS32b:$idx)),
8376            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
8377              (UImmS1XForm $idx))>;
8378
8379  def : Pat<(v4i32 (OpNodeLane
8380                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
8381                     VectorIndexD32b:$idx)),
8382            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
8383              (SUBREG_TO_REG (i32 0), $Rm, dsub),
8384              (UImmS1XForm $idx))>;
8385
8386  def : Pat<(v4i32 (OpNodeLaneQ
8387                     (v4i32 V128:$Rn),
8388                     (v4i32 V128:$Rm),
8389                     VectorIndexS32b:$idx)),
8390            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
8391              (UImmS1XForm $idx))>;
8392
8393}
8394
8395multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
8396                         SDPatternOperator OpNode> {
8397  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
8398                                      V128_lo, VectorIndexH,
8399                                      asm, ".4h", ".4h", ".4h", ".h",
8400    [(set (v4i16 V64:$Rd),
8401        (OpNode (v4i16 V64:$Rn),
8402         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8403    bits<3> idx;
8404    let Inst{11} = idx{2};
8405    let Inst{21} = idx{1};
8406    let Inst{20} = idx{0};
8407  }
8408
8409  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8410                                      V128, V128,
8411                                      V128_lo, VectorIndexH,
8412                                      asm, ".8h", ".8h", ".8h", ".h",
8413    [(set (v8i16 V128:$Rd),
8414       (OpNode (v8i16 V128:$Rn),
8415         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8416    bits<3> idx;
8417    let Inst{11} = idx{2};
8418    let Inst{21} = idx{1};
8419    let Inst{20} = idx{0};
8420  }
8421
8422  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8423                                      V64, V64,
8424                                      V128, VectorIndexS,
8425                                      asm, ".2s", ".2s", ".2s",  ".s",
8426    [(set (v2i32 V64:$Rd),
8427       (OpNode (v2i32 V64:$Rn),
8428          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8429    bits<2> idx;
8430    let Inst{11} = idx{1};
8431    let Inst{21} = idx{0};
8432  }
8433
8434  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8435                                      V128, V128,
8436                                      V128, VectorIndexS,
8437                                      asm, ".4s", ".4s", ".4s", ".s",
8438    [(set (v4i32 V128:$Rd),
8439       (OpNode (v4i32 V128:$Rn),
8440          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8441    bits<2> idx;
8442    let Inst{11} = idx{1};
8443    let Inst{21} = idx{0};
8444  }
8445
8446  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8447                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8448                                      asm, ".h", "", "", ".h", []> {
8449    bits<3> idx;
8450    let Inst{11} = idx{2};
8451    let Inst{21} = idx{1};
8452    let Inst{20} = idx{0};
8453  }
8454
8455  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8456                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8457                                      asm, ".s", "", "", ".s",
8458      [(set (i32 FPR32Op:$Rd),
8459            (OpNode FPR32Op:$Rn,
8460                    (i32 (vector_extract (v4i32 V128:$Rm),
8461                                         VectorIndexS:$idx))))]> {
8462    bits<2> idx;
8463    let Inst{11} = idx{1};
8464    let Inst{21} = idx{0};
8465  }
8466}
8467
8468multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
8469                               SDPatternOperator OpNode> {
8470  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8471                                      V64, V64,
8472                                      V128_lo, VectorIndexH,
8473                                      asm, ".4h", ".4h", ".4h", ".h",
8474    [(set (v4i16 V64:$Rd),
8475        (OpNode (v4i16 V64:$Rn),
8476         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8477    bits<3> idx;
8478    let Inst{11} = idx{2};
8479    let Inst{21} = idx{1};
8480    let Inst{20} = idx{0};
8481  }
8482
8483  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8484                                      V128, V128,
8485                                      V128_lo, VectorIndexH,
8486                                      asm, ".8h", ".8h", ".8h", ".h",
8487    [(set (v8i16 V128:$Rd),
8488       (OpNode (v8i16 V128:$Rn),
8489         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8490    bits<3> idx;
8491    let Inst{11} = idx{2};
8492    let Inst{21} = idx{1};
8493    let Inst{20} = idx{0};
8494  }
8495
8496  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8497                                      V64, V64,
8498                                      V128, VectorIndexS,
8499                                      asm, ".2s", ".2s", ".2s", ".s",
8500    [(set (v2i32 V64:$Rd),
8501       (OpNode (v2i32 V64:$Rn),
8502          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8503    bits<2> idx;
8504    let Inst{11} = idx{1};
8505    let Inst{21} = idx{0};
8506  }
8507
8508  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8509                                      V128, V128,
8510                                      V128, VectorIndexS,
8511                                      asm, ".4s", ".4s", ".4s", ".s",
8512    [(set (v4i32 V128:$Rd),
8513       (OpNode (v4i32 V128:$Rn),
8514          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8515    bits<2> idx;
8516    let Inst{11} = idx{1};
8517    let Inst{21} = idx{0};
8518  }
8519}
8520
8521multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
8522                                   SDPatternOperator OpNode> {
8523  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
8524                                          V128_lo, VectorIndexH,
8525                                          asm, ".4h", ".4h", ".4h", ".h",
8526    [(set (v4i16 V64:$dst),
8527        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
8528         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8529    bits<3> idx;
8530    let Inst{11} = idx{2};
8531    let Inst{21} = idx{1};
8532    let Inst{20} = idx{0};
8533  }
8534
8535  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8536                                      V128, V128,
8537                                      V128_lo, VectorIndexH,
8538                                      asm, ".8h", ".8h", ".8h", ".h",
8539    [(set (v8i16 V128:$dst),
8540       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
8541         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8542    bits<3> idx;
8543    let Inst{11} = idx{2};
8544    let Inst{21} = idx{1};
8545    let Inst{20} = idx{0};
8546  }
8547
8548  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8549                                      V64, V64,
8550                                      V128, VectorIndexS,
8551                                      asm, ".2s", ".2s", ".2s", ".s",
8552    [(set (v2i32 V64:$dst),
8553       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
8554          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8555    bits<2> idx;
8556    let Inst{11} = idx{1};
8557    let Inst{21} = idx{0};
8558  }
8559
8560  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8561                                      V128, V128,
8562                                      V128, VectorIndexS,
8563                                      asm, ".4s", ".4s", ".4s", ".s",
8564    [(set (v4i32 V128:$dst),
8565       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
8566          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8567    bits<2> idx;
8568    let Inst{11} = idx{1};
8569    let Inst{21} = idx{0};
8570  }
8571}
8572
8573multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
8574                             SDPatternOperator OpNode> {
8575  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8576                                      V128, V64,
8577                                      V128_lo, VectorIndexH,
8578                                      asm, ".4s", ".4s", ".4h", ".h",
8579    [(set (v4i32 V128:$Rd),
8580        (OpNode (v4i16 V64:$Rn),
8581         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8582    bits<3> idx;
8583    let Inst{11} = idx{2};
8584    let Inst{21} = idx{1};
8585    let Inst{20} = idx{0};
8586  }
8587
8588  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8589                                      V128, V128,
8590                                      V128_lo, VectorIndexH,
8591                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8592    [(set (v4i32 V128:$Rd),
8593          (OpNode (extract_high_v8i16 V128:$Rn),
8594                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8595                                                      VectorIndexH:$idx))))]> {
8596
8597    bits<3> idx;
8598    let Inst{11} = idx{2};
8599    let Inst{21} = idx{1};
8600    let Inst{20} = idx{0};
8601  }
8602
8603  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8604                                      V128, V64,
8605                                      V128, VectorIndexS,
8606                                      asm, ".2d", ".2d", ".2s", ".s",
8607    [(set (v2i64 V128:$Rd),
8608        (OpNode (v2i32 V64:$Rn),
8609         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8610    bits<2> idx;
8611    let Inst{11} = idx{1};
8612    let Inst{21} = idx{0};
8613  }
8614
8615  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8616                                      V128, V128,
8617                                      V128, VectorIndexS,
8618                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8619    [(set (v2i64 V128:$Rd),
8620          (OpNode (extract_high_v4i32 V128:$Rn),
8621                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8622                                                      VectorIndexS:$idx))))]> {
8623    bits<2> idx;
8624    let Inst{11} = idx{1};
8625    let Inst{21} = idx{0};
8626  }
8627
8628  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
8629                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8630                                      asm, ".h", "", "", ".h", []> {
8631    bits<3> idx;
8632    let Inst{11} = idx{2};
8633    let Inst{21} = idx{1};
8634    let Inst{20} = idx{0};
8635  }
8636
8637  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8638                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8639                                      asm, ".s", "", "", ".s", []> {
8640    bits<2> idx;
8641    let Inst{11} = idx{1};
8642    let Inst{21} = idx{0};
8643  }
8644}
8645
8646multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
8647                                       SDPatternOperator Accum> {
8648  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8649                                      V128, V64,
8650                                      V128_lo, VectorIndexH,
8651                                      asm, ".4s", ".4s", ".4h", ".h",
8652    [(set (v4i32 V128:$dst),
8653          (Accum (v4i32 V128:$Rd),
8654                 (v4i32 (int_aarch64_neon_sqdmull
8655                             (v4i16 V64:$Rn),
8656                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8657                                                    VectorIndexH:$idx))))))]> {
8658    bits<3> idx;
8659    let Inst{11} = idx{2};
8660    let Inst{21} = idx{1};
8661    let Inst{20} = idx{0};
8662  }
8663
8664  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but an
8665  // intermediate EXTRACT_SUBREG would be untyped.
8666  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
8667                (i32 (vector_extract (v4i32
8668                         (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
8669                             (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8670                                                    VectorIndexH:$idx)))),
8671                         (i64 0))))),
8672            (EXTRACT_SUBREG
8673                (!cast<Instruction>(NAME # v4i16_indexed)
8674                    (SUBREG_TO_REG (i32 0), FPR32Op:$Rd, ssub), V64:$Rn,
8675                    V128_lo:$Rm, VectorIndexH:$idx),
8676                ssub)>;
8677
8678  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8679                                      V128, V128,
8680                                      V128_lo, VectorIndexH,
8681                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8682    [(set (v4i32 V128:$dst),
8683          (Accum (v4i32 V128:$Rd),
8684                 (v4i32 (int_aarch64_neon_sqdmull
8685                            (extract_high_v8i16 V128:$Rn),
8686                            (extract_high_v8i16
8687                                (AArch64duplane16 (v8i16 V128_lo:$Rm),
8688                                                VectorIndexH:$idx))))))]> {
8689    bits<3> idx;
8690    let Inst{11} = idx{2};
8691    let Inst{21} = idx{1};
8692    let Inst{20} = idx{0};
8693  }
8694
8695  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8696                                      V128, V64,
8697                                      V128, VectorIndexS,
8698                                      asm, ".2d", ".2d", ".2s", ".s",
8699    [(set (v2i64 V128:$dst),
8700        (Accum (v2i64 V128:$Rd),
8701               (v2i64 (int_aarch64_neon_sqdmull
8702                          (v2i32 V64:$Rn),
8703                          (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
8704                                                 VectorIndexS:$idx))))))]> {
8705    bits<2> idx;
8706    let Inst{11} = idx{1};
8707    let Inst{21} = idx{0};
8708  }
8709
8710  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8711                                      V128, V128,
8712                                      V128, VectorIndexS,
8713                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8714    [(set (v2i64 V128:$dst),
8715          (Accum (v2i64 V128:$Rd),
8716                 (v2i64 (int_aarch64_neon_sqdmull
8717                            (extract_high_v4i32 V128:$Rn),
8718                            (extract_high_v4i32
8719                                (AArch64duplane32 (v4i32 V128:$Rm),
8720                                                VectorIndexS:$idx))))))]> {
8721    bits<2> idx;
8722    let Inst{11} = idx{1};
8723    let Inst{21} = idx{0};
8724  }
8725
8726  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
8727                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
8728                                      asm, ".h", "", "", ".h", []> {
8729    bits<3> idx;
8730    let Inst{11} = idx{2};
8731    let Inst{21} = idx{1};
8732    let Inst{20} = idx{0};
8733  }
8734
8735
8736  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
8737                                      FPR64Op, FPR32Op, V128, VectorIndexS,
8738                                      asm, ".s", "", "", ".s",
8739    [(set (i64 FPR64Op:$dst),
8740          (Accum (i64 FPR64Op:$Rd),
8741                 (i64 (int_aarch64_neon_sqdmulls_scalar
8742                            (i32 FPR32Op:$Rn),
8743                            (i32 (vector_extract (v4i32 V128:$Rm),
8744                                                 VectorIndexS:$idx))))))]> {
8745
8746    bits<2> idx;
8747    let Inst{11} = idx{1};
8748    let Inst{21} = idx{0};
8749  }
8750}
8751
8752multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
8753                                   SDPatternOperator OpNode> {
8754  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8755  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
8756                                      V128, V64,
8757                                      V128_lo, VectorIndexH,
8758                                      asm, ".4s", ".4s", ".4h", ".h",
8759    [(set (v4i32 V128:$Rd),
8760        (OpNode (v4i16 V64:$Rn),
8761         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8762    bits<3> idx;
8763    let Inst{11} = idx{2};
8764    let Inst{21} = idx{1};
8765    let Inst{20} = idx{0};
8766  }
8767
8768  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
8769                                      V128, V128,
8770                                      V128_lo, VectorIndexH,
8771                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8772    [(set (v4i32 V128:$Rd),
8773          (OpNode (extract_high_v8i16 V128:$Rn),
8774                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8775                                                      VectorIndexH:$idx))))]> {
8776
8777    bits<3> idx;
8778    let Inst{11} = idx{2};
8779    let Inst{21} = idx{1};
8780    let Inst{20} = idx{0};
8781  }
8782
8783  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8784                                      V128, V64,
8785                                      V128, VectorIndexS,
8786                                      asm, ".2d", ".2d", ".2s", ".s",
8787    [(set (v2i64 V128:$Rd),
8788        (OpNode (v2i32 V64:$Rn),
8789         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8790    bits<2> idx;
8791    let Inst{11} = idx{1};
8792    let Inst{21} = idx{0};
8793  }
8794
8795  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8796                                      V128, V128,
8797                                      V128, VectorIndexS,
8798                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8799    [(set (v2i64 V128:$Rd),
8800          (OpNode (extract_high_v4i32 V128:$Rn),
8801                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8802                                                      VectorIndexS:$idx))))]> {
8803    bits<2> idx;
8804    let Inst{11} = idx{1};
8805    let Inst{21} = idx{0};
8806  }
8807  }
8808}
8809
8810multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
8811                                       SDPatternOperator OpNode> {
8812  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
8813  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
8814                                      V128, V64,
8815                                      V128_lo, VectorIndexH,
8816                                      asm, ".4s", ".4s", ".4h", ".h",
8817    [(set (v4i32 V128:$dst),
8818        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
8819         (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8820    bits<3> idx;
8821    let Inst{11} = idx{2};
8822    let Inst{21} = idx{1};
8823    let Inst{20} = idx{0};
8824  }
8825
8826  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
8827                                      V128, V128,
8828                                      V128_lo, VectorIndexH,
8829                                      asm#"2", ".4s", ".4s", ".8h", ".h",
8830    [(set (v4i32 V128:$dst),
8831          (OpNode (v4i32 V128:$Rd),
8832                  (extract_high_v8i16 V128:$Rn),
8833                  (extract_high_v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
8834                                                      VectorIndexH:$idx))))]> {
8835    bits<3> idx;
8836    let Inst{11} = idx{2};
8837    let Inst{21} = idx{1};
8838    let Inst{20} = idx{0};
8839  }
8840
8841  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
8842                                      V128, V64,
8843                                      V128, VectorIndexS,
8844                                      asm, ".2d", ".2d", ".2s", ".s",
8845    [(set (v2i64 V128:$dst),
8846        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
8847         (v2i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
8848    bits<2> idx;
8849    let Inst{11} = idx{1};
8850    let Inst{21} = idx{0};
8851  }
8852
8853  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
8854                                      V128, V128,
8855                                      V128, VectorIndexS,
8856                                      asm#"2", ".2d", ".2d", ".4s", ".s",
8857    [(set (v2i64 V128:$dst),
8858          (OpNode (v2i64 V128:$Rd),
8859                  (extract_high_v4i32 V128:$Rn),
8860                  (extract_high_v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
8861                                                      VectorIndexS:$idx))))]> {
8862    bits<2> idx;
8863    let Inst{11} = idx{1};
8864    let Inst{21} = idx{0};
8865  }
8866  }
8867}
8868
8869//----------------------------------------------------------------------------
8870// AdvSIMD scalar shift by immediate
8871//----------------------------------------------------------------------------
8872
8873let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8874class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
8875                     RegisterClass regtype1, RegisterClass regtype2,
8876                     Operand immtype, string asm, list<dag> pattern>
8877  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
8878      asm, "\t$Rd, $Rn, $imm", "", pattern>,
8879    Sched<[WriteV]> {
8880  bits<5> Rd;
8881  bits<5> Rn;
8882  bits<7> imm;
8883  let Inst{31-30} = 0b01;
8884  let Inst{29}    = U;
8885  let Inst{28-23} = 0b111110;
8886  let Inst{22-16} = fixed_imm;
8887  let Inst{15-11} = opc;
8888  let Inst{10}    = 1;
8889  let Inst{9-5} = Rn;
8890  let Inst{4-0} = Rd;
8891}
8892
8893let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8894class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
8895                     RegisterClass regtype1, RegisterClass regtype2,
8896                     Operand immtype, string asm, list<dag> pattern>
8897  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
8898      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
8899    Sched<[WriteV]> {
8900  bits<5> Rd;
8901  bits<5> Rn;
8902  bits<7> imm;
8903  let Inst{31-30} = 0b01;
8904  let Inst{29}    = U;
8905  let Inst{28-23} = 0b111110;
8906  let Inst{22-16} = fixed_imm;
8907  let Inst{15-11} = opc;
8908  let Inst{10}    = 1;
8909  let Inst{9-5} = Rn;
8910  let Inst{4-0} = Rd;
8911}
8912
8913
8914multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
8915  let Predicates = [HasNEON, HasFullFP16] in {
8916  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8917                              FPR16, FPR16, vecshiftR16, asm, []> {
8918    let Inst{19-16} = imm{3-0};
8919  }
8920  } // Predicates = [HasNEON, HasFullFP16]
8921  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8922                              FPR32, FPR32, vecshiftR32, asm, []> {
8923    let Inst{20-16} = imm{4-0};
8924  }
8925  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8926                              FPR64, FPR64, vecshiftR64, asm, []> {
8927    let Inst{21-16} = imm{5-0};
8928  }
8929}
8930
8931multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
8932                             SDPatternOperator OpNode> {
8933  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8934                              FPR64, FPR64, vecshiftR64, asm,
8935  [(set (i64 FPR64:$Rd),
8936     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
8937    let Inst{21-16} = imm{5-0};
8938  }
8939
8940  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
8941            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
8942}
8943
8944multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
8945                                 SDPatternOperator OpNode = null_frag> {
8946  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8947                              FPR64, FPR64, vecshiftR64, asm,
8948  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
8949                                                   (i32 vecshiftR64:$imm)))]> {
8950    let Inst{21-16} = imm{5-0};
8951  }
8952
8953  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
8954                           (i32 vecshiftR64:$imm))),
8955            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
8956                                            vecshiftR64:$imm)>;
8957}
8958
8959multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
8960                             SDPatternOperator OpNode> {
8961  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
8962                              FPR64, FPR64, vecshiftL64, asm,
8963    [(set (i64 FPR64:$Rd),
8964       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
8965    let Inst{21-16} = imm{5-0};
8966  }
8967
8968  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
8969            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
8970}
8971
8972let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8973multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
8974  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
8975                              FPR64, FPR64, vecshiftL64, asm, []> {
8976    let Inst{21-16} = imm{5-0};
8977  }
8978}
8979
8980let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8981multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
8982                               SDPatternOperator OpNode = null_frag> {
8983  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
8984                              FPR8, FPR16, vecshiftR8, asm, []> {
8985    let Inst{18-16} = imm{2-0};
8986  }
8987
8988  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
8989                              FPR16, FPR32, vecshiftR16, asm, []> {
8990    let Inst{19-16} = imm{3-0};
8991  }
8992
8993  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
8994                              FPR32, FPR64, vecshiftR32, asm,
8995    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
8996    let Inst{20-16} = imm{4-0};
8997  }
8998}
8999
9000multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9001                                SDPatternOperator OpNode> {
9002  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9003                              FPR8, FPR8, vecshiftL8, asm, []> {
9004    let Inst{18-16} = imm{2-0};
9005  }
9006
9007  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9008                              FPR16, FPR16, vecshiftL16, asm, []> {
9009    let Inst{19-16} = imm{3-0};
9010  }
9011
9012  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9013                              FPR32, FPR32, vecshiftL32, asm,
9014    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9015    let Inst{20-16} = imm{4-0};
9016  }
9017
9018  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9019                              FPR64, FPR64, vecshiftL64, asm,
9020    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9021    let Inst{21-16} = imm{5-0};
9022  }
9023
9024  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9025            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9026}
9027
9028multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9029  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9030                              FPR8, FPR8, vecshiftR8, asm, []> {
9031    let Inst{18-16} = imm{2-0};
9032  }
9033
9034  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9035                              FPR16, FPR16, vecshiftR16, asm, []> {
9036    let Inst{19-16} = imm{3-0};
9037  }
9038
9039  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9040                              FPR32, FPR32, vecshiftR32, asm, []> {
9041    let Inst{20-16} = imm{4-0};
9042  }
9043
9044  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9045                              FPR64, FPR64, vecshiftR64, asm, []> {
9046    let Inst{21-16} = imm{5-0};
9047  }
9048}
9049
9050//----------------------------------------------------------------------------
9051// AdvSIMD vector x indexed element
9052//----------------------------------------------------------------------------
9053
9054let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9055class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9056                     RegisterOperand dst_reg, RegisterOperand src_reg,
9057                     Operand immtype,
9058                     string asm, string dst_kind, string src_kind,
9059                     list<dag> pattern>
9060  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9061      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9062           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9063    Sched<[WriteV]> {
9064  bits<5> Rd;
9065  bits<5> Rn;
9066  let Inst{31}    = 0;
9067  let Inst{30}    = Q;
9068  let Inst{29}    = U;
9069  let Inst{28-23} = 0b011110;
9070  let Inst{22-16} = fixed_imm;
9071  let Inst{15-11} = opc;
9072  let Inst{10}    = 1;
9073  let Inst{9-5}   = Rn;
9074  let Inst{4-0}   = Rd;
9075}
9076
9077let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9078class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9079                     RegisterOperand vectype1, RegisterOperand vectype2,
9080                     Operand immtype,
9081                     string asm, string dst_kind, string src_kind,
9082                     list<dag> pattern>
9083  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9084      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9085           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9086    Sched<[WriteV]> {
9087  bits<5> Rd;
9088  bits<5> Rn;
9089  let Inst{31}    = 0;
9090  let Inst{30}    = Q;
9091  let Inst{29}    = U;
9092  let Inst{28-23} = 0b011110;
9093  let Inst{22-16} = fixed_imm;
9094  let Inst{15-11} = opc;
9095  let Inst{10}    = 1;
9096  let Inst{9-5}   = Rn;
9097  let Inst{4-0}   = Rd;
9098}
9099
9100multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9101                              Intrinsic OpNode> {
9102  let Predicates = [HasNEON, HasFullFP16] in {
9103  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9104                                  V64, V64, vecshiftR16,
9105                                  asm, ".4h", ".4h",
9106      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9107    bits<4> imm;
9108    let Inst{19-16} = imm;
9109  }
9110
9111  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9112                                  V128, V128, vecshiftR16,
9113                                  asm, ".8h", ".8h",
9114      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9115    bits<4> imm;
9116    let Inst{19-16} = imm;
9117  }
9118  } // Predicates = [HasNEON, HasFullFP16]
9119  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9120                                  V64, V64, vecshiftR32,
9121                                  asm, ".2s", ".2s",
9122      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9123    bits<5> imm;
9124    let Inst{20-16} = imm;
9125  }
9126
9127  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9128                                  V128, V128, vecshiftR32,
9129                                  asm, ".4s", ".4s",
9130      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9131    bits<5> imm;
9132    let Inst{20-16} = imm;
9133  }
9134
9135  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9136                                  V128, V128, vecshiftR64,
9137                                  asm, ".2d", ".2d",
9138      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9139    bits<6> imm;
9140    let Inst{21-16} = imm;
9141  }
9142}
9143
9144multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9145                                  Intrinsic OpNode> {
9146  let Predicates = [HasNEON, HasFullFP16] in {
9147  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9148                                  V64, V64, vecshiftR16,
9149                                  asm, ".4h", ".4h",
9150      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9151    bits<4> imm;
9152    let Inst{19-16} = imm;
9153  }
9154
9155  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9156                                  V128, V128, vecshiftR16,
9157                                  asm, ".8h", ".8h",
9158      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9159    bits<4> imm;
9160    let Inst{19-16} = imm;
9161  }
9162  } // Predicates = [HasNEON, HasFullFP16]
9163
9164  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9165                                  V64, V64, vecshiftR32,
9166                                  asm, ".2s", ".2s",
9167      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9168    bits<5> imm;
9169    let Inst{20-16} = imm;
9170  }
9171
9172  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9173                                  V128, V128, vecshiftR32,
9174                                  asm, ".4s", ".4s",
9175      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9176    bits<5> imm;
9177    let Inst{20-16} = imm;
9178  }
9179
9180  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9181                                  V128, V128, vecshiftR64,
9182                                  asm, ".2d", ".2d",
9183      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9184    bits<6> imm;
9185    let Inst{21-16} = imm;
9186  }
9187}
9188
9189multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9190                                     SDPatternOperator OpNode> {
9191  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9192                                  V64, V128, vecshiftR16Narrow,
9193                                  asm, ".8b", ".8h",
9194      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9195    bits<3> imm;
9196    let Inst{18-16} = imm;
9197  }
9198
9199  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9200                                  V128, V128, vecshiftR16Narrow,
9201                                  asm#"2", ".16b", ".8h", []> {
9202    bits<3> imm;
9203    let Inst{18-16} = imm;
9204    let hasSideEffects = 0;
9205  }
9206
9207  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9208                                  V64, V128, vecshiftR32Narrow,
9209                                  asm, ".4h", ".4s",
9210      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9211    bits<4> imm;
9212    let Inst{19-16} = imm;
9213  }
9214
9215  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9216                                  V128, V128, vecshiftR32Narrow,
9217                                  asm#"2", ".8h", ".4s", []> {
9218    bits<4> imm;
9219    let Inst{19-16} = imm;
9220    let hasSideEffects = 0;
9221  }
9222
9223  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9224                                  V64, V128, vecshiftR64Narrow,
9225                                  asm, ".2s", ".2d",
9226      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9227    bits<5> imm;
9228    let Inst{20-16} = imm;
9229  }
9230
9231  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9232                                  V128, V128, vecshiftR64Narrow,
9233                                  asm#"2", ".4s", ".2d", []> {
9234    bits<5> imm;
9235    let Inst{20-16} = imm;
9236    let hasSideEffects = 0;
9237  }
9238
9239  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
9240  // themselves, so put them here instead.
9241
9242  // Patterns involving what's effectively an insert high and a normal
9243  // intrinsic, represented by CONCAT_VECTORS.
9244  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
9245                                                   vecshiftR16Narrow:$imm)),
9246            (!cast<Instruction>(NAME # "v16i8_shift")
9247                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9248                V128:$Rn, vecshiftR16Narrow:$imm)>;
9249  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
9250                                                     vecshiftR32Narrow:$imm)),
9251            (!cast<Instruction>(NAME # "v8i16_shift")
9252                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9253                V128:$Rn, vecshiftR32Narrow:$imm)>;
9254  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
9255                                                     vecshiftR64Narrow:$imm)),
9256            (!cast<Instruction>(NAME # "v4i32_shift")
9257                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
9258                V128:$Rn, vecshiftR64Narrow:$imm)>;
9259}
9260
9261multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
9262                                SDPatternOperator OpNode> {
9263  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9264                                  V64, V64, vecshiftL8,
9265                                  asm, ".8b", ".8b",
9266                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9267                       (i32 vecshiftL8:$imm)))]> {
9268    bits<3> imm;
9269    let Inst{18-16} = imm;
9270  }
9271
9272  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9273                                  V128, V128, vecshiftL8,
9274                                  asm, ".16b", ".16b",
9275             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9276                   (i32 vecshiftL8:$imm)))]> {
9277    bits<3> imm;
9278    let Inst{18-16} = imm;
9279  }
9280
9281  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9282                                  V64, V64, vecshiftL16,
9283                                  asm, ".4h", ".4h",
9284              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9285                    (i32 vecshiftL16:$imm)))]> {
9286    bits<4> imm;
9287    let Inst{19-16} = imm;
9288  }
9289
9290  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9291                                  V128, V128, vecshiftL16,
9292                                  asm, ".8h", ".8h",
9293            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9294                  (i32 vecshiftL16:$imm)))]> {
9295    bits<4> imm;
9296    let Inst{19-16} = imm;
9297  }
9298
9299  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9300                                  V64, V64, vecshiftL32,
9301                                  asm, ".2s", ".2s",
9302              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9303                    (i32 vecshiftL32:$imm)))]> {
9304    bits<5> imm;
9305    let Inst{20-16} = imm;
9306  }
9307
9308  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9309                                  V128, V128, vecshiftL32,
9310                                  asm, ".4s", ".4s",
9311            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9312                  (i32 vecshiftL32:$imm)))]> {
9313    bits<5> imm;
9314    let Inst{20-16} = imm;
9315  }
9316
9317  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9318                                  V128, V128, vecshiftL64,
9319                                  asm, ".2d", ".2d",
9320            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9321                  (i32 vecshiftL64:$imm)))]> {
9322    bits<6> imm;
9323    let Inst{21-16} = imm;
9324  }
9325}
9326
9327multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
9328                                SDPatternOperator OpNode> {
9329  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9330                                  V64, V64, vecshiftR8,
9331                                  asm, ".8b", ".8b",
9332                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
9333                       (i32 vecshiftR8:$imm)))]> {
9334    bits<3> imm;
9335    let Inst{18-16} = imm;
9336  }
9337
9338  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9339                                  V128, V128, vecshiftR8,
9340                                  asm, ".16b", ".16b",
9341             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
9342                   (i32 vecshiftR8:$imm)))]> {
9343    bits<3> imm;
9344    let Inst{18-16} = imm;
9345  }
9346
9347  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9348                                  V64, V64, vecshiftR16,
9349                                  asm, ".4h", ".4h",
9350              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
9351                    (i32 vecshiftR16:$imm)))]> {
9352    bits<4> imm;
9353    let Inst{19-16} = imm;
9354  }
9355
9356  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9357                                  V128, V128, vecshiftR16,
9358                                  asm, ".8h", ".8h",
9359            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
9360                  (i32 vecshiftR16:$imm)))]> {
9361    bits<4> imm;
9362    let Inst{19-16} = imm;
9363  }
9364
9365  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9366                                  V64, V64, vecshiftR32,
9367                                  asm, ".2s", ".2s",
9368              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
9369                    (i32 vecshiftR32:$imm)))]> {
9370    bits<5> imm;
9371    let Inst{20-16} = imm;
9372  }
9373
9374  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9375                                  V128, V128, vecshiftR32,
9376                                  asm, ".4s", ".4s",
9377            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
9378                  (i32 vecshiftR32:$imm)))]> {
9379    bits<5> imm;
9380    let Inst{20-16} = imm;
9381  }
9382
9383  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9384                                  V128, V128, vecshiftR64,
9385                                  asm, ".2d", ".2d",
9386            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
9387                  (i32 vecshiftR64:$imm)))]> {
9388    bits<6> imm;
9389    let Inst{21-16} = imm;
9390  }
9391}
9392
9393let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
9394multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
9395                                    SDPatternOperator OpNode = null_frag> {
9396  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9397                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
9398                 [(set (v8i8 V64:$dst),
9399                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9400                           (i32 vecshiftR8:$imm)))]> {
9401    bits<3> imm;
9402    let Inst{18-16} = imm;
9403  }
9404
9405  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9406                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
9407             [(set (v16i8 V128:$dst),
9408               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9409                       (i32 vecshiftR8:$imm)))]> {
9410    bits<3> imm;
9411    let Inst{18-16} = imm;
9412  }
9413
9414  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9415                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
9416              [(set (v4i16 V64:$dst),
9417                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9418                        (i32 vecshiftR16:$imm)))]> {
9419    bits<4> imm;
9420    let Inst{19-16} = imm;
9421  }
9422
9423  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9424                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
9425            [(set (v8i16 V128:$dst),
9426              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9427                      (i32 vecshiftR16:$imm)))]> {
9428    bits<4> imm;
9429    let Inst{19-16} = imm;
9430  }
9431
9432  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9433                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
9434              [(set (v2i32 V64:$dst),
9435                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9436                        (i32 vecshiftR32:$imm)))]> {
9437    bits<5> imm;
9438    let Inst{20-16} = imm;
9439  }
9440
9441  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9442                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
9443            [(set (v4i32 V128:$dst),
9444              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9445                      (i32 vecshiftR32:$imm)))]> {
9446    bits<5> imm;
9447    let Inst{20-16} = imm;
9448  }
9449
9450  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9451                                  V128, V128, vecshiftR64,
9452                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
9453              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9454                      (i32 vecshiftR64:$imm)))]> {
9455    bits<6> imm;
9456    let Inst{21-16} = imm;
9457  }
9458}
9459
9460multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
9461                                    SDPatternOperator OpNode = null_frag> {
9462  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
9463                                  V64, V64, vecshiftL8,
9464                                  asm, ".8b", ".8b",
9465                    [(set (v8i8 V64:$dst),
9466                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
9467                                  (i32 vecshiftL8:$imm)))]> {
9468    bits<3> imm;
9469    let Inst{18-16} = imm;
9470  }
9471
9472  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9473                                  V128, V128, vecshiftL8,
9474                                  asm, ".16b", ".16b",
9475                    [(set (v16i8 V128:$dst),
9476                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
9477                                  (i32 vecshiftL8:$imm)))]> {
9478    bits<3> imm;
9479    let Inst{18-16} = imm;
9480  }
9481
9482  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
9483                                  V64, V64, vecshiftL16,
9484                                  asm, ".4h", ".4h",
9485                    [(set (v4i16 V64:$dst),
9486                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
9487                                   (i32 vecshiftL16:$imm)))]> {
9488    bits<4> imm;
9489    let Inst{19-16} = imm;
9490  }
9491
9492  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9493                                  V128, V128, vecshiftL16,
9494                                  asm, ".8h", ".8h",
9495                    [(set (v8i16 V128:$dst),
9496                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9497                                  (i32 vecshiftL16:$imm)))]> {
9498    bits<4> imm;
9499    let Inst{19-16} = imm;
9500  }
9501
9502  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
9503                                  V64, V64, vecshiftL32,
9504                                  asm, ".2s", ".2s",
9505                    [(set (v2i32 V64:$dst),
9506                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9507                                  (i32 vecshiftL32:$imm)))]> {
9508    bits<5> imm;
9509    let Inst{20-16} = imm;
9510  }
9511
9512  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9513                                  V128, V128, vecshiftL32,
9514                                  asm, ".4s", ".4s",
9515                    [(set (v4i32 V128:$dst),
9516                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9517                                  (i32 vecshiftL32:$imm)))]> {
9518    bits<5> imm;
9519    let Inst{20-16} = imm;
9520  }
9521
9522  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
9523                                  V128, V128, vecshiftL64,
9524                                  asm, ".2d", ".2d",
9525                    [(set (v2i64 V128:$dst),
9526                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
9527                                  (i32 vecshiftL64:$imm)))]> {
9528    bits<6> imm;
9529    let Inst{21-16} = imm;
9530  }
9531}
9532
9533multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
9534                                   SDPatternOperator OpNode> {
9535  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9536                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
9537      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
9538    bits<3> imm;
9539    let Inst{18-16} = imm;
9540  }
9541
9542  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
9543                                  V128, V128, vecshiftL8,
9544                                  asm#"2", ".8h", ".16b",
9545      [(set (v8i16 V128:$Rd),
9546            (OpNode (extract_high_v16i8 V128:$Rn), vecshiftL8:$imm))]> {
9547    bits<3> imm;
9548    let Inst{18-16} = imm;
9549  }
9550
9551  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9552                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
9553      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
9554    bits<4> imm;
9555    let Inst{19-16} = imm;
9556  }
9557
9558  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9559                                  V128, V128, vecshiftL16,
9560                                  asm#"2", ".4s", ".8h",
9561      [(set (v4i32 V128:$Rd),
9562            (OpNode (extract_high_v8i16 V128:$Rn), vecshiftL16:$imm))]> {
9563
9564    bits<4> imm;
9565    let Inst{19-16} = imm;
9566  }
9567
9568  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9569                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
9570      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
9571    bits<5> imm;
9572    let Inst{20-16} = imm;
9573  }
9574
9575  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9576                                  V128, V128, vecshiftL32,
9577                                  asm#"2", ".2d", ".4s",
9578      [(set (v2i64 V128:$Rd),
9579            (OpNode (extract_high_v4i32 V128:$Rn), vecshiftL32:$imm))]> {
9580    bits<5> imm;
9581    let Inst{20-16} = imm;
9582  }
9583}
9584
9585
9586//---
9587// Vector load/store
9588//---
9589// SIMD ldX/stX no-index memory references don't allow the optional
9590// ", #0" constant and handle post-indexing explicitly, so we use
9591// a more specialized parse method for them. Otherwise, it's the same as
9592// the general GPR64sp handling.
9593
9594class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
9595                   string asm, dag oops, dag iops, list<dag> pattern>
9596  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
9597  bits<5> Vt;
9598  bits<5> Rn;
9599  let Inst{31} = 0;
9600  let Inst{30} = Q;
9601  let Inst{29-23} = 0b0011000;
9602  let Inst{22} = L;
9603  let Inst{21-16} = 0b000000;
9604  let Inst{15-12} = opcode;
9605  let Inst{11-10} = size;
9606  let Inst{9-5} = Rn;
9607  let Inst{4-0} = Vt;
9608}
9609
9610class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
9611                       string asm, dag oops, dag iops>
9612  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
9613  bits<5> Vt;
9614  bits<5> Rn;
9615  bits<5> Xm;
9616  let Inst{31} = 0;
9617  let Inst{30} = Q;
9618  let Inst{29-23} = 0b0011001;
9619  let Inst{22} = L;
9620  let Inst{21} = 0;
9621  let Inst{20-16} = Xm;
9622  let Inst{15-12} = opcode;
9623  let Inst{11-10} = size;
9624  let Inst{9-5} = Rn;
9625  let Inst{4-0} = Vt;
9626}
9627
9628// The immediate form of AdvSIMD post-indexed addressing is encoded with
9629// register post-index addressing from the zero register.
9630multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
9631                           int Offset, int Size> {
9632  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
9633  //      "ld1\t$Vt, [$Rn], #16"
9634  // may get mapped to
9635  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
9636  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9637                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9638                      GPR64sp:$Rn,
9639                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9640                      XZR), 1>;
9641
9642  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
9643  //      "ld1.8b\t$Vt, [$Rn], #16"
9644  // may get mapped to
9645  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
9646  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9647                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9648                      GPR64sp:$Rn,
9649                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9650                      XZR), 0>;
9651
9652  // E.g. "ld1.8b { v0, v1 }, [x1]"
9653  //      "ld1\t$Vt, [$Rn]"
9654  // may get mapped to
9655  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
9656  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9657                  (!cast<Instruction>(BaseName # Count # "v" # layout)
9658                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9659                      GPR64sp:$Rn), 0>;
9660
9661  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
9662  //      "ld1\t$Vt, [$Rn], $Xm"
9663  // may get mapped to
9664  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
9665  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9666                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
9667                      GPR64sp:$Rn,
9668                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9669                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9670}
9671
9672multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
9673                       int Offset128, int Offset64, bits<4> opcode> {
9674  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9675    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
9676                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
9677                           (ins GPR64sp:$Rn), []>;
9678    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
9679                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
9680                           (ins GPR64sp:$Rn), []>;
9681    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
9682                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
9683                           (ins GPR64sp:$Rn), []>;
9684    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
9685                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
9686                           (ins GPR64sp:$Rn), []>;
9687    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
9688                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
9689                           (ins GPR64sp:$Rn), []>;
9690    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
9691                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
9692                           (ins GPR64sp:$Rn), []>;
9693    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
9694                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
9695                           (ins GPR64sp:$Rn), []>;
9696
9697
9698    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
9699                       (outs GPR64sp:$wback,
9700                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
9701                       (ins GPR64sp:$Rn,
9702                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9703    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
9704                       (outs GPR64sp:$wback,
9705                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
9706                       (ins GPR64sp:$Rn,
9707                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9708    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
9709                       (outs GPR64sp:$wback,
9710                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
9711                       (ins GPR64sp:$Rn,
9712                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9713    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
9714                       (outs GPR64sp:$wback,
9715                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
9716                       (ins GPR64sp:$Rn,
9717                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9718    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
9719                       (outs GPR64sp:$wback,
9720                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
9721                       (ins GPR64sp:$Rn,
9722                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9723    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
9724                       (outs GPR64sp:$wback,
9725                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
9726                       (ins GPR64sp:$Rn,
9727                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9728    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
9729                       (outs GPR64sp:$wback,
9730                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
9731                       (ins GPR64sp:$Rn,
9732                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9733  }
9734
9735  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9736  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9737  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9738  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9739  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9740  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9741  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9742}
9743
9744// Only ld1/st1 has a v1d version.
9745multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
9746                       int Offset128, int Offset64, bits<4> opcode> {
9747  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
9748    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
9749                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9750                                 GPR64sp:$Rn), []>;
9751    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
9752                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9753                                GPR64sp:$Rn), []>;
9754    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
9755                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9756                                GPR64sp:$Rn), []>;
9757    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
9758                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9759                                GPR64sp:$Rn), []>;
9760    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
9761                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9762                                GPR64sp:$Rn), []>;
9763    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
9764                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9765                                GPR64sp:$Rn), []>;
9766    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
9767                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9768                                GPR64sp:$Rn), []>;
9769
9770    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
9771                       (outs GPR64sp:$wback),
9772                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
9773                            GPR64sp:$Rn,
9774                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9775    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
9776                       (outs GPR64sp:$wback),
9777                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
9778                            GPR64sp:$Rn,
9779                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9780    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
9781                       (outs GPR64sp:$wback),
9782                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
9783                            GPR64sp:$Rn,
9784                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9785    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
9786                       (outs GPR64sp:$wback),
9787                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
9788                            GPR64sp:$Rn,
9789                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
9790    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
9791                       (outs GPR64sp:$wback),
9792                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
9793                            GPR64sp:$Rn,
9794                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9795    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
9796                       (outs GPR64sp:$wback),
9797                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
9798                            GPR64sp:$Rn,
9799                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9800    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
9801                       (outs GPR64sp:$wback),
9802                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
9803                            GPR64sp:$Rn,
9804                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9805  }
9806
9807  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
9808  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
9809  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
9810  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
9811  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
9812  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
9813  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
9814}
9815
9816multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
9817                       int Offset128, int Offset64, bits<4> opcode>
9818  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9819
9820  // LD1 instructions have extra "1d" variants.
9821  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
9822    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
9823                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
9824                           (ins GPR64sp:$Rn), []>;
9825
9826    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
9827                       (outs GPR64sp:$wback,
9828                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
9829                       (ins GPR64sp:$Rn,
9830                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9831  }
9832
9833  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9834}
9835
9836multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
9837                       int Offset128, int Offset64, bits<4> opcode>
9838  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
9839
9840  // ST1 instructions have extra "1d" variants.
9841  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
9842    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
9843                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9844                                GPR64sp:$Rn), []>;
9845
9846    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
9847                       (outs GPR64sp:$wback),
9848                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
9849                            GPR64sp:$Rn,
9850                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
9851  }
9852
9853  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
9854}
9855
9856multiclass SIMDLd1Multiple<string asm> {
9857  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9858  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9859  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9860  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9861}
9862
9863multiclass SIMDSt1Multiple<string asm> {
9864  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
9865  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
9866  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
9867  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
9868}
9869
9870multiclass SIMDLd2Multiple<string asm> {
9871  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9872}
9873
9874multiclass SIMDSt2Multiple<string asm> {
9875  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
9876}
9877
9878multiclass SIMDLd3Multiple<string asm> {
9879  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9880}
9881
9882multiclass SIMDSt3Multiple<string asm> {
9883  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
9884}
9885
9886multiclass SIMDLd4Multiple<string asm> {
9887  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9888}
9889
9890multiclass SIMDSt4Multiple<string asm> {
9891  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
9892}
9893
9894//---
9895// AdvSIMD Load/store single-element
9896//---
9897
9898class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
9899                         string asm, string operands, string cst,
9900                         dag oops, dag iops, list<dag> pattern>
9901  : I<oops, iops, asm, operands, cst, pattern> {
9902  bits<5> Vt;
9903  bits<5> Rn;
9904  let Inst{31} = 0;
9905  let Inst{29-24} = 0b001101;
9906  let Inst{22} = L;
9907  let Inst{21} = R;
9908  let Inst{15-13} = opcode;
9909  let Inst{9-5} = Rn;
9910  let Inst{4-0} = Vt;
9911}
9912
9913class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
9914                         string asm, string operands, string cst,
9915                         dag oops, dag iops, list<dag> pattern>
9916  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
9917  bits<5> Vt;
9918  bits<5> Rn;
9919  let Inst{31} = 0;
9920  let Inst{29-24} = 0b001101;
9921  let Inst{22} = L;
9922  let Inst{21} = R;
9923  let Inst{15-13} = opcode;
9924  let Inst{9-5} = Rn;
9925  let Inst{4-0} = Vt;
9926}
9927
9928
9929let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9930class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
9931                  DAGOperand listtype>
9932  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
9933                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
9934                       []> {
9935  let Inst{30} = Q;
9936  let Inst{23} = 0;
9937  let Inst{20-16} = 0b00000;
9938  let Inst{12} = S;
9939  let Inst{11-10} = size;
9940}
9941let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
9942class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
9943                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
9944  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
9945                       "$Rn = $wback",
9946                       (outs GPR64sp:$wback, listtype:$Vt),
9947                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
9948  bits<5> Xm;
9949  let Inst{30} = Q;
9950  let Inst{23} = 1;
9951  let Inst{20-16} = Xm;
9952  let Inst{12} = S;
9953  let Inst{11-10} = size;
9954}
9955
9956multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
9957                          int Offset, int Size> {
9958  // E.g. "ld1r { v0.8b }, [x1], #1"
9959  //      "ld1r.8b\t$Vt, [$Rn], #1"
9960  // may get mapped to
9961  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
9962  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
9963                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9964                      GPR64sp:$Rn,
9965                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
9966                      XZR), 1>;
9967
9968  // E.g. "ld1r.8b { v0 }, [x1], #1"
9969  //      "ld1r.8b\t$Vt, [$Rn], #1"
9970  // may get mapped to
9971  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
9972  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
9973                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9974                      GPR64sp:$Rn,
9975                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9976                      XZR), 0>;
9977
9978  // E.g. "ld1r.8b { v0 }, [x1]"
9979  //      "ld1r.8b\t$Vt, [$Rn]"
9980  // may get mapped to
9981  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
9982  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
9983                  (!cast<Instruction>(BaseName # "v" # layout)
9984                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9985                      GPR64sp:$Rn), 0>;
9986
9987  // E.g. "ld1r.8b { v0 }, [x1], x2"
9988  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
9989  // may get mapped to
9990  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
9991  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
9992                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
9993                      GPR64sp:$Rn,
9994                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
9995                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
9996}
9997
9998multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
9999  int Offset1, int Offset2, int Offset4, int Offset8> {
10000  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10001                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10002  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10003                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10004  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10005                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10006  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10007                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10008  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10009                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10010  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10011                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10012  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10013                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10014  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10015                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10016
10017  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10018                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10019                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10020  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10021                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10022                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10023  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10024                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10025                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10026  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10027                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10028                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10029  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10030                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10031                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10032  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10033                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10034                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10035  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10036                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10037                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10038  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10039                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10040                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10041
10042  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10043  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10044  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10045  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10046  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10047  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10048  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10049  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10050}
10051
10052class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10053                      dag oops, dag iops, list<dag> pattern>
10054  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10055                       pattern> {
10056  // idx encoded in Q:S:size fields.
10057  bits<4> idx;
10058  let Inst{30} = idx{3};
10059  let Inst{23} = 0;
10060  let Inst{20-16} = 0b00000;
10061  let Inst{12} = idx{2};
10062  let Inst{11-10} = idx{1-0};
10063}
10064class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10065                      dag oops, dag iops, list<dag> pattern>
10066  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10067                           oops, iops, pattern> {
10068  // idx encoded in Q:S:size fields.
10069  bits<4> idx;
10070  let Inst{30} = idx{3};
10071  let Inst{23} = 0;
10072  let Inst{20-16} = 0b00000;
10073  let Inst{12} = idx{2};
10074  let Inst{11-10} = idx{1-0};
10075}
10076class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10077                          dag oops, dag iops>
10078  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10079                       "$Rn = $wback", oops, iops, []> {
10080  // idx encoded in Q:S:size fields.
10081  bits<4> idx;
10082  bits<5> Xm;
10083  let Inst{30} = idx{3};
10084  let Inst{23} = 1;
10085  let Inst{20-16} = Xm;
10086  let Inst{12} = idx{2};
10087  let Inst{11-10} = idx{1-0};
10088}
10089class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10090                          dag oops, dag iops>
10091  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10092                           "$Rn = $wback", oops, iops, []> {
10093  // idx encoded in Q:S:size fields.
10094  bits<4> idx;
10095  bits<5> Xm;
10096  let Inst{30} = idx{3};
10097  let Inst{23} = 1;
10098  let Inst{20-16} = Xm;
10099  let Inst{12} = idx{2};
10100  let Inst{11-10} = idx{1-0};
10101}
10102
10103class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10104                      dag oops, dag iops, list<dag> pattern>
10105  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10106                       pattern> {
10107  // idx encoded in Q:S:size<1> fields.
10108  bits<3> idx;
10109  let Inst{30} = idx{2};
10110  let Inst{23} = 0;
10111  let Inst{20-16} = 0b00000;
10112  let Inst{12} = idx{1};
10113  let Inst{11} = idx{0};
10114  let Inst{10} = size;
10115}
10116class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10117                      dag oops, dag iops, list<dag> pattern>
10118  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10119                           oops, iops, pattern> {
10120  // idx encoded in Q:S:size<1> fields.
10121  bits<3> idx;
10122  let Inst{30} = idx{2};
10123  let Inst{23} = 0;
10124  let Inst{20-16} = 0b00000;
10125  let Inst{12} = idx{1};
10126  let Inst{11} = idx{0};
10127  let Inst{10} = size;
10128}
10129
10130class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10131                          dag oops, dag iops>
10132  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10133                       "$Rn = $wback", oops, iops, []> {
10134  // idx encoded in Q:S:size<1> fields.
10135  bits<3> idx;
10136  bits<5> Xm;
10137  let Inst{30} = idx{2};
10138  let Inst{23} = 1;
10139  let Inst{20-16} = Xm;
10140  let Inst{12} = idx{1};
10141  let Inst{11} = idx{0};
10142  let Inst{10} = size;
10143}
10144class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10145                          dag oops, dag iops>
10146  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10147                           "$Rn = $wback", oops, iops, []> {
10148  // idx encoded in Q:S:size<1> fields.
10149  bits<3> idx;
10150  bits<5> Xm;
10151  let Inst{30} = idx{2};
10152  let Inst{23} = 1;
10153  let Inst{20-16} = Xm;
10154  let Inst{12} = idx{1};
10155  let Inst{11} = idx{0};
10156  let Inst{10} = size;
10157}
10158class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10159                      dag oops, dag iops, list<dag> pattern>
10160  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10161                       pattern> {
10162  // idx encoded in Q:S fields.
10163  bits<2> idx;
10164  let Inst{30} = idx{1};
10165  let Inst{23} = 0;
10166  let Inst{20-16} = 0b00000;
10167  let Inst{12} = idx{0};
10168  let Inst{11-10} = size;
10169}
10170class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10171                      dag oops, dag iops, list<dag> pattern>
10172  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10173                           oops, iops, pattern> {
10174  // idx encoded in Q:S fields.
10175  bits<2> idx;
10176  let Inst{30} = idx{1};
10177  let Inst{23} = 0;
10178  let Inst{20-16} = 0b00000;
10179  let Inst{12} = idx{0};
10180  let Inst{11-10} = size;
10181}
10182class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10183                          string asm, dag oops, dag iops>
10184  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10185                       "$Rn = $wback", oops, iops, []> {
10186  // idx encoded in Q:S fields.
10187  bits<2> idx;
10188  bits<5> Xm;
10189  let Inst{30} = idx{1};
10190  let Inst{23} = 1;
10191  let Inst{20-16} = Xm;
10192  let Inst{12} = idx{0};
10193  let Inst{11-10} = size;
10194}
10195class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10196                          string asm, dag oops, dag iops>
10197  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10198                           "$Rn = $wback", oops, iops, []> {
10199  // idx encoded in Q:S fields.
10200  bits<2> idx;
10201  bits<5> Xm;
10202  let Inst{30} = idx{1};
10203  let Inst{23} = 1;
10204  let Inst{20-16} = Xm;
10205  let Inst{12} = idx{0};
10206  let Inst{11-10} = size;
10207}
10208class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10209                      dag oops, dag iops, list<dag> pattern>
10210  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10211                       pattern> {
10212  // idx encoded in Q field.
10213  bits<1> idx;
10214  let Inst{30} = idx;
10215  let Inst{23} = 0;
10216  let Inst{20-16} = 0b00000;
10217  let Inst{12} = 0;
10218  let Inst{11-10} = size;
10219}
10220class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10221                      dag oops, dag iops, list<dag> pattern>
10222  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10223                           oops, iops, pattern> {
10224  // idx encoded in Q field.
10225  bits<1> idx;
10226  let Inst{30} = idx;
10227  let Inst{23} = 0;
10228  let Inst{20-16} = 0b00000;
10229  let Inst{12} = 0;
10230  let Inst{11-10} = size;
10231}
10232class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10233                          string asm, dag oops, dag iops>
10234  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10235                       "$Rn = $wback", oops, iops, []> {
10236  // idx encoded in Q field.
10237  bits<1> idx;
10238  bits<5> Xm;
10239  let Inst{30} = idx;
10240  let Inst{23} = 1;
10241  let Inst{20-16} = Xm;
10242  let Inst{12} = 0;
10243  let Inst{11-10} = size;
10244}
10245class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10246                          string asm, dag oops, dag iops>
10247  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10248                           "$Rn = $wback", oops, iops, []> {
10249  // idx encoded in Q field.
10250  bits<1> idx;
10251  bits<5> Xm;
10252  let Inst{30} = idx;
10253  let Inst{23} = 1;
10254  let Inst{20-16} = Xm;
10255  let Inst{12} = 0;
10256  let Inst{11-10} = size;
10257}
10258
10259let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10260multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
10261                         RegisterOperand listtype,
10262                         RegisterOperand GPR64pi> {
10263  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
10264                           (outs listtype:$dst),
10265                           (ins listtype:$Vt, VectorIndexB:$idx,
10266                                GPR64sp:$Rn), []>;
10267
10268  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
10269                            (outs GPR64sp:$wback, listtype:$dst),
10270                            (ins listtype:$Vt, VectorIndexB:$idx,
10271                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10272}
10273let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10274multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
10275                         RegisterOperand listtype,
10276                         RegisterOperand GPR64pi> {
10277  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
10278                            (outs listtype:$dst),
10279                            (ins listtype:$Vt, VectorIndexH:$idx,
10280                                 GPR64sp:$Rn), []>;
10281
10282  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
10283                            (outs GPR64sp:$wback, listtype:$dst),
10284                            (ins listtype:$Vt, VectorIndexH:$idx,
10285                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10286}
10287let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10288multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
10289                         RegisterOperand listtype,
10290                         RegisterOperand GPR64pi> {
10291  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
10292                            (outs listtype:$dst),
10293                            (ins listtype:$Vt, VectorIndexS:$idx,
10294                                 GPR64sp:$Rn), []>;
10295
10296  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
10297                            (outs GPR64sp:$wback, listtype:$dst),
10298                            (ins listtype:$Vt, VectorIndexS:$idx,
10299                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10300}
10301let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10302multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
10303                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10304  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
10305                            (outs listtype:$dst),
10306                            (ins listtype:$Vt, VectorIndexD:$idx,
10307                                 GPR64sp:$Rn), []>;
10308
10309  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
10310                            (outs GPR64sp:$wback, listtype:$dst),
10311                            (ins listtype:$Vt, VectorIndexD:$idx,
10312                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10313}
10314let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10315multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
10316                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10317  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
10318                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
10319                                        GPR64sp:$Rn), []>;
10320
10321  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
10322                                    (outs GPR64sp:$wback),
10323                                    (ins listtype:$Vt, VectorIndexB:$idx,
10324                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
10325}
10326let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10327multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
10328                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10329  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
10330                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
10331                                         GPR64sp:$Rn), []>;
10332
10333  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
10334                            (outs GPR64sp:$wback),
10335                            (ins listtype:$Vt, VectorIndexH:$idx,
10336                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10337}
10338let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10339multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
10340                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10341  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
10342                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
10343                                         GPR64sp:$Rn), []>;
10344
10345  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
10346                            (outs GPR64sp:$wback),
10347                            (ins listtype:$Vt, VectorIndexS:$idx,
10348                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10349}
10350let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
10351multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
10352                         RegisterOperand listtype, RegisterOperand GPR64pi> {
10353  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
10354                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
10355                                         GPR64sp:$Rn), []>;
10356
10357  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
10358                            (outs GPR64sp:$wback),
10359                            (ins listtype:$Vt, VectorIndexD:$idx,
10360                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
10361}
10362
10363multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
10364                                 string Count, int Offset, Operand idxtype> {
10365  // E.g. "ld1 { v0.8b }[0], [x1], #1"
10366  //      "ld1\t$Vt, [$Rn], #1"
10367  // may get mapped to
10368  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10369  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
10370                  (!cast<Instruction>(NAME # Type  # "_POST")
10371                      GPR64sp:$Rn,
10372                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10373                      idxtype:$idx, XZR), 1>;
10374
10375  // E.g. "ld1.8b { v0 }[0], [x1], #1"
10376  //      "ld1.8b\t$Vt, [$Rn], #1"
10377  // may get mapped to
10378  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10379  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
10380                  (!cast<Instruction>(NAME # Type # "_POST")
10381                      GPR64sp:$Rn,
10382                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10383                      idxtype:$idx, XZR), 0>;
10384
10385  // E.g. "ld1.8b { v0 }[0], [x1]"
10386  //      "ld1.8b\t$Vt, [$Rn]"
10387  // may get mapped to
10388  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10389  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
10390                      (!cast<Instruction>(NAME # Type)
10391                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10392                         idxtype:$idx, GPR64sp:$Rn), 0>;
10393
10394  // E.g. "ld1.8b { v0 }[0], [x1], x2"
10395  //      "ld1.8b\t$Vt, [$Rn], $Xm"
10396  // may get mapped to
10397  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10398  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
10399                      (!cast<Instruction>(NAME # Type # "_POST")
10400                         GPR64sp:$Rn,
10401                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
10402                         idxtype:$idx,
10403                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10404}
10405
10406multiclass SIMDLdSt1SingleAliases<string asm> {
10407  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
10408  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
10409  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
10410  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
10411}
10412
10413multiclass SIMDLdSt2SingleAliases<string asm> {
10414  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
10415  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
10416  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
10417  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
10418}
10419
10420multiclass SIMDLdSt3SingleAliases<string asm> {
10421  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
10422  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
10423  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
10424  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
10425}
10426
10427multiclass SIMDLdSt4SingleAliases<string asm> {
10428  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
10429  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
10430  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
10431  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
10432}
10433} // end of 'let Predicates = [HasNEON]'
10434
10435//----------------------------------------------------------------------------
10436// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
10437//----------------------------------------------------------------------------
10438
10439let Predicates = [HasNEON, HasRDM] in {
10440
10441class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
10442                                    RegisterOperand regtype, string asm,
10443                                    string kind, list<dag> pattern>
10444  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
10445                                pattern> {
10446}
10447multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
10448                                             SDPatternOperator Accum> {
10449  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
10450    [(set (v4i16 V64:$dst),
10451          (Accum (v4i16 V64:$Rd),
10452                 (v4i16 (int_aarch64_neon_sqrdmulh (v4i16 V64:$Rn),
10453                                                   (v4i16 V64:$Rm)))))]>;
10454  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
10455    [(set (v8i16 V128:$dst),
10456          (Accum (v8i16 V128:$Rd),
10457                 (v8i16 (int_aarch64_neon_sqrdmulh (v8i16 V128:$Rn),
10458                                                   (v8i16 V128:$Rm)))))]>;
10459  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
10460    [(set (v2i32 V64:$dst),
10461          (Accum (v2i32 V64:$Rd),
10462                 (v2i32 (int_aarch64_neon_sqrdmulh (v2i32 V64:$Rn),
10463                                                   (v2i32 V64:$Rm)))))]>;
10464  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
10465    [(set (v4i32 V128:$dst),
10466          (Accum (v4i32 V128:$Rd),
10467                 (v4i32 (int_aarch64_neon_sqrdmulh (v4i32 V128:$Rn),
10468                                                   (v4i32 V128:$Rm)))))]>;
10469}
10470
10471multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
10472                                     SDPatternOperator Accum> {
10473  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
10474                                          V64, V64, V128_lo, VectorIndexH,
10475                                          asm, ".4h", ".4h", ".4h", ".h",
10476    [(set (v4i16 V64:$dst),
10477          (Accum (v4i16 V64:$Rd),
10478                 (v4i16 (int_aarch64_neon_sqrdmulh
10479                          (v4i16 V64:$Rn),
10480                          (v4i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10481                                                    VectorIndexH:$idx))))))]> {
10482    bits<3> idx;
10483    let Inst{11} = idx{2};
10484    let Inst{21} = idx{1};
10485    let Inst{20} = idx{0};
10486  }
10487
10488  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
10489                                          V128, V128, V128_lo, VectorIndexH,
10490                                          asm, ".8h", ".8h", ".8h", ".h",
10491    [(set (v8i16 V128:$dst),
10492          (Accum (v8i16 V128:$Rd),
10493                 (v8i16 (int_aarch64_neon_sqrdmulh
10494                          (v8i16 V128:$Rn),
10495                          (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
10496                                                   VectorIndexH:$idx))))))]> {
10497    bits<3> idx;
10498    let Inst{11} = idx{2};
10499    let Inst{21} = idx{1};
10500    let Inst{20} = idx{0};
10501  }
10502
10503  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
10504                                          V64, V64, V128, VectorIndexS,
10505                                          asm, ".2s", ".2s", ".2s", ".s",
10506    [(set (v2i32 V64:$dst),
10507        (Accum (v2i32 V64:$Rd),
10508               (v2i32 (int_aarch64_neon_sqrdmulh
10509                        (v2i32 V64:$Rn),
10510                        (v2i32 (AArch64duplane32 (v4i32 V128:$Rm),
10511                                                 VectorIndexS:$idx))))))]> {
10512    bits<2> idx;
10513    let Inst{11} = idx{1};
10514    let Inst{21} = idx{0};
10515  }
10516
10517  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10518  // an intermediate EXTRACT_SUBREG would be untyped.
10519  // FIXME: direct EXTRACT_SUBREG from v2i32 to i32 is illegal, that's why we
10520  // got it lowered here as (i32 vector_extract (v4i32 insert_subvector(..)))
10521  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10522                       (i32 (vector_extract
10523                               (v4i32 (insert_subvector
10524                                       (undef),
10525                                        (v2i32 (int_aarch64_neon_sqrdmulh
10526                                                 (v2i32 V64:$Rn),
10527                                                 (v2i32 (AArch64duplane32
10528                                                          (v4i32 V128:$Rm),
10529                                                          VectorIndexS:$idx)))),
10530                                      (i64 0))),
10531                               (i64 0))))),
10532            (EXTRACT_SUBREG
10533                (v2i32 (!cast<Instruction>(NAME # v2i32_indexed)
10534                          (v2i32 (INSERT_SUBREG (v2i32 (IMPLICIT_DEF)),
10535                                                FPR32Op:$Rd,
10536                                                ssub)),
10537                          V64:$Rn,
10538                          V128:$Rm,
10539                          VectorIndexS:$idx)),
10540                ssub)>;
10541
10542  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
10543                                          V128, V128, V128, VectorIndexS,
10544                                          asm, ".4s", ".4s", ".4s", ".s",
10545    [(set (v4i32 V128:$dst),
10546          (Accum (v4i32 V128:$Rd),
10547                 (v4i32 (int_aarch64_neon_sqrdmulh
10548                          (v4i32 V128:$Rn),
10549                          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
10550                                                   VectorIndexS:$idx))))))]> {
10551    bits<2> idx;
10552    let Inst{11} = idx{1};
10553    let Inst{21} = idx{0};
10554  }
10555
10556  // FIXME: it would be nice to use the scalar (v1i32) instruction here, but
10557  // an intermediate EXTRACT_SUBREG would be untyped.
10558  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
10559                        (i32 (vector_extract
10560                               (v4i32 (int_aarch64_neon_sqrdmulh
10561                                        (v4i32 V128:$Rn),
10562                                        (v4i32 (AArch64duplane32
10563                                                 (v4i32 V128:$Rm),
10564                                                 VectorIndexS:$idx)))),
10565                               (i64 0))))),
10566            (EXTRACT_SUBREG
10567                (v4i32 (!cast<Instruction>(NAME # v4i32_indexed)
10568                         (v4i32 (INSERT_SUBREG (v4i32 (IMPLICIT_DEF)),
10569                                               FPR32Op:$Rd,
10570                                               ssub)),
10571                         V128:$Rn,
10572                         V128:$Rm,
10573                         VectorIndexS:$idx)),
10574                ssub)>;
10575
10576  def i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
10577                                        FPR16Op, FPR16Op, V128_lo,
10578                                        VectorIndexH, asm, ".h", "", "", ".h",
10579                                        []> {
10580    bits<3> idx;
10581    let Inst{11} = idx{2};
10582    let Inst{21} = idx{1};
10583    let Inst{20} = idx{0};
10584  }
10585
10586  def i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
10587                                        FPR32Op, FPR32Op, V128, VectorIndexS,
10588                                        asm, ".s", "", "", ".s",
10589    [(set (i32 FPR32Op:$dst),
10590          (Accum (i32 FPR32Op:$Rd),
10591                 (i32 (int_aarch64_neon_sqrdmulh
10592                        (i32 FPR32Op:$Rn),
10593                        (i32 (vector_extract (v4i32 V128:$Rm),
10594                                             VectorIndexS:$idx))))))]> {
10595    bits<2> idx;
10596    let Inst{11} = idx{1};
10597    let Inst{21} = idx{0};
10598  }
10599}
10600} // let Predicates = [HasNeon, HasRDM]
10601
10602//----------------------------------------------------------------------------
10603// ARMv8.3 Complex ADD/MLA instructions
10604//----------------------------------------------------------------------------
10605
10606class ComplexRotationOperand<int Angle, int Remainder, string Type>
10607  : AsmOperandClass {
10608  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
10609  let DiagnosticType = "InvalidComplexRotation" # Type;
10610  let Name = "ComplexRotation" # Type;
10611}
10612def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10613                                                  SDNodeXForm<imm, [{
10614  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
10615}]>> {
10616  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
10617  let PrintMethod = "printComplexRotationOp<90, 0>";
10618}
10619def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
10620                                                  SDNodeXForm<imm, [{
10621  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
10622}]>> {
10623  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
10624  let PrintMethod = "printComplexRotationOp<180, 90>";
10625}
10626let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10627class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
10628                                     RegisterOperand regtype, Operand rottype,
10629                                     string asm, string kind, list<dag> pattern>
10630  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10631      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10632      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
10633    Sched<[WriteV]> {
10634  bits<5> Rd;
10635  bits<5> Rn;
10636  bits<5> Rm;
10637  bits<1> rot;
10638  let Inst{31}    = 0;
10639  let Inst{30}    = Q;
10640  let Inst{29}    = U;
10641  let Inst{28-24} = 0b01110;
10642  let Inst{23-22} = size;
10643  let Inst{21}    = 0;
10644  let Inst{20-16} = Rm;
10645  let Inst{15-13} = opcode;
10646  // Non-tied version (FCADD) only has one rotation bit
10647  let Inst{12}    = rot;
10648  let Inst{11}    = 0;
10649  let Inst{10}    = 1;
10650  let Inst{9-5}   = Rn;
10651  let Inst{4-0}   = Rd;
10652}
10653
10654//8.3 CompNum - Floating-point complex number support
10655multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
10656                                          string asm, SDPatternOperator OpNode>{
10657  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10658  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
10659              asm, ".4h",
10660              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10661                                              (v4f16 V64:$Rn),
10662                                              (v4f16 V64:$Rm),
10663                                              (i32 rottype:$rot)))]>;
10664
10665  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
10666              asm, ".8h",
10667              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10668                                               (v8f16 V128:$Rn),
10669                                               (v8f16 V128:$Rm),
10670                                               (i32 rottype:$rot)))]>;
10671  }
10672
10673  let Predicates = [HasComplxNum, HasNEON] in {
10674  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
10675              asm, ".2s",
10676              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10677                                              (v2f32 V64:$Rn),
10678                                              (v2f32 V64:$Rm),
10679                                              (i32 rottype:$rot)))]>;
10680
10681  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
10682              asm, ".4s",
10683              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10684                                               (v4f32 V128:$Rn),
10685                                               (v4f32 V128:$Rm),
10686                                               (i32 rottype:$rot)))]>;
10687
10688  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
10689              asm, ".2d",
10690              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10691                                               (v2f64 V128:$Rn),
10692                                               (v2f64 V128:$Rm),
10693                                               (i32 rottype:$rot)))]>;
10694  }
10695}
10696
10697let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10698class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
10699                                         bits<3> opcode,
10700                                         RegisterOperand regtype,
10701                                         Operand rottype, string asm,
10702                                         string kind, list<dag> pattern>
10703  : I<(outs regtype:$dst),
10704      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
10705      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
10706      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
10707    Sched<[WriteV]> {
10708  bits<5> Rd;
10709  bits<5> Rn;
10710  bits<5> Rm;
10711  bits<2> rot;
10712  let Inst{31}    = 0;
10713  let Inst{30}    = Q;
10714  let Inst{29}    = U;
10715  let Inst{28-24} = 0b01110;
10716  let Inst{23-22} = size;
10717  let Inst{21}    = 0;
10718  let Inst{20-16} = Rm;
10719  let Inst{15-13} = opcode;
10720  let Inst{12-11} = rot;
10721  let Inst{10}    = 1;
10722  let Inst{9-5}   = Rn;
10723  let Inst{4-0}   = Rd;
10724}
10725
10726multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
10727                                             Operand rottype, string asm,
10728                                             SDPatternOperator OpNode> {
10729  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10730  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
10731              rottype, asm, ".4h",
10732              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
10733                                              (v4f16 V64:$Rn),
10734                                              (v4f16 V64:$Rm),
10735                                              (i32 rottype:$rot)))]>;
10736
10737  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
10738              rottype, asm, ".8h",
10739              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
10740                                               (v8f16 V128:$Rn),
10741                                               (v8f16 V128:$Rm),
10742                                               (i32 rottype:$rot)))]>;
10743  }
10744
10745  let Predicates = [HasComplxNum, HasNEON] in {
10746  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
10747              rottype, asm, ".2s",
10748              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
10749                                              (v2f32 V64:$Rn),
10750                                              (v2f32 V64:$Rm),
10751                                              (i32 rottype:$rot)))]>;
10752
10753  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
10754              rottype, asm, ".4s",
10755              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
10756                                               (v4f32 V128:$Rn),
10757                                               (v4f32 V128:$Rm),
10758                                               (i32 rottype:$rot)))]>;
10759
10760  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
10761              rottype, asm, ".2d",
10762              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
10763                                               (v2f64 V128:$Rn),
10764                                               (v2f64 V128:$Rm),
10765                                               (i32 rottype:$rot)))]>;
10766  }
10767}
10768
10769let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10770class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
10771                                 bit opc1, bit opc2, RegisterOperand dst_reg,
10772                                 RegisterOperand lhs_reg,
10773                                 RegisterOperand rhs_reg, Operand vec_idx,
10774                                 Operand rottype, string asm, string apple_kind,
10775                                 string dst_kind, string lhs_kind,
10776                                 string rhs_kind, list<dag> pattern>
10777  : I<(outs dst_reg:$dst),
10778      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
10779      asm,
10780      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
10781      "$idx, $rot" # "|" # apple_kind #
10782      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
10783    Sched<[WriteV]> {
10784  bits<5> Rd;
10785  bits<5> Rn;
10786  bits<5> Rm;
10787  bits<2> rot;
10788
10789  let Inst{31}    = 0;
10790  let Inst{30}    = Q;
10791  let Inst{29}    = U;
10792  let Inst{28}    = Scalar;
10793  let Inst{27-24} = 0b1111;
10794  let Inst{23-22} = size;
10795  // Bit 21 must be set by the derived class.
10796  let Inst{20-16} = Rm;
10797  let Inst{15}    = opc1;
10798  let Inst{14-13} = rot;
10799  let Inst{12}    = opc2;
10800  // Bit 11 must be set by the derived class.
10801  let Inst{10}    = 0;
10802  let Inst{9-5}   = Rn;
10803  let Inst{4-0}   = Rd;
10804}
10805
10806// The complex instructions index by pairs of elements, so the VectorIndexes
10807// don't match the lane types, and the index bits are different to the other
10808// classes.
10809multiclass SIMDIndexedTiedComplexHSD<bit U, bit opc1, bit opc2, Operand rottype,
10810                                     string asm, SDPatternOperator OpNode> {
10811  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
10812  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
10813                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
10814                      ".4h", ".h", []> {
10815    bits<1> idx;
10816    let Inst{11} = 0;
10817    let Inst{21} = idx{0};
10818  }
10819
10820  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
10821                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
10822                      ".8h", ".8h", ".h", []> {
10823    bits<2> idx;
10824    let Inst{11} = idx{1};
10825    let Inst{21} = idx{0};
10826  }
10827  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
10828
10829  let Predicates = [HasComplxNum, HasNEON] in {
10830  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
10831                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
10832                      ".4s", ".4s", ".s", []> {
10833    bits<1> idx;
10834    let Inst{11} = idx{0};
10835    let Inst{21} = 0;
10836  }
10837  } // Predicates = [HasComplxNum, HasNEON]
10838}
10839
10840//----------------------------------------------------------------------------
10841// Crypto extensions
10842//----------------------------------------------------------------------------
10843
10844let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10845class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
10846              list<dag> pat>
10847  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
10848    Sched<[WriteV]>{
10849  bits<5> Rd;
10850  bits<5> Rn;
10851  let Inst{31-16} = 0b0100111000101000;
10852  let Inst{15-12} = opc;
10853  let Inst{11-10} = 0b10;
10854  let Inst{9-5}   = Rn;
10855  let Inst{4-0}   = Rd;
10856}
10857
10858class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
10859  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
10860            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
10861
10862class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
10863  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
10864            "$Rd = $dst",
10865            [(set (v16i8 V128:$dst),
10866                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
10867
10868let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10869class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
10870                     dag oops, dag iops, list<dag> pat>
10871  : I<oops, iops, asm,
10872      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
10873      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
10874    Sched<[WriteV]>{
10875  bits<5> Rd;
10876  bits<5> Rn;
10877  bits<5> Rm;
10878  let Inst{31-21} = 0b01011110000;
10879  let Inst{20-16} = Rm;
10880  let Inst{15}    = 0;
10881  let Inst{14-12} = opc;
10882  let Inst{11-10} = 0b00;
10883  let Inst{9-5}   = Rn;
10884  let Inst{4-0}   = Rd;
10885}
10886
10887class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
10888  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10889                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
10890                   [(set (v4i32 FPR128:$dst),
10891                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
10892                                 (v4i32 V128:$Rm)))]>;
10893
10894class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
10895  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
10896                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
10897                   [(set (v4i32 V128:$dst),
10898                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10899                                 (v4i32 V128:$Rm)))]>;
10900
10901class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
10902  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
10903                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
10904                   [(set (v4i32 FPR128:$dst),
10905                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
10906                                 (v4i32 V128:$Rm)))]>;
10907
10908let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10909class SHA2OpInst<bits<4> opc, string asm, string kind,
10910                 string cstr, dag oops, dag iops,
10911                 list<dag> pat>
10912  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
10913                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
10914    Sched<[WriteV]>{
10915  bits<5> Rd;
10916  bits<5> Rn;
10917  let Inst{31-16} = 0b0101111000101000;
10918  let Inst{15-12} = opc;
10919  let Inst{11-10} = 0b10;
10920  let Inst{9-5}   = Rn;
10921  let Inst{4-0}   = Rd;
10922}
10923
10924class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
10925  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
10926               (ins V128:$Rd, V128:$Rn),
10927               [(set (v4i32 V128:$dst),
10928                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
10929
10930class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
10931  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
10932               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
10933
10934// Armv8.2-A Crypto extensions
10935class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
10936                    list<dag> pattern>
10937  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteV]> {
10938  bits<5> Vd;
10939  bits<5> Vn;
10940  let Inst{31-25} = 0b1100111;
10941  let Inst{9-5}   = Vn;
10942  let Inst{4-0}   = Vd;
10943}
10944
10945class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
10946  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
10947                  "$Vd = $Vdst", []> {
10948  let Inst{31-25} = 0b1100111;
10949  let Inst{24-21} = 0b0110;
10950  let Inst{20-15} = 0b000001;
10951  let Inst{14}    = op0;
10952  let Inst{13-12} = 0b00;
10953  let Inst{11-10} = op1;
10954}
10955class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
10956  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
10957class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
10958  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
10959
10960class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
10961                string asmops, string cst>
10962  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
10963  bits<5> Vm;
10964  let Inst{24-21} = 0b0011;
10965  let Inst{20-16} = Vm;
10966  let Inst{15}    = 0b1;
10967  let Inst{14}    = op0;
10968  let Inst{13-12} = 0b00;
10969  let Inst{11-10} = op1;
10970}
10971class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
10972  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10973              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
10974class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
10975  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10976              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10977class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
10978  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
10979              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
10980class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
10981  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
10982              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10983class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
10984  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
10985              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
10986
10987class CryptoRRRR<bits<2>op0, string asm, string asmops>
10988  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
10989                  asmops, "", []> {
10990  bits<5> Vm;
10991  bits<5> Va;
10992  let Inst{24-23} = 0b00;
10993  let Inst{22-21} = op0;
10994  let Inst{20-16} = Vm;
10995  let Inst{15}    = 0b0;
10996  let Inst{14-10} = Va;
10997}
10998class CryptoRRRR_16B<bits<2>op0, string asm>
10999 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11000                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11001}
11002class CryptoRRRR_4S<bits<2>op0, string asm>
11003 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11004                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11005}
11006
11007class CryptoRRRi6<string asm>
11008  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11009                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11010                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11011  bits<6> imm;
11012  bits<5> Vm;
11013  let Inst{24-21} = 0b0100;
11014  let Inst{20-16} = Vm;
11015  let Inst{15-10} = imm;
11016  let Inst{9-5}   = Vn;
11017  let Inst{4-0}   = Vd;
11018}
11019
11020class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11021  : BaseCryptoV82<(outs V128:$Vdst),
11022                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11023                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11024                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11025  bits<2> imm;
11026  bits<5> Vm;
11027  let Inst{24-21} = 0b0010;
11028  let Inst{20-16} = Vm;
11029  let Inst{15}    = 0b1;
11030  let Inst{14}    = op0;
11031  let Inst{13-12} = imm;
11032  let Inst{11-10} = op1;
11033}
11034
11035//----------------------------------------------------------------------------
11036// v8.1 atomic instructions extension:
11037// * CAS
11038// * CASP
11039// * SWP
11040// * LDOPregister<OP>, and aliases STOPregister<OP>
11041
11042// Instruction encodings:
11043//
11044//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11045// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11046// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11047// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11048// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11049// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11050
11051// Instruction syntax:
11052//
11053// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11054// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11055// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11056// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11057// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11058// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11059// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11060// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11061// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11062// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11063
11064let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11065class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11066                      string cstr, list<dag> pattern>
11067      : I<oops, iops, asm, operands, cstr, pattern> {
11068  bits<2> Sz;
11069  bit NP;
11070  bit Acq;
11071  bit Rel;
11072  bits<5> Rs;
11073  bits<5> Rn;
11074  bits<5> Rt;
11075  let Inst{31-30} = Sz;
11076  let Inst{29-24} = 0b001000;
11077  let Inst{23} = NP;
11078  let Inst{22} = Acq;
11079  let Inst{21} = 0b1;
11080  let Inst{20-16} = Rs;
11081  let Inst{15} = Rel;
11082  let Inst{14-10} = 0b11111;
11083  let Inst{9-5} = Rn;
11084  let Inst{4-0} = Rt;
11085  let Predicates = [HasLSE];
11086}
11087
11088class BaseCAS<string order, string size, RegisterClass RC>
11089      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11090                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11091                        "$out = $Rs",[]>,
11092        Sched<[WriteAtomic]> {
11093  let NP = 1;
11094}
11095
11096multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11097  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11098  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11099  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11100  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11101}
11102
11103class BaseCASP<string order, string size, RegisterOperand RC>
11104      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11105                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11106                        "$out = $Rs",[]>,
11107        Sched<[WriteAtomic]> {
11108  let NP = 0;
11109}
11110
11111multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11112  let Sz = 0b00, Acq = Acq, Rel = Rel in
11113    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11114  let Sz = 0b01, Acq = Acq, Rel = Rel in
11115    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11116}
11117
11118let Predicates = [HasLSE] in
11119class BaseSWP<string order, string size, RegisterClass RC>
11120      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11121          "\t$Rs, $Rt, [$Rn]","",[]>,
11122        Sched<[WriteAtomic]> {
11123  bits<2> Sz;
11124  bit Acq;
11125  bit Rel;
11126  bits<5> Rs;
11127  bits<3> opc = 0b000;
11128  bits<5> Rn;
11129  bits<5> Rt;
11130  let Inst{31-30} = Sz;
11131  let Inst{29-24} = 0b111000;
11132  let Inst{23} = Acq;
11133  let Inst{22} = Rel;
11134  let Inst{21} = 0b1;
11135  let Inst{20-16} = Rs;
11136  let Inst{15} = 0b1;
11137  let Inst{14-12} = opc;
11138  let Inst{11-10} = 0b00;
11139  let Inst{9-5} = Rn;
11140  let Inst{4-0} = Rt;
11141  let Predicates = [HasLSE];
11142}
11143
11144multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11145  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11146  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11147  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11148  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11149}
11150
11151let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11152class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11153      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11154          "\t$Rs, $Rt, [$Rn]","",[]>,
11155        Sched<[WriteAtomic]> {
11156  bits<2> Sz;
11157  bit Acq;
11158  bit Rel;
11159  bits<5> Rs;
11160  bits<3> opc;
11161  bits<5> Rn;
11162  bits<5> Rt;
11163  let Inst{31-30} = Sz;
11164  let Inst{29-24} = 0b111000;
11165  let Inst{23} = Acq;
11166  let Inst{22} = Rel;
11167  let Inst{21} = 0b1;
11168  let Inst{20-16} = Rs;
11169  let Inst{15} = 0b0;
11170  let Inst{14-12} = opc;
11171  let Inst{11-10} = 0b00;
11172  let Inst{9-5} = Rn;
11173  let Inst{4-0} = Rt;
11174  let Predicates = [HasLSE];
11175}
11176
11177multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11178                        string order> {
11179  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11180    def B : BaseLDOPregister<op, order, "b", GPR32>;
11181  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11182    def H : BaseLDOPregister<op, order, "h", GPR32>;
11183  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11184    def W : BaseLDOPregister<op, order, "", GPR32>;
11185  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11186    def X : BaseLDOPregister<op, order, "", GPR64>;
11187}
11188
11189// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11190// complex DAG for DstRHS.
11191let Predicates = [HasLSE] in
11192multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11193                                         string size, dag SrcRHS, dag DstRHS> {
11194  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11195            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11196  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11197            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11198  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11199            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11200  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11201            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11202  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11203            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11204}
11205
11206multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11207                                     string size, dag RHS> {
11208  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11209}
11210
11211multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11212                                         string size, dag LHS, dag RHS> {
11213  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11214}
11215
11216multiclass LDOPregister_patterns<string inst, string op> {
11217  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11218  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11219  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11220  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11221}
11222
11223multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11224  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11225                        (i64 GPR64:$Rm),
11226                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11227  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11228                        (i32 GPR32:$Rm),
11229                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11230  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11231                        (i32 GPR32:$Rm),
11232                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11233  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11234                        (i32 GPR32:$Rm),
11235                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11236}
11237
11238let Predicates = [HasLSE] in
11239multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11240                                        string size, dag OLD, dag NEW> {
11241  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11242            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11243  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11244            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11245  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11246            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11247  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11248            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11249  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11250            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11251}
11252
11253multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11254                                    string size, dag OLD, dag NEW> {
11255  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11256}
11257
11258multiclass CASregister_patterns<string inst, string op> {
11259  defm : CASregister_patterns_ord<inst, "X", op, "64",
11260                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11261  defm : CASregister_patterns_ord<inst, "W", op, "32",
11262                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11263  defm : CASregister_patterns_ord<inst, "H", op, "16",
11264                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11265  defm : CASregister_patterns_ord<inst, "B", op, "8",
11266                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11267}
11268
11269let Predicates = [HasLSE] in
11270class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11271                        Instruction inst> :
11272      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11273
11274multiclass STOPregister<string asm, string instr> {
11275  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11276                    !cast<Instruction>(instr # "LB")>;
11277  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11278                    !cast<Instruction>(instr # "LH")>;
11279  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11280                    !cast<Instruction>(instr # "LW")>;
11281  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11282                    !cast<Instruction>(instr # "LX")>;
11283  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11284                    !cast<Instruction>(instr # "B")>;
11285  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11286                    !cast<Instruction>(instr # "H")>;
11287  def : BaseSTOPregister<asm,        GPR32, WZR,
11288                    !cast<Instruction>(instr # "W")>;
11289  def : BaseSTOPregister<asm,        GPR64, XZR,
11290                    !cast<Instruction>(instr # "X")>;
11291}
11292
11293class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11294                        dag iops, dag oops, list<dag> pat>
11295    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11296      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11297  bits<5> Rt;
11298  bits<5> Rn;
11299  let Inst{31-21} = 0b11111000001;
11300  let Inst{15}    = 1;
11301  let Inst{14-12} = opc;
11302  let Inst{11-10} = 0b00;
11303  let Inst{9-5}   = Rn;
11304  let Inst{4-0}   = Rt;
11305
11306  let Predicates = [HasV8_7a];
11307}
11308
11309class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
11310                      list<dag> pat = []>
11311    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
11312  let Inst{20-16} = 0b11111;
11313}
11314
11315class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
11316    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
11317                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
11318  bits<5> Rs;
11319  let Inst{20-16} = Rs;
11320}
11321
11322//----------------------------------------------------------------------------
11323// Allow the size specifier tokens to be upper case, not just lower.
11324def : TokenAlias<".4B", ".4b">;  // Add dot product
11325def : TokenAlias<".8B", ".8b">;
11326def : TokenAlias<".4H", ".4h">;
11327def : TokenAlias<".2S", ".2s">;
11328def : TokenAlias<".1D", ".1d">;
11329def : TokenAlias<".16B", ".16b">;
11330def : TokenAlias<".8H", ".8h">;
11331def : TokenAlias<".4S", ".4s">;
11332def : TokenAlias<".2D", ".2d">;
11333def : TokenAlias<".1Q", ".1q">;
11334def : TokenAlias<".2H", ".2h">;
11335def : TokenAlias<".B", ".b">;
11336def : TokenAlias<".H", ".h">;
11337def : TokenAlias<".S", ".s">;
11338def : TokenAlias<".D", ".d">;
11339def : TokenAlias<".Q", ".q">;
11340