xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64InstrFormats.td (revision 3ceba58a7509418b47b8fca2d2b6bbf088714e26)
1//===- AArch64InstrFormats.td - AArch64 Instruction Formats --*- tblgen -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9//===----------------------------------------------------------------------===//
10//  Describe AArch64 instructions format here
11//
12
13// Format specifies the encoding used by the instruction.  This is part of the
14// ad-hoc solution used to emit machine instruction encodings by our machine
15// code emitter.
16class Format<bits<2> val> {
17  bits<2> Value = val;
18}
19
20def PseudoFrm   : Format<0>;
21def NormalFrm   : Format<1>; // Do we need any others?
22
23// Enum describing whether an instruction is
24// destructive in its first source operand.
25class DestructiveInstTypeEnum<bits<4> val> {
26  bits<4> Value = val;
27}
28def NotDestructive                : DestructiveInstTypeEnum<0>;
29// Destructive in its first operand and can be MOVPRFX'd, but has no other
30// special properties.
31def DestructiveOther              : DestructiveInstTypeEnum<1>;
32def DestructiveUnary              : DestructiveInstTypeEnum<2>;
33def DestructiveBinaryImm          : DestructiveInstTypeEnum<3>;
34def DestructiveBinaryShImmUnpred  : DestructiveInstTypeEnum<4>;
35def DestructiveBinary             : DestructiveInstTypeEnum<5>;
36def DestructiveBinaryComm         : DestructiveInstTypeEnum<6>;
37def DestructiveBinaryCommWithRev  : DestructiveInstTypeEnum<7>;
38def DestructiveTernaryCommWithRev : DestructiveInstTypeEnum<8>;
39def DestructiveUnaryPassthru      : DestructiveInstTypeEnum<9>;
40
41class FalseLanesEnum<bits<2> val> {
42  bits<2> Value = val;
43}
44def FalseLanesNone  : FalseLanesEnum<0>;
45def FalseLanesZero  : FalseLanesEnum<1>;
46def FalseLanesUndef : FalseLanesEnum<2>;
47
48class SMEMatrixTypeEnum<bits<3> val> {
49  bits<3> Value = val;
50}
51def SMEMatrixNone  : SMEMatrixTypeEnum<0>;
52def SMEMatrixTileB : SMEMatrixTypeEnum<1>;
53def SMEMatrixTileH : SMEMatrixTypeEnum<2>;
54def SMEMatrixTileS : SMEMatrixTypeEnum<3>;
55def SMEMatrixTileD : SMEMatrixTypeEnum<4>;
56def SMEMatrixTileQ : SMEMatrixTypeEnum<5>;
57def SMEMatrixArray : SMEMatrixTypeEnum<6>;
58
59// AArch64 Instruction Format
60class AArch64Inst<Format f, string cstr> : Instruction {
61  field bits<32> Inst; // Instruction encoding.
62  // Mask of bits that cause an encoding to be UNPREDICTABLE.
63  // If a bit is set, then if the corresponding bit in the
64  // target encoding differs from its value in the "Inst" field,
65  // the instruction is UNPREDICTABLE (SoftFail in abstract parlance).
66  field bits<32> Unpredictable = 0;
67  // SoftFail is the generic name for this field, but we alias it so
68  // as to make it more obvious what it means in ARM-land.
69  field bits<32> SoftFail = Unpredictable;
70  let Namespace   = "AArch64";
71  Format F        = f;
72  bits<2> Form    = F.Value;
73
74  // Defaults
75  bit isWhile = 0;
76  bit isPTestLike = 0;
77  FalseLanesEnum FalseLanes = FalseLanesNone;
78  DestructiveInstTypeEnum DestructiveInstType = NotDestructive;
79  SMEMatrixTypeEnum SMEMatrixType = SMEMatrixNone;
80  ElementSizeEnum ElementSize = ElementSizeNone;
81
82  let TSFlags{13-11} = SMEMatrixType.Value;
83  let TSFlags{10}    = isPTestLike;
84  let TSFlags{9}     = isWhile;
85  let TSFlags{8-7}   = FalseLanes.Value;
86  let TSFlags{6-3}   = DestructiveInstType.Value;
87  let TSFlags{2-0}   = ElementSize.Value;
88
89  let Pattern       = [];
90  let Constraints   = cstr;
91}
92
93class InstSubst<string Asm, dag Result, bit EmitPriority = 0>
94  : InstAlias<Asm, Result, EmitPriority>, Requires<[UseNegativeImmediates]>;
95
96// Pseudo instructions (don't have encoding information)
97class Pseudo<dag oops, dag iops, list<dag> pattern, string cstr = "">
98    : AArch64Inst<PseudoFrm, cstr> {
99  dag OutOperandList = oops;
100  dag InOperandList  = iops;
101  let Pattern        = pattern;
102  let isCodeGenOnly  = 1;
103  let isPseudo       = 1;
104}
105
106// Real instructions (have encoding information)
107class EncodedI<string cstr, list<dag> pattern> : AArch64Inst<NormalFrm, cstr> {
108  let Pattern = pattern;
109  let Size = 4;
110}
111
112// Normal instructions
113class I<dag oops, dag iops, string asm, string operands, string cstr,
114        list<dag> pattern>
115    : EncodedI<cstr, pattern> {
116  dag OutOperandList = oops;
117  dag InOperandList  = iops;
118  let AsmString      = !strconcat(asm, operands);
119}
120
121class TriOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$MHS, node:$RHS), res>;
122class BinOpFrag<dag res> : PatFrag<(ops node:$LHS, node:$RHS), res>;
123class UnOpFrag<dag res>  : PatFrag<(ops node:$LHS), res>;
124
125// Helper fragment for an extract of the high portion of a 128-bit vector. The
126// ComplexPattern match both extract_subvector and bitcast(extract_subvector(..)).
127def extract_high_v16i8 :
128    ComplexPattern<v8i8, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
129def extract_high_v8i16 :
130    ComplexPattern<v4i16, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
131def extract_high_v4i32 :
132    ComplexPattern<v2i32, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
133def extract_high_v2i64 :
134    ComplexPattern<v1i64, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
135
136def gi_extract_high_v16i8 :
137  GIComplexOperandMatcher<v8s8, "selectExtractHigh">,
138  GIComplexPatternEquiv<extract_high_v16i8>;
139def gi_extract_high_v8i16 :
140  GIComplexOperandMatcher<v4s16, "selectExtractHigh">,
141  GIComplexPatternEquiv<extract_high_v8i16>;
142def gi_extract_high_v4i32 :
143  GIComplexOperandMatcher<v2s32, "selectExtractHigh">,
144  GIComplexPatternEquiv<extract_high_v4i32>;
145
146def extract_high_v8f16 :
147    ComplexPattern<v4f16, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
148def extract_high_v4f32 :
149    ComplexPattern<v2f32, 1, "SelectExtractHigh", [extract_subvector, bitconvert]>;
150
151def gi_extract_high_v8f16 :
152  GIComplexOperandMatcher<v4s16, "selectExtractHigh">,
153  GIComplexPatternEquiv<extract_high_v8f16>;
154def gi_extract_high_v4f32 :
155  GIComplexOperandMatcher<v2s32, "selectExtractHigh">,
156  GIComplexPatternEquiv<extract_high_v4f32>;
157
158def extract_high_dup_v8i16 :
159   BinOpFrag<(extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 4))>;
160def extract_high_dup_v4i32 :
161   BinOpFrag<(extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 2))>;
162
163def dup_v8i16 :
164    PatFrags<(ops node:$LHS, node:$RHS),
165             [(v4i16 (extract_subvector (v8i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS)), (i64 0))),
166              (v4i16 (AArch64duplane16 (v8i16 node:$LHS), node:$RHS))]>;
167def dup_v4i32 :
168    PatFrags<(ops node:$LHS, node:$RHS),
169             [(v2i32 (extract_subvector (v4i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS)), (i64 0))),
170              (v2i32 (AArch64duplane32 (v4i32 node:$LHS), node:$RHS))]>;
171def dup_v8f16 :
172    PatFrags<(ops node:$LHS, node:$RHS),
173             [(v4f16 (extract_subvector (v8f16 (AArch64duplane16 (v8f16 node:$LHS), node:$RHS)), (i64 0))),
174              (v4f16 (AArch64duplane16 (v8f16 node:$LHS), node:$RHS))]>;
175def dup_v4f32 :
176    PatFrags<(ops node:$LHS, node:$RHS),
177             [(v2f32 (extract_subvector (v4f32 (AArch64duplane32 (v4f32 node:$LHS), node:$RHS)), (i64 0))),
178              (v2f32 (AArch64duplane32 (v4f32 node:$LHS), node:$RHS))]>;
179
180//===----------------------------------------------------------------------===//
181// Asm Operand Classes.
182//
183
184// Shifter operand for arithmetic shifted encodings.
185def ShifterOperand : AsmOperandClass {
186  let Name = "Shifter";
187}
188
189// Shifter operand for mov immediate encodings.
190def MovImm32ShifterOperand : AsmOperandClass {
191  let SuperClasses = [ShifterOperand];
192  let Name = "MovImm32Shifter";
193  let RenderMethod = "addShifterOperands";
194  let DiagnosticType = "InvalidMovImm32Shift";
195}
196def MovImm64ShifterOperand : AsmOperandClass {
197  let SuperClasses = [ShifterOperand];
198  let Name = "MovImm64Shifter";
199  let RenderMethod = "addShifterOperands";
200  let DiagnosticType = "InvalidMovImm64Shift";
201}
202
203// Shifter operand for arithmetic register shifted encodings.
204class ArithmeticShifterOperand<int width> : AsmOperandClass {
205  let SuperClasses = [ShifterOperand];
206  let Name = "ArithmeticShifter" # width;
207  let PredicateMethod = "isArithmeticShifter<" # width # ">";
208  let RenderMethod = "addShifterOperands";
209  let DiagnosticType = "AddSubRegShift" # width;
210}
211
212def ArithmeticShifterOperand32 : ArithmeticShifterOperand<32>;
213def ArithmeticShifterOperand64 : ArithmeticShifterOperand<64>;
214
215// Shifter operand for logical register shifted encodings.
216class LogicalShifterOperand<int width> : AsmOperandClass {
217  let SuperClasses = [ShifterOperand];
218  let Name = "LogicalShifter" # width;
219  let PredicateMethod = "isLogicalShifter<" # width # ">";
220  let RenderMethod = "addShifterOperands";
221  let DiagnosticType = "AddSubRegShift" # width;
222}
223
224def LogicalShifterOperand32 : LogicalShifterOperand<32>;
225def LogicalShifterOperand64 : LogicalShifterOperand<64>;
226
227// Shifter operand for logical vector 128/64-bit shifted encodings.
228def LogicalVecShifterOperand : AsmOperandClass {
229  let SuperClasses = [ShifterOperand];
230  let Name = "LogicalVecShifter";
231  let RenderMethod = "addShifterOperands";
232}
233def LogicalVecHalfWordShifterOperand : AsmOperandClass {
234  let SuperClasses = [LogicalVecShifterOperand];
235  let Name = "LogicalVecHalfWordShifter";
236  let RenderMethod = "addShifterOperands";
237}
238
239// The "MSL" shifter on the vector MOVI instruction.
240def MoveVecShifterOperand : AsmOperandClass {
241  let SuperClasses = [ShifterOperand];
242  let Name = "MoveVecShifter";
243  let RenderMethod = "addShifterOperands";
244}
245
246// Extend operand for arithmetic encodings.
247def ExtendOperand : AsmOperandClass {
248  let Name = "Extend";
249  let DiagnosticType = "AddSubRegExtendLarge";
250}
251def ExtendOperand64 : AsmOperandClass {
252  let SuperClasses = [ExtendOperand];
253  let Name = "Extend64";
254  let DiagnosticType = "AddSubRegExtendSmall";
255}
256// 'extend' that's a lsl of a 64-bit register.
257def ExtendOperandLSL64 : AsmOperandClass {
258  let SuperClasses = [ExtendOperand];
259  let Name = "ExtendLSL64";
260  let RenderMethod = "addExtend64Operands";
261  let DiagnosticType = "AddSubRegExtendLarge";
262}
263
264// 8-bit floating-point immediate encodings.
265def FPImmOperand : AsmOperandClass {
266  let Name = "FPImm";
267  let ParserMethod = "tryParseFPImm<true>";
268  let DiagnosticType = "InvalidFPImm";
269}
270
271def CondCode : AsmOperandClass {
272  let Name = "CondCode";
273  let DiagnosticType = "InvalidCondCode";
274}
275
276// A 32-bit register pasrsed as 64-bit
277def GPR32as64Operand : AsmOperandClass {
278  let Name = "GPR32as64";
279  let ParserMethod =
280      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSubReg>";
281}
282def GPR32as64 : RegisterOperand<GPR32> {
283  let ParserMatchClass = GPR32as64Operand;
284}
285
286// A 64-bit register pasrsed as 32-bit
287def GPR64as32Operand : AsmOperandClass {
288  let Name = "GPR64as32";
289  let ParserMethod =
290      "tryParseGPROperand<false, RegConstraintEqualityTy::EqualsSuperReg>";
291}
292def GPR64as32 : RegisterOperand<GPR64, "printGPR64as32"> {
293  let ParserMatchClass = GPR64as32Operand;
294}
295
296// 8-bit immediate for AdvSIMD where 64-bit values of the form:
297// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
298// are encoded as the eight bit value 'abcdefgh'.
299def SIMDImmType10Operand : AsmOperandClass { let Name = "SIMDImmType10"; }
300
301class UImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
302  let Name = "UImm" # Width # "s" # Scale;
303  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "UImm" # Width;
304  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
305  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ">";
306}
307
308class SImmScaledMemoryIndexed<int Width, int Scale> : AsmOperandClass {
309  let Name = "SImm" # Width # "s" # Scale;
310  let DiagnosticType = "InvalidMemoryIndexed" # Scale # "SImm" # Width;
311  let RenderMethod = "addImmScaledOperands<" # Scale # ">";
312  let PredicateMethod = "isSImmScaled<" # Width # ", " # Scale # ">";
313}
314
315//===----------------------------------------------------------------------===//
316// Operand Definitions.
317//
318
319// ADR[P] instruction labels.
320def AdrpOperand : AsmOperandClass {
321  let Name = "AdrpLabel";
322  let ParserMethod = "tryParseAdrpLabel";
323  let DiagnosticType = "InvalidLabel";
324}
325def adrplabel : Operand<i64> {
326  let EncoderMethod = "getAdrLabelOpValue";
327  let PrintMethod = "printAdrAdrpLabel";
328  let ParserMatchClass = AdrpOperand;
329  let OperandType = "OPERAND_PCREL";
330}
331
332def AdrOperand : AsmOperandClass {
333  let Name = "AdrLabel";
334  let ParserMethod = "tryParseAdrLabel";
335  let DiagnosticType = "InvalidLabel";
336}
337def adrlabel : Operand<i64> {
338  let EncoderMethod = "getAdrLabelOpValue";
339  let PrintMethod = "printAdrAdrpLabel";
340  let ParserMatchClass = AdrOperand;
341  let OperandType = "OPERAND_PCREL";
342}
343
344class SImmOperand<int width> : AsmOperandClass {
345  let Name = "SImm" # width;
346  let DiagnosticType = "InvalidMemoryIndexedSImm" # width;
347  let RenderMethod = "addImmOperands";
348  let PredicateMethod = "isSImm<" # width # ">";
349}
350
351class AsmImmRange<int Low, int High> : AsmOperandClass {
352  let Name = "Imm" # Low # "_" # High;
353  let DiagnosticType = "InvalidImm" # Low # "_" # High;
354  let RenderMethod = "addImmOperands";
355  let PredicateMethod = "isImmInRange<" # Low # "," # High # ">";
356}
357
358// Authenticated loads for v8.3 can have scaled 10-bit immediate offsets.
359def SImm10s8Operand : SImmScaledMemoryIndexed<10, 8>;
360def simm10Scaled : Operand<i64> {
361  let ParserMatchClass = SImm10s8Operand;
362  let DecoderMethod = "DecodeSImm<10>";
363  let PrintMethod = "printImmScale<8>";
364}
365
366def simm9s16 : Operand<i64> {
367  let ParserMatchClass = SImmScaledMemoryIndexed<9, 16>;
368  let DecoderMethod = "DecodeSImm<9>";
369  let PrintMethod = "printImmScale<16>";
370}
371
372// uimm6 predicate - True if the immediate is in the range [0, 63].
373def UImm6Operand : AsmOperandClass {
374  let Name = "UImm6";
375  let DiagnosticType = "InvalidImm0_63";
376}
377
378def uimm6 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
379  let ParserMatchClass = UImm6Operand;
380}
381
382def uimm16 : Operand<i16>, ImmLeaf<i16, [{return Imm >= 0 && Imm < 65536;}]>{
383  let ParserMatchClass = AsmImmRange<0, 65535>;
384}
385
386def SImm9Operand : SImmOperand<9>;
387def simm9 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -256 && Imm < 256; }]> {
388  let ParserMatchClass = SImm9Operand;
389  let DecoderMethod = "DecodeSImm<9>";
390}
391
392// imm0_255 predicate - True if the immediate is in the range [0,255].
393def Imm0_255Operand : AsmImmRange<0,255>;
394
395def uimm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= 0 && Imm < 256; }]> {
396  let ParserMatchClass = Imm0_255Operand;
397}
398def uimm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 256; }]> {
399  let ParserMatchClass = Imm0_255Operand;
400}
401
402def SImm8Operand : SImmOperand<8>;
403def simm8_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -128 && Imm < 128; }]> {
404  let ParserMatchClass = SImm8Operand;
405  let DecoderMethod = "DecodeSImm<8>";
406}
407def simm8_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -128 && Imm < 128; }]> {
408  let ParserMatchClass = SImm8Operand;
409  let DecoderMethod = "DecodeSImm<8>";
410}
411
412def SImm6Operand : SImmOperand<6>;
413def simm6_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -32 && Imm < 32; }]> {
414  let ParserMatchClass = SImm6Operand;
415  let DecoderMethod = "DecodeSImm<6>";
416}
417
418def SImm5Operand : SImmOperand<5>;
419def simm5_64b : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -16 && Imm < 16; }]> {
420  let ParserMatchClass = SImm5Operand;
421  let DecoderMethod = "DecodeSImm<5>";
422}
423
424def simm5_32b : Operand<i32>, ImmLeaf<i32, [{ return Imm >= -16 && Imm < 16; }]> {
425  let ParserMatchClass = SImm5Operand;
426  let DecoderMethod = "DecodeSImm<5>";
427}
428
429def simm5_8b : Operand<i32>, ImmLeaf<i32, [{ return (int8_t)Imm >= -16 && (int8_t)Imm < 16; }]> {
430  let ParserMatchClass = SImm5Operand;
431  let DecoderMethod = "DecodeSImm<5>";
432  let PrintMethod = "printSImm<8>";
433}
434
435def simm5_16b : Operand<i32>, ImmLeaf<i32, [{ return (int16_t)Imm >= -16 && (int16_t)Imm < 16; }]> {
436  let ParserMatchClass = SImm5Operand;
437  let DecoderMethod = "DecodeSImm<5>";
438  let PrintMethod = "printSImm<16>";
439}
440
441// simm7sN predicate - True if the immediate is a multiple of N in the range
442// [-64 * N, 63 * N].
443
444def SImm7s4Operand : SImmScaledMemoryIndexed<7, 4>;
445def SImm7s8Operand : SImmScaledMemoryIndexed<7, 8>;
446def SImm7s16Operand : SImmScaledMemoryIndexed<7, 16>;
447
448def simm7s4 : Operand<i32> {
449  let ParserMatchClass = SImm7s4Operand;
450  let PrintMethod = "printImmScale<4>";
451}
452
453def simm7s8 : Operand<i32> {
454  let ParserMatchClass = SImm7s8Operand;
455  let PrintMethod = "printImmScale<8>";
456}
457
458def simm7s16 : Operand<i32> {
459  let ParserMatchClass = SImm7s16Operand;
460  let PrintMethod = "printImmScale<16>";
461}
462
463def am_sve_fi : ComplexPattern<iPTR, 2, "SelectAddrModeFrameIndexSVE", []>;
464
465def am_indexed7s8   : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S8", []>;
466def am_indexed7s16  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S16", []>;
467def am_indexed7s32  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S32", []>;
468def am_indexed7s64  : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S64", []>;
469def am_indexed7s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed7S128", []>;
470
471def am_indexedu6s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedU6S128", []>;
472def am_indexeds9s128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedS9S128", []>;
473
474def UImmS1XForm : SDNodeXForm<imm, [{
475  return CurDAG->getTargetConstant(N->getZExtValue(), SDLoc(N), MVT::i64);
476}]>;
477def UImmS2XForm : SDNodeXForm<imm, [{
478  return CurDAG->getTargetConstant(N->getZExtValue() / 2, SDLoc(N), MVT::i64);
479}]>;
480def UImmS4XForm : SDNodeXForm<imm, [{
481  return CurDAG->getTargetConstant(N->getZExtValue() / 4, SDLoc(N), MVT::i64);
482}]>;
483def UImmS8XForm : SDNodeXForm<imm, [{
484  return CurDAG->getTargetConstant(N->getZExtValue() / 8, SDLoc(N), MVT::i64);
485}]>;
486
487// uimm5sN predicate - True if the immediate is a multiple of N in the range
488// [0 * N, 32 * N].
489def UImm5s2Operand : UImmScaledMemoryIndexed<5, 2>;
490def UImm5s4Operand : UImmScaledMemoryIndexed<5, 4>;
491def UImm5s8Operand : UImmScaledMemoryIndexed<5, 8>;
492
493def uimm5s2 : Operand<i64>, ImmLeaf<i64,
494                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
495                UImmS2XForm> {
496  let ParserMatchClass = UImm5s2Operand;
497  let PrintMethod = "printImmScale<2>";
498}
499def uimm5s4 : Operand<i64>, ImmLeaf<i64,
500                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
501                UImmS4XForm> {
502  let ParserMatchClass = UImm5s4Operand;
503  let PrintMethod = "printImmScale<4>";
504}
505def uimm5s8 : Operand<i64>, ImmLeaf<i64,
506                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
507                UImmS8XForm> {
508  let ParserMatchClass = UImm5s8Operand;
509  let PrintMethod = "printImmScale<8>";
510}
511
512// tuimm5sN predicate - similiar to uimm5sN, but use TImmLeaf (TargetConstant)
513// instead of ImmLeaf (Constant)
514def tuimm5s2 : Operand<i64>, TImmLeaf<i64,
515                [{ return Imm >= 0 && Imm < (32*2) && ((Imm % 2) == 0); }],
516                UImmS2XForm> {
517  let ParserMatchClass = UImm5s2Operand;
518  let PrintMethod = "printImmScale<2>";
519}
520def tuimm5s4 : Operand<i64>, TImmLeaf<i64,
521                [{ return Imm >= 0 && Imm < (32*4) && ((Imm % 4) == 0); }],
522                UImmS4XForm> {
523  let ParserMatchClass = UImm5s4Operand;
524  let PrintMethod = "printImmScale<4>";
525}
526def tuimm5s8 : Operand<i64>, TImmLeaf<i64,
527                [{ return Imm >= 0 && Imm < (32*8) && ((Imm % 8) == 0); }],
528                UImmS8XForm> {
529  let ParserMatchClass = UImm5s8Operand;
530  let PrintMethod = "printImmScale<8>";
531}
532
533// uimm6sN predicate - True if the immediate is a multiple of N in the range
534// [0 * N, 64 * N].
535def UImm6s1Operand : UImmScaledMemoryIndexed<6, 1>;
536def UImm6s2Operand : UImmScaledMemoryIndexed<6, 2>;
537def UImm6s4Operand : UImmScaledMemoryIndexed<6, 4>;
538def UImm6s8Operand : UImmScaledMemoryIndexed<6, 8>;
539def UImm6s16Operand : UImmScaledMemoryIndexed<6, 16>;
540
541def uimm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= 0 && Imm < 64; }]> {
542  let ParserMatchClass = UImm6s1Operand;
543}
544def uimm6s2 : Operand<i64>, ImmLeaf<i64,
545[{ return Imm >= 0 && Imm < (64*2) && ((Imm % 2) == 0); }]> {
546  let PrintMethod = "printImmScale<2>";
547  let ParserMatchClass = UImm6s2Operand;
548}
549def uimm6s4 : Operand<i64>, ImmLeaf<i64,
550[{ return Imm >= 0 && Imm < (64*4) && ((Imm % 4) == 0); }]> {
551  let PrintMethod = "printImmScale<4>";
552  let ParserMatchClass = UImm6s4Operand;
553}
554def uimm6s8 : Operand<i64>, ImmLeaf<i64,
555[{ return Imm >= 0 && Imm < (64*8) && ((Imm % 8) == 0); }]> {
556  let PrintMethod = "printImmScale<8>";
557  let ParserMatchClass = UImm6s8Operand;
558}
559def uimm6s16 : Operand<i64>, ImmLeaf<i64,
560[{ return Imm >= 0 && Imm < (64*16) && ((Imm % 16) == 0); }]> {
561  let PrintMethod = "printImmScale<16>";
562  let ParserMatchClass = UImm6s16Operand;
563}
564
565def SImmS2XForm : SDNodeXForm<imm, [{
566  return CurDAG->getTargetConstant(N->getSExtValue() / 2, SDLoc(N), MVT::i64);
567}]>;
568def SImmS3XForm : SDNodeXForm<imm, [{
569  return CurDAG->getTargetConstant(N->getSExtValue() / 3, SDLoc(N), MVT::i64);
570}]>;
571def SImmS4XForm : SDNodeXForm<imm, [{
572  return CurDAG->getTargetConstant(N->getSExtValue() / 4, SDLoc(N), MVT::i64);
573}]>;
574def SImmS16XForm : SDNodeXForm<imm, [{
575  return CurDAG->getTargetConstant(N->getSExtValue() / 16, SDLoc(N), MVT::i64);
576}]>;
577def SImmS32XForm : SDNodeXForm<imm, [{
578  return CurDAG->getTargetConstant(N->getSExtValue() / 32, SDLoc(N), MVT::i64);
579}]>;
580
581// simm6sN predicate - True if the immediate is a multiple of N in the range
582// [-32 * N, 31 * N].
583def SImm6s1Operand : SImmScaledMemoryIndexed<6, 1>;
584def simm6s1 : Operand<i64>, ImmLeaf<i64, [{ return Imm >= -32 && Imm < 32; }]> {
585  let ParserMatchClass = SImm6s1Operand;
586  let DecoderMethod = "DecodeSImm<6>";
587}
588
589// simm4sN predicate - True if the immediate is a multiple of N in the range
590// [ -8* N, 7 * N].
591def SImm4s1Operand  : SImmScaledMemoryIndexed<4, 1>;
592def SImm4s2Operand  : SImmScaledMemoryIndexed<4, 2>;
593def SImm4s3Operand  : SImmScaledMemoryIndexed<4, 3>;
594def SImm4s4Operand  : SImmScaledMemoryIndexed<4, 4>;
595def SImm4s16Operand : SImmScaledMemoryIndexed<4, 16>;
596def SImm4s32Operand : SImmScaledMemoryIndexed<4, 32>;
597
598def simm4s1 : Operand<i64>, ImmLeaf<i64,
599[{ return Imm >=-8  && Imm <= 7; }]> {
600  let ParserMatchClass = SImm4s1Operand;
601  let DecoderMethod = "DecodeSImm<4>";
602}
603
604def simm4s2 : Operand<i64>, ImmLeaf<i64,
605[{ return Imm >=-16  && Imm <= 14 && (Imm % 2) == 0x0; }], SImmS2XForm> {
606  let PrintMethod = "printImmScale<2>";
607  let ParserMatchClass = SImm4s2Operand;
608  let DecoderMethod = "DecodeSImm<4>";
609}
610
611def simm4s3 : Operand<i64>, ImmLeaf<i64,
612[{ return Imm >=-24  && Imm <= 21 && (Imm % 3) == 0x0; }], SImmS3XForm> {
613  let PrintMethod = "printImmScale<3>";
614  let ParserMatchClass = SImm4s3Operand;
615  let DecoderMethod = "DecodeSImm<4>";
616}
617
618def simm4s4 : Operand<i64>, ImmLeaf<i64,
619[{ return Imm >=-32  && Imm <= 28 && (Imm % 4) == 0x0; }], SImmS4XForm> {
620  let PrintMethod = "printImmScale<4>";
621  let ParserMatchClass = SImm4s4Operand;
622  let DecoderMethod = "DecodeSImm<4>";
623}
624def simm4s16 : Operand<i64>, ImmLeaf<i64,
625[{ return Imm >=-128  && Imm <= 112 && (Imm % 16) == 0x0; }], SImmS16XForm> {
626  let PrintMethod = "printImmScale<16>";
627  let ParserMatchClass = SImm4s16Operand;
628  let DecoderMethod = "DecodeSImm<4>";
629}
630def simm4s32 : Operand<i64>, ImmLeaf<i64,
631[{ return Imm >=-256  && Imm <= 224 && (Imm % 32) == 0x0; }], SImmS32XForm> {
632  let PrintMethod = "printImmScale<32>";
633  let ParserMatchClass = SImm4s32Operand;
634  let DecoderMethod = "DecodeSImm<4>";
635}
636
637def Imm1_8Operand : AsmImmRange<1, 8>;
638def Imm1_16Operand : AsmImmRange<1, 16>;
639def Imm1_32Operand : AsmImmRange<1, 32>;
640def Imm1_64Operand : AsmImmRange<1, 64>;
641
642class BranchTarget<int N> : AsmOperandClass {
643  let Name = "BranchTarget" # N;
644  let DiagnosticType = "InvalidLabel";
645  let PredicateMethod = "isBranchTarget<" # N # ">";
646}
647
648class PCRelLabel<int N> : BranchTarget<N> {
649  let Name = "PCRelLabel" # N;
650}
651
652def BranchTarget14Operand : BranchTarget<14>;
653def BranchTarget26Operand : BranchTarget<26>;
654def PCRelLabel19Operand   : PCRelLabel<19>;
655
656def MovWSymbolG3AsmOperand : AsmOperandClass {
657  let Name = "MovWSymbolG3";
658  let RenderMethod = "addImmOperands";
659}
660
661def movw_symbol_g3 : Operand<i32> {
662  let ParserMatchClass = MovWSymbolG3AsmOperand;
663}
664
665def MovWSymbolG2AsmOperand : AsmOperandClass {
666  let Name = "MovWSymbolG2";
667  let RenderMethod = "addImmOperands";
668}
669
670def movw_symbol_g2 : Operand<i32> {
671  let ParserMatchClass = MovWSymbolG2AsmOperand;
672}
673
674def MovWSymbolG1AsmOperand : AsmOperandClass {
675  let Name = "MovWSymbolG1";
676  let RenderMethod = "addImmOperands";
677}
678
679def movw_symbol_g1 : Operand<i32> {
680  let ParserMatchClass = MovWSymbolG1AsmOperand;
681}
682
683def MovWSymbolG0AsmOperand : AsmOperandClass {
684  let Name = "MovWSymbolG0";
685  let RenderMethod = "addImmOperands";
686}
687
688def movw_symbol_g0 : Operand<i32> {
689  let ParserMatchClass = MovWSymbolG0AsmOperand;
690}
691
692class fixedpoint_i32<ValueType FloatVT>
693  : Operand<FloatVT>,
694    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<32>", [fpimm, ld]> {
695  let EncoderMethod = "getFixedPointScaleOpValue";
696  let DecoderMethod = "DecodeFixedPointScaleImm32";
697  let ParserMatchClass = Imm1_32Operand;
698}
699
700class fixedpoint_i64<ValueType FloatVT>
701  : Operand<FloatVT>,
702    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosOperand<64>", [fpimm, ld]> {
703  let EncoderMethod = "getFixedPointScaleOpValue";
704  let DecoderMethod = "DecodeFixedPointScaleImm64";
705  let ParserMatchClass = Imm1_64Operand;
706}
707
708def fixedpoint_f16_i32 : fixedpoint_i32<f16>;
709def fixedpoint_f32_i32 : fixedpoint_i32<f32>;
710def fixedpoint_f64_i32 : fixedpoint_i32<f64>;
711
712def fixedpoint_f16_i64 : fixedpoint_i64<f16>;
713def fixedpoint_f32_i64 : fixedpoint_i64<f32>;
714def fixedpoint_f64_i64 : fixedpoint_i64<f64>;
715
716class fixedpoint_recip_i32<ValueType FloatVT>
717  : Operand<FloatVT>,
718    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosRecipOperand<32>", [fpimm, ld]> {
719  let EncoderMethod = "getFixedPointScaleOpValue";
720  let DecoderMethod = "DecodeFixedPointScaleImm32";
721}
722
723class fixedpoint_recip_i64<ValueType FloatVT>
724  : Operand<FloatVT>,
725    ComplexPattern<FloatVT, 1, "SelectCVTFixedPosRecipOperand<64>", [fpimm, ld]> {
726  let EncoderMethod = "getFixedPointScaleOpValue";
727  let DecoderMethod = "DecodeFixedPointScaleImm64";
728}
729
730def fixedpoint_recip_f16_i32 : fixedpoint_recip_i32<f16>;
731def fixedpoint_recip_f32_i32 : fixedpoint_recip_i32<f32>;
732def fixedpoint_recip_f64_i32 : fixedpoint_recip_i32<f64>;
733
734def fixedpoint_recip_f16_i64 : fixedpoint_recip_i64<f16>;
735def fixedpoint_recip_f32_i64 : fixedpoint_recip_i64<f32>;
736def fixedpoint_recip_f64_i64 : fixedpoint_recip_i64<f64>;
737
738def vecshiftR8 : Operand<i32>, ImmLeaf<i32, [{
739  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
740}]> {
741  let EncoderMethod = "getVecShiftR8OpValue";
742  let DecoderMethod = "DecodeVecShiftR8Imm";
743  let ParserMatchClass = Imm1_8Operand;
744}
745def vecshiftR16 : Operand<i32>, ImmLeaf<i32, [{
746  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
747}]> {
748  let EncoderMethod = "getVecShiftR16OpValue";
749  let DecoderMethod = "DecodeVecShiftR16Imm";
750  let ParserMatchClass = Imm1_16Operand;
751}
752def vecshiftR16Narrow : Operand<i32>, ImmLeaf<i32, [{
753  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
754}]> {
755  let EncoderMethod = "getVecShiftR16OpValue";
756  let DecoderMethod = "DecodeVecShiftR16ImmNarrow";
757  let ParserMatchClass = Imm1_8Operand;
758}
759def vecshiftR32 : Operand<i32>, ImmLeaf<i32, [{
760  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
761}]> {
762  let EncoderMethod = "getVecShiftR32OpValue";
763  let DecoderMethod = "DecodeVecShiftR32Imm";
764  let ParserMatchClass = Imm1_32Operand;
765}
766def vecshiftR32Narrow : Operand<i32>, ImmLeaf<i32, [{
767  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
768}]> {
769  let EncoderMethod = "getVecShiftR32OpValue";
770  let DecoderMethod = "DecodeVecShiftR32ImmNarrow";
771  let ParserMatchClass = Imm1_16Operand;
772}
773def vecshiftR64 : Operand<i32>, ImmLeaf<i32, [{
774  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
775}]> {
776  let EncoderMethod = "getVecShiftR64OpValue";
777  let DecoderMethod = "DecodeVecShiftR64Imm";
778  let ParserMatchClass = Imm1_64Operand;
779}
780def vecshiftR64Narrow : Operand<i32>, ImmLeaf<i32, [{
781  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
782}]> {
783  let EncoderMethod = "getVecShiftR64OpValue";
784  let DecoderMethod = "DecodeVecShiftR64ImmNarrow";
785  let ParserMatchClass = Imm1_32Operand;
786}
787
788// Same as vecshiftR#N, but use TargetConstant (TimmLeaf) instead of Constant
789// (ImmLeaf)
790def tvecshiftR8 : Operand<i32>, TImmLeaf<i32, [{
791  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 9);
792}]> {
793  let EncoderMethod = "getVecShiftR8OpValue";
794  let DecoderMethod = "DecodeVecShiftR8Imm";
795  let ParserMatchClass = Imm1_8Operand;
796}
797def tvecshiftR16 : Operand<i32>, TImmLeaf<i32, [{
798  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 17);
799}]> {
800  let EncoderMethod = "getVecShiftR16OpValue";
801  let DecoderMethod = "DecodeVecShiftR16Imm";
802  let ParserMatchClass = Imm1_16Operand;
803}
804def tvecshiftR32 : Operand<i32>, TImmLeaf<i32, [{
805  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 33);
806}]> {
807  let EncoderMethod = "getVecShiftR32OpValue";
808  let DecoderMethod = "DecodeVecShiftR32Imm";
809  let ParserMatchClass = Imm1_32Operand;
810}
811def tvecshiftR64 : Operand<i32>, TImmLeaf<i32, [{
812  return (((uint32_t)Imm) > 0) && (((uint32_t)Imm) < 65);
813}]> {
814  let EncoderMethod = "getVecShiftR64OpValue";
815  let DecoderMethod = "DecodeVecShiftR64Imm";
816  let ParserMatchClass = Imm1_64Operand;
817}
818
819def Imm0_0Operand : AsmImmRange<0, 0>;
820def Imm0_1Operand : AsmImmRange<0, 1>;
821def Imm1_1Operand : AsmImmRange<1, 1>;
822def Imm0_3Operand : AsmImmRange<0, 3>;
823def Imm1_3Operand : AsmImmRange<1, 3>;
824def Imm0_7Operand : AsmImmRange<0, 7>;
825def Imm1_7Operand : AsmImmRange<1, 7>;
826def Imm0_15Operand : AsmImmRange<0, 15>;
827def Imm0_31Operand : AsmImmRange<0, 31>;
828def Imm0_63Operand : AsmImmRange<0, 63>;
829
830def vecshiftL8 : Operand<i32>, ImmLeaf<i32, [{
831  return (((uint32_t)Imm) < 8);
832}]> {
833  let EncoderMethod = "getVecShiftL8OpValue";
834  let DecoderMethod = "DecodeVecShiftL8Imm";
835  let ParserMatchClass = Imm0_7Operand;
836}
837def vecshiftL16 : Operand<i32>, ImmLeaf<i32, [{
838  return (((uint32_t)Imm) < 16);
839}]> {
840  let EncoderMethod = "getVecShiftL16OpValue";
841  let DecoderMethod = "DecodeVecShiftL16Imm";
842  let ParserMatchClass = Imm0_15Operand;
843}
844def vecshiftL32 : Operand<i32>, ImmLeaf<i32, [{
845  return (((uint32_t)Imm) < 32);
846}]> {
847  let EncoderMethod = "getVecShiftL32OpValue";
848  let DecoderMethod = "DecodeVecShiftL32Imm";
849  let ParserMatchClass = Imm0_31Operand;
850}
851def vecshiftL64 : Operand<i32>, ImmLeaf<i32, [{
852  return (((uint32_t)Imm) < 64);
853}]> {
854  let EncoderMethod = "getVecShiftL64OpValue";
855  let DecoderMethod = "DecodeVecShiftL64Imm";
856  let ParserMatchClass = Imm0_63Operand;
857}
858
859// Same as vecshiftL#N, but use TargetConstant (TimmLeaf) instead of Constant
860// (ImmLeaf)
861def tvecshiftL8 : Operand<i32>, TImmLeaf<i32, [{
862  return (((uint32_t)Imm) < 8);
863}]> {
864  let EncoderMethod = "getVecShiftL8OpValue";
865  let DecoderMethod = "DecodeVecShiftL8Imm";
866  let ParserMatchClass = Imm0_7Operand;
867}
868def tvecshiftL16 : Operand<i32>, TImmLeaf<i32, [{
869  return (((uint32_t)Imm) < 16);
870}]> {
871  let EncoderMethod = "getVecShiftL16OpValue";
872  let DecoderMethod = "DecodeVecShiftL16Imm";
873  let ParserMatchClass = Imm0_15Operand;
874}
875def tvecshiftL32 : Operand<i32>, TImmLeaf<i32, [{
876  return (((uint32_t)Imm) < 32);
877}]> {
878  let EncoderMethod = "getVecShiftL32OpValue";
879  let DecoderMethod = "DecodeVecShiftL32Imm";
880  let ParserMatchClass = Imm0_31Operand;
881}
882def tvecshiftL64 : Operand<i32>, TImmLeaf<i32, [{
883  return (((uint32_t)Imm) < 64);
884}]> {
885  let EncoderMethod = "getVecShiftL64OpValue";
886  let DecoderMethod = "DecodeVecShiftL64Imm";
887  let ParserMatchClass = Imm0_63Operand;
888}
889
890// Crazy immediate formats used by 32-bit and 64-bit logical immediate
891// instructions for splatting repeating bit patterns across the immediate.
892def logical_imm32_XFORM : SDNodeXForm<imm, [{
893  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 32);
894  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
895}]>;
896def logical_imm64_XFORM : SDNodeXForm<imm, [{
897  uint64_t enc = AArch64_AM::encodeLogicalImmediate(N->getZExtValue(), 64);
898  return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
899}]>;
900
901def gi_logical_imm32_XFORM : GICustomOperandRenderer<"renderLogicalImm32">,
902  GISDNodeXFormEquiv<logical_imm32_XFORM>;
903def gi_logical_imm64_XFORM : GICustomOperandRenderer<"renderLogicalImm64">,
904  GISDNodeXFormEquiv<logical_imm64_XFORM>;
905
906let DiagnosticType = "LogicalSecondSource" in {
907  def LogicalImm32Operand : AsmOperandClass {
908    let Name = "LogicalImm32";
909    let PredicateMethod = "isLogicalImm<int32_t>";
910    let RenderMethod = "addLogicalImmOperands<int32_t>";
911  }
912  def LogicalImm64Operand : AsmOperandClass {
913    let Name = "LogicalImm64";
914    let PredicateMethod = "isLogicalImm<int64_t>";
915    let RenderMethod = "addLogicalImmOperands<int64_t>";
916  }
917  def LogicalImm32NotOperand : AsmOperandClass {
918    let Name = "LogicalImm32Not";
919    let PredicateMethod = "isLogicalImm<int32_t>";
920    let RenderMethod = "addLogicalImmNotOperands<int32_t>";
921  }
922  def LogicalImm64NotOperand : AsmOperandClass {
923    let Name = "LogicalImm64Not";
924    let PredicateMethod = "isLogicalImm<int64_t>";
925    let RenderMethod = "addLogicalImmNotOperands<int64_t>";
926  }
927}
928
929def Imm0_127Operand : AsmImmRange<0, 127>;
930
931let OperandType = "OPERAND_IMMEDIATE" in {
932
933def logical_imm32 : Operand<i32>, IntImmLeaf<i32, [{
934  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 32);
935}], logical_imm32_XFORM> {
936  let PrintMethod = "printLogicalImm<int32_t>";
937  let ParserMatchClass = LogicalImm32Operand;
938}
939def logical_imm64 : Operand<i64>, IntImmLeaf<i64, [{
940  return AArch64_AM::isLogicalImmediate(Imm.getZExtValue(), 64);
941}], logical_imm64_XFORM> {
942  let PrintMethod = "printLogicalImm<int64_t>";
943  let ParserMatchClass = LogicalImm64Operand;
944}
945def logical_imm32_not : Operand<i32> {
946  let ParserMatchClass = LogicalImm32NotOperand;
947}
948def logical_imm64_not : Operand<i64> {
949  let ParserMatchClass = LogicalImm64NotOperand;
950}
951
952// immXX_0_65535 predicates - True if the immediate is in the range [0,65535].
953let ParserMatchClass = AsmImmRange<0, 65535>, PrintMethod = "printImmHex" in {
954def timm32_0_65535 : Operand<i32>, TImmLeaf<i32, [{
955  return ((uint32_t)Imm) < 65536;
956}]>;
957
958def timm64_0_65535 : Operand<i64>, TImmLeaf<i64, [{
959  return ((uint64_t)Imm) < 65536;
960}]>;
961
962def imm64_0_65535 : Operand<i64>, ImmLeaf<i64, [{
963  return ((uint64_t)Imm) < 65536;
964}]>;
965} // ParserMatchClass
966
967def imm0_255 : Operand<i32>, ImmLeaf<i32, [{
968  return ((uint32_t)Imm) < 256;
969}]> {
970  let ParserMatchClass = Imm0_255Operand;
971  let PrintMethod = "printImm";
972}
973
974// imm0_127 predicate - True if the immediate is in the range [0,127]
975def imm0_127 : Operand<i32>, ImmLeaf<i32, [{
976  return ((uint32_t)Imm) < 128;
977}]> {
978  let ParserMatchClass = Imm0_127Operand;
979  let PrintMethod = "printImm";
980}
981
982def imm0_127_64b : Operand<i64>, ImmLeaf<i64, [{
983  return ((uint64_t)Imm) < 128;
984}]> {
985  let ParserMatchClass = Imm0_127Operand;
986  let PrintMethod = "printImm";
987}
988
989// NOTE: These imm0_N operands have to be of type i64 because i64 is the size
990// for all shift-amounts.
991
992// imm0_63 predicate - True if the immediate is in the range [0,63]
993def imm0_63 : Operand<i64>, ImmLeaf<i64, [{
994  return ((uint64_t)Imm) < 64;
995}]> {
996  let ParserMatchClass = Imm0_63Operand;
997}
998
999def timm0_63 : Operand<i64>, TImmLeaf<i64, [{
1000  return ((uint64_t)Imm) < 64;
1001}]> {
1002  let ParserMatchClass = Imm0_63Operand;
1003}
1004
1005// imm0_31 predicate - True if the immediate is in the range [0,31]
1006def imm0_31 : Operand<i64>, ImmLeaf<i64, [{
1007  return ((uint64_t)Imm) < 32;
1008}]> {
1009  let ParserMatchClass = Imm0_31Operand;
1010}
1011
1012// timm0_31 predicate - same ass imm0_31, but use TargetConstant (TimmLeaf)
1013// instead of Constant (ImmLeaf)
1014def timm0_31 : Operand<i64>, TImmLeaf<i64, [{
1015  return ((uint64_t)Imm) < 32;
1016}]> {
1017  let ParserMatchClass = Imm0_31Operand;
1018}
1019
1020// True if the 32-bit immediate is in the range [0,31]
1021def imm32_0_31 : Operand<i32>, ImmLeaf<i32, [{
1022  return ((uint64_t)Imm) < 32;
1023}]> {
1024  let ParserMatchClass = Imm0_31Operand;
1025}
1026
1027// imm0_1 predicate - True if the immediate is in the range [0,1]
1028def imm0_1 : Operand<i64>, ImmLeaf<i64, [{
1029  return ((uint64_t)Imm) < 2;
1030}]> {
1031  let ParserMatchClass = Imm0_1Operand;
1032}
1033
1034// timm0_1 - as above, but use TargetConstant (TImmLeaf)
1035def timm0_1 : Operand<i64>, TImmLeaf<i64, [{
1036  return ((uint64_t)Imm) < 2;
1037}]> {
1038  let ParserMatchClass = Imm0_1Operand;
1039}
1040
1041// timm32_0_0 predicate - True if the 32-bit immediate is in the range [0,0]
1042def timm32_0_0 : Operand<i32>, TImmLeaf<i32, [{
1043  return ((uint32_t)Imm) == 0;
1044}]> {
1045  let ParserMatchClass = Imm0_0Operand;
1046}
1047
1048// timm32_0_1 predicate - True if the 32-bit immediate is in the range [0,1]
1049def timm32_0_1 : Operand<i32>, TImmLeaf<i32, [{
1050  return ((uint32_t)Imm) < 2;
1051}]> {
1052  let ParserMatchClass = Imm0_1Operand;
1053}
1054
1055// timm32_1_1 - True if the 32-bit immediate is in the range [1,1]
1056def timm32_1_1 : Operand<i32>, TImmLeaf<i32, [{
1057    return ((uint32_t)Imm) == 1;
1058}]> {
1059  let ParserMatchClass = Imm1_1Operand;
1060}
1061
1062// timm32_1_3 predicate - True if the 32-bit immediate is in the range [1,3]
1063def timm32_1_3 : Operand<i32>, TImmLeaf<i32, [{
1064  return ((uint32_t)Imm) > 0 && ((uint32_t)Imm) < 4;
1065}]> {
1066  let ParserMatchClass = Imm1_3Operand;
1067}
1068
1069// imm0_15 predicate - True if the immediate is in the range [0,15]
1070def imm0_15 : Operand<i64>, ImmLeaf<i64, [{
1071  return ((uint64_t)Imm) < 16;
1072}]> {
1073  let ParserMatchClass = Imm0_15Operand;
1074}
1075
1076// imm0_7 predicate - True if the immediate is in the range [0,7]
1077def imm0_7 : Operand<i64>, ImmLeaf<i64, [{
1078  return ((uint64_t)Imm) < 8;
1079}]> {
1080  let ParserMatchClass = Imm0_7Operand;
1081}
1082
1083// imm0_3 predicate - True if the immediate is in the range [0,3]
1084def imm0_3 : Operand<i64>, ImmLeaf<i64, [{
1085  return ((uint64_t)Imm) < 4;
1086}]> {
1087  let ParserMatchClass = Imm0_3Operand;
1088}
1089
1090// timm32_0_3 predicate - True if the 32-bit immediate is in the range [0,3]
1091def timm32_0_3 : Operand<i32>, TImmLeaf<i32, [{
1092  return ((uint32_t)Imm) < 4;
1093}]> {
1094  let ParserMatchClass = Imm0_3Operand;
1095}
1096
1097// timm32_0_7 predicate - True if the 32-bit immediate is in the range [0,7]
1098def timm32_0_7 : Operand<i32>, TImmLeaf<i32, [{
1099  return ((uint32_t)Imm) < 8;
1100}]> {
1101  let ParserMatchClass = Imm0_7Operand;
1102}
1103
1104// timm32_1_7 predicate - True if the 32-bit immediate is in the range [1,7]
1105def timm32_1_7 : Operand<i32>, TImmLeaf<i32, [{
1106  return ((uint32_t)Imm) > 0 && ((uint32_t)Imm) < 8;
1107}]> {
1108  let ParserMatchClass = Imm1_7Operand;
1109}
1110
1111// imm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1112def imm32_0_15 : Operand<i32>, ImmLeaf<i32, [{
1113  return ((uint32_t)Imm) < 16;
1114}]> {
1115  let ParserMatchClass = Imm0_15Operand;
1116}
1117
1118// timm32_0_15 predicate - True if the 32-bit immediate is in the range [0,15]
1119def timm32_0_15 : Operand<i32>, TImmLeaf<i32, [{
1120  return ((uint32_t)Imm) < 16;
1121}]> {
1122  let ParserMatchClass = Imm0_15Operand;
1123}
1124
1125// timm32_0_31 predicate - True if the 32-bit immediate is in the range [0,31]
1126def timm32_0_31 : Operand<i32>, TImmLeaf<i32, [{
1127  return ((uint32_t)Imm) < 32;
1128}]> {
1129  let ParserMatchClass = Imm0_31Operand;
1130}
1131
1132// timm32_0_255 predicate - True if the 32-bit immediate is in the range [0,255]
1133def timm32_0_255 : Operand<i32>, TImmLeaf<i32, [{
1134  return ((uint32_t)Imm) < 256;
1135}]> {
1136  let ParserMatchClass = Imm0_255Operand;
1137}
1138
1139} // let OperandType = "OPERAND_IMMEDIATE"
1140
1141// An arithmetic shifter operand:
1142//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr
1143//  {5-0} - imm6
1144class arith_shift<ValueType Ty, int width> : Operand<Ty> {
1145  let PrintMethod = "printShifter";
1146  let ParserMatchClass = !cast<AsmOperandClass>(
1147                         "ArithmeticShifterOperand" # width);
1148}
1149
1150def arith_shift32 : arith_shift<i32, 32>;
1151def arith_shift64 : arith_shift<i64, 64>;
1152
1153class arith_shifted_reg<ValueType Ty, RegisterClass regclass, int width>
1154    : Operand<Ty>,
1155      ComplexPattern<Ty, 2, "SelectArithShiftedRegister", []> {
1156  let PrintMethod = "printShiftedRegister";
1157  let MIOperandInfo = (ops regclass, !cast<Operand>("arith_shift" # width));
1158}
1159
1160def arith_shifted_reg32 : arith_shifted_reg<i32, GPR32, 32>;
1161def arith_shifted_reg64 : arith_shifted_reg<i64, GPR64, 64>;
1162
1163def gi_arith_shifted_reg32 :
1164  GIComplexOperandMatcher<s32, "selectArithShiftedRegister">,
1165  GIComplexPatternEquiv<arith_shifted_reg32>;
1166
1167def gi_arith_shifted_reg64 :
1168  GIComplexOperandMatcher<s64, "selectArithShiftedRegister">,
1169  GIComplexPatternEquiv<arith_shifted_reg64>;
1170
1171// An arithmetic shifter operand:
1172//  {7-6} - shift type: 00 = lsl, 01 = lsr, 10 = asr, 11 = ror
1173//  {5-0} - imm6
1174class logical_shift<int width> : Operand<i32> {
1175  let PrintMethod = "printShifter";
1176  let ParserMatchClass = !cast<AsmOperandClass>(
1177                         "LogicalShifterOperand" # width);
1178}
1179
1180def logical_shift32 : logical_shift<32>;
1181def logical_shift64 : logical_shift<64>;
1182
1183class logical_shifted_reg<ValueType Ty, RegisterClass regclass, Operand shiftop>
1184    : Operand<Ty>,
1185      ComplexPattern<Ty, 2, "SelectLogicalShiftedRegister", []> {
1186  let PrintMethod = "printShiftedRegister";
1187  let MIOperandInfo = (ops regclass, shiftop);
1188}
1189
1190def logical_shifted_reg32 : logical_shifted_reg<i32, GPR32, logical_shift32>;
1191def logical_shifted_reg64 : logical_shifted_reg<i64, GPR64, logical_shift64>;
1192
1193def gi_logical_shifted_reg32 :
1194  GIComplexOperandMatcher<s32, "selectLogicalShiftedRegister">,
1195  GIComplexPatternEquiv<logical_shifted_reg32>;
1196
1197def gi_logical_shifted_reg64 :
1198  GIComplexOperandMatcher<s64, "selectLogicalShiftedRegister">,
1199  GIComplexPatternEquiv<logical_shifted_reg64>;
1200
1201// A logical vector shifter operand:
1202//  {7-6} - shift type: 00 = lsl
1203//  {5-0} - imm6: #0, #8, #16, or #24
1204def logical_vec_shift : Operand<i32> {
1205  let PrintMethod = "printShifter";
1206  let EncoderMethod = "getVecShifterOpValue";
1207  let ParserMatchClass = LogicalVecShifterOperand;
1208}
1209
1210// A logical vector half-word shifter operand:
1211//  {7-6} - shift type: 00 = lsl
1212//  {5-0} - imm6: #0 or #8
1213def logical_vec_hw_shift : Operand<i32> {
1214  let PrintMethod = "printShifter";
1215  let EncoderMethod = "getVecShifterOpValue";
1216  let ParserMatchClass = LogicalVecHalfWordShifterOperand;
1217}
1218
1219// A vector move shifter operand:
1220//  {0} - imm1: #8 or #16
1221def move_vec_shift : Operand<i32> {
1222  let PrintMethod = "printShifter";
1223  let EncoderMethod = "getMoveVecShifterOpValue";
1224  let ParserMatchClass = MoveVecShifterOperand;
1225}
1226
1227let DiagnosticType = "AddSubSecondSource" in {
1228  def AddSubImmOperand : AsmOperandClass {
1229    let Name = "AddSubImm";
1230    let ParserMethod = "tryParseImmWithOptionalShift";
1231    let RenderMethod = "addImmWithOptionalShiftOperands<12>";
1232  }
1233  def AddSubImmNegOperand : AsmOperandClass {
1234    let Name = "AddSubImmNeg";
1235    let ParserMethod = "tryParseImmWithOptionalShift";
1236    let RenderMethod = "addImmNegWithOptionalShiftOperands<12>";
1237  }
1238}
1239// An ADD/SUB immediate shifter operand:
1240//  second operand:
1241//  {7-6} - shift type: 00 = lsl
1242//  {5-0} - imm6: #0 or #12
1243class addsub_shifted_imm<ValueType Ty>
1244    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectArithImmed", [imm]> {
1245  let PrintMethod = "printAddSubImm";
1246  let EncoderMethod = "getAddSubImmOpValue";
1247  let ParserMatchClass = AddSubImmOperand;
1248  let MIOperandInfo = (ops i32imm, i32imm);
1249}
1250
1251class addsub_shifted_imm_neg<ValueType Ty>
1252    : Operand<Ty> {
1253  let EncoderMethod = "getAddSubImmOpValue";
1254  let ParserMatchClass = AddSubImmNegOperand;
1255  let MIOperandInfo = (ops i32imm, i32imm);
1256}
1257
1258def addsub_shifted_imm32 : addsub_shifted_imm<i32>;
1259def addsub_shifted_imm64 : addsub_shifted_imm<i64>;
1260def addsub_shifted_imm32_neg : addsub_shifted_imm_neg<i32>;
1261def addsub_shifted_imm64_neg : addsub_shifted_imm_neg<i64>;
1262
1263def gi_addsub_shifted_imm32 :
1264    GIComplexOperandMatcher<s32, "selectArithImmed">,
1265    GIComplexPatternEquiv<addsub_shifted_imm32>;
1266
1267def gi_addsub_shifted_imm64 :
1268    GIComplexOperandMatcher<s64, "selectArithImmed">,
1269    GIComplexPatternEquiv<addsub_shifted_imm64>;
1270
1271class neg_addsub_shifted_imm<ValueType Ty>
1272    : Operand<Ty>, ComplexPattern<Ty, 2, "SelectNegArithImmed", [imm]> {
1273  let PrintMethod = "printAddSubImm";
1274  let EncoderMethod = "getAddSubImmOpValue";
1275  let ParserMatchClass = AddSubImmOperand;
1276  let MIOperandInfo = (ops i32imm, i32imm);
1277}
1278
1279def neg_addsub_shifted_imm32 : neg_addsub_shifted_imm<i32>;
1280def neg_addsub_shifted_imm64 : neg_addsub_shifted_imm<i64>;
1281
1282def gi_neg_addsub_shifted_imm32 :
1283    GIComplexOperandMatcher<s32, "selectNegArithImmed">,
1284    GIComplexPatternEquiv<neg_addsub_shifted_imm32>;
1285
1286def gi_neg_addsub_shifted_imm64 :
1287    GIComplexOperandMatcher<s64, "selectNegArithImmed">,
1288    GIComplexPatternEquiv<neg_addsub_shifted_imm64>;
1289
1290// An extend operand:
1291//  {5-3} - extend type
1292//  {2-0} - imm3
1293def arith_extend : Operand<i32> {
1294  let PrintMethod = "printArithExtend";
1295  let ParserMatchClass = ExtendOperand;
1296}
1297def arith_extend64 : Operand<i32> {
1298  let PrintMethod = "printArithExtend";
1299  let ParserMatchClass = ExtendOperand64;
1300}
1301
1302// 'extend' that's a lsl of a 64-bit register.
1303def arith_extendlsl64 : Operand<i32> {
1304  let PrintMethod = "printArithExtend";
1305  let ParserMatchClass = ExtendOperandLSL64;
1306}
1307
1308class arith_extended_reg32<ValueType Ty> : Operand<Ty>,
1309                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1310  let PrintMethod = "printExtendedRegister";
1311  let MIOperandInfo = (ops GPR32, arith_extend);
1312}
1313
1314class arith_extended_reg32to64<ValueType Ty> : Operand<Ty>,
1315                    ComplexPattern<Ty, 2, "SelectArithExtendedRegister", []> {
1316  let PrintMethod = "printExtendedRegister";
1317  let MIOperandInfo = (ops GPR32, arith_extend64);
1318}
1319
1320def arith_extended_reg32_i32 : arith_extended_reg32<i32>;
1321def gi_arith_extended_reg32_i32 :
1322    GIComplexOperandMatcher<s32, "selectArithExtendedRegister">,
1323    GIComplexPatternEquiv<arith_extended_reg32_i32>;
1324
1325def arith_extended_reg32_i64 : arith_extended_reg32<i64>;
1326def gi_arith_extended_reg32_i64 :
1327    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1328    GIComplexPatternEquiv<arith_extended_reg32_i64>;
1329
1330def arith_extended_reg32to64_i64 : arith_extended_reg32to64<i64>;
1331def gi_arith_extended_reg32to64_i64 :
1332    GIComplexOperandMatcher<s64, "selectArithExtendedRegister">,
1333    GIComplexPatternEquiv<arith_extended_reg32to64_i64>;
1334
1335def arith_uxtx : ComplexPattern<i64, 2, "SelectArithUXTXRegister", []>;
1336
1337// Floating-point immediate.
1338
1339def fpimm16XForm : SDNodeXForm<fpimm, [{
1340      APFloat InVal = N->getValueAPF();
1341      uint32_t enc = AArch64_AM::getFP16Imm(InVal);
1342      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1343    }]>;
1344
1345def fpimm32XForm : SDNodeXForm<fpimm, [{
1346      APFloat InVal = N->getValueAPF();
1347      uint32_t enc = AArch64_AM::getFP32Imm(InVal);
1348      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1349    }]>;
1350
1351def fpimm32SIMDModImmType4XForm : SDNodeXForm<fpimm, [{
1352      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType4(N->getValueAPF()
1353                                                          .bitcastToAPInt()
1354                                                          .getZExtValue());
1355      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1356    }]>;
1357
1358def fpimm64XForm : SDNodeXForm<fpimm, [{
1359      APFloat InVal = N->getValueAPF();
1360      uint32_t enc = AArch64_AM::getFP64Imm(InVal);
1361      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1362    }]>;
1363
1364def fpimm16 : Operand<f16>,
1365              FPImmLeaf<f16, [{
1366      return AArch64_AM::getFP16Imm(Imm) != -1;
1367    }], fpimm16XForm> {
1368  let ParserMatchClass = FPImmOperand;
1369  let PrintMethod = "printFPImmOperand";
1370}
1371
1372def fpimmbf16 : Operand<bf16>,
1373                FPImmLeaf<bf16, [{
1374      return AArch64_AM::getFP16Imm(Imm) != -1;
1375    }], fpimm16XForm>;
1376
1377def fpimm32 : Operand<f32>,
1378              FPImmLeaf<f32, [{
1379      return AArch64_AM::getFP32Imm(Imm) != -1;
1380    }], fpimm32XForm> {
1381  let ParserMatchClass = FPImmOperand;
1382  let PrintMethod = "printFPImmOperand";
1383}
1384
1385def fpimm32SIMDModImmType4 : FPImmLeaf<f32, [{
1386      uint64_t Enc = Imm.bitcastToAPInt().getZExtValue();
1387      return Enc != 0 && AArch64_AM::isAdvSIMDModImmType4(Enc << 32 | Enc);
1388    }], fpimm32SIMDModImmType4XForm> {
1389}
1390
1391def fpimm64 : Operand<f64>,
1392              FPImmLeaf<f64, [{
1393      return AArch64_AM::getFP64Imm(Imm) != -1;
1394    }], fpimm64XForm> {
1395  let ParserMatchClass = FPImmOperand;
1396  let PrintMethod = "printFPImmOperand";
1397}
1398
1399def fpimm8 : Operand<i32> {
1400  let ParserMatchClass = FPImmOperand;
1401  let PrintMethod = "printFPImmOperand";
1402}
1403
1404def fpimm0 : FPImmLeaf<fAny, [{
1405  return Imm.isExactlyValue(+0.0);
1406}]>;
1407
1408def fpimm_minus0 : FPImmLeaf<fAny, [{
1409  return Imm.isExactlyValue(-0.0);
1410}]>;
1411
1412def fpimm_half : FPImmLeaf<fAny, [{
1413  return Imm.isExactlyValue(+0.5);
1414}]>;
1415
1416def fpimm_one : FPImmLeaf<fAny, [{
1417  return Imm.isExactlyValue(+1.0);
1418}]>;
1419
1420def fpimm_two : FPImmLeaf<fAny, [{
1421  return Imm.isExactlyValue(+2.0);
1422}]>;
1423
1424def gi_fpimm16 : GICustomOperandRenderer<"renderFPImm16">,
1425  GISDNodeXFormEquiv<fpimm16XForm>;
1426def gi_fpimm32 : GICustomOperandRenderer<"renderFPImm32">,
1427  GISDNodeXFormEquiv<fpimm32XForm>;
1428def gi_fpimm64 : GICustomOperandRenderer<"renderFPImm64">,
1429  GISDNodeXFormEquiv<fpimm64XForm>;
1430def gi_fpimm32SIMDModImmType4 :
1431    GICustomOperandRenderer<"renderFPImm32SIMDModImmType4">,
1432  GISDNodeXFormEquiv<fpimm32SIMDModImmType4XForm>;
1433
1434// Vector lane operands
1435class AsmVectorIndex<int Min, int Max, string NamePrefix=""> : AsmOperandClass {
1436  let Name = NamePrefix # "IndexRange" # Min # "_" # Max;
1437  let DiagnosticType = "Invalid" # Name;
1438  let PredicateMethod = "isVectorIndex<" # Min # ", " # Max #  ">";
1439  let RenderMethod = "addVectorIndexOperands";
1440}
1441
1442class AsmVectorIndexOpnd<ValueType ty, AsmOperandClass mc>
1443    : Operand<ty> {
1444  let ParserMatchClass = mc;
1445  let PrintMethod = "printVectorIndex";
1446}
1447
1448multiclass VectorIndex<ValueType ty, AsmOperandClass mc, code pred> {
1449  def "" : AsmVectorIndexOpnd<ty, mc>, ImmLeaf<ty, pred>;
1450  def _timm : AsmVectorIndexOpnd<ty, mc>, TImmLeaf<ty, pred>;
1451}
1452
1453def VectorIndex0Operand : AsmVectorIndex<0, 0>;
1454def VectorIndex1Operand : AsmVectorIndex<1, 1>;
1455def VectorIndexBOperand : AsmVectorIndex<0, 15>;
1456def VectorIndexHOperand : AsmVectorIndex<0, 7>;
1457def VectorIndexSOperand : AsmVectorIndex<0, 3>;
1458def VectorIndexDOperand : AsmVectorIndex<0, 1>;
1459
1460let OperandNamespace = "AArch64" in {
1461  let OperandType = "OPERAND_IMPLICIT_IMM_0" in {
1462    defm VectorIndex0 : VectorIndex<i64, VectorIndex0Operand,
1463                                [{ return ((uint64_t)Imm) == 0; }]>;
1464    defm VectorIndex032b : VectorIndex<i32, VectorIndex0Operand,
1465                                [{ return ((uint32_t)Imm) == 0; }]>;
1466  }
1467}
1468defm VectorIndex1 : VectorIndex<i64, VectorIndex1Operand,
1469                                [{ return ((uint64_t)Imm) == 1; }]>;
1470defm VectorIndexB : VectorIndex<i64, VectorIndexBOperand,
1471                                [{ return ((uint64_t)Imm) < 16; }]>;
1472defm VectorIndexH : VectorIndex<i64, VectorIndexHOperand,
1473                                [{ return ((uint64_t)Imm) < 8; }]>;
1474defm VectorIndexS : VectorIndex<i64, VectorIndexSOperand,
1475                                [{ return ((uint64_t)Imm) < 4; }]>;
1476defm VectorIndexD : VectorIndex<i64, VectorIndexDOperand,
1477                                [{ return ((uint64_t)Imm) < 2; }]>;
1478
1479defm VectorIndex132b : VectorIndex<i32, VectorIndex1Operand,
1480                                   [{ return ((uint64_t)Imm) == 1; }]>;
1481defm VectorIndexB32b : VectorIndex<i32, VectorIndexBOperand,
1482                                   [{ return ((uint64_t)Imm) < 16; }]>;
1483defm VectorIndexH32b : VectorIndex<i32, VectorIndexHOperand,
1484                                   [{ return ((uint64_t)Imm) < 8; }]>;
1485defm VectorIndexS32b : VectorIndex<i32, VectorIndexSOperand,
1486                                   [{ return ((uint64_t)Imm) < 4; }]>;
1487defm VectorIndexD32b : VectorIndex<i32, VectorIndexDOperand,
1488                                   [{ return ((uint64_t)Imm) < 2; }]>;
1489
1490def SVEVectorIndexExtDupBOperand : AsmVectorIndex<0, 63, "SVE">;
1491def SVEVectorIndexExtDupHOperand : AsmVectorIndex<0, 31, "SVE">;
1492def SVEVectorIndexExtDupSOperand : AsmVectorIndex<0, 15, "SVE">;
1493def SVEVectorIndexExtDupDOperand : AsmVectorIndex<0, 7, "SVE">;
1494def SVEVectorIndexExtDupQOperand : AsmVectorIndex<0, 3, "SVE">;
1495
1496defm sve_elm_idx_extdup_b
1497  : VectorIndex<i64, SVEVectorIndexExtDupBOperand,
1498                [{ return ((uint64_t)Imm) < 64; }]>;
1499defm sve_elm_idx_extdup_h
1500  : VectorIndex<i64, SVEVectorIndexExtDupHOperand,
1501                [{ return ((uint64_t)Imm) < 32; }]>;
1502defm sve_elm_idx_extdup_s
1503  : VectorIndex<i64, SVEVectorIndexExtDupSOperand,
1504                [{ return ((uint64_t)Imm) < 16; }]>;
1505defm sve_elm_idx_extdup_d
1506  : VectorIndex<i64, SVEVectorIndexExtDupDOperand,
1507                [{ return ((uint64_t)Imm) < 8; }]>;
1508defm sve_elm_idx_extdup_q
1509  : VectorIndex<i64, SVEVectorIndexExtDupQOperand,
1510                [{ return ((uint64_t)Imm) < 4; }]>;
1511
1512def sme_elm_idx0_0 : Operand<i32>, TImmLeaf<i32, [{
1513  return ((uint32_t)Imm) == 0;
1514}]> {
1515  let ParserMatchClass = Imm0_0Operand;
1516  let PrintMethod = "printMatrixIndex";
1517  let OperandNamespace = "AArch64";
1518  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1519}
1520def sme_elm_idx0_1 : Operand<i32>, TImmLeaf<i32, [{
1521  return ((uint32_t)Imm) <= 1;
1522}]> {
1523  let ParserMatchClass = Imm0_1Operand;
1524  let PrintMethod = "printMatrixIndex";
1525}
1526def sme_elm_idx0_3 : Operand<i32>, TImmLeaf<i32, [{
1527  return ((uint32_t)Imm) <= 3;
1528}]> {
1529  let ParserMatchClass = Imm0_3Operand;
1530  let PrintMethod = "printMatrixIndex";
1531}
1532def sme_elm_idx0_7 : Operand<i32>, TImmLeaf<i32, [{
1533  return ((uint32_t)Imm) <= 7;
1534}]> {
1535  let ParserMatchClass = Imm0_7Operand;
1536  let PrintMethod = "printMatrixIndex";
1537}
1538def sme_elm_idx0_15 : Operand<i32>, TImmLeaf<i32, [{
1539  return ((uint32_t)Imm) <= 15;
1540}]> {
1541  let ParserMatchClass = Imm0_15Operand;
1542  let PrintMethod = "printMatrixIndex";
1543}
1544
1545// SME2 vector select offset operands
1546
1547// uimm3s8 predicate
1548// True if the immediate is a multiple of 8 in the range [0,56].
1549def UImm3s8Operand : UImmScaledMemoryIndexed<3, 8>;
1550
1551def uimm3s8 : Operand<i64>, ImmLeaf<i64,
1552[{ return Imm >= 0 && Imm <= 56 && ((Imm % 8) == 0); }], UImmS8XForm> {
1553  let PrintMethod = "printMatrixIndex<8>";
1554  let ParserMatchClass = UImm3s8Operand;
1555}
1556
1557class UImmScaledMemoryIndexedRange<int Width, int Scale, int OffsetVal> : AsmOperandClass {
1558  let Name = "UImm" # Width # "s" # Scale # "Range";
1559  let DiagnosticType = "InvalidMemoryIndexedRange" # Scale # "UImm" # Width;
1560  let RenderMethod = "addImmScaledRangeOperands<" # Scale # ">";
1561  let PredicateMethod = "isUImmScaled<" # Width # ", " # Scale # ", " # OffsetVal # ", /*IsRange=*/true>";
1562  let ParserMethod = "tryParseImmRange";
1563}
1564
1565// Implicit immediate ranges 0:1 and 0:3, scale has no meaning
1566// since the immediate is zero
1567def UImm0s2RangeOperand : UImmScaledMemoryIndexedRange<0, 2, 1>;
1568def UImm0s4RangeOperand : UImmScaledMemoryIndexedRange<0, 4, 3>;
1569
1570def UImm1s2RangeOperand : UImmScaledMemoryIndexedRange<1, 2, 1>;
1571def UImm1s4RangeOperand : UImmScaledMemoryIndexedRange<1, 4, 3>;
1572def UImm2s2RangeOperand : UImmScaledMemoryIndexedRange<2, 2, 1>;
1573def UImm2s4RangeOperand : UImmScaledMemoryIndexedRange<2, 4, 3>;
1574def UImm3s2RangeOperand : UImmScaledMemoryIndexedRange<3, 2, 1>;
1575
1576def uimm0s2range : Operand<i64>, ImmLeaf<i64,
1577[{ return Imm == 0; }], UImmS1XForm> {
1578  let PrintMethod = "printImmRangeScale<2, 1>";
1579  let ParserMatchClass = UImm0s2RangeOperand;
1580  let OperandNamespace = "AArch64";
1581  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1582}
1583
1584def uimm0s4range : Operand<i64>, ImmLeaf<i64,
1585[{ return Imm == 0; }], UImmS1XForm> {
1586  let PrintMethod = "printImmRangeScale<4, 3>";
1587  let ParserMatchClass = UImm0s4RangeOperand;
1588  let OperandNamespace = "AArch64";
1589  let OperandType = "OPERAND_IMPLICIT_IMM_0";
1590}
1591
1592def uimm1s2range : Operand<i64>, ImmLeaf<i64,
1593[{ return Imm >= 0 && Imm <= 2 && ((Imm % 2) == 0); }], UImmS2XForm> {
1594  let PrintMethod = "printImmRangeScale<2, 1>";
1595  let ParserMatchClass = UImm1s2RangeOperand;
1596}
1597
1598def uimm1s4range : Operand<i64>, ImmLeaf<i64,
1599[{ return Imm >= 0 && Imm <= 4 && ((Imm % 4) == 0); }], UImmS4XForm> {
1600  let PrintMethod = "printImmRangeScale<4, 3>";
1601  let ParserMatchClass = UImm1s4RangeOperand;
1602}
1603
1604def uimm2s2range : Operand<i64>, ImmLeaf<i64,
1605[{ return Imm >= 0 && Imm <= 6 && ((Imm % 2) == 0); }], UImmS2XForm> {
1606  let PrintMethod = "printImmRangeScale<2, 1>";
1607  let ParserMatchClass = UImm2s2RangeOperand;
1608}
1609
1610def uimm2s4range : Operand<i64>, ImmLeaf<i64,
1611[{ return Imm >= 0 && Imm <= 12 && ((Imm % 4) == 0); }], UImmS4XForm> {
1612  let PrintMethod = "printImmRangeScale<4, 3>";
1613  let ParserMatchClass = UImm2s4RangeOperand;
1614}
1615
1616def uimm3s2range : Operand<i64>, ImmLeaf<i64,
1617[{ return Imm >= 0 && Imm <= 14 && ((Imm % 2) == 0); }], UImmS2XForm> {
1618  let PrintMethod = "printImmRangeScale<2, 1>";
1619  let ParserMatchClass = UImm3s2RangeOperand;
1620}
1621
1622
1623// 8-bit immediate for AdvSIMD where 64-bit values of the form:
1624// aaaaaaaa bbbbbbbb cccccccc dddddddd eeeeeeee ffffffff gggggggg hhhhhhhh
1625// are encoded as the eight bit value 'abcdefgh'.
1626def simdimmtype10 : Operand<i32>,
1627                    FPImmLeaf<f64, [{
1628      return AArch64_AM::isAdvSIMDModImmType10(
1629                 Imm.bitcastToAPInt().getZExtValue());
1630    }], SDNodeXForm<fpimm, [{
1631      APFloat InVal = N->getValueAPF();
1632      uint32_t enc = AArch64_AM::encodeAdvSIMDModImmType10(N->getValueAPF()
1633                                                           .bitcastToAPInt()
1634                                                           .getZExtValue());
1635      return CurDAG->getTargetConstant(enc, SDLoc(N), MVT::i32);
1636    }]>> {
1637  let ParserMatchClass = SIMDImmType10Operand;
1638  let PrintMethod = "printSIMDType10Operand";
1639}
1640
1641
1642//---
1643// System management
1644//---
1645
1646// Base encoding for system instruction operands.
1647let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
1648class BaseSystemI<bit L, dag oops, dag iops, string asm, string operands,
1649                  list<dag> pattern = []>
1650    : I<oops, iops, asm, operands, "", pattern> {
1651  let Inst{31-22} = 0b1101010100;
1652  let Inst{21}    = L;
1653}
1654
1655// System instructions which do not have an Rt register.
1656class SimpleSystemI<bit L, dag iops, string asm, string operands,
1657                    list<dag> pattern = []>
1658    : BaseSystemI<L, (outs), iops, asm, operands, pattern> {
1659  let Inst{4-0} = 0b11111;
1660}
1661
1662// System instructions which have an Rt register.
1663class RtSystemI<bit L, dag oops, dag iops, string asm, string operands,
1664                list<dag> pattern = []>
1665    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1666      Sched<[WriteSys]> {
1667  bits<5> Rt;
1668  let Inst{4-0} = Rt;
1669}
1670
1671// System instructions for transactional memory extension
1672class TMBaseSystemI<bit L, bits<4> CRm, bits<3> op2, dag oops, dag iops,
1673                    string asm, string operands, list<dag> pattern>
1674    : BaseSystemI<L, oops, iops, asm, operands, pattern>,
1675      Sched<[WriteSys]> {
1676  let Inst{20-12} = 0b000110011;
1677  let Inst{11-8} = CRm;
1678  let Inst{7-5} = op2;
1679  let DecoderMethod = "";
1680
1681  let mayLoad = 1;
1682  let mayStore = 1;
1683}
1684
1685// System instructions for transactional memory - single input operand
1686class TMSystemI<bits<4> CRm, string asm, list<dag> pattern>
1687    : TMBaseSystemI<0b1, CRm, 0b011,
1688                    (outs GPR64:$Rt), (ins), asm, "\t$Rt", pattern> {
1689  bits<5> Rt;
1690  let Inst{4-0} = Rt;
1691}
1692
1693// System instructions that pass a register argument
1694// This class assumes the register is for input rather than output.
1695class RegInputSystemI<bits<4> CRm, bits<3> Op2, string asm,
1696                      list<dag> pattern = []>
1697    : RtSystemI<0, (outs), (ins GPR64:$Rt), asm, "\t$Rt", pattern> {
1698  let Inst{20-12} = 0b000110001;
1699  let Inst{11-8} = CRm;
1700  let Inst{7-5} = Op2;
1701}
1702
1703// System instructions for transactional memory - no operand
1704class TMSystemINoOperand<bits<4> CRm, string asm, list<dag> pattern>
1705    : TMBaseSystemI<0b0, CRm, 0b011, (outs), (ins), asm, "", pattern> {
1706  let Inst{4-0} = 0b11111;
1707}
1708
1709// System instructions for exit from transactions
1710class TMSystemException<bits<3> op1, string asm, list<dag> pattern>
1711    : I<(outs), (ins timm64_0_65535:$imm), asm, "\t$imm", "", pattern>,
1712      Sched<[WriteSys]> {
1713  bits<16> imm;
1714  let Inst{31-24} = 0b11010100;
1715  let Inst{23-21} = op1;
1716  let Inst{20-5}  = imm;
1717  let Inst{4-0}   = 0b00000;
1718}
1719
1720// Hint instructions that take both a CRm and a 3-bit immediate.
1721// NOTE: ideally, this would have mayStore = 0, mayLoad = 0, but we cannot
1722// model patterns with sufficiently fine granularity
1723let mayStore = 1, mayLoad = 1, hasSideEffects = 1 in
1724  class HintI<string mnemonic>
1725      : SimpleSystemI<0, (ins imm0_127:$imm), mnemonic#"\t$imm", "",
1726                      [(int_aarch64_hint imm0_127:$imm)]>,
1727        Sched<[WriteHint]> {
1728    bits <7> imm;
1729    let Inst{20-12} = 0b000110010;
1730    let Inst{11-5} = imm;
1731  }
1732
1733// System instructions taking a single literal operand which encodes into
1734// CRm. op2 differentiates the opcodes.
1735def BarrierAsmOperand : AsmOperandClass {
1736  let Name = "Barrier";
1737  let ParserMethod = "tryParseBarrierOperand";
1738}
1739def barrier_op : Operand<i32> {
1740  let PrintMethod = "printBarrierOption";
1741  let ParserMatchClass = BarrierAsmOperand;
1742}
1743def BarriernXSAsmOperand : AsmOperandClass {
1744  let Name = "BarriernXS";
1745  let ParserMethod = "tryParseBarriernXSOperand";
1746}
1747def barrier_nxs_op : Operand<i32> {
1748  let PrintMethod = "printBarriernXSOption";
1749  let ParserMatchClass = BarriernXSAsmOperand;
1750}
1751class CRmSystemI<Operand crmtype, bits<3> opc, string asm,
1752                 list<dag> pattern = []>
1753    : SimpleSystemI<0, (ins crmtype:$CRm), asm, "\t$CRm", pattern>,
1754      Sched<[WriteBarrier]> {
1755  bits<4> CRm;
1756  let Inst{20-12} = 0b000110011;
1757  let Inst{11-8} = CRm;
1758  let Inst{7-5} = opc;
1759}
1760
1761class SystemNoOperands<bits<3> op2, string asm, list<dag> pattern = []>
1762    : SimpleSystemI<0, (ins), asm, "", pattern>,
1763      Sched<[WriteHint]> {
1764  bits<4> CRm;
1765  let CRm = 0b0011;
1766  let Inst{31-12} = 0b11010101000000110010;
1767  let Inst{11-8} = CRm;
1768  let Inst{7-5} = op2;
1769  let Inst{4-0} = 0b11111;
1770}
1771
1772// MRS/MSR system instructions. These have different operand classes because
1773// a different subset of registers can be accessed through each instruction.
1774def MRSSystemRegisterOperand : AsmOperandClass {
1775  let Name = "MRSSystemRegister";
1776  let ParserMethod = "tryParseSysReg";
1777  let DiagnosticType = "MRS";
1778}
1779// concatenation of op0, op1, CRn, CRm, op2. 16-bit immediate.
1780def mrs_sysreg_op : Operand<i32> {
1781  let ParserMatchClass = MRSSystemRegisterOperand;
1782  let DecoderMethod = "DecodeMRSSystemRegister";
1783  let PrintMethod = "printMRSSystemRegister";
1784}
1785
1786def MSRSystemRegisterOperand : AsmOperandClass {
1787  let Name = "MSRSystemRegister";
1788  let ParserMethod = "tryParseSysReg";
1789  let DiagnosticType = "MSR";
1790}
1791def msr_sysreg_op : Operand<i32> {
1792  let ParserMatchClass = MSRSystemRegisterOperand;
1793  let DecoderMethod = "DecodeMSRSystemRegister";
1794  let PrintMethod = "printMSRSystemRegister";
1795}
1796
1797def PSBHintOperand : AsmOperandClass {
1798  let Name = "PSBHint";
1799  let ParserMethod = "tryParsePSBHint";
1800}
1801def psbhint_op : Operand<i32> {
1802  let ParserMatchClass = PSBHintOperand;
1803  let PrintMethod = "printPSBHintOp";
1804  let MCOperandPredicate = [{
1805    // Check, if operand is valid, to fix exhaustive aliasing in disassembly.
1806    // "psb" is an alias to "hint" only for certain values of CRm:Op2 fields.
1807    if (!MCOp.isImm())
1808      return false;
1809    return AArch64PSBHint::lookupPSBByEncoding(MCOp.getImm()) != nullptr;
1810  }];
1811}
1812
1813def BTIHintOperand : AsmOperandClass {
1814  let Name = "BTIHint";
1815  let ParserMethod = "tryParseBTIHint";
1816}
1817def btihint_op : Operand<i32> {
1818  let ParserMatchClass = BTIHintOperand;
1819  let PrintMethod = "printBTIHintOp";
1820  let MCOperandPredicate = [{
1821    // "bti" is an alias to "hint" only for certain values of CRm:Op2 fields.
1822    if (!MCOp.isImm())
1823      return false;
1824    return AArch64BTIHint::lookupBTIByEncoding(MCOp.getImm() ^ 32) != nullptr;
1825  }];
1826}
1827
1828class MRSI : RtSystemI<1, (outs GPR64:$Rt), (ins mrs_sysreg_op:$systemreg),
1829                       "mrs", "\t$Rt, $systemreg"> {
1830  bits<16> systemreg;
1831  let Inst{20-5} = systemreg;
1832  let DecoderNamespace = "Fallback";
1833  // The MRS is set as a NZCV setting instruction. Not all MRS instructions
1834  // require doing this. The alternative was to explicitly model each one, but
1835  // it feels like it is unnecessary because it seems there are no negative
1836  // consequences setting these flags for all.
1837  let Defs = [NZCV];
1838}
1839
1840// FIXME: Some of these def NZCV, others don't. Best way to model that?
1841// Explicitly modeling each of the system register as a register class
1842// would do it, but feels like overkill at this point.
1843class MSRI : RtSystemI<0, (outs), (ins msr_sysreg_op:$systemreg, GPR64:$Rt),
1844                       "msr", "\t$systemreg, $Rt"> {
1845  bits<16> systemreg;
1846  let Inst{20-5} = systemreg;
1847  let DecoderNamespace = "Fallback";
1848}
1849
1850def SystemPStateFieldWithImm0_15Operand : AsmOperandClass {
1851  let Name = "SystemPStateFieldWithImm0_15";
1852  let ParserMethod = "tryParseSysReg";
1853}
1854def pstatefield4_op : Operand<i32> {
1855  let ParserMatchClass = SystemPStateFieldWithImm0_15Operand;
1856  let PrintMethod = "printSystemPStateField";
1857  let MCOperandPredicate = [{
1858    if (!MCOp.isImm())
1859      return false;
1860    return AArch64SVCR::lookupPStateImm0_15ByEncoding(MCOp.getImm()) != nullptr;
1861  }];
1862}
1863
1864// Instructions to modify PSTATE, no input reg
1865let Defs = [NZCV] in
1866class PstateWriteSimple<dag iops, string asm, string operands>
1867  : SimpleSystemI<0, iops, asm, operands> {
1868
1869  let Inst{20-19} = 0b00;
1870  let Inst{15-12} = 0b0100;
1871}
1872
1873class MSRpstateImm0_15
1874  : PstateWriteSimple<(ins pstatefield4_op:$pstatefield, imm0_15:$imm), "msr",
1875                  "\t$pstatefield, $imm">,
1876    Sched<[WriteSys]> {
1877
1878  bits<6> pstatefield;
1879  bits<4> imm;
1880  let Inst{18-16} = pstatefield{5-3};
1881  let Inst{11-8} = imm;
1882  let Inst{7-5} = pstatefield{2-0};
1883
1884  let DecoderMethod = "DecodeSystemPStateImm0_15Instruction";
1885  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1886  // Fail the decoder should attempt to decode the instruction as MSRI.
1887  let hasCompleteDecoder = false;
1888}
1889
1890def SystemPStateFieldWithImm0_1Operand : AsmOperandClass {
1891  let Name = "SystemPStateFieldWithImm0_1";
1892  let ParserMethod = "tryParseSysReg";
1893}
1894def pstatefield1_op : Operand<i32> {
1895  let ParserMatchClass = SystemPStateFieldWithImm0_1Operand;
1896  let PrintMethod = "printSystemPStateField";
1897  let MCOperandPredicate = [{
1898    if (!MCOp.isImm())
1899      return false;
1900    return AArch64SVCR::lookupPStateImm0_1ByEncoding(MCOp.getImm()) != nullptr;
1901  }];
1902}
1903
1904class MSRpstateImm0_1
1905  : PstateWriteSimple<(ins pstatefield1_op:$pstatefield, imm0_1:$imm), "msr",
1906                 "\t$pstatefield, $imm">,
1907    Sched<[WriteSys]> {
1908
1909  bits<9> pstatefield;
1910  bit imm;
1911  let Inst{18-16} = pstatefield{5-3};
1912  let Inst{11-9} = pstatefield{8-6};
1913  let Inst{8} = imm;
1914  let Inst{7-5} = pstatefield{2-0};
1915
1916  let DecoderMethod = "DecodeSystemPStateImm0_1Instruction";
1917  // MSRpstateI aliases with MSRI. When the MSRpstateI decoder method returns
1918  // Fail the decoder should attempt to decode the instruction as MSRI.
1919  let hasCompleteDecoder = false;
1920  let DecoderNamespace = "Fallback";
1921}
1922
1923// SYS and SYSL generic system instructions.
1924def SysCRAsmOperand : AsmOperandClass {
1925  let Name = "SysCR";
1926  let ParserMethod = "tryParseSysCROperand";
1927}
1928
1929def sys_cr_op : Operand<i32> {
1930  let PrintMethod = "printSysCROperand";
1931  let ParserMatchClass = SysCRAsmOperand;
1932}
1933
1934class SystemXtI<bit L, string asm>
1935  : RtSystemI<L, (outs),
1936       (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, GPR64:$Rt),
1937       asm, "\t$op1, $Cn, $Cm, $op2, $Rt"> {
1938  bits<3> op1;
1939  bits<4> Cn;
1940  bits<4> Cm;
1941  bits<3> op2;
1942  let Inst{20-19} = 0b01;
1943  let Inst{18-16} = op1;
1944  let Inst{15-12} = Cn;
1945  let Inst{11-8}  = Cm;
1946  let Inst{7-5}   = op2;
1947}
1948
1949class SystemLXtI<bit L, string asm>
1950  : RtSystemI<L, (outs),
1951       (ins GPR64:$Rt, imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2),
1952       asm, "\t$Rt, $op1, $Cn, $Cm, $op2"> {
1953  bits<3> op1;
1954  bits<4> Cn;
1955  bits<4> Cm;
1956  bits<3> op2;
1957  let Inst{20-19} = 0b01;
1958  let Inst{18-16} = op1;
1959  let Inst{15-12} = Cn;
1960  let Inst{11-8}  = Cm;
1961  let Inst{7-5}   = op2;
1962}
1963
1964def RangePrefetchOperand : AsmOperandClass {
1965  let Name = "RangePrefetch";
1966  let ParserMethod = "tryParseRPRFMOperand";
1967  let PredicateMethod = "isPrefetch";
1968  let RenderMethod = "addPrefetchOperands";
1969}
1970
1971def rprfop : Operand<i32>, TImmLeaf<i32, [{
1972    return (((uint32_t)Imm) <= 63);
1973  }]> {
1974  let PrintMethod = "printRPRFMOperand";
1975  let ParserMatchClass = RangePrefetchOperand;
1976}
1977
1978// Branch (register) instructions:
1979//
1980//  case opc of
1981//    0001 blr
1982//    0000 br
1983//    0101 dret
1984//    0100 eret
1985//    0010 ret
1986//    otherwise UNDEFINED
1987class BaseBranchReg<bits<4> opc, dag oops, dag iops, string asm,
1988                    string operands, list<dag> pattern>
1989    : I<oops, iops, asm, operands, "", pattern>, Sched<[WriteBrReg]> {
1990  let Inst{31-25} = 0b1101011;
1991  let Inst{24-21} = opc;
1992  let Inst{20-16} = 0b11111;
1993  let Inst{15-10} = 0b000000;
1994  let Inst{4-0}   = 0b00000;
1995}
1996
1997class BranchReg<bits<4> opc, string asm, list<dag> pattern>
1998    : BaseBranchReg<opc, (outs), (ins GPR64:$Rn), asm, "\t$Rn", pattern> {
1999  bits<5> Rn;
2000  let Inst{9-5} = Rn;
2001}
2002
2003let mayLoad = 0, mayStore = 0, hasSideEffects = 1, isReturn = 1 in
2004class SpecialReturn<bits<4> opc, string asm>
2005    : BaseBranchReg<opc, (outs), (ins), asm, "", []> {
2006  let Inst{9-5} = 0b11111;
2007}
2008
2009let mayLoad = 1 in
2010class RCPCLoad<bits<2> sz, string asm, RegisterClass RC>
2011  : I<(outs RC:$Rt), (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]", "", []>,
2012  Sched<[]> {
2013  bits<5> Rn;
2014  bits<5> Rt;
2015  let Inst{31-30} = sz;
2016  let Inst{29-10} = 0b11100010111111110000;
2017  let Inst{9-5} = Rn;
2018  let Inst{4-0} = Rt;
2019}
2020
2021class AuthBase<bits<1> M, dag oops, dag iops, string asm, string operands,
2022               list<dag> pattern>
2023  : I<oops, iops, asm, operands, "", pattern>, Sched<[]> {
2024  let isAuthenticated = 1;
2025  let Inst{31-25} = 0b1101011;
2026  let Inst{20-11} = 0b1111100001;
2027  let Inst{10} = M;
2028  let Inst{4-0} = 0b11111;
2029}
2030
2031class AuthBranchTwoOperands<bits<1> op, bits<1> M, string asm>
2032  : AuthBase<M, (outs), (ins GPR64:$Rn, GPR64sp:$Rm), asm, "\t$Rn, $Rm", []> {
2033  bits<5> Rn;
2034  bits<5> Rm;
2035  let Inst{24-22} = 0b100;
2036  let Inst{21} = op;
2037  let Inst{9-5} = Rn;
2038  let Inst{4-0} = Rm;
2039}
2040
2041class AuthOneOperand<bits<3> opc, bits<1> M, string asm>
2042  : AuthBase<M, (outs), (ins GPR64:$Rn), asm, "\t$Rn", []> {
2043  bits<5> Rn;
2044  let Inst{24} = 0;
2045  let Inst{23-21} = opc;
2046  let Inst{9-5} = Rn;
2047}
2048
2049let Uses = [LR,SP] in
2050class AuthReturn<bits<3> op, bits<1> M, string asm>
2051  : AuthBase<M, (outs), (ins), asm, "", []> {
2052  let Inst{24} = 0;
2053  let Inst{23-21} = op;
2054  let Inst{9-0} = 0b1111111111;
2055}
2056
2057let mayLoad = 1 in
2058class BaseAuthLoad<bit M, bit W, dag oops, dag iops, string asm,
2059                   string operands, string cstr>
2060  : I<oops, iops, asm, operands, cstr, []>, Sched<[]> {
2061  bits<10> offset;
2062  bits<5> Rn;
2063  bits<5> Rt;
2064  let isAuthenticated = 1;
2065  let Inst{31-24} = 0b11111000;
2066  let Inst{23} = M;
2067  let Inst{22} = offset{9};
2068  let Inst{21} = 1;
2069  let Inst{20-12} = offset{8-0};
2070  let Inst{11} = W;
2071  let Inst{10} = 1;
2072  let Inst{9-5} = Rn;
2073  let Inst{4-0} = Rt;
2074
2075  let DecoderMethod = "DecodeAuthLoadInstruction";
2076}
2077
2078multiclass AuthLoad<bit M, string asm, Operand opr> {
2079  def indexed   : BaseAuthLoad<M, 0, (outs GPR64:$Rt),
2080                               (ins GPR64sp:$Rn, opr:$offset),
2081                               asm, "\t$Rt, [$Rn, $offset]", "">;
2082  def writeback : BaseAuthLoad<M, 1, (outs GPR64sp:$wback, GPR64:$Rt),
2083                               (ins GPR64sp:$Rn, opr:$offset),
2084                               asm, "\t$Rt, [$Rn, $offset]!",
2085                               "$Rn = $wback,@earlyclobber $wback">;
2086
2087  def : InstAlias<asm # "\t$Rt, [$Rn]",
2088                  (!cast<Instruction>(NAME # "indexed") GPR64:$Rt, GPR64sp:$Rn, 0)>;
2089
2090  def : InstAlias<asm # "\t$Rt, [$wback]!",
2091                  (!cast<Instruction>(NAME # "writeback") GPR64sp:$wback, GPR64:$Rt, 0), 0>;
2092}
2093
2094//---
2095// Conditional branch instruction.
2096//---
2097
2098// Condition code.
2099// 4-bit immediate. Pretty-printed as <cc>
2100def ccode : Operand<i32> {
2101  let PrintMethod = "printCondCode";
2102  let ParserMatchClass = CondCode;
2103}
2104def inv_ccode : Operand<i32> {
2105  // AL and NV are invalid in the aliases which use inv_ccode
2106  let PrintMethod = "printInverseCondCode";
2107  let ParserMatchClass = CondCode;
2108  let MCOperandPredicate = [{
2109    return MCOp.isImm() &&
2110           MCOp.getImm() != AArch64CC::AL &&
2111           MCOp.getImm() != AArch64CC::NV;
2112  }];
2113}
2114
2115// Conditional branch target. 19-bit immediate. The low two bits of the target
2116// offset are implied zero and so are not part of the immediate.
2117def am_brcond : Operand<OtherVT> {
2118  let EncoderMethod = "getCondBranchTargetOpValue";
2119  let DecoderMethod = "DecodePCRelLabel19";
2120  let PrintMethod = "printAlignedLabel";
2121  let ParserMatchClass = PCRelLabel19Operand;
2122  let OperandType = "OPERAND_PCREL";
2123}
2124
2125class BranchCond<bit bit4, string mnemonic>
2126   : I<(outs), (ins ccode:$cond, am_brcond:$target),
2127       mnemonic, ".$cond\t$target", "",
2128       [(AArch64brcond bb:$target, imm:$cond, NZCV)]>, Sched<[WriteBr]> {
2129  let isBranch = 1;
2130  let isTerminator = 1;
2131  let Uses = [NZCV];
2132
2133  bits<4> cond;
2134  bits<19> target;
2135  let Inst{31-24} = 0b01010100;
2136  let Inst{23-5} = target;
2137  let Inst{4} = bit4;
2138  let Inst{3-0} = cond;
2139}
2140
2141//---
2142// Compare-and-branch instructions.
2143//---
2144class BaseCmpBranch<RegisterClass regtype, bit op, string asm, SDNode node>
2145    : I<(outs), (ins regtype:$Rt, am_brcond:$target),
2146         asm, "\t$Rt, $target", "",
2147         [(node regtype:$Rt, bb:$target)]>,
2148      Sched<[WriteBr]> {
2149  let isBranch = 1;
2150  let isTerminator = 1;
2151
2152  bits<5> Rt;
2153  bits<19> target;
2154  let Inst{30-25} = 0b011010;
2155  let Inst{24}    = op;
2156  let Inst{23-5}  = target;
2157  let Inst{4-0}   = Rt;
2158}
2159
2160multiclass CmpBranch<bit op, string asm, SDNode node> {
2161  def W : BaseCmpBranch<GPR32, op, asm, node> {
2162    let Inst{31} = 0;
2163  }
2164  def X : BaseCmpBranch<GPR64, op, asm, node> {
2165    let Inst{31} = 1;
2166  }
2167}
2168
2169//---
2170// Test-bit-and-branch instructions.
2171//---
2172// Test-and-branch target. 14-bit sign-extended immediate. The low two bits of
2173// the target offset are implied zero and so are not part of the immediate.
2174def am_tbrcond : Operand<OtherVT> {
2175  let EncoderMethod = "getTestBranchTargetOpValue";
2176  let PrintMethod = "printAlignedLabel";
2177  let ParserMatchClass = BranchTarget14Operand;
2178  let OperandType = "OPERAND_PCREL";
2179}
2180
2181// AsmOperand classes to emit (or not) special diagnostics
2182def TBZImm0_31Operand : AsmOperandClass {
2183  let Name = "TBZImm0_31";
2184  let PredicateMethod = "isImmInRange<0,31>";
2185  let RenderMethod = "addImmOperands";
2186}
2187def TBZImm32_63Operand : AsmOperandClass {
2188  let Name = "Imm32_63";
2189  let PredicateMethod = "isImmInRange<32,63>";
2190  let DiagnosticType = "InvalidImm0_63";
2191  let RenderMethod = "addImmOperands";
2192}
2193
2194class tbz_imm0_31<AsmOperandClass matcher> : Operand<i64>, ImmLeaf<i64, [{
2195  return (((uint32_t)Imm) < 32);
2196}]> {
2197  let ParserMatchClass = matcher;
2198}
2199
2200def tbz_imm0_31_diag : tbz_imm0_31<Imm0_31Operand>;
2201def tbz_imm0_31_nodiag : tbz_imm0_31<TBZImm0_31Operand>;
2202
2203def tbz_imm32_63 : Operand<i64>, ImmLeaf<i64, [{
2204  return (((uint32_t)Imm) > 31) && (((uint32_t)Imm) < 64);
2205}]> {
2206  let ParserMatchClass = TBZImm32_63Operand;
2207}
2208
2209class BaseTestBranch<RegisterClass regtype, Operand immtype,
2210                     bit op, string asm, SDNode node>
2211    : I<(outs), (ins regtype:$Rt, immtype:$bit_off, am_tbrcond:$target),
2212       asm, "\t$Rt, $bit_off, $target", "",
2213       [(node regtype:$Rt, immtype:$bit_off, bb:$target)]>,
2214      Sched<[WriteBr]> {
2215  let isBranch = 1;
2216  let isTerminator = 1;
2217
2218  bits<5> Rt;
2219  bits<6> bit_off;
2220  bits<14> target;
2221
2222  let Inst{30-25} = 0b011011;
2223  let Inst{24}    = op;
2224  let Inst{23-19} = bit_off{4-0};
2225  let Inst{18-5}  = target;
2226  let Inst{4-0}   = Rt;
2227
2228  let DecoderMethod = "DecodeTestAndBranch";
2229}
2230
2231multiclass TestBranch<bit op, string asm, SDNode node> {
2232  def W : BaseTestBranch<GPR32, tbz_imm0_31_diag, op, asm, node> {
2233    let Inst{31} = 0;
2234  }
2235
2236  def X : BaseTestBranch<GPR64, tbz_imm32_63, op, asm, node> {
2237    let Inst{31} = 1;
2238  }
2239
2240  // Alias X-reg with 0-31 imm to W-Reg.
2241  def : InstAlias<asm # "\t$Rd, $imm, $target",
2242                  (!cast<Instruction>(NAME#"W") GPR32as64:$Rd,
2243                  tbz_imm0_31_nodiag:$imm, am_tbrcond:$target), 0>;
2244  def : Pat<(node GPR64:$Rn, tbz_imm0_31_diag:$imm, bb:$target),
2245            (!cast<Instruction>(NAME#"W") (EXTRACT_SUBREG GPR64:$Rn, sub_32),
2246            tbz_imm0_31_diag:$imm, bb:$target)>;
2247}
2248
2249//---
2250// Unconditional branch (immediate) instructions.
2251//---
2252def am_b_target : Operand<OtherVT> {
2253  let EncoderMethod = "getBranchTargetOpValue";
2254  let PrintMethod = "printAlignedLabel";
2255  let ParserMatchClass = BranchTarget26Operand;
2256  let OperandType = "OPERAND_PCREL";
2257}
2258def am_bl_target : Operand<i64> {
2259  let EncoderMethod = "getBranchTargetOpValue";
2260  let PrintMethod = "printAlignedLabel";
2261  let ParserMatchClass = BranchTarget26Operand;
2262  let OperandType = "OPERAND_PCREL";
2263}
2264
2265class BImm<bit op, dag iops, string asm, list<dag> pattern>
2266    : I<(outs), iops, asm, "\t$addr", "", pattern>, Sched<[WriteBr]> {
2267  bits<26> addr;
2268  let Inst{31}    = op;
2269  let Inst{30-26} = 0b00101;
2270  let Inst{25-0}  = addr;
2271
2272  let DecoderMethod = "DecodeUnconditionalBranch";
2273}
2274
2275class BranchImm<bit op, string asm, list<dag> pattern>
2276    : BImm<op, (ins am_b_target:$addr), asm, pattern>;
2277class CallImm<bit op, string asm, list<dag> pattern>
2278    : BImm<op, (ins am_bl_target:$addr), asm, pattern>;
2279
2280//---
2281// Basic one-operand data processing instructions.
2282//---
2283
2284let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2285class BaseOneOperandData<bit sf, bit S, bits<5> opc2, bits<6> opc,
2286                         RegisterClass regtype, string asm,
2287                         SDPatternOperator node>
2288  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
2289      [(set regtype:$Rd, (node regtype:$Rn))]>,
2290    Sched<[WriteI, ReadI]> {
2291  bits<5> Rd;
2292  bits<5> Rn;
2293
2294  let Inst{31} = sf;
2295  let Inst{30} = 0b1;
2296  let Inst{29} = S;
2297  let Inst{28-21} = 0b11010110;
2298  let Inst{20-16} = opc2;
2299  let Inst{15-10} = opc;
2300  let Inst{9-5}   = Rn;
2301  let Inst{4-0}   = Rd;
2302}
2303
2304let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2305multiclass OneOperandData<bits<6> opc, string asm,
2306                          SDPatternOperator node = null_frag> {
2307  def Wr : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2308
2309  def Xr : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2310}
2311
2312class OneWRegData<bits<6> opc, string asm, SDPatternOperator node>
2313    : BaseOneOperandData<0b0, 0b0, 0b00000, opc, GPR32, asm, node>;
2314
2315class OneXRegData<bits<6> opc, string asm, SDPatternOperator node>
2316    : BaseOneOperandData<0b1, 0b0, 0b00000, opc, GPR64, asm, node>;
2317
2318class SignAuthOneData<bits<3> opcode_prefix, bits<2> opcode, string asm,
2319                      SDPatternOperator op>
2320  : I<(outs GPR64:$dst), (ins GPR64:$Rd, GPR64sp:$Rn), asm, "\t$Rd, $Rn",
2321      "$dst = $Rd", [(set GPR64:$dst, (op GPR64:$Rd, opcode, GPR64sp:$Rn))]>,
2322    Sched<[WriteI, ReadI]> {
2323  bits<5> Rd;
2324  bits<5> Rn;
2325  let Inst{31-15} = 0b11011010110000010;
2326  let Inst{14-12} = opcode_prefix;
2327  let Inst{11-10} = opcode;
2328  let Inst{9-5} = Rn;
2329  let Inst{4-0} = Rd;
2330}
2331
2332class SignAuthZero<bits<3> opcode_prefix, bits<2> opcode, string asm,
2333                   SDPatternOperator op>
2334  : I<(outs GPR64:$dst), (ins GPR64:$Rd), asm, "\t$Rd", "$dst = $Rd",
2335      [(set GPR64:$dst, (op GPR64:$Rd, opcode, (i64 0)))]>,
2336    Sched<[]> {
2337  bits<5> Rd;
2338  let Inst{31-15} = 0b11011010110000010;
2339  let Inst{14-12} = opcode_prefix;
2340  let Inst{11-10} = opcode;
2341  let Inst{9-5} = 0b11111;
2342  let Inst{4-0} = Rd;
2343}
2344
2345class SignAuthTwoOperand<bits<4> opc, string asm,
2346                         SDPatternOperator OpNode>
2347  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64sp:$Rm),
2348      asm, "\t$Rd, $Rn, $Rm", "",
2349      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64sp:$Rm))]>,
2350    Sched<[WriteI, ReadI, ReadI]> {
2351  bits<5> Rd;
2352  bits<5> Rn;
2353  bits<5> Rm;
2354  let Inst{31-21} = 0b10011010110;
2355  let Inst{20-16} = Rm;
2356  let Inst{15-14} = 0b00;
2357  let Inst{13-10} = opc;
2358  let Inst{9-5}   = Rn;
2359  let Inst{4-0}   = Rd;
2360}
2361
2362class ClearAuth<bits<1> data, string asm>
2363  : I<(outs GPR64:$Rd), (ins GPR64:$Rn), asm, "\t$Rd", "$Rd = $Rn", []>, Sched<[]> {
2364  bits<5> Rd;
2365  let Inst{31-11} = 0b110110101100000101000;
2366  let Inst{10} = data;
2367  let Inst{9-5} = 0b11111;
2368  let Inst{4-0} = Rd;
2369}
2370
2371// v9.5-A FEAT_PAuth_LR
2372
2373class SignAuthFixedRegs<bits<5> opcode2, bits<6> opcode, string asm>
2374  : I<(outs), (ins), asm, "", "", []>,
2375    Sched<[WriteI, ReadI]> {
2376  let Inst{31} = 0b1; // sf
2377  let Inst{30} = 0b1;
2378  let Inst{29} = 0b0; // S
2379  let Inst{28-21} = 0b11010110;
2380  let Inst{20-16} = opcode2;
2381  let Inst{15-10} = opcode;
2382  let Inst{9-5} = 0b11111; // Rn
2383  let Inst{4-0} = 0b11110; // Rd
2384}
2385
2386def PAuthPCRelLabel16Operand : PCRelLabel<16> {
2387  let Name = "PAuthPCRelLabel16";
2388  let PredicateMethod = "isPAuthPCRelLabel16Operand";
2389}
2390def am_pauth_pcrel : Operand<OtherVT> {
2391  let EncoderMethod = "getPAuthPCRelOpValue";
2392  let DecoderMethod = "DecodePCRelLabel16";
2393  let PrintMethod = "printAlignedLabel";
2394  let ParserMatchClass = PAuthPCRelLabel16Operand;
2395  let OperandType = "OPERAND_PCREL";
2396}
2397
2398class SignAuthPCRel<bits<2> opc, string asm>
2399  : I<(outs), (ins am_pauth_pcrel:$label), asm, "\t$label", "", []>,
2400    Sched<[]> {
2401  bits<16> label;
2402  let Inst{31} = 0b1; // sf
2403  let Inst{30-23} = 0b11100111;
2404  let Inst{22-21} = opc;
2405  let Inst{20-5} = label; // imm
2406  let Inst{4-0} = 0b11111; // Rd
2407}
2408
2409class SignAuthOneReg<bits<5> opcode2, bits<6> opcode, string asm>
2410  : I<(outs), (ins GPR64:$Rn), asm, "\t$Rn", "", []>,
2411    Sched<[]> {
2412  bits<5> Rn;
2413  let Inst{31} = 0b1; // sf
2414  let Inst{30} = 0b1;
2415  let Inst{29} = 0b0; // S
2416  let Inst{28-21} = 0b11010110;
2417  let Inst{20-16} = opcode2;
2418  let Inst{15-10} = opcode;
2419  let Inst{9-5} = Rn;
2420  let Inst{4-0} = 0b11110; // Rd
2421}
2422
2423class SignAuthReturnPCRel<bits<3> opc, bits<5> op2, string asm>
2424  : I<(outs), (ins am_pauth_pcrel:$label), asm, "\t$label", "", []>,
2425    Sched<[WriteAtomic]> {
2426  bits<16> label;
2427  let Inst{31-24} = 0b01010101;
2428  let Inst{23-21} = opc;
2429  let Inst{20-5} = label; // imm16
2430  let Inst{4-0} = op2;
2431}
2432
2433class SignAuthReturnReg<bits<6> op3, string asm>
2434  : I<(outs), (ins GPR64common:$Rm), asm, "\t$Rm", "", []>,
2435    Sched<[WriteAtomic]> {
2436  bits<5> Rm;
2437  let Inst{31-25} = 0b1101011;
2438  let Inst{24-21} = 0b0010; // opc
2439  let Inst{20-16} = 0b11111; // op2
2440  let Inst{15-10} = op3;
2441  let Inst{9-5} = 0b11111; // Rn
2442  let Inst{4-0} = Rm; // op4 (Rm)
2443}
2444
2445// Base class for the Armv8.4-A 8 and 16-bit flag manipulation instructions
2446class BaseFlagManipulation<bit sf, bit sz, dag iops, string asm, string ops>
2447    : I<(outs), iops, asm, ops, "", []>,
2448      Sched<[WriteI, ReadI, ReadI]> {
2449  let Uses = [NZCV];
2450  let Defs = [NZCV];
2451  bits<5> Rn;
2452  let Inst{31}    = sf;
2453  let Inst{30-15} = 0b0111010000000000;
2454  let Inst{14}    = sz;
2455  let Inst{13-10} = 0b0010;
2456  let Inst{9-5}   = Rn;
2457  let Inst{4-0}   = 0b01101;
2458}
2459
2460class FlagRotate<dag iops, string asm, string ops>
2461    : BaseFlagManipulation<0b1, 0b0, iops, asm, ops> {
2462  bits<6> imm;
2463  bits<4> mask;
2464  let Inst{20-15} = imm;
2465  let Inst{13-10} = 0b0001;
2466  let Inst{4}     = 0b0;
2467  let Inst{3-0}   = mask;
2468}
2469
2470//---
2471// Basic two-operand data processing instructions.
2472//---
2473class BaseBaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2474                          list<dag> pattern>
2475    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2476        asm, "\t$Rd, $Rn, $Rm", "", pattern>,
2477      Sched<[WriteI, ReadI, ReadI]> {
2478  let Uses = [NZCV];
2479  bits<5> Rd;
2480  bits<5> Rn;
2481  bits<5> Rm;
2482  let Inst{30}    = isSub;
2483  let Inst{28-21} = 0b11010000;
2484  let Inst{20-16} = Rm;
2485  let Inst{15-10} = 0;
2486  let Inst{9-5}   = Rn;
2487  let Inst{4-0}   = Rd;
2488}
2489
2490class BaseAddSubCarry<bit isSub, RegisterClass regtype, string asm,
2491                      SDNode OpNode>
2492    : BaseBaseAddSubCarry<isSub, regtype, asm,
2493        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV))]>;
2494
2495class BaseAddSubCarrySetFlags<bit isSub, RegisterClass regtype, string asm,
2496                              SDNode OpNode>
2497    : BaseBaseAddSubCarry<isSub, regtype, asm,
2498        [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm, NZCV)),
2499         (implicit NZCV)]> {
2500  let Defs = [NZCV];
2501}
2502
2503multiclass AddSubCarry<bit isSub, string asm, string asm_setflags,
2504                       SDNode OpNode, SDNode OpNode_setflags> {
2505  def Wr : BaseAddSubCarry<isSub, GPR32, asm, OpNode> {
2506    let Inst{31} = 0;
2507    let Inst{29} = 0;
2508  }
2509  def Xr : BaseAddSubCarry<isSub, GPR64, asm, OpNode> {
2510    let Inst{31} = 1;
2511    let Inst{29} = 0;
2512  }
2513
2514  // Sets flags.
2515  def SWr : BaseAddSubCarrySetFlags<isSub, GPR32, asm_setflags,
2516                                    OpNode_setflags> {
2517    let Inst{31} = 0;
2518    let Inst{29} = 1;
2519  }
2520  def SXr : BaseAddSubCarrySetFlags<isSub, GPR64, asm_setflags,
2521                                    OpNode_setflags> {
2522    let Inst{31} = 1;
2523    let Inst{29} = 1;
2524  }
2525}
2526
2527class BaseTwoOperandRegReg<bit sf, bit S, bits<6> opc, RegisterClass regtype,
2528                           string asm, SDPatternOperator OpNode,
2529                           RegisterClass in1regtype = regtype,
2530                           RegisterClass in2regtype = regtype>
2531  : I<(outs regtype:$Rd), (ins in1regtype:$Rn, in2regtype:$Rm),
2532      asm, "\t$Rd, $Rn, $Rm", "",
2533      [(set regtype:$Rd, (OpNode in1regtype:$Rn, in2regtype:$Rm))]> {
2534  bits<5> Rd;
2535  bits<5> Rn;
2536  bits<5> Rm;
2537  let Inst{31}    = sf;
2538  let Inst{30}    = 0b0;
2539  let Inst{29}    = S;
2540  let Inst{28-21} = 0b11010110;
2541  let Inst{20-16} = Rm;
2542  let Inst{15-10} = opc;
2543  let Inst{9-5}   = Rn;
2544  let Inst{4-0}   = Rd;
2545}
2546
2547class BaseDiv<bit size, bit isSigned, RegisterClass regtype, string asm,
2548              SDPatternOperator OpNode>
2549    : BaseTwoOperandRegReg<size, 0b0, {0,0,0,0,1,?}, regtype, asm, OpNode> {
2550  let Inst{10}    = isSigned;
2551}
2552
2553multiclass Div<bit isSigned, string asm, SDPatternOperator OpNode> {
2554  def Wr : BaseDiv<0b0, isSigned, GPR32, asm, OpNode>,
2555           Sched<[WriteID32, ReadID, ReadID]>;
2556
2557  def Xr : BaseDiv<0b1, isSigned, GPR64, asm, OpNode>,
2558           Sched<[WriteID64, ReadID, ReadID]>;
2559}
2560
2561class BaseShift<bit size, bits<2> shift_type, RegisterClass regtype, string asm,
2562                SDPatternOperator OpNode = null_frag>
2563  : BaseTwoOperandRegReg<size, 0b0, {0,0,1,0,?,?}, regtype, asm, OpNode>,
2564    Sched<[WriteIS, ReadI]> {
2565  let Inst{11-10} = shift_type;
2566}
2567
2568multiclass Shift<bits<2> shift_type, string asm, SDNode OpNode> {
2569  def Wr : BaseShift<0b0, shift_type, GPR32, asm>;
2570
2571  def Xr : BaseShift<0b1, shift_type, GPR64, asm, OpNode>;
2572
2573  def : Pat<(i32 (OpNode GPR32:$Rn, i64:$Rm)),
2574            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn,
2575                                             (EXTRACT_SUBREG i64:$Rm, sub_32))>;
2576
2577  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (zext GPR32:$Rm)))),
2578            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2579
2580  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (anyext GPR32:$Rm)))),
2581            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2582
2583  def : Pat<(i32 (OpNode GPR32:$Rn, (i64 (sext GPR32:$Rm)))),
2584            (!cast<Instruction>(NAME # "Wr") GPR32:$Rn, GPR32:$Rm)>;
2585
2586  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (sext GPR32:$Rm)))),
2587            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2588                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2589
2590  def : Pat<(i64 (OpNode GPR64:$Rn, (i64 (zext GPR32:$Rm)))),
2591            (!cast<Instruction>(NAME # "Xr") GPR64:$Rn,
2592                (SUBREG_TO_REG (i32 0), GPR32:$Rm, sub_32))>;
2593}
2594
2595class ShiftAlias<string asm, Instruction inst, RegisterClass regtype>
2596    : InstAlias<asm#"\t$dst, $src1, $src2",
2597                (inst regtype:$dst, regtype:$src1, regtype:$src2), 0>;
2598
2599class BaseMulAccum<bit isSub, bits<3> opc, RegisterClass multype,
2600                       RegisterClass addtype, string asm,
2601                       list<dag> pattern>
2602  : I<(outs addtype:$Rd), (ins multype:$Rn, multype:$Rm, addtype:$Ra),
2603      asm, "\t$Rd, $Rn, $Rm, $Ra", "", pattern> {
2604  bits<5> Rd;
2605  bits<5> Rn;
2606  bits<5> Rm;
2607  bits<5> Ra;
2608  let Inst{30-24} = 0b0011011;
2609  let Inst{23-21} = opc;
2610  let Inst{20-16} = Rm;
2611  let Inst{15}    = isSub;
2612  let Inst{14-10} = Ra;
2613  let Inst{9-5}   = Rn;
2614  let Inst{4-0}   = Rd;
2615}
2616
2617multiclass MulAccum<bit isSub, string asm> {
2618  // MADD/MSUB generation is decided by MachineCombiner.cpp
2619  def Wrrr : BaseMulAccum<isSub, 0b000, GPR32, GPR32, asm, []>,
2620      Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2621    let Inst{31} = 0;
2622  }
2623
2624  def Xrrr : BaseMulAccum<isSub, 0b000, GPR64, GPR64, asm, []>,
2625      Sched<[WriteIM64, ReadIM, ReadIM, ReadIMA]> {
2626    let Inst{31} = 1;
2627  }
2628}
2629
2630class WideMulAccum<bit isSub, bits<3> opc, string asm,
2631                   SDNode AccNode, SDNode ExtNode>
2632  : BaseMulAccum<isSub, opc, GPR32, GPR64, asm,
2633    [(set GPR64:$Rd, (AccNode GPR64:$Ra,
2634                            (mul (ExtNode GPR32:$Rn), (ExtNode GPR32:$Rm))))]>,
2635    Sched<[WriteIM32, ReadIM, ReadIM, ReadIMA]> {
2636  let Inst{31} = 1;
2637}
2638
2639class MulHi<bits<3> opc, string asm, SDNode OpNode>
2640  : I<(outs GPR64:$Rd), (ins GPR64:$Rn, GPR64:$Rm),
2641      asm, "\t$Rd, $Rn, $Rm", "",
2642      [(set GPR64:$Rd, (OpNode GPR64:$Rn, GPR64:$Rm))]>,
2643    Sched<[WriteIM64, ReadIM, ReadIM]> {
2644  bits<5> Rd;
2645  bits<5> Rn;
2646  bits<5> Rm;
2647  let Inst{31-24} = 0b10011011;
2648  let Inst{23-21} = opc;
2649  let Inst{20-16} = Rm;
2650  let Inst{15}    = 0;
2651  let Inst{9-5}   = Rn;
2652  let Inst{4-0}   = Rd;
2653
2654  // The Ra field of SMULH and UMULH is unused: it should be assembled as 31
2655  // (i.e. all bits 1) but is ignored by the processor.
2656  let PostEncoderMethod = "fixMulHigh";
2657}
2658
2659class MulAccumWAlias<string asm, Instruction inst>
2660    : InstAlias<asm#"\t$dst, $src1, $src2",
2661                (inst GPR32:$dst, GPR32:$src1, GPR32:$src2, WZR)>;
2662class MulAccumXAlias<string asm, Instruction inst>
2663    : InstAlias<asm#"\t$dst, $src1, $src2",
2664                (inst GPR64:$dst, GPR64:$src1, GPR64:$src2, XZR)>;
2665class WideMulAccumAlias<string asm, Instruction inst>
2666    : InstAlias<asm#"\t$dst, $src1, $src2",
2667                (inst GPR64:$dst, GPR32:$src1, GPR32:$src2, XZR)>;
2668
2669class BaseCRC32<bit sf, bits<2> sz, bit C, RegisterClass StreamReg,
2670              SDPatternOperator OpNode, string asm>
2671  : I<(outs GPR32:$Rd), (ins GPR32:$Rn, StreamReg:$Rm),
2672      asm, "\t$Rd, $Rn, $Rm", "",
2673      [(set GPR32:$Rd, (OpNode GPR32:$Rn, StreamReg:$Rm))]>,
2674    Sched<[WriteISReg, ReadI, ReadISReg]> {
2675  bits<5> Rd;
2676  bits<5> Rn;
2677  bits<5> Rm;
2678
2679  let Inst{31} = sf;
2680  let Inst{30-21} = 0b0011010110;
2681  let Inst{20-16} = Rm;
2682  let Inst{15-13} = 0b010;
2683  let Inst{12} = C;
2684  let Inst{11-10} = sz;
2685  let Inst{9-5} = Rn;
2686  let Inst{4-0} = Rd;
2687  let Predicates = [HasCRC];
2688}
2689
2690//---
2691// Address generation.
2692//---
2693
2694class ADRI<bit page, string asm, Operand adr, list<dag> pattern>
2695    : I<(outs GPR64:$Xd), (ins adr:$label), asm, "\t$Xd, $label", "",
2696        pattern>,
2697      Sched<[WriteI]> {
2698  bits<5>  Xd;
2699  bits<21> label;
2700  let Inst{31}    = page;
2701  let Inst{30-29} = label{1-0};
2702  let Inst{28-24} = 0b10000;
2703  let Inst{23-5}  = label{20-2};
2704  let Inst{4-0}   = Xd;
2705
2706  let DecoderMethod = "DecodeAdrInstruction";
2707}
2708
2709//---
2710// Move immediate.
2711//---
2712
2713def movimm32_imm : Operand<i32> {
2714  let ParserMatchClass = AsmImmRange<0, 65535>;
2715  let EncoderMethod = "getMoveWideImmOpValue";
2716  let PrintMethod = "printImm";
2717}
2718def movimm32_shift : Operand<i32> {
2719  let PrintMethod = "printShifter";
2720  let ParserMatchClass = MovImm32ShifterOperand;
2721}
2722def movimm64_shift : Operand<i32> {
2723  let PrintMethod = "printShifter";
2724  let ParserMatchClass = MovImm64ShifterOperand;
2725}
2726
2727let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2728class BaseMoveImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2729                        string asm>
2730  : I<(outs regtype:$Rd), (ins movimm32_imm:$imm, shifter:$shift),
2731       asm, "\t$Rd, $imm$shift", "", []>,
2732    Sched<[WriteImm]> {
2733  bits<5> Rd;
2734  bits<16> imm;
2735  bits<6> shift;
2736  let Inst{30-29} = opc;
2737  let Inst{28-23} = 0b100101;
2738  let Inst{22-21} = shift{5-4};
2739  let Inst{20-5}  = imm;
2740  let Inst{4-0}   = Rd;
2741
2742  let DecoderMethod = "DecodeMoveImmInstruction";
2743}
2744
2745multiclass MoveImmediate<bits<2> opc, string asm> {
2746  def Wi : BaseMoveImmediate<opc, GPR32, movimm32_shift, asm> {
2747    let Inst{31} = 0;
2748  }
2749
2750  def Xi : BaseMoveImmediate<opc, GPR64, movimm64_shift, asm> {
2751    let Inst{31} = 1;
2752  }
2753}
2754
2755let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2756class BaseInsertImmediate<bits<2> opc, RegisterClass regtype, Operand shifter,
2757                          string asm>
2758  : I<(outs regtype:$Rd),
2759      (ins regtype:$src, movimm32_imm:$imm, shifter:$shift),
2760       asm, "\t$Rd, $imm$shift", "$src = $Rd", []>,
2761    Sched<[WriteI, ReadI]> {
2762  bits<5> Rd;
2763  bits<16> imm;
2764  bits<6> shift;
2765  let Inst{30-29} = opc;
2766  let Inst{28-23} = 0b100101;
2767  let Inst{22-21} = shift{5-4};
2768  let Inst{20-5}  = imm;
2769  let Inst{4-0}   = Rd;
2770
2771  let DecoderMethod = "DecodeMoveImmInstruction";
2772}
2773
2774multiclass InsertImmediate<bits<2> opc, string asm> {
2775  def Wi : BaseInsertImmediate<opc, GPR32, movimm32_shift, asm> {
2776    let Inst{31} = 0;
2777  }
2778
2779  def Xi : BaseInsertImmediate<opc, GPR64, movimm64_shift, asm> {
2780    let Inst{31} = 1;
2781  }
2782}
2783
2784//---
2785// Add/Subtract
2786//---
2787
2788class BaseAddSubImm<bit isSub, bit setFlags, RegisterClass dstRegtype,
2789                    string asm_inst, string asm_ops,
2790                    dag inputs, dag pattern>
2791    : I<(outs dstRegtype:$Rd), inputs, asm_inst, asm_ops, "", [pattern]>,
2792      Sched<[WriteI, ReadI]> {
2793  bits<5>  Rd;
2794  bits<5>  Rn;
2795  let Inst{30}    = isSub;
2796  let Inst{29}    = setFlags;
2797  let Inst{28-24} = 0b10001;
2798  let Inst{9-5}   = Rn;
2799  let Inst{4-0}   = Rd;
2800}
2801
2802class AddSubImmShift<bit isSub, bit setFlags, RegisterClass dstRegtype,
2803                     RegisterClass srcRegtype, addsub_shifted_imm immtype,
2804                     string asm_inst, SDPatternOperator OpNode>
2805    : BaseAddSubImm<isSub, setFlags, dstRegtype, asm_inst, "\t$Rd, $Rn, $imm",
2806                    (ins srcRegtype:$Rn, immtype:$imm),
2807                    (set dstRegtype:$Rd, (OpNode srcRegtype:$Rn, immtype:$imm))> {
2808  bits<14> imm;
2809  let Inst{23-22} = imm{13-12}; // '00' => lsl #0, '01' => lsl #12
2810  let Inst{21-10} = imm{11-0};
2811  let DecoderMethod = "DecodeAddSubImmShift";
2812  let hasPostISelHook = 1;
2813}
2814
2815class BaseAddSubRegPseudo<RegisterClass regtype,
2816                          SDPatternOperator OpNode>
2817    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2818             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2819      Sched<[WriteI, ReadI, ReadI]>;
2820
2821class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2822                     arith_shifted_reg shifted_regtype, string asm,
2823                     SDPatternOperator OpNode>
2824    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
2825        asm, "\t$Rd, $Rn, $Rm_and_shift", "",
2826        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm_and_shift))]>,
2827      Sched<[WriteISReg, ReadI, ReadISReg]> {
2828  bits<5> Rd;
2829  bits<5> Rn;
2830  bits<5> Rm;
2831  bits<8> shift;
2832  let Inst{30}    = isSub;
2833  let Inst{29}    = setFlags;
2834  let Inst{28-24} = 0b01011;
2835  let Inst{23-22} = shift{7-6};
2836  let Inst{21}    = 0;
2837  let Inst{20-16} = Rm;
2838  let Inst{15-10} = shift{5-0};
2839  let Inst{9-5}   = Rn;
2840  let Inst{4-0}   = Rd;
2841
2842  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2843}
2844
2845class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2846                     RegisterClass src1Regtype, Operand src2Regtype,
2847                     string asm, SDPatternOperator OpNode>
2848    : I<(outs dstRegtype:$Rd),
2849        (ins src1Regtype:$Rn, (src2Regtype $Rm, $extend):$Rm_and_extend),
2850        asm, "\t$Rd, $Rn, $Rm_and_extend", "",
2851        [(set dstRegtype:$Rd, (OpNode src1Regtype:$Rn, src2Regtype:$Rm_and_extend))]>,
2852      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2853  bits<5> Rd;
2854  bits<5> Rn;
2855  bits<5> Rm;
2856  bits<6> extend;
2857  let Inst{30}    = isSub;
2858  let Inst{29}    = setFlags;
2859  let Inst{28-24} = 0b01011;
2860  let Inst{23-21} = 0b001;
2861  let Inst{20-16} = Rm;
2862  let Inst{15-13} = extend{5-3};
2863  let Inst{12-10} = extend{2-0};
2864  let Inst{9-5}   = Rn;
2865  let Inst{4-0}   = Rd;
2866
2867  let DecoderMethod = "DecodeAddSubERegInstruction";
2868}
2869
2870let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2871class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2872                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2873                       Operand ext_op, string asm>
2874    : I<(outs dstRegtype:$Rd),
2875        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2876        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2877      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2878  bits<5> Rd;
2879  bits<5> Rn;
2880  bits<5> Rm;
2881  bits<6> ext;
2882  let Inst{30}    = isSub;
2883  let Inst{29}    = setFlags;
2884  let Inst{28-24} = 0b01011;
2885  let Inst{23-21} = 0b001;
2886  let Inst{20-16} = Rm;
2887  let Inst{15}    = ext{5};
2888  let Inst{12-10} = ext{2-0};
2889  let Inst{9-5}   = Rn;
2890  let Inst{4-0}   = Rd;
2891
2892  let DecoderMethod = "DecodeAddSubERegInstruction";
2893}
2894
2895// Aliases for register+register add/subtract.
2896class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2897                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2898                     int shiftExt>
2899    : InstAlias<asm#"\t$dst, $src1, $src2",
2900                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2901                      shiftExt)>;
2902
2903multiclass AddSub<bit isSub, string mnemonic, string alias,
2904                  SDPatternOperator OpNode = null_frag> {
2905  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2906  // Add/Subtract immediate
2907  // Increase the weight of the immediate variant to try to match it before
2908  // the extended register variant.
2909  // We used to match the register variant before the immediate when the
2910  // register argument could be implicitly zero-extended.
2911  let AddedComplexity = 6 in
2912  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2913                           mnemonic, OpNode> {
2914    let Inst{31} = 0;
2915  }
2916  let AddedComplexity = 6 in
2917  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2918                           mnemonic, OpNode> {
2919    let Inst{31} = 1;
2920  }
2921
2922  // Add/Subtract register - Only used for CodeGen
2923  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2924  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2925
2926  // Add/Subtract shifted register
2927  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2928                           OpNode> {
2929    let Inst{31} = 0;
2930  }
2931  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2932                           OpNode> {
2933    let Inst{31} = 1;
2934  }
2935  }
2936
2937  // Add/Subtract extended register
2938  let AddedComplexity = 1, hasSideEffects = 0 in {
2939  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2940                           arith_extended_reg32_i32, mnemonic, OpNode> {
2941    let Inst{31} = 0;
2942  }
2943  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2944                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2945    let Inst{31} = 1;
2946  }
2947  }
2948
2949  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2950                               arith_extendlsl64, mnemonic> {
2951    // UXTX and SXTX only.
2952    let Inst{14-13} = 0b11;
2953    let Inst{31} = 1;
2954  }
2955
2956  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2957  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2958                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2959                      addsub_shifted_imm32_neg:$imm), 0>;
2960  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2961                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2962                       addsub_shifted_imm64_neg:$imm), 0>;
2963
2964  // Register/register aliases with no shift when SP is not used.
2965  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2966                       GPR32, GPR32, GPR32, 0>;
2967  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2968                       GPR64, GPR64, GPR64, 0>;
2969
2970  // Register/register aliases with no shift when either the destination or
2971  // first source register is SP.
2972  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2973                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2974  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2975                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2976  def : AddSubRegAlias<mnemonic,
2977                       !cast<Instruction>(NAME#"Xrx64"),
2978                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2979  def : AddSubRegAlias<mnemonic,
2980                       !cast<Instruction>(NAME#"Xrx64"),
2981                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2982}
2983
2984multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2985                   string alias, string cmpAlias> {
2986  let isCompare = 1, Defs = [NZCV] in {
2987  // Add/Subtract immediate
2988  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2989                           mnemonic, OpNode> {
2990    let Inst{31} = 0;
2991  }
2992  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2993                           mnemonic, OpNode> {
2994    let Inst{31} = 1;
2995  }
2996
2997  // Add/Subtract register
2998  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2999  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
3000
3001  // Add/Subtract shifted register
3002  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
3003                           OpNode> {
3004    let Inst{31} = 0;
3005  }
3006  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
3007                           OpNode> {
3008    let Inst{31} = 1;
3009  }
3010
3011  // Add/Subtract extended register
3012  let AddedComplexity = 1 in {
3013  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
3014                           arith_extended_reg32_i32, mnemonic, OpNode> {
3015    let Inst{31} = 0;
3016  }
3017  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
3018                           arith_extended_reg32_i64, mnemonic, OpNode> {
3019    let Inst{31} = 1;
3020  }
3021  }
3022
3023  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
3024                               arith_extendlsl64, mnemonic> {
3025    // UXTX and SXTX only.
3026    let Inst{14-13} = 0b11;
3027    let Inst{31} = 1;
3028  }
3029  } // Defs = [NZCV]
3030
3031  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
3032  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
3033                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
3034                      addsub_shifted_imm32_neg:$imm), 0>;
3035  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
3036                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
3037                       addsub_shifted_imm64_neg:$imm), 0>;
3038
3039  // Compare aliases
3040  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
3041                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
3042  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
3043                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
3044  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
3045                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
3046  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
3047                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
3048  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
3049                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
3050  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
3051                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
3052  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
3053                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
3054
3055  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
3056  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
3057                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
3058  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
3059                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
3060
3061  // Compare shorthands
3062  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
3063                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
3064  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
3065                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
3066  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
3067                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
3068  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
3069                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
3070
3071  // Register/register aliases with no shift when SP is not used.
3072  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
3073                       GPR32, GPR32, GPR32, 0>;
3074  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
3075                       GPR64, GPR64, GPR64, 0>;
3076
3077  // Register/register aliases with no shift when the first source register
3078  // is SP.
3079  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
3080                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
3081  def : AddSubRegAlias<mnemonic,
3082                       !cast<Instruction>(NAME#"Xrx64"),
3083                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
3084}
3085
3086class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
3087      : BaseAddSubImm<
3088          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
3089          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
3090          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
3091  bits<6> imm6;
3092  bits<4> imm4;
3093  let Inst{31} = 1;
3094  let Inst{23-22} = 0b10;
3095  let Inst{21-16} = imm6;
3096  let Inst{15-14} = 0b00;
3097  let Inst{13-10} = imm4;
3098  let Unpredictable{15-14} = 0b11;
3099}
3100
3101class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
3102      : BaseTwoOperandRegReg<0b1, setsFlags, 0b000000, GPR64, asm_instr, OpNode,
3103                             GPR64sp, GPR64sp>;
3104
3105//---
3106// Extract
3107//---
3108def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
3109                                      SDTCisPtrTy<3>]>;
3110def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
3111
3112class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
3113                     list<dag> patterns>
3114    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
3115         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
3116      Sched<[WriteExtr, ReadExtrHi]> {
3117  bits<5> Rd;
3118  bits<5> Rn;
3119  bits<5> Rm;
3120  bits<6> imm;
3121
3122  let Inst{30-23} = 0b00100111;
3123  let Inst{21}    = 0;
3124  let Inst{20-16} = Rm;
3125  let Inst{15-10} = imm;
3126  let Inst{9-5}   = Rn;
3127  let Inst{4-0}   = Rd;
3128}
3129
3130multiclass ExtractImm<string asm> {
3131  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
3132                      [(set GPR32:$Rd,
3133                        (fshr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
3134    let Inst{31} = 0;
3135    let Inst{22} = 0;
3136    // imm<5> must be zero.
3137    let imm{5}   = 0;
3138  }
3139  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
3140                      [(set GPR64:$Rd,
3141                        (fshr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
3142
3143    let Inst{31} = 1;
3144    let Inst{22} = 1;
3145  }
3146}
3147
3148//---
3149// Bitfield
3150//---
3151
3152let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3153class BaseBitfieldImm<bits<2> opc,
3154                      RegisterClass regtype, Operand imm_type, string asm>
3155    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
3156         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
3157      Sched<[WriteIS, ReadI]> {
3158  bits<5> Rd;
3159  bits<5> Rn;
3160  bits<6> immr;
3161  bits<6> imms;
3162
3163  let Inst{30-29} = opc;
3164  let Inst{28-23} = 0b100110;
3165  let Inst{21-16} = immr;
3166  let Inst{15-10} = imms;
3167  let Inst{9-5}   = Rn;
3168  let Inst{4-0}   = Rd;
3169}
3170
3171multiclass BitfieldImm<bits<2> opc, string asm> {
3172  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
3173    let Inst{31} = 0;
3174    let Inst{22} = 0;
3175    // imms<5> and immr<5> must be zero, else ReservedValue().
3176    let Inst{21} = 0;
3177    let Inst{15} = 0;
3178  }
3179  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
3180    let Inst{31} = 1;
3181    let Inst{22} = 1;
3182  }
3183}
3184
3185let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3186class BaseBitfieldImmWith2RegArgs<bits<2> opc,
3187                      RegisterClass regtype, Operand imm_type, string asm>
3188    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
3189                             imm_type:$imms),
3190         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
3191      Sched<[WriteIS, ReadI]> {
3192  bits<5> Rd;
3193  bits<5> Rn;
3194  bits<6> immr;
3195  bits<6> imms;
3196
3197  let Inst{30-29} = opc;
3198  let Inst{28-23} = 0b100110;
3199  let Inst{21-16} = immr;
3200  let Inst{15-10} = imms;
3201  let Inst{9-5}   = Rn;
3202  let Inst{4-0}   = Rd;
3203}
3204
3205multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
3206  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
3207    let Inst{31} = 0;
3208    let Inst{22} = 0;
3209    // imms<5> and immr<5> must be zero, else ReservedValue().
3210    let Inst{21} = 0;
3211    let Inst{15} = 0;
3212  }
3213  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
3214    let Inst{31} = 1;
3215    let Inst{22} = 1;
3216  }
3217}
3218
3219//---
3220// Logical
3221//---
3222
3223// Logical (immediate)
3224class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
3225                     RegisterClass sregtype, Operand imm_type, string asm,
3226                     list<dag> pattern>
3227    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
3228         asm, "\t$Rd, $Rn, $imm", "", pattern>,
3229      Sched<[WriteI, ReadI]> {
3230  bits<5>  Rd;
3231  bits<5>  Rn;
3232  bits<13> imm;
3233  let Inst{30-29} = opc;
3234  let Inst{28-23} = 0b100100;
3235  let Inst{22}    = imm{12};
3236  let Inst{21-16} = imm{11-6};
3237  let Inst{15-10} = imm{5-0};
3238  let Inst{9-5}   = Rn;
3239  let Inst{4-0}   = Rd;
3240
3241  let DecoderMethod = "DecodeLogicalImmInstruction";
3242}
3243
3244// Logical (shifted register)
3245class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
3246                      logical_shifted_reg shifted_regtype, string asm,
3247                      list<dag> pattern>
3248    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
3249        asm, "\t$Rd, $Rn, $Rm_and_shift", "", pattern>,
3250      Sched<[WriteISReg, ReadI, ReadISReg]> {
3251  bits<5> Rd;
3252  bits<5> Rn;
3253  bits<5> Rm;
3254  bits<8> shift;
3255  let Inst{30-29} = opc;
3256  let Inst{28-24} = 0b01010;
3257  let Inst{23-22} = shift{7-6};
3258  let Inst{21}    = N;
3259  let Inst{20-16} = Rm;
3260  let Inst{15-10} = shift{5-0};
3261  let Inst{9-5}   = Rn;
3262  let Inst{4-0}   = Rd;
3263
3264  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
3265}
3266
3267// Aliases for register+register logical instructions.
3268class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
3269    : InstAlias<asm#"\t$dst, $src1, $src2",
3270                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
3271
3272multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
3273                      string Alias> {
3274  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3275  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
3276                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
3277                                               logical_imm32:$imm))]> {
3278    let Inst{31} = 0;
3279    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3280  }
3281  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3282  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
3283                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
3284                                               logical_imm64:$imm))]> {
3285    let Inst{31} = 1;
3286  }
3287
3288  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3289                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
3290                      logical_imm32_not:$imm), 0>;
3291  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3292                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
3293                       logical_imm64_not:$imm), 0>;
3294}
3295
3296multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
3297                       string Alias> {
3298  let isCompare = 1, Defs = [NZCV] in {
3299  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
3300      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
3301    let Inst{31} = 0;
3302    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3303  }
3304  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
3305      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
3306    let Inst{31} = 1;
3307  }
3308  } // end Defs = [NZCV]
3309
3310  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3311                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
3312                      logical_imm32_not:$imm), 0>;
3313  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3314                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
3315                       logical_imm64_not:$imm), 0>;
3316}
3317
3318class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
3319    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3320             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
3321      Sched<[WriteI, ReadI, ReadI]>;
3322
3323// Split from LogicalImm as not all instructions have both.
3324multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
3325                      SDPatternOperator OpNode, int AddedComplexityVal = 0> {
3326  let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = AddedComplexityVal in {
3327  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3328  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3329  }
3330
3331  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3332                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
3333                                                 logical_shifted_reg32:$Rm_and_shift))]> {
3334    let Inst{31} = 0;
3335  }
3336  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3337                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
3338                                                 logical_shifted_reg64:$Rm_and_shift))]> {
3339    let Inst{31} = 1;
3340  }
3341
3342  def : LogicalRegAlias<mnemonic,
3343                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3344  def : LogicalRegAlias<mnemonic,
3345                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3346}
3347
3348// Split from LogicalReg to allow setting NZCV Defs
3349multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
3350                       SDPatternOperator OpNode = null_frag> {
3351  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
3352  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3353  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3354
3355  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3356            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm_and_shift))]> {
3357    let Inst{31} = 0;
3358  }
3359  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3360            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm_and_shift))]> {
3361    let Inst{31} = 1;
3362  }
3363  } // Defs = [NZCV]
3364
3365  def : LogicalRegAlias<mnemonic,
3366                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3367  def : LogicalRegAlias<mnemonic,
3368                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3369}
3370
3371//---
3372// Conditionally set flags
3373//---
3374
3375let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3376class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3377                            string mnemonic, SDNode OpNode>
3378    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3379         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3380         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3381                             (i32 imm:$cond), NZCV))]>,
3382      Sched<[WriteI, ReadI]> {
3383  let Uses = [NZCV];
3384  let Defs = [NZCV];
3385
3386  bits<5> Rn;
3387  bits<5> imm;
3388  bits<4> nzcv;
3389  bits<4> cond;
3390
3391  let Inst{30}    = op;
3392  let Inst{29-21} = 0b111010010;
3393  let Inst{20-16} = imm;
3394  let Inst{15-12} = cond;
3395  let Inst{11-10} = 0b10;
3396  let Inst{9-5}   = Rn;
3397  let Inst{4}     = 0b0;
3398  let Inst{3-0}   = nzcv;
3399}
3400
3401let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3402class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3403                            SDNode OpNode>
3404    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3405         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3406         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3407                             (i32 imm:$cond), NZCV))]>,
3408      Sched<[WriteI, ReadI, ReadI]> {
3409  let Uses = [NZCV];
3410  let Defs = [NZCV];
3411
3412  bits<5> Rn;
3413  bits<5> Rm;
3414  bits<4> nzcv;
3415  bits<4> cond;
3416
3417  let Inst{30}    = op;
3418  let Inst{29-21} = 0b111010010;
3419  let Inst{20-16} = Rm;
3420  let Inst{15-12} = cond;
3421  let Inst{11-10} = 0b00;
3422  let Inst{9-5}   = Rn;
3423  let Inst{4}     = 0b0;
3424  let Inst{3-0}   = nzcv;
3425}
3426
3427multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3428  // immediate operand variants
3429  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3430    let Inst{31} = 0;
3431  }
3432  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3433    let Inst{31} = 1;
3434  }
3435  // register operand variants
3436  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3437    let Inst{31} = 0;
3438  }
3439  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3440    let Inst{31} = 1;
3441  }
3442}
3443
3444//---
3445// Conditional select
3446//---
3447
3448class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3449    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3450         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3451         [(set regtype:$Rd,
3452               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3453      Sched<[WriteI, ReadI, ReadI]> {
3454  let Uses = [NZCV];
3455
3456  bits<5> Rd;
3457  bits<5> Rn;
3458  bits<5> Rm;
3459  bits<4> cond;
3460
3461  let Inst{30}    = op;
3462  let Inst{29-21} = 0b011010100;
3463  let Inst{20-16} = Rm;
3464  let Inst{15-12} = cond;
3465  let Inst{11-10} = op2;
3466  let Inst{9-5}   = Rn;
3467  let Inst{4-0}   = Rd;
3468}
3469
3470multiclass CondSelect<bit op, bits<2> op2, string asm> {
3471  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3472    let Inst{31} = 0;
3473  }
3474  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3475    let Inst{31} = 1;
3476  }
3477}
3478
3479class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3480                       PatFrag frag>
3481    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3482         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3483         [(set regtype:$Rd,
3484               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3485               (i32 imm:$cond), NZCV))]>,
3486      Sched<[WriteI, ReadI, ReadI]> {
3487  let Uses = [NZCV];
3488
3489  bits<5> Rd;
3490  bits<5> Rn;
3491  bits<5> Rm;
3492  bits<4> cond;
3493
3494  let Inst{30}    = op;
3495  let Inst{29-21} = 0b011010100;
3496  let Inst{20-16} = Rm;
3497  let Inst{15-12} = cond;
3498  let Inst{11-10} = op2;
3499  let Inst{9-5}   = Rn;
3500  let Inst{4-0}   = Rd;
3501}
3502
3503def inv_cond_XFORM : SDNodeXForm<imm, [{
3504  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3505  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3506                                   MVT::i32);
3507}]>;
3508
3509multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3510  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3511    let Inst{31} = 0;
3512  }
3513  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3514    let Inst{31} = 1;
3515  }
3516
3517  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3518            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3519                                           (inv_cond_XFORM imm:$cond))>;
3520
3521  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3522            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3523                                           (inv_cond_XFORM imm:$cond))>;
3524}
3525
3526//---
3527// Special Mask Value
3528//---
3529def maski8_or_more : Operand<i32>,
3530  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3531}
3532def maski16_or_more : Operand<i32>,
3533  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3534}
3535
3536
3537//---
3538// Load/store
3539//---
3540
3541// (unsigned immediate)
3542// Indexed for 8-bit registers. offset is in range [0,4095].
3543def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3544def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3545def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3546def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3547def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3548
3549// (unsigned immediate)
3550// Indexed for 8-bit registers. offset is in range [0,63].
3551def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3552def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3553def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3554def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3555
3556def gi_am_indexed8 :
3557    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3558    GIComplexPatternEquiv<am_indexed8>;
3559def gi_am_indexed16 :
3560    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3561    GIComplexPatternEquiv<am_indexed16>;
3562def gi_am_indexed32 :
3563    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3564    GIComplexPatternEquiv<am_indexed32>;
3565def gi_am_indexed64 :
3566    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3567    GIComplexPatternEquiv<am_indexed64>;
3568def gi_am_indexed128 :
3569    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3570    GIComplexPatternEquiv<am_indexed128>;
3571
3572class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3573  let Name = "UImm12Offset" # Scale;
3574  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3575  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3576  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3577}
3578
3579def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3580def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3581def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3582def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3583def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3584
3585class uimm12_scaled<int Scale> : Operand<i64> {
3586  let ParserMatchClass
3587   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3588  let EncoderMethod
3589   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3590  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3591}
3592
3593def uimm12s1 : uimm12_scaled<1>;
3594def uimm12s2 : uimm12_scaled<2>;
3595def uimm12s4 : uimm12_scaled<4>;
3596def uimm12s8 : uimm12_scaled<8>;
3597def uimm12s16 : uimm12_scaled<16>;
3598
3599class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3600                      string asm, list<dag> pattern>
3601    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3602  bits<5> Rt;
3603
3604  bits<5> Rn;
3605  bits<12> offset;
3606
3607  let Inst{31-30} = sz;
3608  let Inst{29-27} = 0b111;
3609  let Inst{26}    = V;
3610  let Inst{25-24} = 0b01;
3611  let Inst{23-22} = opc;
3612  let Inst{21-10} = offset;
3613  let Inst{9-5}   = Rn;
3614  let Inst{4-0}   = Rt;
3615
3616  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3617}
3618
3619multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3620                  Operand indextype, string asm, list<dag> pattern> {
3621  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3622  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3623                           (ins GPR64sp:$Rn, indextype:$offset),
3624                           asm, pattern>,
3625           Sched<[WriteLD]>;
3626
3627  def : InstAlias<asm # "\t$Rt, [$Rn]",
3628                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3629}
3630
3631multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3632             Operand indextype, string asm, list<dag> pattern> {
3633  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3634  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3635                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3636                           asm, pattern>,
3637           Sched<[WriteST]>;
3638
3639  def : InstAlias<asm # "\t$Rt, [$Rn]",
3640                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3641}
3642
3643// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3644// substitute zero-registers automatically.
3645//
3646// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3647//       into StoreUI.
3648multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3649             Operand indextype, string asm, list<dag> pattern> {
3650  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3651  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3652                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3653                           asm, pattern>,
3654           Sched<[WriteST]>;
3655
3656  def : InstAlias<asm # "\t$Rt, [$Rn]",
3657                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3658}
3659
3660def PrefetchOperand : AsmOperandClass {
3661  let Name = "Prefetch";
3662  let ParserMethod = "tryParsePrefetch";
3663}
3664def prfop : Operand<i32> {
3665  let PrintMethod = "printPrefetchOp";
3666  let ParserMatchClass = PrefetchOperand;
3667}
3668
3669let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3670class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3671    : BaseLoadStoreUI<sz, V, opc,
3672                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3673                      asm, pat>,
3674      Sched<[WriteLD]>;
3675
3676//---
3677// Load literal
3678//---
3679
3680// Load literal address: 19-bit immediate. The low two bits of the target
3681// offset are implied zero and so are not part of the immediate.
3682def am_ldrlit : Operand<iPTR> {
3683  let EncoderMethod = "getLoadLiteralOpValue";
3684  let DecoderMethod = "DecodePCRelLabel19";
3685  let PrintMethod = "printAlignedLabel";
3686  let ParserMatchClass = PCRelLabel19Operand;
3687  let OperandType = "OPERAND_PCREL";
3688}
3689
3690let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3691class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3692    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3693        asm, "\t$Rt, $label", "", pat>,
3694      Sched<[WriteLD]> {
3695  bits<5> Rt;
3696  bits<19> label;
3697  let Inst{31-30} = opc;
3698  let Inst{29-27} = 0b011;
3699  let Inst{26}    = V;
3700  let Inst{25-24} = 0b00;
3701  let Inst{23-5}  = label;
3702  let Inst{4-0}   = Rt;
3703}
3704
3705let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3706class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3707    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3708        asm, "\t$Rt, $label", "", pat>,
3709      Sched<[WriteLD]> {
3710  bits<5> Rt;
3711  bits<19> label;
3712  let Inst{31-30} = opc;
3713  let Inst{29-27} = 0b011;
3714  let Inst{26}    = V;
3715  let Inst{25-24} = 0b00;
3716  let Inst{23-5}  = label;
3717  let Inst{4-0}   = Rt;
3718}
3719
3720//---
3721// Load/store register offset
3722//---
3723
3724def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3725def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3726def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3727def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3728def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3729
3730def gi_ro_Xindexed8 :
3731    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3732    GIComplexPatternEquiv<ro_Xindexed8>;
3733def gi_ro_Xindexed16 :
3734    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3735    GIComplexPatternEquiv<ro_Xindexed16>;
3736def gi_ro_Xindexed32 :
3737    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3738    GIComplexPatternEquiv<ro_Xindexed32>;
3739def gi_ro_Xindexed64 :
3740    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3741    GIComplexPatternEquiv<ro_Xindexed64>;
3742def gi_ro_Xindexed128 :
3743    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3744    GIComplexPatternEquiv<ro_Xindexed128>;
3745
3746def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3747def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3748def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3749def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3750def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3751
3752def gi_ro_Windexed8 :
3753    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3754    GIComplexPatternEquiv<ro_Windexed8>;
3755def gi_ro_Windexed16 :
3756    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3757    GIComplexPatternEquiv<ro_Windexed16>;
3758def gi_ro_Windexed32 :
3759    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3760    GIComplexPatternEquiv<ro_Windexed32>;
3761def gi_ro_Windexed64 :
3762    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3763    GIComplexPatternEquiv<ro_Windexed64>;
3764def gi_ro_Windexed128 :
3765    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3766    GIComplexPatternEquiv<ro_Windexed128>;
3767
3768class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3769  let Name = "Mem" # Reg # "Extend" # Width;
3770  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3771  let RenderMethod = "addMemExtendOperands";
3772  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3773}
3774
3775def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3776  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3777  // the trivial shift.
3778  let RenderMethod = "addMemExtend8Operands";
3779}
3780def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3781def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3782def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3783def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3784
3785def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3786  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3787  // the trivial shift.
3788  let RenderMethod = "addMemExtend8Operands";
3789}
3790def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3791def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3792def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3793def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3794
3795class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3796        : Operand<i32> {
3797  let ParserMatchClass = ParserClass;
3798  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3799  let DecoderMethod = "DecodeMemExtend";
3800  let EncoderMethod = "getMemExtendOpValue";
3801  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3802}
3803
3804def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3805def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3806def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3807def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3808def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3809
3810def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3811def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3812def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3813def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3814def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3815
3816class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3817                  Operand wextend, Operand xextend>  {
3818  // CodeGen-level pattern covering the entire addressing mode.
3819  ComplexPattern Wpat = windex;
3820  ComplexPattern Xpat = xindex;
3821
3822  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3823  Operand Wext = wextend;
3824  Operand Xext = xextend;
3825}
3826
3827def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3828def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3829def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3830def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3831def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3832                       ro_Xextend128>;
3833
3834class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3835                   dag outs, list<dag> pat>
3836    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3837  bits<5> Rt;
3838  bits<5> Rn;
3839  bits<5> Rm;
3840  bits<2> extend;
3841  let Inst{31-30} = sz;
3842  let Inst{29-27} = 0b111;
3843  let Inst{26}    = V;
3844  let Inst{25-24} = 0b00;
3845  let Inst{23-22} = opc;
3846  let Inst{21}    = 1;
3847  let Inst{20-16} = Rm;
3848  let Inst{15}    = extend{1}; // sign extend Rm?
3849  let Inst{14}    = 1;
3850  let Inst{12}    = extend{0}; // do shift?
3851  let Inst{11-10} = 0b10;
3852  let Inst{9-5}   = Rn;
3853  let Inst{4-0}   = Rt;
3854}
3855
3856class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3857  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3858              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3859
3860multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3861                   string asm, ValueType Ty, SDPatternOperator loadop> {
3862  let AddedComplexity = 10 in
3863  def roW : LoadStore8RO<sz, V, opc, asm,
3864                 (outs regtype:$Rt),
3865                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3866                 [(set (Ty regtype:$Rt),
3867                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3868                                             ro_Wextend8:$extend)))]>,
3869           Sched<[WriteLDIdx, ReadAdrBase]> {
3870    let Inst{13} = 0b0;
3871  }
3872
3873  let AddedComplexity = 10 in
3874  def roX : LoadStore8RO<sz, V, opc, asm,
3875                 (outs regtype:$Rt),
3876                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3877                 [(set (Ty regtype:$Rt),
3878                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3879                                             ro_Xextend8:$extend)))]>,
3880           Sched<[WriteLDIdx, ReadAdrBase]> {
3881    let Inst{13} = 0b1;
3882  }
3883
3884  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3885}
3886
3887multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3888                    string asm, ValueType Ty, SDPatternOperator storeop> {
3889  let AddedComplexity = 10 in
3890  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
3891                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3892                 [(storeop (Ty regtype:$Rt),
3893                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3894                                         ro_Wextend8:$extend))]>,
3895            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3896    let Inst{13} = 0b0;
3897  }
3898
3899  let AddedComplexity = 10 in
3900  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
3901                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3902                 [(storeop (Ty regtype:$Rt),
3903                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3904                                         ro_Xextend8:$extend))]>,
3905            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3906    let Inst{13} = 0b1;
3907  }
3908
3909  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3910}
3911
3912class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3913                    dag outs, list<dag> pat>
3914    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3915  bits<5> Rt;
3916  bits<5> Rn;
3917  bits<5> Rm;
3918  bits<2> extend;
3919  let Inst{31-30} = sz;
3920  let Inst{29-27} = 0b111;
3921  let Inst{26}    = V;
3922  let Inst{25-24} = 0b00;
3923  let Inst{23-22} = opc;
3924  let Inst{21}    = 1;
3925  let Inst{20-16} = Rm;
3926  let Inst{15}    = extend{1}; // sign extend Rm?
3927  let Inst{14}    = 1;
3928  let Inst{12}    = extend{0}; // do shift?
3929  let Inst{11-10} = 0b10;
3930  let Inst{9-5}   = Rn;
3931  let Inst{4-0}   = Rt;
3932}
3933
3934multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3935                    string asm, ValueType Ty, SDPatternOperator loadop> {
3936  let AddedComplexity = 10 in
3937  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3938                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3939                 [(set (Ty regtype:$Rt),
3940                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3941                                              ro_Wextend16:$extend)))]>,
3942            Sched<[WriteLDIdx, ReadAdrBase]> {
3943    let Inst{13} = 0b0;
3944  }
3945
3946  let AddedComplexity = 10 in
3947  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3948                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3949                 [(set (Ty regtype:$Rt),
3950                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3951                                             ro_Xextend16:$extend)))]>,
3952            Sched<[WriteLDIdx, ReadAdrBase]> {
3953    let Inst{13} = 0b1;
3954  }
3955
3956  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3957}
3958
3959multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3960                     string asm, ValueType Ty, SDPatternOperator storeop> {
3961  let AddedComplexity = 10 in
3962  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
3963                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3964                [(storeop (Ty regtype:$Rt),
3965                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3966                                         ro_Wextend16:$extend))]>,
3967           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3968    let Inst{13} = 0b0;
3969  }
3970
3971  let AddedComplexity = 10 in
3972  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
3973                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3974                [(storeop (Ty regtype:$Rt),
3975                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3976                                         ro_Xextend16:$extend))]>,
3977           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3978    let Inst{13} = 0b1;
3979  }
3980
3981  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3982}
3983
3984class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3985                    dag outs, list<dag> pat>
3986    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3987  bits<5> Rt;
3988  bits<5> Rn;
3989  bits<5> Rm;
3990  bits<2> extend;
3991  let Inst{31-30} = sz;
3992  let Inst{29-27} = 0b111;
3993  let Inst{26}    = V;
3994  let Inst{25-24} = 0b00;
3995  let Inst{23-22} = opc;
3996  let Inst{21}    = 1;
3997  let Inst{20-16} = Rm;
3998  let Inst{15}    = extend{1}; // sign extend Rm?
3999  let Inst{14}    = 1;
4000  let Inst{12}    = extend{0}; // do shift?
4001  let Inst{11-10} = 0b10;
4002  let Inst{9-5}   = Rn;
4003  let Inst{4-0}   = Rt;
4004}
4005
4006multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4007                    string asm, ValueType Ty, SDPatternOperator loadop> {
4008  let AddedComplexity = 10 in
4009  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
4010                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
4011                 [(set (Ty regtype:$Rt),
4012                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
4013                                              ro_Wextend32:$extend)))]>,
4014           Sched<[WriteLDIdx, ReadAdrBase]> {
4015    let Inst{13} = 0b0;
4016  }
4017
4018  let AddedComplexity = 10 in
4019  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
4020                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
4021                 [(set (Ty regtype:$Rt),
4022                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
4023                                              ro_Xextend32:$extend)))]>,
4024           Sched<[WriteLDIdx, ReadAdrBase]> {
4025    let Inst{13} = 0b1;
4026  }
4027
4028  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4029}
4030
4031multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4032                     string asm, ValueType Ty, SDPatternOperator storeop> {
4033  let AddedComplexity = 10 in
4034  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
4035                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
4036                [(storeop (Ty regtype:$Rt),
4037                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
4038                                         ro_Wextend32:$extend))]>,
4039            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4040    let Inst{13} = 0b0;
4041  }
4042
4043  let AddedComplexity = 10 in
4044  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
4045                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
4046                [(storeop (Ty regtype:$Rt),
4047                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
4048                                        ro_Xextend32:$extend))]>,
4049            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4050    let Inst{13} = 0b1;
4051  }
4052
4053  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4054}
4055
4056class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
4057                    dag outs, list<dag> pat>
4058    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
4059  bits<5> Rt;
4060  bits<5> Rn;
4061  bits<5> Rm;
4062  bits<2> extend;
4063  let Inst{31-30} = sz;
4064  let Inst{29-27} = 0b111;
4065  let Inst{26}    = V;
4066  let Inst{25-24} = 0b00;
4067  let Inst{23-22} = opc;
4068  let Inst{21}    = 1;
4069  let Inst{20-16} = Rm;
4070  let Inst{15}    = extend{1}; // sign extend Rm?
4071  let Inst{14}    = 1;
4072  let Inst{12}    = extend{0}; // do shift?
4073  let Inst{11-10} = 0b10;
4074  let Inst{9-5}   = Rn;
4075  let Inst{4-0}   = Rt;
4076}
4077
4078multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4079                    string asm, ValueType Ty, SDPatternOperator loadop> {
4080  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4081  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
4082                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4083                [(set (Ty regtype:$Rt),
4084                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4085                                             ro_Wextend64:$extend)))]>,
4086           Sched<[WriteLDIdx, ReadAdrBase]> {
4087    let Inst{13} = 0b0;
4088  }
4089
4090  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4091  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
4092                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4093                 [(set (Ty regtype:$Rt),
4094                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4095                                              ro_Xextend64:$extend)))]>,
4096           Sched<[WriteLDIdx, ReadAdrBase]> {
4097    let Inst{13} = 0b1;
4098  }
4099
4100  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4101}
4102
4103multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4104                     string asm, ValueType Ty, SDPatternOperator storeop> {
4105  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4106  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
4107                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4108                [(storeop (Ty regtype:$Rt),
4109                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4110                                         ro_Wextend64:$extend))]>,
4111            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4112    let Inst{13} = 0b0;
4113  }
4114
4115  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4116  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
4117                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4118                [(storeop (Ty regtype:$Rt),
4119                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4120                                         ro_Xextend64:$extend))]>,
4121            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4122    let Inst{13} = 0b1;
4123  }
4124
4125  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4126}
4127
4128class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
4129                     dag outs, list<dag> pat>
4130    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
4131  bits<5> Rt;
4132  bits<5> Rn;
4133  bits<5> Rm;
4134  bits<2> extend;
4135  let Inst{31-30} = sz;
4136  let Inst{29-27} = 0b111;
4137  let Inst{26}    = V;
4138  let Inst{25-24} = 0b00;
4139  let Inst{23-22} = opc;
4140  let Inst{21}    = 1;
4141  let Inst{20-16} = Rm;
4142  let Inst{15}    = extend{1}; // sign extend Rm?
4143  let Inst{14}    = 1;
4144  let Inst{12}    = extend{0}; // do shift?
4145  let Inst{11-10} = 0b10;
4146  let Inst{9-5}   = Rn;
4147  let Inst{4-0}   = Rt;
4148}
4149
4150multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4151                     string asm, ValueType Ty, SDPatternOperator loadop> {
4152  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4153  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4154                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4155                 [(set (Ty regtype:$Rt),
4156                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
4157                                               ro_Wextend128:$extend)))]>,
4158            Sched<[WriteLDIdx, ReadAdrBase]> {
4159    let Inst{13} = 0b0;
4160  }
4161
4162  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4163  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4164                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4165                 [(set (Ty regtype:$Rt),
4166                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
4167                                               ro_Xextend128:$extend)))]>,
4168            Sched<[WriteLDIdx, ReadAdrBase]> {
4169    let Inst{13} = 0b1;
4170  }
4171
4172  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4173}
4174
4175multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4176                      string asm> {
4177  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4178  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
4179               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4180                []>,
4181            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4182    let Inst{13} = 0b0;
4183  }
4184
4185  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4186  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
4187               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4188                []>,
4189            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4190    let Inst{13} = 0b1;
4191  }
4192
4193  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4194}
4195
4196let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4197class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
4198                     string asm, list<dag> pat>
4199    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
4200      Sched<[WriteLD]> {
4201  bits<5> Rt;
4202  bits<5> Rn;
4203  bits<5> Rm;
4204  bits<2> extend;
4205  let Inst{31-30} = sz;
4206  let Inst{29-27} = 0b111;
4207  let Inst{26}    = V;
4208  let Inst{25-24} = 0b00;
4209  let Inst{23-22} = opc;
4210  let Inst{21}    = 1;
4211  let Inst{20-16} = Rm;
4212  let Inst{15}    = extend{1}; // sign extend Rm?
4213  let Inst{14}    = 1;
4214  let Inst{12}    = extend{0}; // do shift?
4215  let Inst{11-10} = 0b10;
4216  let Inst{9-5}   = Rn;
4217  let Inst{4-0}   = Rt;
4218  let DecoderMethod = "DecodePRFMRegInstruction";
4219  // PRFM (reg) aliases with RPRFM added to the base A64 instruction set. When
4220  // the decoder method returns Fail, the decoder should attempt to decode the
4221  // instruction as RPRFM.
4222  let hasCompleteDecoder = 0;
4223}
4224
4225multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
4226  def roW : BasePrefetchRO<sz, V, opc, (outs),
4227                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4228                asm, [(AArch64Prefetch timm:$Rt,
4229                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4230                                                    ro_Wextend64:$extend))]> {
4231    let Inst{13} = 0b0;
4232  }
4233
4234  def roX : BasePrefetchRO<sz, V, opc, (outs),
4235                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4236                asm,  [(AArch64Prefetch timm:$Rt,
4237                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4238                                                     ro_Xextend64:$extend))]> {
4239    let Inst{13} = 0b1;
4240  }
4241
4242  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
4243               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
4244                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
4245}
4246
4247//---
4248// Load/store unscaled immediate
4249//---
4250
4251def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
4252def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
4253def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
4254def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
4255def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
4256
4257def gi_am_unscaled8 :
4258    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
4259    GIComplexPatternEquiv<am_unscaled8>;
4260def gi_am_unscaled16 :
4261    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
4262    GIComplexPatternEquiv<am_unscaled16>;
4263def gi_am_unscaled32 :
4264    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
4265    GIComplexPatternEquiv<am_unscaled32>;
4266def gi_am_unscaled64 :
4267    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
4268    GIComplexPatternEquiv<am_unscaled64>;
4269def gi_am_unscaled128 :
4270    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
4271    GIComplexPatternEquiv<am_unscaled128>;
4272
4273
4274class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4275                           string asm, list<dag> pattern>
4276    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
4277  bits<5> Rt;
4278  bits<5> Rn;
4279  bits<9> offset;
4280  let Inst{31-30} = sz;
4281  let Inst{29-27} = 0b111;
4282  let Inst{26}    = V;
4283  let Inst{25-24} = 0b00;
4284  let Inst{23-22} = opc;
4285  let Inst{21}    = 0;
4286  let Inst{20-12} = offset;
4287  let Inst{11-10} = 0b00;
4288  let Inst{9-5}   = Rn;
4289  let Inst{4-0}   = Rt;
4290
4291  let DecoderMethod = "DecodeSignedLdStInstruction";
4292}
4293
4294// Armv8.4 LDAPR & STLR with Immediate Offset instruction
4295multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4296                              DAGOperand regtype > {
4297  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
4298                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
4299          Sched<[WriteST]> {
4300    let Inst{29} = 0;
4301    let Inst{24} = 1;
4302  }
4303  def : InstAlias<asm # "\t$Rt, [$Rn]",
4304                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4305}
4306
4307multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4308                               DAGOperand regtype > {
4309  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
4310                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4311                               asm, []>,
4312          Sched<[WriteST]> {
4313    let Inst{29} = 0;
4314    let Inst{24} = 1;
4315  }
4316  def : InstAlias<asm # "\t$Rt, [$Rn]",
4317                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4318}
4319
4320multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4321                   string asm, list<dag> pattern> {
4322  let AddedComplexity = 1 in // try this before LoadUI
4323  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
4324                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
4325          Sched<[WriteLD]>;
4326
4327  def : InstAlias<asm # "\t$Rt, [$Rn]",
4328                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4329}
4330
4331multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4332                         string asm, list<dag> pattern> {
4333  let AddedComplexity = 1 in // try this before StoreUI
4334  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4335                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4336                               asm, pattern>,
4337          Sched<[WriteST]>;
4338
4339  def : InstAlias<asm # "\t$Rt, [$Rn]",
4340                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4341}
4342
4343multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
4344                            list<dag> pat> {
4345  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4346  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4347                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
4348                               asm, pat>,
4349          Sched<[WriteLD]>;
4350
4351  def : InstAlias<asm # "\t$Rt, [$Rn]",
4352                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
4353}
4354
4355//---
4356// Load/store unscaled immediate, unprivileged
4357//---
4358
4359class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4360                                dag oops, dag iops, string asm>
4361    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
4362  bits<5> Rt;
4363  bits<5> Rn;
4364  bits<9> offset;
4365  let Inst{31-30} = sz;
4366  let Inst{29-27} = 0b111;
4367  let Inst{26}    = V;
4368  let Inst{25-24} = 0b00;
4369  let Inst{23-22} = opc;
4370  let Inst{21}    = 0;
4371  let Inst{20-12} = offset;
4372  let Inst{11-10} = 0b10;
4373  let Inst{9-5}   = Rn;
4374  let Inst{4-0}   = Rt;
4375
4376  let DecoderMethod = "DecodeSignedLdStInstruction";
4377}
4378
4379multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4380                            RegisterClass regtype, string asm> {
4381  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4382  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4383                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4384          Sched<[WriteLD]>;
4385
4386  def : InstAlias<asm # "\t$Rt, [$Rn]",
4387                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4388}
4389
4390multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4391                             RegisterClass regtype, string asm> {
4392  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4393  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4394                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4395                                 asm>,
4396          Sched<[WriteST]>;
4397
4398  def : InstAlias<asm # "\t$Rt, [$Rn]",
4399                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4400}
4401
4402//---
4403// Load/store pre-indexed
4404//---
4405
4406class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4407                          string asm, string cstr, list<dag> pat>
4408    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4409  bits<5> Rt;
4410  bits<5> Rn;
4411  bits<9> offset;
4412  let Inst{31-30} = sz;
4413  let Inst{29-27} = 0b111;
4414  let Inst{26}    = V;
4415  let Inst{25-24} = 0;
4416  let Inst{23-22} = opc;
4417  let Inst{21}    = 0;
4418  let Inst{20-12} = offset;
4419  let Inst{11-10} = 0b11;
4420  let Inst{9-5}   = Rn;
4421  let Inst{4-0}   = Rt;
4422
4423  let DecoderMethod = "DecodeSignedLdStInstruction";
4424}
4425
4426let hasSideEffects = 0 in {
4427let mayStore = 0, mayLoad = 1 in
4428class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4429             string asm>
4430    : BaseLoadStorePreIdx<sz, V, opc,
4431                     (outs GPR64sp:$wback, regtype:$Rt),
4432                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4433                     "$Rn = $wback,@earlyclobber $wback", []>,
4434      Sched<[WriteAdr, WriteLD]>;
4435
4436let mayStore = 1, mayLoad = 0 in
4437class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4438                  string asm, SDPatternOperator storeop, ValueType Ty>
4439    : BaseLoadStorePreIdx<sz, V, opc,
4440                      (outs GPR64sp:$wback),
4441                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4442                      asm, "$Rn = $wback,@earlyclobber $wback",
4443      [(set GPR64sp:$wback,
4444            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4445      Sched<[WriteAdr, WriteST]>;
4446} // hasSideEffects = 0
4447
4448//---
4449// Load/store post-indexed
4450//---
4451
4452class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4453                          string asm, string cstr, list<dag> pat>
4454    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4455  bits<5> Rt;
4456  bits<5> Rn;
4457  bits<9> offset;
4458  let Inst{31-30} = sz;
4459  let Inst{29-27} = 0b111;
4460  let Inst{26}    = V;
4461  let Inst{25-24} = 0b00;
4462  let Inst{23-22} = opc;
4463  let Inst{21}    = 0b0;
4464  let Inst{20-12} = offset;
4465  let Inst{11-10} = 0b01;
4466  let Inst{9-5}   = Rn;
4467  let Inst{4-0}   = Rt;
4468
4469  let DecoderMethod = "DecodeSignedLdStInstruction";
4470}
4471
4472let hasSideEffects = 0 in {
4473let mayStore = 0, mayLoad = 1 in
4474class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4475             string asm>
4476    : BaseLoadStorePostIdx<sz, V, opc,
4477                      (outs GPR64sp:$wback, regtype:$Rt),
4478                      (ins GPR64sp:$Rn, simm9:$offset),
4479                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4480      Sched<[WriteAdr, WriteLD]>;
4481
4482let mayStore = 1, mayLoad = 0 in
4483class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4484                   string asm, SDPatternOperator storeop, ValueType Ty>
4485    : BaseLoadStorePostIdx<sz, V, opc,
4486                      (outs GPR64sp:$wback),
4487                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4488                       asm, "$Rn = $wback,@earlyclobber $wback",
4489      [(set GPR64sp:$wback,
4490            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4491    Sched<[WriteAdr, WriteST]>;
4492} // hasSideEffects = 0
4493
4494
4495//---
4496// Load/store pair
4497//---
4498
4499// (indexed, offset)
4500
4501class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4502                              string asm>
4503    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4504  bits<5> Rt;
4505  bits<5> Rt2;
4506  bits<5> Rn;
4507  bits<7> offset;
4508  let Inst{31-30} = opc;
4509  let Inst{29-27} = 0b101;
4510  let Inst{26}    = V;
4511  let Inst{25-23} = 0b010;
4512  let Inst{22}    = L;
4513  let Inst{21-15} = offset;
4514  let Inst{14-10} = Rt2;
4515  let Inst{9-5}   = Rn;
4516  let Inst{4-0}   = Rt;
4517
4518  let DecoderMethod = "DecodePairLdStInstruction";
4519}
4520
4521multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4522                          Operand indextype, string asm> {
4523  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4524  def i : BaseLoadStorePairOffset<opc, V, 1,
4525                                  (outs regtype:$Rt, regtype:$Rt2),
4526                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4527          Sched<[WriteLD, WriteLDHi]>;
4528
4529  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4530                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4531                                                  GPR64sp:$Rn, 0)>;
4532}
4533
4534
4535multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4536                           Operand indextype, string asm> {
4537  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4538  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4539                                  (ins regtype:$Rt, regtype:$Rt2,
4540                                       GPR64sp:$Rn, indextype:$offset),
4541                                  asm>,
4542          Sched<[WriteSTP]>;
4543
4544  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4545                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4546                                                  GPR64sp:$Rn, 0)>;
4547}
4548
4549// (pre-indexed)
4550class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4551                              string asm>
4552    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4553  bits<5> Rt;
4554  bits<5> Rt2;
4555  bits<5> Rn;
4556  bits<7> offset;
4557  let Inst{31-30} = opc;
4558  let Inst{29-27} = 0b101;
4559  let Inst{26}    = V;
4560  let Inst{25-23} = 0b011;
4561  let Inst{22}    = L;
4562  let Inst{21-15} = offset;
4563  let Inst{14-10} = Rt2;
4564  let Inst{9-5}   = Rn;
4565  let Inst{4-0}   = Rt;
4566
4567  let DecoderMethod = "DecodePairLdStInstruction";
4568}
4569
4570let hasSideEffects = 0 in {
4571let mayStore = 0, mayLoad = 1 in
4572class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4573                     Operand indextype, string asm>
4574    : BaseLoadStorePairPreIdx<opc, V, 1,
4575                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4576                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4577      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4578
4579let mayStore = 1, mayLoad = 0 in
4580class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4581                      Operand indextype, string asm>
4582    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4583                             (ins regtype:$Rt, regtype:$Rt2,
4584                                  GPR64sp:$Rn, indextype:$offset),
4585                             asm>,
4586      Sched<[WriteAdr, WriteSTP]>;
4587} // hasSideEffects = 0
4588
4589// (post-indexed)
4590
4591class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4592                              string asm>
4593    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4594  bits<5> Rt;
4595  bits<5> Rt2;
4596  bits<5> Rn;
4597  bits<7> offset;
4598  let Inst{31-30} = opc;
4599  let Inst{29-27} = 0b101;
4600  let Inst{26}    = V;
4601  let Inst{25-23} = 0b001;
4602  let Inst{22}    = L;
4603  let Inst{21-15} = offset;
4604  let Inst{14-10} = Rt2;
4605  let Inst{9-5}   = Rn;
4606  let Inst{4-0}   = Rt;
4607
4608  let DecoderMethod = "DecodePairLdStInstruction";
4609}
4610
4611let hasSideEffects = 0 in {
4612let mayStore = 0, mayLoad = 1 in
4613class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4614                      Operand idxtype, string asm>
4615    : BaseLoadStorePairPostIdx<opc, V, 1,
4616                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4617                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4618      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4619
4620let mayStore = 1, mayLoad = 0 in
4621class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4622                       Operand idxtype, string asm>
4623    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4624                             (ins regtype:$Rt, regtype:$Rt2,
4625                                  GPR64sp:$Rn, idxtype:$offset),
4626                             asm>,
4627      Sched<[WriteAdr, WriteSTP]>;
4628} // hasSideEffects = 0
4629
4630//  (no-allocate)
4631
4632class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4633                              string asm>
4634    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4635  bits<5> Rt;
4636  bits<5> Rt2;
4637  bits<5> Rn;
4638  bits<7> offset;
4639  let Inst{31-30} = opc;
4640  let Inst{29-27} = 0b101;
4641  let Inst{26}    = V;
4642  let Inst{25-23} = 0b000;
4643  let Inst{22}    = L;
4644  let Inst{21-15} = offset;
4645  let Inst{14-10} = Rt2;
4646  let Inst{9-5}   = Rn;
4647  let Inst{4-0}   = Rt;
4648
4649  let DecoderMethod = "DecodePairLdStInstruction";
4650}
4651
4652multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4653                           Operand indextype, string asm> {
4654  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4655  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4656                                   (outs regtype:$Rt, regtype:$Rt2),
4657                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4658          Sched<[WriteLD, WriteLDHi]>;
4659
4660
4661  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4662                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4663                                                  GPR64sp:$Rn, 0)>;
4664}
4665
4666multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4667                      Operand indextype, string asm> {
4668  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4669  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4670                                   (ins regtype:$Rt, regtype:$Rt2,
4671                                        GPR64sp:$Rn, indextype:$offset),
4672                                   asm>,
4673          Sched<[WriteSTP]>;
4674
4675  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4676                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4677                                                  GPR64sp:$Rn, 0)>;
4678}
4679
4680//---
4681// Load/store exclusive
4682//---
4683
4684// True exclusive operations write to and/or read from the system's exclusive
4685// monitors, which as far as a compiler is concerned can be modelled as a
4686// random shared memory address. Hence LoadExclusive mayStore.
4687//
4688// Since these instructions have the undefined register bits set to 1 in
4689// their canonical form, we need a post encoder method to set those bits
4690// to 1 when encoding these instructions. We do this using the
4691// fixLoadStoreExclusive function. This function has template parameters:
4692//
4693// fixLoadStoreExclusive<int hasRs, int hasRt2>
4694//
4695// hasRs indicates that the instruction uses the Rs field, so we won't set
4696// it to 1 (and the same for Rt2). We don't need template parameters for
4697// the other register fields since Rt and Rn are always used.
4698//
4699let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4700class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4701                             dag oops, dag iops, string asm, string operands>
4702    : I<oops, iops, asm, operands, "", []> {
4703  let Inst{31-30} = sz;
4704  let Inst{29-24} = 0b001000;
4705  let Inst{23}    = o2;
4706  let Inst{22}    = L;
4707  let Inst{21}    = o1;
4708  let Inst{15}    = o0;
4709
4710  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4711}
4712
4713// Neither Rs nor Rt2 operands.
4714class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4715                               dag oops, dag iops, string asm, string operands>
4716    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4717  bits<5> Rt;
4718  bits<5> Rn;
4719  let Inst{20-16} = 0b11111;
4720  let Unpredictable{20-16} = 0b11111;
4721  let Inst{14-10} = 0b11111;
4722  let Unpredictable{14-10} = 0b11111;
4723  let Inst{9-5} = Rn;
4724  let Inst{4-0} = Rt;
4725
4726  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4727}
4728
4729// Simple load acquires don't set the exclusive monitor
4730let mayLoad = 1, mayStore = 0 in
4731class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4732                  RegisterClass regtype, string asm>
4733    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4734                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4735      Sched<[WriteLD]>;
4736
4737class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4738                    RegisterClass regtype, string asm>
4739    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4740                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4741      Sched<[WriteLD]>;
4742
4743class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4744                       RegisterClass regtype, string asm>
4745    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4746                             (outs regtype:$Rt, regtype:$Rt2),
4747                             (ins GPR64sp0:$Rn), asm,
4748                             "\t$Rt, $Rt2, [$Rn]">,
4749      Sched<[WriteLD, WriteLDHi]> {
4750  bits<5> Rt;
4751  bits<5> Rt2;
4752  bits<5> Rn;
4753  let Inst{14-10} = Rt2;
4754  let Inst{9-5} = Rn;
4755  let Inst{4-0} = Rt;
4756
4757  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4758}
4759
4760// Simple store release operations do not check the exclusive monitor.
4761let mayLoad = 0, mayStore = 1 in
4762class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4763                   RegisterClass regtype, string asm>
4764    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4765                               (ins regtype:$Rt, GPR64sp:$Rn),
4766                               asm, "\t$Rt, [$Rn]">,
4767      Sched<[WriteST]>;
4768
4769let mayLoad = 1, mayStore = 1 in
4770class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4771                     RegisterClass regtype, string asm>
4772    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4773                             (ins regtype:$Rt, GPR64sp0:$Rn),
4774                             asm, "\t$Ws, $Rt, [$Rn]">,
4775      Sched<[WriteSTX]> {
4776  bits<5> Ws;
4777  bits<5> Rt;
4778  bits<5> Rn;
4779  let Inst{20-16} = Ws;
4780  let Inst{9-5} = Rn;
4781  let Inst{4-0} = Rt;
4782
4783  let Constraints = "@earlyclobber $Ws";
4784  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4785}
4786
4787class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4788                         RegisterClass regtype, string asm>
4789    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4790                             (outs GPR32:$Ws),
4791                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4792                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4793      Sched<[WriteSTX]> {
4794  bits<5> Ws;
4795  bits<5> Rt;
4796  bits<5> Rt2;
4797  bits<5> Rn;
4798  let Inst{20-16} = Ws;
4799  let Inst{14-10} = Rt2;
4800  let Inst{9-5} = Rn;
4801  let Inst{4-0} = Rt;
4802
4803  let Constraints = "@earlyclobber $Ws";
4804}
4805
4806// Armv8.5-A Memory Tagging Extension
4807class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4808                 string asm_opnds, string cstr, dag oops, dag iops>
4809    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4810      Sched<[]> {
4811  bits<5> Rn;
4812
4813  let Inst{31-24} = 0b11011001;
4814  let Inst{23-22} = opc1;
4815  let Inst{21}    = 1;
4816  // Inst{20-12} defined by subclass
4817  let Inst{11-10} = opc2;
4818  let Inst{9-5}   = Rn;
4819  // Inst{4-0} defined by subclass
4820}
4821
4822class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4823                   dag oops, dag iops>
4824    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4825                  "", oops, iops> {
4826  bits<5> Rt;
4827
4828  let Inst{20-12} = 0b000000000;
4829  let Inst{4-0}   = Rt;
4830
4831  let mayLoad = Load;
4832}
4833
4834class MemTagLoad<string asm_insn, string asm_opnds>
4835    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4836                 (outs GPR64:$wback),
4837                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4838  bits<5> Rt;
4839  bits<9> offset;
4840
4841  let Inst{20-12} = offset;
4842  let Inst{4-0}   = Rt;
4843
4844  let mayLoad = 1;
4845}
4846
4847class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4848                     string asm_opnds, string cstr, dag oops, dag iops>
4849    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4850  bits<5> Rt;
4851  bits<9> offset;
4852
4853  let Inst{20-12} = offset;
4854  let Inst{4-0}   = Rt;
4855
4856  let mayStore = 1;
4857}
4858
4859multiclass MemTagStore<bits<2> opc1, string insn> {
4860  def i :
4861    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4862                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4863  def PreIndex :
4864    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4865                    "$Rn = $wback",
4866                    (outs GPR64sp:$wback),
4867                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4868  def PostIndex :
4869    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4870                    "$Rn = $wback",
4871                    (outs GPR64sp:$wback),
4872                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4873
4874  def : InstAlias<insn # "\t$Rt, [$Rn]",
4875                  (!cast<Instruction>(NAME # "i") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4876}
4877
4878//---
4879// Exception generation
4880//---
4881
4882let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4883class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm,
4884                          list<dag> pattern = []>
4885    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", pattern>,
4886      Sched<[WriteSys]> {
4887  bits<16> imm;
4888  let Inst{31-24} = 0b11010100;
4889  let Inst{23-21} = op1;
4890  let Inst{20-5}  = imm;
4891  let Inst{4-2}   = 0b000;
4892  let Inst{1-0}   = ll;
4893}
4894
4895//---
4896// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4897//--
4898let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4899class UDFType<bits<16> opc, string asm>
4900  : I<(outs), (ins uimm16:$imm),
4901       asm, "\t$imm", "", []>,
4902    Sched<[]> {
4903  bits<16> imm;
4904  let Inst{31-16} = opc;
4905  let Inst{15-0} = imm;
4906}
4907}
4908let Predicates = [HasFPARMv8] in {
4909
4910//---
4911// Floating point to integer conversion
4912//---
4913
4914let mayRaiseFPException = 1, Uses = [FPCR] in
4915class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4916                      RegisterClass srcType, RegisterClass dstType,
4917                      string asm, list<dag> pattern>
4918    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4919         asm, "\t$Rd, $Rn", "", pattern>,
4920      Sched<[WriteFCvt]> {
4921  bits<5> Rd;
4922  bits<5> Rn;
4923  let Inst{30-29} = 0b00;
4924  let Inst{28-24} = 0b11110;
4925  let Inst{23-22} = type;
4926  let Inst{21}    = 1;
4927  let Inst{20-19} = rmode;
4928  let Inst{18-16} = opcode;
4929  let Inst{15-10} = 0;
4930  let Inst{9-5}   = Rn;
4931  let Inst{4-0}   = Rd;
4932}
4933
4934let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
4935class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4936                      RegisterClass srcType, RegisterClass dstType,
4937                      Operand immType, string asm, list<dag> pattern>
4938    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4939         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4940      Sched<[WriteFCvt]> {
4941  bits<5> Rd;
4942  bits<5> Rn;
4943  bits<6> scale;
4944  let Inst{30-29} = 0b00;
4945  let Inst{28-24} = 0b11110;
4946  let Inst{23-22} = type;
4947  let Inst{21}    = 0;
4948  let Inst{20-19} = rmode;
4949  let Inst{18-16} = opcode;
4950  let Inst{15-10} = scale;
4951  let Inst{9-5}   = Rn;
4952  let Inst{4-0}   = Rd;
4953}
4954
4955multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4956           SDPatternOperator OpN> {
4957  // Unscaled half-precision to 32-bit
4958  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4959                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4960    let Inst{31} = 0; // 32-bit GPR flag
4961    let Predicates = [HasFullFP16];
4962  }
4963
4964  // Unscaled half-precision to 64-bit
4965  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4966                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4967    let Inst{31} = 1; // 64-bit GPR flag
4968    let Predicates = [HasFullFP16];
4969  }
4970
4971  // Unscaled single-precision to 32-bit
4972  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4973                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4974    let Inst{31} = 0; // 32-bit GPR flag
4975  }
4976
4977  // Unscaled single-precision to 64-bit
4978  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4979                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4980    let Inst{31} = 1; // 64-bit GPR flag
4981  }
4982
4983  // Unscaled double-precision to 32-bit
4984  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4985                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4986    let Inst{31} = 0; // 32-bit GPR flag
4987  }
4988
4989  // Unscaled double-precision to 64-bit
4990  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4991                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4992    let Inst{31} = 1; // 64-bit GPR flag
4993  }
4994}
4995
4996multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4997                             SDPatternOperator OpN> {
4998  // Scaled half-precision to 32-bit
4999  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
5000                              fixedpoint_f16_i32, asm,
5001              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
5002                                          fixedpoint_f16_i32:$scale)))]> {
5003    let Inst{31} = 0; // 32-bit GPR flag
5004    let scale{5} = 1;
5005    let Predicates = [HasFullFP16];
5006  }
5007
5008  // Scaled half-precision to 64-bit
5009  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
5010                              fixedpoint_f16_i64, asm,
5011              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
5012                                          fixedpoint_f16_i64:$scale)))]> {
5013    let Inst{31} = 1; // 64-bit GPR flag
5014    let Predicates = [HasFullFP16];
5015  }
5016
5017  // Scaled single-precision to 32-bit
5018  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
5019                              fixedpoint_f32_i32, asm,
5020              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
5021                                          fixedpoint_f32_i32:$scale)))]> {
5022    let Inst{31} = 0; // 32-bit GPR flag
5023    let scale{5} = 1;
5024  }
5025
5026  // Scaled single-precision to 64-bit
5027  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
5028                              fixedpoint_f32_i64, asm,
5029              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
5030                                          fixedpoint_f32_i64:$scale)))]> {
5031    let Inst{31} = 1; // 64-bit GPR flag
5032  }
5033
5034  // Scaled double-precision to 32-bit
5035  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
5036                              fixedpoint_f64_i32, asm,
5037              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
5038                                          fixedpoint_f64_i32:$scale)))]> {
5039    let Inst{31} = 0; // 32-bit GPR flag
5040    let scale{5} = 1;
5041  }
5042
5043  // Scaled double-precision to 64-bit
5044  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
5045                              fixedpoint_f64_i64, asm,
5046              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
5047                                          fixedpoint_f64_i64:$scale)))]> {
5048    let Inst{31} = 1; // 64-bit GPR flag
5049  }
5050}
5051
5052//---
5053// Integer to floating point conversion
5054//---
5055
5056let mayStore = 0, mayLoad = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5057class BaseIntegerToFP<bit isUnsigned,
5058                      RegisterClass srcType, RegisterClass dstType,
5059                      Operand immType, string asm, list<dag> pattern>
5060    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
5061         asm, "\t$Rd, $Rn, $scale", "", pattern>,
5062      Sched<[WriteFCvt]> {
5063  bits<5> Rd;
5064  bits<5> Rn;
5065  bits<6> scale;
5066  let Inst{30-24} = 0b0011110;
5067  let Inst{21-17} = 0b00001;
5068  let Inst{16}    = isUnsigned;
5069  let Inst{15-10} = scale;
5070  let Inst{9-5}   = Rn;
5071  let Inst{4-0}   = Rd;
5072}
5073
5074let mayRaiseFPException = 1, Uses = [FPCR] in
5075class BaseIntegerToFPUnscaled<bit isUnsigned,
5076                      RegisterClass srcType, RegisterClass dstType,
5077                      ValueType dvt, string asm, SDPatternOperator node>
5078    : I<(outs dstType:$Rd), (ins srcType:$Rn),
5079         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
5080      Sched<[WriteFCvt]> {
5081  bits<5> Rd;
5082  bits<5> Rn;
5083  bits<6> scale;
5084  let Inst{30-24} = 0b0011110;
5085  let Inst{21-17} = 0b10001;
5086  let Inst{16}    = isUnsigned;
5087  let Inst{15-10} = 0b000000;
5088  let Inst{9-5}   = Rn;
5089  let Inst{4-0}   = Rd;
5090}
5091
5092multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
5093  // Unscaled
5094  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
5095    let Inst{31} = 0; // 32-bit GPR flag
5096    let Inst{23-22} = 0b11; // 16-bit FPR flag
5097    let Predicates = [HasFullFP16];
5098  }
5099
5100  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
5101    let Inst{31} = 0; // 32-bit GPR flag
5102    let Inst{23-22} = 0b00; // 32-bit FPR flag
5103  }
5104
5105  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
5106    let Inst{31} = 0; // 32-bit GPR flag
5107    let Inst{23-22} = 0b01; // 64-bit FPR flag
5108  }
5109
5110  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
5111    let Inst{31} = 1; // 64-bit GPR flag
5112    let Inst{23-22} = 0b11; // 16-bit FPR flag
5113    let Predicates = [HasFullFP16];
5114  }
5115
5116  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
5117    let Inst{31} = 1; // 64-bit GPR flag
5118    let Inst{23-22} = 0b00; // 32-bit FPR flag
5119  }
5120
5121  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
5122    let Inst{31} = 1; // 64-bit GPR flag
5123    let Inst{23-22} = 0b01; // 64-bit FPR flag
5124  }
5125
5126  // Scaled
5127  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_recip_f16_i32, asm,
5128                             [(set (f16 FPR16:$Rd),
5129                                   (fmul (node GPR32:$Rn),
5130                                         fixedpoint_recip_f16_i32:$scale))]> {
5131    let Inst{31} = 0; // 32-bit GPR flag
5132    let Inst{23-22} = 0b11; // 16-bit FPR flag
5133    let scale{5} = 1;
5134    let Predicates = [HasFullFP16];
5135  }
5136
5137  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_recip_f32_i32, asm,
5138                             [(set FPR32:$Rd,
5139                                   (fmul (node GPR32:$Rn),
5140                                         fixedpoint_recip_f32_i32:$scale))]> {
5141    let Inst{31} = 0; // 32-bit GPR flag
5142    let Inst{23-22} = 0b00; // 32-bit FPR flag
5143    let scale{5} = 1;
5144  }
5145
5146  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_recip_f64_i32, asm,
5147                             [(set FPR64:$Rd,
5148                                   (fmul (node GPR32:$Rn),
5149                                         fixedpoint_recip_f64_i32:$scale))]> {
5150    let Inst{31} = 0; // 32-bit GPR flag
5151    let Inst{23-22} = 0b01; // 64-bit FPR flag
5152    let scale{5} = 1;
5153  }
5154
5155  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_recip_f16_i64, asm,
5156                             [(set (f16 FPR16:$Rd),
5157                                   (fmul (node GPR64:$Rn),
5158                                         fixedpoint_recip_f16_i64:$scale))]> {
5159    let Inst{31} = 1; // 64-bit GPR flag
5160    let Inst{23-22} = 0b11; // 16-bit FPR flag
5161    let Predicates = [HasFullFP16];
5162  }
5163
5164  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_recip_f32_i64, asm,
5165                             [(set FPR32:$Rd,
5166                                   (fmul (node GPR64:$Rn),
5167                                         fixedpoint_recip_f32_i64:$scale))]> {
5168    let Inst{31} = 1; // 64-bit GPR flag
5169    let Inst{23-22} = 0b00; // 32-bit FPR flag
5170  }
5171
5172  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_recip_f64_i64, asm,
5173                             [(set FPR64:$Rd,
5174                                   (fmul (node GPR64:$Rn),
5175                                         fixedpoint_recip_f64_i64:$scale))]> {
5176    let Inst{31} = 1; // 64-bit GPR flag
5177    let Inst{23-22} = 0b01; // 64-bit FPR flag
5178  }
5179}
5180
5181//---
5182// Unscaled integer <-> floating point conversion (i.e. FMOV)
5183//---
5184
5185let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5186class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
5187                      RegisterClass srcType, RegisterClass dstType,
5188                      string asm>
5189    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
5190        // We use COPY_TO_REGCLASS for these bitconvert operations.
5191        // copyPhysReg() expands the resultant COPY instructions after
5192        // regalloc is done. This gives greater freedom for the allocator
5193        // and related passes (coalescing, copy propagation, et. al.) to
5194        // be more effective.
5195        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
5196      Sched<[WriteFCopy]> {
5197  bits<5> Rd;
5198  bits<5> Rn;
5199  let Inst{30-24} = 0b0011110;
5200  let Inst{21}    = 1;
5201  let Inst{20-19} = rmode;
5202  let Inst{18-16} = opcode;
5203  let Inst{15-10} = 0b000000;
5204  let Inst{9-5}   = Rn;
5205  let Inst{4-0}   = Rd;
5206}
5207
5208let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5209class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
5210                     RegisterClass srcType, RegisterOperand dstType, string asm,
5211                     string kind>
5212    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5213        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
5214      Sched<[WriteFCopy]> {
5215  bits<5> Rd;
5216  bits<5> Rn;
5217  let Inst{30-23} = 0b00111101;
5218  let Inst{21}    = 1;
5219  let Inst{20-19} = rmode;
5220  let Inst{18-16} = opcode;
5221  let Inst{15-10} = 0b000000;
5222  let Inst{9-5}   = Rn;
5223  let Inst{4-0}   = Rd;
5224
5225  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5226}
5227
5228let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5229class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
5230                     RegisterOperand srcType, RegisterClass dstType, string asm,
5231                     string kind>
5232    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5233        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
5234      Sched<[WriteFCopy]> {
5235  bits<5> Rd;
5236  bits<5> Rn;
5237  let Inst{30-23} = 0b00111101;
5238  let Inst{21}    = 1;
5239  let Inst{20-19} = rmode;
5240  let Inst{18-16} = opcode;
5241  let Inst{15-10} = 0b000000;
5242  let Inst{9-5}   = Rn;
5243  let Inst{4-0}   = Rd;
5244
5245  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5246}
5247
5248
5249multiclass UnscaledConversion<string asm> {
5250  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
5251    let Inst{31} = 0; // 32-bit GPR flag
5252    let Inst{23-22} = 0b11; // 16-bit FPR flag
5253    let Predicates = [HasFullFP16];
5254  }
5255
5256  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
5257    let Inst{31} = 1; // 64-bit GPR flag
5258    let Inst{23-22} = 0b11; // 16-bit FPR flag
5259    let Predicates = [HasFullFP16];
5260  }
5261
5262  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
5263    let Inst{31} = 0; // 32-bit GPR flag
5264    let Inst{23-22} = 0b00; // 32-bit FPR flag
5265  }
5266
5267  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
5268    let Inst{31} = 1; // 64-bit GPR flag
5269    let Inst{23-22} = 0b01; // 64-bit FPR flag
5270  }
5271
5272  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
5273    let Inst{31} = 0; // 32-bit GPR flag
5274    let Inst{23-22} = 0b11; // 16-bit FPR flag
5275    let Predicates = [HasFullFP16];
5276  }
5277
5278  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
5279    let Inst{31} = 1; // 64-bit GPR flag
5280    let Inst{23-22} = 0b11; // 16-bit FPR flag
5281    let Predicates = [HasFullFP16];
5282  }
5283
5284  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
5285    let Inst{31} = 0; // 32-bit GPR flag
5286    let Inst{23-22} = 0b00; // 32-bit FPR flag
5287  }
5288
5289  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
5290    let Inst{31} = 1; // 64-bit GPR flag
5291    let Inst{23-22} = 0b01; // 64-bit FPR flag
5292  }
5293
5294  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
5295                                             asm, ".d"> {
5296    let Inst{31} = 1;
5297    let Inst{22} = 0;
5298  }
5299
5300  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
5301                                               asm, ".d"> {
5302    let Inst{31} = 1;
5303    let Inst{22} = 0;
5304  }
5305}
5306
5307//---
5308// Floating point conversion
5309//---
5310
5311let mayRaiseFPException = 1, Uses = [FPCR] in
5312class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
5313                       RegisterClass srcType, string asm, list<dag> pattern>
5314    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
5315      Sched<[WriteFCvt]> {
5316  bits<5> Rd;
5317  bits<5> Rn;
5318  let Inst{31-24} = 0b00011110;
5319  let Inst{23-22} = type;
5320  let Inst{21-17} = 0b10001;
5321  let Inst{16-15} = opcode;
5322  let Inst{14-10} = 0b10000;
5323  let Inst{9-5}   = Rn;
5324  let Inst{4-0}   = Rd;
5325}
5326
5327multiclass FPConversion<string asm> {
5328  // Double-precision to Half-precision
5329  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
5330                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
5331
5332  // Double-precision to Single-precision
5333  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
5334                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
5335
5336  // Half-precision to Double-precision
5337  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
5338                             [(set FPR64:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5339
5340  // Half-precision to Single-precision
5341  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
5342                             [(set FPR32:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5343
5344  // Single-precision to Double-precision
5345  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
5346                             [(set FPR64:$Rd, (any_fpextend FPR32:$Rn))]>;
5347
5348  // Single-precision to Half-precision
5349  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
5350                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
5351}
5352
5353//---
5354// Single operand floating point data processing
5355//---
5356
5357let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5358class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
5359                              ValueType vt, string asm, SDPatternOperator node>
5360    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
5361         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
5362      Sched<[WriteF]> {
5363  bits<5> Rd;
5364  bits<5> Rn;
5365  let Inst{31-24} = 0b00011110;
5366  let Inst{21}    = 0b1;
5367  let Inst{20-15} = opcode;
5368  let Inst{14-10} = 0b10000;
5369  let Inst{9-5}   = Rn;
5370  let Inst{4-0}   = Rd;
5371}
5372
5373multiclass SingleOperandFPData<bits<4> opcode, string asm,
5374                               SDPatternOperator node = null_frag,
5375                               int fpexceptions = 1> {
5376  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
5377  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5378    let Inst{23-22} = 0b11; // 16-bit size flag
5379    let Predicates = [HasFullFP16];
5380  }
5381
5382  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5383    let Inst{23-22} = 0b00; // 32-bit size flag
5384  }
5385
5386  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5387    let Inst{23-22} = 0b01; // 64-bit size flag
5388  }
5389  }
5390}
5391
5392multiclass SingleOperandFPDataNoException<bits<4> opcode, string asm,
5393                                       SDPatternOperator node = null_frag>
5394    : SingleOperandFPData<opcode, asm, node, 0>;
5395
5396let mayRaiseFPException = 1, Uses = [FPCR] in
5397multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5398                  SDPatternOperator node = null_frag>{
5399
5400  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5401    let Inst{23-22} = 0b00; // 32-bit registers
5402  }
5403
5404  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5405    let Inst{23-22} = 0b01; // 64-bit registers
5406  }
5407}
5408
5409// FRInt[32|64][Z|N] instructions
5410multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5411      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5412
5413//---
5414// Two operand floating point data processing
5415//---
5416
5417let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5418class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5419                           string asm, list<dag> pat>
5420    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5421         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5422      Sched<[WriteF]> {
5423  bits<5> Rd;
5424  bits<5> Rn;
5425  bits<5> Rm;
5426  let Inst{31-24} = 0b00011110;
5427  let Inst{21}    = 1;
5428  let Inst{20-16} = Rm;
5429  let Inst{15-12} = opcode;
5430  let Inst{11-10} = 0b10;
5431  let Inst{9-5}   = Rn;
5432  let Inst{4-0}   = Rd;
5433}
5434
5435multiclass TwoOperandFPData<bits<4> opcode, string asm,
5436                            SDPatternOperator node = null_frag> {
5437  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5438                         [(set (f16 FPR16:$Rd),
5439                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5440    let Inst{23-22} = 0b11; // 16-bit size flag
5441    let Predicates = [HasFullFP16];
5442  }
5443
5444  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5445                         [(set (f32 FPR32:$Rd),
5446                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5447    let Inst{23-22} = 0b00; // 32-bit size flag
5448  }
5449
5450  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5451                         [(set (f64 FPR64:$Rd),
5452                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5453    let Inst{23-22} = 0b01; // 64-bit size flag
5454  }
5455}
5456
5457multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm,
5458                               SDPatternOperator node> {
5459  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5460                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5461    let Inst{23-22} = 0b11; // 16-bit size flag
5462    let Predicates = [HasFullFP16];
5463  }
5464
5465  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5466                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5467    let Inst{23-22} = 0b00; // 32-bit size flag
5468  }
5469
5470  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5471                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5472    let Inst{23-22} = 0b01; // 64-bit size flag
5473  }
5474}
5475
5476
5477//---
5478// Three operand floating point data processing
5479//---
5480
5481let mayRaiseFPException = 1, Uses = [FPCR] in
5482class BaseThreeOperandFPData<bit isNegated, bit isSub,
5483                             RegisterClass regtype, string asm, list<dag> pat>
5484    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5485         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5486      Sched<[WriteFMul]> {
5487  bits<5> Rd;
5488  bits<5> Rn;
5489  bits<5> Rm;
5490  bits<5> Ra;
5491  let Inst{31-24} = 0b00011111;
5492  let Inst{21}    = isNegated;
5493  let Inst{20-16} = Rm;
5494  let Inst{15}    = isSub;
5495  let Inst{14-10} = Ra;
5496  let Inst{9-5}   = Rn;
5497  let Inst{4-0}   = Rd;
5498}
5499
5500multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5501                              SDPatternOperator node> {
5502  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5503            [(set (f16 FPR16:$Rd),
5504                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5505    let Inst{23-22} = 0b11; // 16-bit size flag
5506    let Predicates = [HasFullFP16];
5507  }
5508
5509  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5510            [(set FPR32:$Rd,
5511                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5512    let Inst{23-22} = 0b00; // 32-bit size flag
5513  }
5514
5515  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5516            [(set FPR64:$Rd,
5517                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5518    let Inst{23-22} = 0b01; // 64-bit size flag
5519  }
5520
5521  let Predicates = [HasFullFP16] in {
5522  def : Pat<(f16 (node (f16 FPR16:$Rn),
5523                       (f16 (extractelt (v8f16 V128:$Rm), (i64 0))),
5524                       (f16 FPR16:$Ra))),
5525            (!cast<Instruction>(NAME # Hrrr)
5526              FPR16:$Rn, (f16 (EXTRACT_SUBREG V128:$Rm, hsub)), FPR16:$Ra)>;
5527
5528  def : Pat<(f16 (node (f16 (extractelt (v8f16 V128:$Rn), (i64 0))),
5529                       (f16 FPR16:$Rm),
5530                       (f16 FPR16:$Ra))),
5531            (!cast<Instruction>(NAME # Hrrr)
5532              (f16 (EXTRACT_SUBREG V128:$Rn, hsub)), FPR16:$Rm, FPR16:$Ra)>;
5533  }
5534
5535  def : Pat<(f32 (node (f32 FPR32:$Rn),
5536                       (f32 (extractelt (v4f32 V128:$Rm), (i64 0))),
5537                       (f32 FPR32:$Ra))),
5538            (!cast<Instruction>(NAME # Srrr)
5539              FPR32:$Rn, (EXTRACT_SUBREG V128:$Rm, ssub), FPR32:$Ra)>;
5540
5541  def : Pat<(f32 (node (f32 (extractelt (v4f32 V128:$Rn), (i64 0))),
5542                       (f32 FPR32:$Rm),
5543                       (f32 FPR32:$Ra))),
5544            (!cast<Instruction>(NAME # Srrr)
5545              (EXTRACT_SUBREG V128:$Rn, ssub), FPR32:$Rm, FPR32:$Ra)>;
5546
5547  def : Pat<(f64 (node (f64 FPR64:$Rn),
5548                       (f64 (extractelt (v2f64 V128:$Rm), (i64 0))),
5549                       (f64 FPR64:$Ra))),
5550            (!cast<Instruction>(NAME # Drrr)
5551              FPR64:$Rn, (EXTRACT_SUBREG V128:$Rm, dsub), FPR64:$Ra)>;
5552
5553  def : Pat<(f64 (node (f64 (extractelt (v2f64 V128:$Rn), (i64 0))),
5554                       (f64 FPR64:$Rm),
5555                       (f64 FPR64:$Ra))),
5556            (!cast<Instruction>(NAME # Drrr)
5557              (EXTRACT_SUBREG V128:$Rn, dsub), FPR64:$Rm, FPR64:$Ra)>;
5558}
5559
5560//---
5561// Floating point data comparisons
5562//---
5563
5564let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5565class BaseOneOperandFPComparison<bit signalAllNans,
5566                                 RegisterClass regtype, string asm,
5567                                 list<dag> pat>
5568    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5569      Sched<[WriteFCmp]> {
5570  bits<5> Rn;
5571  let Inst{31-24} = 0b00011110;
5572  let Inst{21}    = 1;
5573
5574  let Inst{15-10} = 0b001000;
5575  let Inst{9-5}   = Rn;
5576  let Inst{4}     = signalAllNans;
5577  let Inst{3-0}   = 0b1000;
5578
5579  // Rm should be 0b00000 canonically, but we need to accept any value.
5580  let PostEncoderMethod = "fixOneOperandFPComparison";
5581}
5582
5583let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5584class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5585                                string asm, list<dag> pat>
5586    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5587      Sched<[WriteFCmp]> {
5588  bits<5> Rm;
5589  bits<5> Rn;
5590  let Inst{31-24} = 0b00011110;
5591  let Inst{21}    = 1;
5592  let Inst{20-16} = Rm;
5593  let Inst{15-10} = 0b001000;
5594  let Inst{9-5}   = Rn;
5595  let Inst{4}     = signalAllNans;
5596  let Inst{3-0}   = 0b0000;
5597}
5598
5599multiclass FPComparison<bit signalAllNans, string asm,
5600                        SDPatternOperator OpNode = null_frag> {
5601  let Defs = [NZCV] in {
5602  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5603      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5604    let Inst{23-22} = 0b11;
5605    let Predicates = [HasFullFP16];
5606  }
5607
5608  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5609      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5610    let Inst{23-22} = 0b11;
5611    let Predicates = [HasFullFP16];
5612  }
5613
5614  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5615      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5616    let Inst{23-22} = 0b00;
5617  }
5618
5619  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5620      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5621    let Inst{23-22} = 0b00;
5622  }
5623
5624  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5625      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5626    let Inst{23-22} = 0b01;
5627  }
5628
5629  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5630      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5631    let Inst{23-22} = 0b01;
5632  }
5633  } // Defs = [NZCV]
5634}
5635
5636//---
5637// Floating point conditional comparisons
5638//---
5639
5640let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5641class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5642                           string mnemonic, list<dag> pat>
5643    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5644         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5645      Sched<[WriteFCmp]> {
5646  let Uses = [NZCV];
5647  let Defs = [NZCV];
5648
5649  bits<5> Rn;
5650  bits<5> Rm;
5651  bits<4> nzcv;
5652  bits<4> cond;
5653
5654  let Inst{31-24} = 0b00011110;
5655  let Inst{21}    = 1;
5656  let Inst{20-16} = Rm;
5657  let Inst{15-12} = cond;
5658  let Inst{11-10} = 0b01;
5659  let Inst{9-5}   = Rn;
5660  let Inst{4}     = signalAllNans;
5661  let Inst{3-0}   = nzcv;
5662}
5663
5664multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5665                            SDPatternOperator OpNode = null_frag> {
5666  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5667      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5668                          (i32 imm:$cond), NZCV))]> {
5669    let Inst{23-22} = 0b11;
5670    let Predicates = [HasFullFP16];
5671  }
5672
5673  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5674      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5675                          (i32 imm:$cond), NZCV))]> {
5676    let Inst{23-22} = 0b00;
5677  }
5678
5679  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5680      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5681                          (i32 imm:$cond), NZCV))]> {
5682    let Inst{23-22} = 0b01;
5683  }
5684}
5685
5686//---
5687// Floating point conditional select
5688//---
5689
5690class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5691    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5692         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5693         [(set regtype:$Rd,
5694               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5695                          (i32 imm:$cond), NZCV))]>,
5696      Sched<[WriteF]> {
5697  bits<5> Rd;
5698  bits<5> Rn;
5699  bits<5> Rm;
5700  bits<4> cond;
5701
5702  let Inst{31-24} = 0b00011110;
5703  let Inst{21}    = 1;
5704  let Inst{20-16} = Rm;
5705  let Inst{15-12} = cond;
5706  let Inst{11-10} = 0b11;
5707  let Inst{9-5}   = Rn;
5708  let Inst{4-0}   = Rd;
5709}
5710
5711multiclass FPCondSelect<string asm> {
5712  let Uses = [NZCV] in {
5713  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5714    let Inst{23-22} = 0b11;
5715    let Predicates = [HasFullFP16];
5716  }
5717
5718  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5719    let Inst{23-22} = 0b00;
5720  }
5721
5722  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5723    let Inst{23-22} = 0b01;
5724  }
5725  } // Uses = [NZCV]
5726}
5727
5728//---
5729// Floating move immediate
5730//---
5731
5732class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5733  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5734      [(set regtype:$Rd, fpimmtype:$imm)]>,
5735    Sched<[WriteFImm]> {
5736  bits<5> Rd;
5737  bits<8> imm;
5738  let Inst{31-24} = 0b00011110;
5739  let Inst{21}    = 1;
5740  let Inst{20-13} = imm;
5741  let Inst{12-5}  = 0b10000000;
5742  let Inst{4-0}   = Rd;
5743}
5744
5745multiclass FPMoveImmediate<string asm> {
5746  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5747    let Inst{23-22} = 0b11;
5748    let Predicates = [HasFullFP16];
5749  }
5750
5751  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5752    let Inst{23-22} = 0b00;
5753  }
5754
5755  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5756    let Inst{23-22} = 0b01;
5757  }
5758}
5759} // end of 'let Predicates = [HasFPARMv8]'
5760
5761//----------------------------------------------------------------------------
5762// AdvSIMD
5763//----------------------------------------------------------------------------
5764
5765let Predicates = [HasNEON] in {
5766
5767//----------------------------------------------------------------------------
5768// AdvSIMD three register vector instructions
5769//----------------------------------------------------------------------------
5770
5771let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5772class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5773                        RegisterOperand regtype, string asm, string kind,
5774                        list<dag> pattern>
5775  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5776      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5777      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5778    Sched<[!if(Q, WriteVq, WriteVd)]> {
5779  bits<5> Rd;
5780  bits<5> Rn;
5781  bits<5> Rm;
5782  let Inst{31}    = 0;
5783  let Inst{30}    = Q;
5784  let Inst{29}    = U;
5785  let Inst{28-24} = 0b01110;
5786  let Inst{23-21} = size;
5787  let Inst{20-16} = Rm;
5788  let Inst{15-11} = opcode;
5789  let Inst{10}    = 1;
5790  let Inst{9-5}   = Rn;
5791  let Inst{4-0}   = Rd;
5792}
5793
5794let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5795class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5796                        RegisterOperand regtype, string asm, string kind,
5797                        list<dag> pattern>
5798  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5799      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5800      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5801    Sched<[!if(Q, WriteVq, WriteVd)]> {
5802  bits<5> Rd;
5803  bits<5> Rn;
5804  bits<5> Rm;
5805  let Inst{31}    = 0;
5806  let Inst{30}    = Q;
5807  let Inst{29}    = U;
5808  let Inst{28-24} = 0b01110;
5809  let Inst{23-21} = size;
5810  let Inst{20-16} = Rm;
5811  let Inst{15-11} = opcode;
5812  let Inst{10}    = 1;
5813  let Inst{9-5}   = Rn;
5814  let Inst{4-0}   = Rd;
5815}
5816
5817let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5818class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5819  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5820    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
5821
5822multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5823  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5824             [(set (v8i8 V64:$dst),
5825                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5826  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5827             [(set (v16i8 V128:$dst),
5828                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5829                           (v16i8 V128:$Rm)))]>;
5830
5831  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5832                           (v4i16 V64:$RHS))),
5833          (!cast<Instruction>(NAME#"v8i8")
5834            V64:$LHS, V64:$MHS, V64:$RHS)>;
5835  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5836                           (v2i32 V64:$RHS))),
5837          (!cast<Instruction>(NAME#"v8i8")
5838            V64:$LHS, V64:$MHS, V64:$RHS)>;
5839  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5840                           (v1i64 V64:$RHS))),
5841          (!cast<Instruction>(NAME#"v8i8")
5842            V64:$LHS, V64:$MHS, V64:$RHS)>;
5843
5844  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5845                           (v8i16 V128:$RHS))),
5846      (!cast<Instruction>(NAME#"v16i8")
5847        V128:$LHS, V128:$MHS, V128:$RHS)>;
5848  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5849                           (v4i32 V128:$RHS))),
5850      (!cast<Instruction>(NAME#"v16i8")
5851        V128:$LHS, V128:$MHS, V128:$RHS)>;
5852  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5853                           (v2i64 V128:$RHS))),
5854      (!cast<Instruction>(NAME#"v16i8")
5855        V128:$LHS, V128:$MHS, V128:$RHS)>;
5856}
5857
5858// All operand sizes distinguished in the encoding.
5859multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5860                               SDPatternOperator OpNode> {
5861  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5862                                      asm, ".8b",
5863         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5864  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5865                                      asm, ".16b",
5866         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5867  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5868                                      asm, ".4h",
5869         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5870  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5871                                      asm, ".8h",
5872         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5873  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5874                                      asm, ".2s",
5875         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5876  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5877                                      asm, ".4s",
5878         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5879  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5880                                      asm, ".2d",
5881         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5882}
5883
5884multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5885  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5886          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5887  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5888          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5889  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5890          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5891
5892  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5893          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5894  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5895          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5896  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5897          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5898  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5899          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5900}
5901
5902// As above, but D sized elements unsupported.
5903multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5904                                  SDPatternOperator OpNode> {
5905  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5906                                      asm, ".8b",
5907        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5908  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5909                                      asm, ".16b",
5910        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5911  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5912                                      asm, ".4h",
5913        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5914  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5915                                      asm, ".8h",
5916        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5917  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5918                                      asm, ".2s",
5919        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5920  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5921                                      asm, ".4s",
5922        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5923}
5924
5925multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5926                                  SDPatternOperator OpNode> {
5927  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5928                                      asm, ".8b",
5929      [(set (v8i8 V64:$dst),
5930            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5931  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5932                                      asm, ".16b",
5933      [(set (v16i8 V128:$dst),
5934            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5935  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5936                                      asm, ".4h",
5937      [(set (v4i16 V64:$dst),
5938            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5939  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5940                                      asm, ".8h",
5941      [(set (v8i16 V128:$dst),
5942            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5943  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5944                                      asm, ".2s",
5945      [(set (v2i32 V64:$dst),
5946            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5947  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5948                                      asm, ".4s",
5949      [(set (v4i32 V128:$dst),
5950            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5951}
5952
5953// As above, but only B sized elements supported.
5954multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5955                                SDPatternOperator OpNode> {
5956  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5957                                      asm, ".8b",
5958    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5959  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5960                                      asm, ".16b",
5961    [(set (v16i8 V128:$Rd),
5962          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5963}
5964
5965// As above, but only floating point elements supported.
5966let mayRaiseFPException = 1, Uses = [FPCR] in
5967multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5968                                 string asm, SDPatternOperator OpNode> {
5969  let Predicates = [HasNEON, HasFullFP16] in {
5970  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5971                                      asm, ".4h",
5972        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5973  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5974                                      asm, ".8h",
5975        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5976  } // Predicates = [HasNEON, HasFullFP16]
5977  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5978                                      asm, ".2s",
5979        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5980  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5981                                      asm, ".4s",
5982        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5983  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5984                                      asm, ".2d",
5985        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5986}
5987
5988let mayRaiseFPException = 1, Uses = [FPCR] in
5989multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5990                                    string asm,
5991                                    SDPatternOperator OpNode> {
5992  let Predicates = [HasNEON, HasFullFP16] in {
5993  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5994                                      asm, ".4h",
5995        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5996  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5997                                      asm, ".8h",
5998        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5999  } // Predicates = [HasNEON, HasFullFP16]
6000  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
6001                                      asm, ".2s",
6002        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
6003  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
6004                                      asm, ".4s",
6005        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
6006  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
6007                                      asm, ".2d",
6008        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
6009}
6010
6011let mayRaiseFPException = 1, Uses = [FPCR] in
6012multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
6013                                 string asm, SDPatternOperator OpNode> {
6014  let Predicates = [HasNEON, HasFullFP16] in {
6015  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
6016                                      asm, ".4h",
6017     [(set (v4f16 V64:$dst),
6018           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
6019  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
6020                                      asm, ".8h",
6021     [(set (v8f16 V128:$dst),
6022           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
6023  } // Predicates = [HasNEON, HasFullFP16]
6024  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
6025                                      asm, ".2s",
6026     [(set (v2f32 V64:$dst),
6027           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
6028  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
6029                                      asm, ".4s",
6030     [(set (v4f32 V128:$dst),
6031           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
6032  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
6033                                      asm, ".2d",
6034     [(set (v2f64 V128:$dst),
6035           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
6036}
6037
6038// As above, but D and B sized elements unsupported.
6039let mayRaiseFPException = 1, Uses = [FPCR] in
6040multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
6041                                SDPatternOperator OpNode> {
6042  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
6043                                      asm, ".4h",
6044        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6045  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
6046                                      asm, ".8h",
6047        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6048  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
6049                                      asm, ".2s",
6050        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6051  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
6052                                      asm, ".4s",
6053        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6054}
6055
6056// Logical three vector ops share opcode bits, and only use B sized elements.
6057multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
6058                                  SDPatternOperator OpNode = null_frag> {
6059  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
6060                                     asm, ".8b",
6061                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
6062  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
6063                                     asm, ".16b",
6064                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
6065
6066  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
6067          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
6068  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
6069          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
6070  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
6071          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
6072
6073  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
6074      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6075  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
6076      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6077  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
6078      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6079}
6080
6081multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
6082                                  string asm, SDPatternOperator OpNode = null_frag> {
6083  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
6084                                     asm, ".8b",
6085             [(set (v8i8 V64:$dst),
6086                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6087  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
6088                                     asm, ".16b",
6089             [(set (v16i8 V128:$dst),
6090                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
6091                           (v16i8 V128:$Rm)))]>;
6092
6093  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
6094                           (v4i16 V64:$RHS))),
6095          (!cast<Instruction>(NAME#"v8i8")
6096            V64:$LHS, V64:$MHS, V64:$RHS)>;
6097  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
6098                           (v2i32 V64:$RHS))),
6099          (!cast<Instruction>(NAME#"v8i8")
6100            V64:$LHS, V64:$MHS, V64:$RHS)>;
6101  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
6102                           (v1i64 V64:$RHS))),
6103          (!cast<Instruction>(NAME#"v8i8")
6104            V64:$LHS, V64:$MHS, V64:$RHS)>;
6105
6106  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
6107                           (v8i16 V128:$RHS))),
6108      (!cast<Instruction>(NAME#"v16i8")
6109        V128:$LHS, V128:$MHS, V128:$RHS)>;
6110  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
6111                           (v4i32 V128:$RHS))),
6112      (!cast<Instruction>(NAME#"v16i8")
6113        V128:$LHS, V128:$MHS, V128:$RHS)>;
6114  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
6115                           (v2i64 V128:$RHS))),
6116      (!cast<Instruction>(NAME#"v16i8")
6117        V128:$LHS, V128:$MHS, V128:$RHS)>;
6118}
6119
6120// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
6121// bytes from S-sized elements.
6122class BaseSIMDThreeSameVectorDot<bit Q, bit U, bits<2> sz, bits<4> opc, string asm,
6123                                 string kind1, string kind2, RegisterOperand RegType,
6124                                 ValueType AccumType, ValueType InputType,
6125                                 SDPatternOperator OpNode> :
6126        BaseSIMDThreeSameVectorTied<Q, U, {sz, 0b0}, {0b1, opc}, RegType, asm, kind1,
6127        [(set (AccumType RegType:$dst),
6128              (OpNode (AccumType RegType:$Rd),
6129                      (InputType RegType:$Rn),
6130                      (InputType RegType:$Rm)))]> {
6131  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
6132}
6133
6134multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
6135  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, 0b10, {0b001, Mixed}, asm, ".2s", ".8b", V64,
6136                                         v2i32, v8i8, OpNode>;
6137  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, 0b10, {0b001, Mixed}, asm, ".4s", ".16b", V128,
6138                                         v4i32, v16i8, OpNode>;
6139}
6140
6141// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
6142// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
6143// 8H to 4S, when Q=1).
6144let mayRaiseFPException = 1, Uses = [FPCR] in
6145class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
6146                                 string kind2, RegisterOperand RegType,
6147                                 ValueType AccumType, ValueType InputType,
6148                                 SDPatternOperator OpNode> :
6149        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
6150		[(set (AccumType RegType:$dst),
6151              (OpNode (AccumType RegType:$Rd),
6152                      (InputType RegType:$Rn),
6153                      (InputType RegType:$Rm)))]> {
6154  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
6155  let Inst{13} = b13;
6156}
6157
6158multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
6159                                  SDPatternOperator OpNode> {
6160  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
6161                                         v2f32, v4f16, OpNode>;
6162  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
6163                                         v4f32, v8f16, OpNode>;
6164}
6165
6166multiclass SIMDThreeSameVectorMLA<bit Q, string asm>{
6167  def v8f16 : BaseSIMDThreeSameVectorDot<Q, 0b0, 0b11, 0b1111, asm, ".8h", ".16b",
6168                                         V128, v8f16, v16i8, null_frag>;
6169}
6170
6171multiclass SIMDThreeSameVectorMLAL<bit Q, bits<2> sz, string asm>{
6172  def v4f32 : BaseSIMDThreeSameVectorDot<Q, 0b0, sz, 0b1000, asm, ".4s", ".16b",
6173                                         V128, v4f32, v16i8, null_frag>;
6174}
6175
6176// FP8 assembly/disassembly classes
6177
6178//----------------------------------------------------------------------------
6179// FP8 Advanced SIMD three-register extension
6180//----------------------------------------------------------------------------
6181class BaseSIMDThreeVectors<bit Q, bit U, bits<2> size, bits<4> op,
6182                           RegisterOperand regtype1,
6183                           RegisterOperand regtype2, string asm,
6184                           string kind1, string kind2>
6185  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, regtype2:$Rm), asm,
6186      "\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2, "", []>, Sched<[]> {
6187  bits<5> Rd;
6188  bits<5> Rn;
6189  bits<5> Rm;
6190  let Inst{31}    = 0;
6191  let Inst{30}    = Q;
6192  let Inst{29}    = U;
6193  let Inst{28-24} = 0b01110;
6194  let Inst{23-22} = size;
6195  let Inst{21}    = 0b0;
6196  let Inst{20-16} = Rm;
6197  let Inst{15}    = 0b1;
6198  let Inst{14-11} = op;
6199  let Inst{10}    = 0b1;
6200  let Inst{9-5}   = Rn;
6201  let Inst{4-0}   = Rd;
6202}
6203
6204
6205// FCVTN (FP16 to FP8)
6206multiclass SIMDThreeSameSizeVectorCvt<string asm> {
6207   def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b01, 0b1110, V64, V64, asm, ".8b",".4h">;
6208   def v16f8 : BaseSIMDThreeVectors<0b1, 0b0, 0b01, 0b1110,  V128, V128, asm, ".16b", ".8h">;
6209}
6210
6211// TODO : Create v16f8 value type
6212// FCVTN, FCVTN2 (FP32 to FP8)
6213multiclass SIMDThreeVectorCvt<string asm> {
6214   def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b00, 0b1110, V64, V128, asm, ".8b", ".4s">;
6215   def 2v16f8 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b00, 0b1110, asm#2, ".16b", ".4s",
6216                                           V128, v16i8, v4f32, null_frag>;
6217}
6218
6219// TODO: Create a new Value Type v8f8 and v16f8
6220multiclass SIMDThreeSameVectorDOT2<string asm> {
6221   def v4f16 : BaseSIMDThreeSameVectorDot<0b0, 0b0, 0b01, 0b1111, asm, ".4h", ".8b",
6222                                          V64, v4f16, v8i8, null_frag>;
6223   def v8f16 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b01, 0b1111, asm, ".8h", ".16b",
6224                                          V128, v8f16, v16i8, null_frag>;
6225}
6226
6227multiclass SIMDThreeSameVectorDOT4<string asm> {
6228   def v2f32 : BaseSIMDThreeSameVectorDot<0b0, 0b0, 0b00, 0b1111, asm, ".2s", ".8b",
6229                                          V64, v2f32, v8i8, null_frag>;
6230   def v4f32 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b00, 0b1111, asm, ".4s", ".16b",
6231                                          V128, v4f32, v16i8, null_frag>;
6232}
6233
6234//----------------------------------------------------------------------------
6235// AdvSIMD two register vector instructions.
6236//----------------------------------------------------------------------------
6237
6238let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6239class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6240                            bits<2> size2, RegisterOperand regtype, string asm,
6241                            string dstkind, string srckind, list<dag> pattern>
6242  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6243      "{\t$Rd" # dstkind # ", $Rn" # srckind #
6244      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
6245    Sched<[!if(Q, WriteVq, WriteVd)]> {
6246  bits<5> Rd;
6247  bits<5> Rn;
6248  let Inst{31}    = 0;
6249  let Inst{30}    = Q;
6250  let Inst{29}    = U;
6251  let Inst{28-24} = 0b01110;
6252  let Inst{23-22} = size;
6253  let Inst{21} = 0b1;
6254  let Inst{20-19} = size2;
6255  let Inst{18-17} = 0b00;
6256  let Inst{16-12} = opcode;
6257  let Inst{11-10} = 0b10;
6258  let Inst{9-5}   = Rn;
6259  let Inst{4-0}   = Rd;
6260}
6261
6262let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6263class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6264                                bits<2> size2, RegisterOperand regtype,
6265                                string asm, string dstkind, string srckind,
6266                                list<dag> pattern>
6267  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
6268      "{\t$Rd" # dstkind # ", $Rn" # srckind #
6269      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6270    Sched<[!if(Q, WriteVq, WriteVd)]> {
6271  bits<5> Rd;
6272  bits<5> Rn;
6273  let Inst{31}    = 0;
6274  let Inst{30}    = Q;
6275  let Inst{29}    = U;
6276  let Inst{28-24} = 0b01110;
6277  let Inst{23-22} = size;
6278  let Inst{21} = 0b1;
6279  let Inst{20-19} = size2;
6280  let Inst{18-17} = 0b00;
6281  let Inst{16-12} = opcode;
6282  let Inst{11-10} = 0b10;
6283  let Inst{9-5}   = Rn;
6284  let Inst{4-0}   = Rd;
6285}
6286
6287// Supports B, H, and S element sizes.
6288multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
6289                            SDPatternOperator OpNode> {
6290  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6291                                      asm, ".8b", ".8b",
6292                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6293  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6294                                      asm, ".16b", ".16b",
6295                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6296  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6297                                      asm, ".4h", ".4h",
6298                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6299  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6300                                      asm, ".8h", ".8h",
6301                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6302  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6303                                      asm, ".2s", ".2s",
6304                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6305  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6306                                      asm, ".4s", ".4s",
6307                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6308}
6309
6310class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
6311                            RegisterOperand regtype, string asm, string dstkind,
6312                            string srckind, string amount>
6313  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
6314      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
6315      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
6316    Sched<[WriteVq]> {
6317  bits<5> Rd;
6318  bits<5> Rn;
6319  let Inst{31}    = 0;
6320  let Inst{30}    = Q;
6321  let Inst{29-24} = 0b101110;
6322  let Inst{23-22} = size;
6323  let Inst{21-10} = 0b100001001110;
6324  let Inst{9-5}   = Rn;
6325  let Inst{4-0}   = Rd;
6326}
6327
6328multiclass SIMDVectorLShiftLongBySizeBHS {
6329  let hasSideEffects = 0 in {
6330  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
6331                                             "shll", ".8h",  ".8b", "8">;
6332  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
6333                                             "shll2", ".8h", ".16b", "8">;
6334  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
6335                                             "shll", ".4s",  ".4h", "16">;
6336  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
6337                                             "shll2", ".4s", ".8h", "16">;
6338  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
6339                                             "shll", ".2d",  ".2s", "32">;
6340  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
6341                                             "shll2", ".2d", ".4s", "32">;
6342  }
6343}
6344
6345// Supports all element sizes.
6346multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
6347                             SDPatternOperator OpNode> {
6348  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6349                                      asm, ".4h", ".8b",
6350               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6351  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6352                                      asm, ".8h", ".16b",
6353               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6354  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6355                                      asm, ".2s", ".4h",
6356               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6357  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6358                                      asm, ".4s", ".8h",
6359               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6360  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6361                                      asm, ".1d", ".2s",
6362               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6363  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6364                                      asm, ".2d", ".4s",
6365               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6366}
6367
6368multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
6369                                 SDPatternOperator OpNode> {
6370  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6371                                          asm, ".4h", ".8b",
6372      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
6373                                      (v8i8 V64:$Rn)))]>;
6374  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6375                                          asm, ".8h", ".16b",
6376      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
6377                                      (v16i8 V128:$Rn)))]>;
6378  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6379                                          asm, ".2s", ".4h",
6380      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
6381                                      (v4i16 V64:$Rn)))]>;
6382  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6383                                          asm, ".4s", ".8h",
6384      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
6385                                      (v8i16 V128:$Rn)))]>;
6386  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6387                                          asm, ".1d", ".2s",
6388      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
6389                                      (v2i32 V64:$Rn)))]>;
6390  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6391                                          asm, ".2d", ".4s",
6392      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
6393                                      (v4i32 V128:$Rn)))]>;
6394}
6395
6396// Supports all element sizes, except 1xD.
6397multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
6398                                  SDPatternOperator OpNode> {
6399  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6400                                    asm, ".8b", ".8b",
6401    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
6402  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6403                                    asm, ".16b", ".16b",
6404    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
6405  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6406                                    asm, ".4h", ".4h",
6407    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
6408  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6409                                    asm, ".8h", ".8h",
6410    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
6411  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6412                                    asm, ".2s", ".2s",
6413    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
6414  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6415                                    asm, ".4s", ".4s",
6416    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
6417  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
6418                                    asm, ".2d", ".2d",
6419    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
6420}
6421
6422multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
6423                             SDPatternOperator OpNode = null_frag> {
6424  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6425                                asm, ".8b", ".8b",
6426    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6427  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6428                                asm, ".16b", ".16b",
6429    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6430  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6431                                asm, ".4h", ".4h",
6432    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6433  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6434                                asm, ".8h", ".8h",
6435    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6436  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6437                                asm, ".2s", ".2s",
6438    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6439  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6440                                asm, ".4s", ".4s",
6441    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6442  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
6443                                asm, ".2d", ".2d",
6444    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6445}
6446
6447
6448// Supports only B element sizes.
6449multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
6450                          SDPatternOperator OpNode> {
6451  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
6452                                asm, ".8b", ".8b",
6453                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6454  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
6455                                asm, ".16b", ".16b",
6456                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6457
6458}
6459
6460// Supports only B and H element sizes.
6461multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
6462                                SDPatternOperator OpNode> {
6463  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6464                                asm, ".8b", ".8b",
6465                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
6466  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6467                                asm, ".16b", ".16b",
6468                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
6469  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6470                                asm, ".4h", ".4h",
6471                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
6472  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6473                                asm, ".8h", ".8h",
6474                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
6475}
6476
6477// Supports H, S and D element sizes, uses high bit of the size field
6478// as an extra opcode bit.
6479multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
6480                           SDPatternOperator OpNode,
6481                           int fpexceptions = 1> {
6482  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
6483  let Predicates = [HasNEON, HasFullFP16] in {
6484  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6485                                asm, ".4h", ".4h",
6486                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6487  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6488                                asm, ".8h", ".8h",
6489                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6490  } // Predicates = [HasNEON, HasFullFP16]
6491  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6492                                asm, ".2s", ".2s",
6493                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6494  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6495                                asm, ".4s", ".4s",
6496                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6497  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6498                                asm, ".2d", ".2d",
6499                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6500  }
6501}
6502
6503multiclass SIMDTwoVectorFPNoException<bit U, bit S, bits<5> opc, string asm,
6504                                      SDPatternOperator OpNode>
6505    : SIMDTwoVectorFP<U, S, opc, asm, OpNode, 0>;
6506
6507// Supports only S and D element sizes
6508let mayRaiseFPException = 1, Uses = [FPCR] in
6509multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6510                           SDPatternOperator OpNode = null_frag> {
6511
6512  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6513                                asm, ".2s", ".2s",
6514                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6515  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6516                                asm, ".4s", ".4s",
6517                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6518  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6519                                asm, ".2d", ".2d",
6520                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6521}
6522
6523multiclass FRIntNNTVector<bit U, bit op, string asm,
6524                          SDPatternOperator OpNode = null_frag> :
6525           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6526
6527// Supports only S element size.
6528multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6529                           SDPatternOperator OpNode> {
6530  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6531                                asm, ".2s", ".2s",
6532                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6533  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6534                                asm, ".4s", ".4s",
6535                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6536}
6537
6538let mayRaiseFPException = 1, Uses = [FPCR] in
6539multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6540                           SDPatternOperator OpNode> {
6541  let Predicates = [HasNEON, HasFullFP16] in {
6542  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6543                                asm, ".4h", ".4h",
6544                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6545  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6546                                asm, ".8h", ".8h",
6547                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6548  } // Predicates = [HasNEON, HasFullFP16]
6549  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6550                                asm, ".2s", ".2s",
6551                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6552  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6553                                asm, ".4s", ".4s",
6554                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6555  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6556                                asm, ".2d", ".2d",
6557                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6558}
6559
6560let mayRaiseFPException = 1, Uses = [FPCR] in
6561multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6562                           SDPatternOperator OpNode> {
6563  let Predicates = [HasNEON, HasFullFP16] in {
6564  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6565                                asm, ".4h", ".4h",
6566                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6567  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6568                                asm, ".8h", ".8h",
6569                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6570  } // Predicates = [HasNEON, HasFullFP16]
6571  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6572                                asm, ".2s", ".2s",
6573                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6574  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6575                                asm, ".4s", ".4s",
6576                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6577  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6578                                asm, ".2d", ".2d",
6579                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6580}
6581
6582let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6583class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6584                           RegisterOperand inreg, RegisterOperand outreg,
6585                           string asm, string outkind, string inkind,
6586                           list<dag> pattern>
6587  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6588      "{\t$Rd" # outkind # ", $Rn" # inkind #
6589      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6590    Sched<[WriteVq]> {
6591  bits<5> Rd;
6592  bits<5> Rn;
6593  let Inst{31}    = 0;
6594  let Inst{30}    = Q;
6595  let Inst{29}    = U;
6596  let Inst{28-24} = 0b01110;
6597  let Inst{23-22} = size;
6598  let Inst{21-17} = 0b10000;
6599  let Inst{16-12} = opcode;
6600  let Inst{11-10} = 0b10;
6601  let Inst{9-5}   = Rn;
6602  let Inst{4-0}   = Rd;
6603}
6604
6605let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6606class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6607                           RegisterOperand inreg, RegisterOperand outreg,
6608                           string asm, string outkind, string inkind,
6609                           list<dag> pattern>
6610  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6611      "{\t$Rd" # outkind # ", $Rn" # inkind #
6612      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6613    Sched<[WriteVq]> {
6614  bits<5> Rd;
6615  bits<5> Rn;
6616  let Inst{31}    = 0;
6617  let Inst{30}    = Q;
6618  let Inst{29}    = U;
6619  let Inst{28-24} = 0b01110;
6620  let Inst{23-22} = size;
6621  let Inst{21-17} = 0b10000;
6622  let Inst{16-12} = opcode;
6623  let Inst{11-10} = 0b10;
6624  let Inst{9-5}   = Rn;
6625  let Inst{4-0}   = Rd;
6626}
6627
6628multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6629                              SDPatternOperator OpNode> {
6630  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6631                                      asm, ".8b", ".8h",
6632        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6633  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6634                                      asm#"2", ".16b", ".8h", []>;
6635  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6636                                      asm, ".4h", ".4s",
6637        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6638  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6639                                      asm#"2", ".8h", ".4s", []>;
6640  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6641                                      asm, ".2s", ".2d",
6642        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6643  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6644                                      asm#"2", ".4s", ".2d", []>;
6645
6646  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6647            (!cast<Instruction>(NAME # "v16i8")
6648                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6649  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6650            (!cast<Instruction>(NAME # "v8i16")
6651                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6652  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6653            (!cast<Instruction>(NAME # "v4i32")
6654                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6655}
6656
6657//----------------------------------------------------------------------------
6658// FP8 Advanced SIMD two-register miscellaneous
6659//----------------------------------------------------------------------------
6660multiclass SIMDMixedTwoVectorFP8<bits<2>sz, string asm> {
6661  def v8f16 : BaseSIMDMixedTwoVector<0b0, 0b1, sz, 0b10111, V64, V128,
6662                                     asm, ".8h", ".8b", []>;
6663  def 2v8f16 : BaseSIMDMixedTwoVector<0b1, 0b1, sz, 0b10111, V128, V128,
6664                                     asm#2, ".8h", ".16b", []>;
6665}
6666
6667class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6668                           bits<5> opcode, RegisterOperand regtype, string asm,
6669                           string kind, string zero, ValueType dty,
6670                           ValueType sty, SDNode OpNode>
6671  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6672      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6673      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6674      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6675    Sched<[!if(Q, WriteVq, WriteVd)]> {
6676  bits<5> Rd;
6677  bits<5> Rn;
6678  let Inst{31}    = 0;
6679  let Inst{30}    = Q;
6680  let Inst{29}    = U;
6681  let Inst{28-24} = 0b01110;
6682  let Inst{23-22} = size;
6683  let Inst{21} = 0b1;
6684  let Inst{20-19} = size2;
6685  let Inst{18-17} = 0b00;
6686  let Inst{16-12} = opcode;
6687  let Inst{11-10} = 0b10;
6688  let Inst{9-5}   = Rn;
6689  let Inst{4-0}   = Rd;
6690}
6691
6692// Comparisons support all element sizes, except 1xD.
6693multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6694                            SDNode OpNode> {
6695  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6696                                     asm, ".8b", "0",
6697                                     v8i8, v8i8, OpNode>;
6698  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6699                                     asm, ".16b", "0",
6700                                     v16i8, v16i8, OpNode>;
6701  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6702                                     asm, ".4h", "0",
6703                                     v4i16, v4i16, OpNode>;
6704  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6705                                     asm, ".8h", "0",
6706                                     v8i16, v8i16, OpNode>;
6707  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6708                                     asm, ".2s", "0",
6709                                     v2i32, v2i32, OpNode>;
6710  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6711                                     asm, ".4s", "0",
6712                                     v4i32, v4i32, OpNode>;
6713  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6714                                     asm, ".2d", "0",
6715                                     v2i64, v2i64, OpNode>;
6716}
6717
6718// FP Comparisons support only S and D element sizes (and H for v8.2a).
6719multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6720                              string asm, SDNode OpNode> {
6721
6722  let mayRaiseFPException = 1, Uses = [FPCR] in {
6723  let Predicates = [HasNEON, HasFullFP16] in {
6724  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6725                                     asm, ".4h", "0.0",
6726                                     v4i16, v4f16, OpNode>;
6727  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6728                                     asm, ".8h", "0.0",
6729                                     v8i16, v8f16, OpNode>;
6730  } // Predicates = [HasNEON, HasFullFP16]
6731  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6732                                     asm, ".2s", "0.0",
6733                                     v2i32, v2f32, OpNode>;
6734  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6735                                     asm, ".4s", "0.0",
6736                                     v4i32, v4f32, OpNode>;
6737  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6738                                     asm, ".2d", "0.0",
6739                                     v2i64, v2f64, OpNode>;
6740  }
6741
6742  let Predicates = [HasNEON, HasFullFP16] in {
6743  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6744                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6745  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6746                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6747  }
6748  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6749                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6750  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6751                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6752  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6753                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6754  let Predicates = [HasNEON, HasFullFP16] in {
6755  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6756                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6757  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6758                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6759  }
6760  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6761                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6762  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6763                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6764  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6765                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6766}
6767
6768let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6769class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6770                             RegisterOperand outtype, RegisterOperand intype,
6771                             string asm, string VdTy, string VnTy,
6772                             list<dag> pattern>
6773  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6774      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6775    Sched<[WriteVq]> {
6776  bits<5> Rd;
6777  bits<5> Rn;
6778  let Inst{31}    = 0;
6779  let Inst{30}    = Q;
6780  let Inst{29}    = U;
6781  let Inst{28-24} = 0b01110;
6782  let Inst{23-22} = size;
6783  let Inst{21-17} = 0b10000;
6784  let Inst{16-12} = opcode;
6785  let Inst{11-10} = 0b10;
6786  let Inst{9-5}   = Rn;
6787  let Inst{4-0}   = Rd;
6788}
6789
6790let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6791class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6792                             RegisterOperand outtype, RegisterOperand intype,
6793                             string asm, string VdTy, string VnTy,
6794                             list<dag> pattern>
6795  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6796      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6797    Sched<[WriteVq]> {
6798  bits<5> Rd;
6799  bits<5> Rn;
6800  let Inst{31}    = 0;
6801  let Inst{30}    = Q;
6802  let Inst{29}    = U;
6803  let Inst{28-24} = 0b01110;
6804  let Inst{23-22} = size;
6805  let Inst{21-17} = 0b10000;
6806  let Inst{16-12} = opcode;
6807  let Inst{11-10} = 0b10;
6808  let Inst{9-5}   = Rn;
6809  let Inst{4-0}   = Rd;
6810}
6811
6812multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6813  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6814                                    asm, ".4s", ".4h", []>;
6815  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6816                                    asm#"2", ".4s", ".8h", []>;
6817  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6818                                    asm, ".2d", ".2s", []>;
6819  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6820                                    asm#"2", ".2d", ".4s", []>;
6821}
6822
6823multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6824  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6825                                    asm, ".4h", ".4s", []>;
6826  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6827                                    asm#"2", ".8h", ".4s", []>;
6828  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6829                                    asm, ".2s", ".2d", []>;
6830  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6831                                    asm#"2", ".4s", ".2d", []>;
6832}
6833
6834multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6835                                     SDPatternOperator OpNode> {
6836  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6837                                     asm, ".2s", ".2d",
6838                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6839  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6840                                    asm#"2", ".4s", ".2d", []>;
6841
6842  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6843            (!cast<Instruction>(NAME # "v4f32")
6844                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6845}
6846
6847//----------------------------------------------------------------------------
6848// AdvSIMD three register different-size vector instructions.
6849//----------------------------------------------------------------------------
6850
6851let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6852class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6853                      RegisterOperand outtype, RegisterOperand intype1,
6854                      RegisterOperand intype2, string asm,
6855                      string outkind, string inkind1, string inkind2,
6856                      list<dag> pattern>
6857  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6858      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6859      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6860    Sched<[WriteVq]> {
6861  bits<5> Rd;
6862  bits<5> Rn;
6863  bits<5> Rm;
6864  let Inst{31}    = 0;
6865  let Inst{30}    = size{0};
6866  let Inst{29}    = U;
6867  let Inst{28-24} = 0b01110;
6868  let Inst{23-22} = size{2-1};
6869  let Inst{21}    = 1;
6870  let Inst{20-16} = Rm;
6871  let Inst{15-12} = opcode;
6872  let Inst{11-10} = 0b00;
6873  let Inst{9-5}   = Rn;
6874  let Inst{4-0}   = Rd;
6875}
6876
6877let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6878class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6879                      RegisterOperand outtype, RegisterOperand intype1,
6880                      RegisterOperand intype2, string asm,
6881                      string outkind, string inkind1, string inkind2,
6882                      list<dag> pattern>
6883  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6884      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6885      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6886    Sched<[WriteVq]> {
6887  bits<5> Rd;
6888  bits<5> Rn;
6889  bits<5> Rm;
6890  let Inst{31}    = 0;
6891  let Inst{30}    = size{0};
6892  let Inst{29}    = U;
6893  let Inst{28-24} = 0b01110;
6894  let Inst{23-22} = size{2-1};
6895  let Inst{21}    = 1;
6896  let Inst{20-16} = Rm;
6897  let Inst{15-12} = opcode;
6898  let Inst{11-10} = 0b00;
6899  let Inst{9-5}   = Rn;
6900  let Inst{4-0}   = Rd;
6901}
6902
6903// FIXME: TableGen doesn't know how to deal with expanded types that also
6904//        change the element count (in this case, placing the results in
6905//        the high elements of the result register rather than the low
6906//        elements). Until that's fixed, we can't code-gen those.
6907multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6908                                    Intrinsic IntOp> {
6909  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6910                                                  V64, V128, V128,
6911                                                  asm, ".8b", ".8h", ".8h",
6912     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6913  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6914                                                  V128, V128, V128,
6915                                                  asm#"2", ".16b", ".8h", ".8h",
6916     []>;
6917  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6918                                                  V64, V128, V128,
6919                                                  asm, ".4h", ".4s", ".4s",
6920     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6921  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6922                                                  V128, V128, V128,
6923                                                  asm#"2", ".8h", ".4s", ".4s",
6924     []>;
6925  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6926                                                  V64, V128, V128,
6927                                                  asm, ".2s", ".2d", ".2d",
6928     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6929  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6930                                                  V128, V128, V128,
6931                                                  asm#"2", ".4s", ".2d", ".2d",
6932     []>;
6933
6934
6935  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6936  // a version attached to an instruction.
6937  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6938                                                   (v8i16 V128:$Rm))),
6939            (!cast<Instruction>(NAME # "v8i16_v16i8")
6940                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6941                V128:$Rn, V128:$Rm)>;
6942  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6943                                                    (v4i32 V128:$Rm))),
6944            (!cast<Instruction>(NAME # "v4i32_v8i16")
6945                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6946                V128:$Rn, V128:$Rm)>;
6947  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6948                                                    (v2i64 V128:$Rm))),
6949            (!cast<Instruction>(NAME # "v2i64_v4i32")
6950                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6951                V128:$Rn, V128:$Rm)>;
6952}
6953
6954multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6955                                      SDPatternOperator OpNode> {
6956  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6957                                            V128, V64, V64,
6958                                            asm, ".8h", ".8b", ".8b",
6959      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6960  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6961                                            V128, V128, V128,
6962                                            asm#"2", ".8h", ".16b", ".16b", []>;
6963  let Predicates = [HasAES] in {
6964    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6965                                              V128, V64, V64,
6966                                              asm, ".1q", ".1d", ".1d",
6967        [(set (v16i8 V128:$Rd), (OpNode (v1i64 V64:$Rn), (v1i64 V64:$Rm)))]>;
6968    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6969                                              V128, V128, V128,
6970                                              asm#"2", ".1q", ".2d", ".2d",
6971        [(set (v16i8 V128:$Rd), (OpNode (extract_high_v2i64 (v2i64 V128:$Rn)),
6972                                        (extract_high_v2i64 (v2i64 V128:$Rm))))]>;
6973  }
6974
6975  def : Pat<(v8i16 (OpNode (v8i8 (extract_high_v16i8 (v16i8 V128:$Rn))),
6976                          (v8i8 (extract_high_v16i8 (v16i8 V128:$Rm))))),
6977      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6978}
6979
6980multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6981                                 SDPatternOperator OpNode> {
6982  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6983                                                  V128, V64, V64,
6984                                                  asm, ".4s", ".4h", ".4h",
6985      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6986  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6987                                                  V128, V128, V128,
6988                                                  asm#"2", ".4s", ".8h", ".8h",
6989      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6990                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6991  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6992                                                  V128, V64, V64,
6993                                                  asm, ".2d", ".2s", ".2s",
6994      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6995  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6996                                                  V128, V128, V128,
6997                                                  asm#"2", ".2d", ".4s", ".4s",
6998      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6999                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7000}
7001
7002multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
7003                                  SDPatternOperator OpNode = null_frag> {
7004  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7005                                                  V128, V64, V64,
7006                                                  asm, ".8h", ".8b", ".8b",
7007      [(set (v8i16 V128:$Rd),
7008            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
7009  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7010                                                 V128, V128, V128,
7011                                                 asm#"2", ".8h", ".16b", ".16b",
7012      [(set (v8i16 V128:$Rd),
7013            (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7014                                (extract_high_v16i8 (v16i8 V128:$Rm))))))]>;
7015  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7016                                                  V128, V64, V64,
7017                                                  asm, ".4s", ".4h", ".4h",
7018      [(set (v4i32 V128:$Rd),
7019            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
7020  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7021                                                  V128, V128, V128,
7022                                                  asm#"2", ".4s", ".8h", ".8h",
7023      [(set (v4i32 V128:$Rd),
7024            (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7025                                  (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
7026  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7027                                                  V128, V64, V64,
7028                                                  asm, ".2d", ".2s", ".2s",
7029      [(set (v2i64 V128:$Rd),
7030            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
7031  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7032                                                  V128, V128, V128,
7033                                                  asm#"2", ".2d", ".4s", ".4s",
7034      [(set (v2i64 V128:$Rd),
7035            (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7036                                 (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
7037}
7038
7039multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
7040                                          string asm,
7041                                          SDPatternOperator OpNode> {
7042  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
7043                                                  V128, V64, V64,
7044                                                  asm, ".8h", ".8b", ".8b",
7045    [(set (v8i16 V128:$dst),
7046          (add (v8i16 V128:$Rd),
7047               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
7048  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
7049                                                 V128, V128, V128,
7050                                                 asm#"2", ".8h", ".16b", ".16b",
7051    [(set (v8i16 V128:$dst),
7052          (add (v8i16 V128:$Rd),
7053               (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7054                                   (extract_high_v16i8 (v16i8 V128:$Rm)))))))]>;
7055  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7056                                                  V128, V64, V64,
7057                                                  asm, ".4s", ".4h", ".4h",
7058    [(set (v4i32 V128:$dst),
7059          (add (v4i32 V128:$Rd),
7060               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
7061  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7062                                                  V128, V128, V128,
7063                                                  asm#"2", ".4s", ".8h", ".8h",
7064    [(set (v4i32 V128:$dst),
7065          (add (v4i32 V128:$Rd),
7066               (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7067                                    (extract_high_v8i16 (v8i16 V128:$Rm)))))))]>;
7068  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7069                                                  V128, V64, V64,
7070                                                  asm, ".2d", ".2s", ".2s",
7071    [(set (v2i64 V128:$dst),
7072          (add (v2i64 V128:$Rd),
7073               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
7074  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7075                                                  V128, V128, V128,
7076                                                  asm#"2", ".2d", ".4s", ".4s",
7077    [(set (v2i64 V128:$dst),
7078          (add (v2i64 V128:$Rd),
7079               (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7080                                    (extract_high_v4i32 (v4i32 V128:$Rm)))))))]>;
7081}
7082
7083multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
7084                                  SDPatternOperator OpNode = null_frag> {
7085  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7086                                                  V128, V64, V64,
7087                                                  asm, ".8h", ".8b", ".8b",
7088      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
7089  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7090                                                 V128, V128, V128,
7091                                                 asm#"2", ".8h", ".16b", ".16b",
7092      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7093                                      (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7094  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7095                                                  V128, V64, V64,
7096                                                  asm, ".4s", ".4h", ".4h",
7097      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
7098  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7099                                                  V128, V128, V128,
7100                                                  asm#"2", ".4s", ".8h", ".8h",
7101      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7102                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7103  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7104                                                  V128, V64, V64,
7105                                                  asm, ".2d", ".2s", ".2s",
7106      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
7107  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7108                                                  V128, V128, V128,
7109                                                  asm#"2", ".2d", ".4s", ".4s",
7110      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7111                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7112}
7113
7114multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
7115                                      string asm,
7116                                      SDPatternOperator OpNode> {
7117  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
7118                                                  V128, V64, V64,
7119                                                  asm, ".8h", ".8b", ".8b",
7120    [(set (v8i16 V128:$dst),
7121          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
7122  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
7123                                                 V128, V128, V128,
7124                                                 asm#"2", ".8h", ".16b", ".16b",
7125    [(set (v8i16 V128:$dst),
7126          (OpNode (v8i16 V128:$Rd),
7127                  (extract_high_v16i8 (v16i8 V128:$Rn)),
7128                  (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7129  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7130                                                  V128, V64, V64,
7131                                                  asm, ".4s", ".4h", ".4h",
7132    [(set (v4i32 V128:$dst),
7133          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
7134  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7135                                                  V128, V128, V128,
7136                                                  asm#"2", ".4s", ".8h", ".8h",
7137    [(set (v4i32 V128:$dst),
7138          (OpNode (v4i32 V128:$Rd),
7139                  (extract_high_v8i16 (v8i16 V128:$Rn)),
7140                  (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7141  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7142                                                  V128, V64, V64,
7143                                                  asm, ".2d", ".2s", ".2s",
7144    [(set (v2i64 V128:$dst),
7145          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
7146  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7147                                                  V128, V128, V128,
7148                                                  asm#"2", ".2d", ".4s", ".4s",
7149    [(set (v2i64 V128:$dst),
7150          (OpNode (v2i64 V128:$Rd),
7151                  (extract_high_v4i32 (v4i32 V128:$Rn)),
7152                  (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7153}
7154
7155multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
7156                                           SDPatternOperator Accum> {
7157  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7158                                                  V128, V64, V64,
7159                                                  asm, ".4s", ".4h", ".4h",
7160    [(set (v4i32 V128:$dst),
7161          (Accum (v4i32 V128:$Rd),
7162                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7163                                                (v4i16 V64:$Rm)))))]>;
7164  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7165                                                  V128, V128, V128,
7166                                                  asm#"2", ".4s", ".8h", ".8h",
7167    [(set (v4i32 V128:$dst),
7168          (Accum (v4i32 V128:$Rd),
7169                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 (v8i16 V128:$Rn)),
7170                                            (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
7171  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7172                                                  V128, V64, V64,
7173                                                  asm, ".2d", ".2s", ".2s",
7174    [(set (v2i64 V128:$dst),
7175          (Accum (v2i64 V128:$Rd),
7176                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
7177                                                (v2i32 V64:$Rm)))))]>;
7178  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7179                                                  V128, V128, V128,
7180                                                  asm#"2", ".2d", ".4s", ".4s",
7181    [(set (v2i64 V128:$dst),
7182          (Accum (v2i64 V128:$Rd),
7183                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 (v4i32 V128:$Rn)),
7184                                            (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
7185}
7186
7187multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
7188                                  SDPatternOperator OpNode> {
7189  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7190                                                  V128, V128, V64,
7191                                                  asm, ".8h", ".8h", ".8b",
7192       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
7193  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7194                                                  V128, V128, V128,
7195                                                  asm#"2", ".8h", ".8h", ".16b",
7196       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7197                                       (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7198  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7199                                                  V128, V128, V64,
7200                                                  asm, ".4s", ".4s", ".4h",
7201       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
7202  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7203                                                  V128, V128, V128,
7204                                                  asm#"2", ".4s", ".4s", ".8h",
7205       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7206                                       (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7207  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7208                                                  V128, V128, V64,
7209                                                  asm, ".2d", ".2d", ".2s",
7210       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
7211  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7212                                                  V128, V128, V128,
7213                                                  asm#"2", ".2d", ".2d", ".4s",
7214       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7215                                       (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7216}
7217
7218//----------------------------------------------------------------------------
7219// AdvSIMD bitwise extract from vector
7220//----------------------------------------------------------------------------
7221
7222class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
7223                             string asm, string kind>
7224  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
7225      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
7226      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
7227      [(set (vty regtype:$Rd),
7228            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
7229    Sched<[!if(size, WriteVq, WriteVd)]> {
7230  bits<5> Rd;
7231  bits<5> Rn;
7232  bits<5> Rm;
7233  bits<4> imm;
7234  let Inst{31}    = 0;
7235  let Inst{30}    = size;
7236  let Inst{29-21} = 0b101110000;
7237  let Inst{20-16} = Rm;
7238  let Inst{15}    = 0;
7239  let Inst{14-11} = imm;
7240  let Inst{10}    = 0;
7241  let Inst{9-5}   = Rn;
7242  let Inst{4-0}   = Rd;
7243}
7244
7245
7246multiclass SIMDBitwiseExtract<string asm> {
7247  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
7248    let imm{3} = 0;
7249  }
7250  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
7251}
7252
7253//----------------------------------------------------------------------------
7254// AdvSIMD zip vector
7255//----------------------------------------------------------------------------
7256
7257class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
7258                        string asm, string kind, SDNode OpNode, ValueType valty>
7259  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7260      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
7261      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
7262      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
7263    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
7264  bits<5> Rd;
7265  bits<5> Rn;
7266  bits<5> Rm;
7267  let Inst{31}    = 0;
7268  let Inst{30}    = size{0};
7269  let Inst{29-24} = 0b001110;
7270  let Inst{23-22} = size{2-1};
7271  let Inst{21}    = 0;
7272  let Inst{20-16} = Rm;
7273  let Inst{15}    = 0;
7274  let Inst{14-12} = opc;
7275  let Inst{11-10} = 0b10;
7276  let Inst{9-5}   = Rn;
7277  let Inst{4-0}   = Rd;
7278}
7279
7280multiclass SIMDZipVector<bits<3>opc, string asm,
7281                         SDNode OpNode> {
7282  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
7283      asm, ".8b", OpNode, v8i8>;
7284  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
7285      asm, ".16b", OpNode, v16i8>;
7286  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
7287      asm, ".4h", OpNode, v4i16>;
7288  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
7289      asm, ".8h", OpNode, v8i16>;
7290  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
7291      asm, ".2s", OpNode, v2i32>;
7292  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
7293      asm, ".4s", OpNode, v4i32>;
7294  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
7295      asm, ".2d", OpNode, v2i64>;
7296
7297  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
7298        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7299  def : Pat<(v4bf16 (OpNode V64:$Rn, V64:$Rm)),
7300        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7301  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
7302        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7303  def : Pat<(v8bf16 (OpNode V128:$Rn, V128:$Rm)),
7304        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7305  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
7306        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
7307  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
7308        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
7309  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
7310        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
7311}
7312
7313//----------------------------------------------------------------------------
7314// AdvSIMD three register scalar instructions
7315//----------------------------------------------------------------------------
7316
7317let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7318class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
7319                        RegisterClass regtype, string asm,
7320                        list<dag> pattern>
7321  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7322      "\t$Rd, $Rn, $Rm", "", pattern>,
7323    Sched<[WriteVd]> {
7324  bits<5> Rd;
7325  bits<5> Rn;
7326  bits<5> Rm;
7327  let Inst{31-30} = 0b01;
7328  let Inst{29}    = U;
7329  let Inst{28-24} = 0b11110;
7330  let Inst{23-21} = size;
7331  let Inst{20-16} = Rm;
7332  let Inst{15-11} = opcode;
7333  let Inst{10}    = 1;
7334  let Inst{9-5}   = Rn;
7335  let Inst{4-0}   = Rd;
7336}
7337
7338let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7339class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
7340                        dag oops, dag iops, string asm,
7341            list<dag> pattern>
7342  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
7343    Sched<[WriteVd]> {
7344  bits<5> Rd;
7345  bits<5> Rn;
7346  bits<5> Rm;
7347  let Inst{31-30} = 0b01;
7348  let Inst{29}    = U;
7349  let Inst{28-24} = 0b11110;
7350  let Inst{23-22} = size;
7351  let Inst{21}    = R;
7352  let Inst{20-16} = Rm;
7353  let Inst{15-11} = opcode;
7354  let Inst{10}    = 1;
7355  let Inst{9-5}   = Rn;
7356  let Inst{4-0}   = Rd;
7357}
7358
7359multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
7360                            SDPatternOperator OpNode> {
7361  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7362    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7363}
7364
7365multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
7366                               SDPatternOperator OpNode> {
7367  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7368    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7369  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
7370  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7371  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
7372
7373  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7374            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
7375  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
7376            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
7377}
7378
7379multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
7380                             SDPatternOperator OpNode> {
7381  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
7382                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7383  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7384}
7385
7386multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
7387  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
7388                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
7389                                     asm, []>;
7390  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
7391                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
7392                                     asm, []>;
7393}
7394
7395multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
7396                             SDPatternOperator OpNode = null_frag,
7397                             Predicate pred = HasNEON> {
7398  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7399    let Predicates = [pred] in {
7400    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7401      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7402    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7403      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7404    }
7405    let Predicates = [pred, HasFullFP16] in {
7406    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7407      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
7408    }
7409  }
7410
7411  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7412            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7413}
7414
7415multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
7416                                SDPatternOperator OpNode = null_frag> {
7417  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7418    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7419      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7420    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7421      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
7422    let Predicates = [HasNEON, HasFullFP16] in {
7423    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7424      []>;
7425    } // Predicates = [HasNEON, HasFullFP16]
7426  }
7427
7428  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7429            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7430}
7431
7432class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
7433              dag oops, dag iops, string asm, string cstr, list<dag> pat>
7434  : I<oops, iops, asm,
7435      "\t$Rd, $Rn, $Rm", cstr, pat>,
7436    Sched<[WriteVd]> {
7437  bits<5> Rd;
7438  bits<5> Rn;
7439  bits<5> Rm;
7440  let Inst{31-30} = 0b01;
7441  let Inst{29}    = U;
7442  let Inst{28-24} = 0b11110;
7443  let Inst{23-22} = size;
7444  let Inst{21}    = 1;
7445  let Inst{20-16} = Rm;
7446  let Inst{15-11} = opcode;
7447  let Inst{10}    = 0;
7448  let Inst{9-5}   = Rn;
7449  let Inst{4-0}   = Rd;
7450}
7451
7452let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7453multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
7454                                  SDPatternOperator OpNode = null_frag> {
7455  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7456                                      (outs FPR32:$Rd),
7457                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
7458  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7459                                      (outs FPR64:$Rd),
7460                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
7461            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7462}
7463
7464let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7465multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
7466                                  SDPatternOperator OpNode = null_frag> {
7467  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7468                                      (outs FPR32:$dst),
7469                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
7470                                      asm, "$Rd = $dst", []>;
7471  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7472                                      (outs FPR64:$dst),
7473                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
7474                                      asm, "$Rd = $dst",
7475            [(set (i64 FPR64:$dst),
7476                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7477}
7478
7479//----------------------------------------------------------------------------
7480// AdvSIMD two register scalar instructions
7481//----------------------------------------------------------------------------
7482
7483let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7484class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7485                        RegisterClass regtype, RegisterClass regtype2,
7486                        string asm, list<dag> pat>
7487  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
7488      "\t$Rd, $Rn", "", pat>,
7489    Sched<[WriteVd]> {
7490  bits<5> Rd;
7491  bits<5> Rn;
7492  let Inst{31-30} = 0b01;
7493  let Inst{29}    = U;
7494  let Inst{28-24} = 0b11110;
7495  let Inst{23-22} = size;
7496  let Inst{21} = 0b1;
7497  let Inst{20-19} = size2;
7498  let Inst{18-17} = 0b00;
7499  let Inst{16-12} = opcode;
7500  let Inst{11-10} = 0b10;
7501  let Inst{9-5}   = Rn;
7502  let Inst{4-0}   = Rd;
7503}
7504
7505let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7506class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
7507                        RegisterClass regtype, RegisterClass regtype2,
7508                        string asm, list<dag> pat>
7509  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
7510      "\t$Rd, $Rn", "$Rd = $dst", pat>,
7511    Sched<[WriteVd]> {
7512  bits<5> Rd;
7513  bits<5> Rn;
7514  let Inst{31-30} = 0b01;
7515  let Inst{29}    = U;
7516  let Inst{28-24} = 0b11110;
7517  let Inst{23-22} = size;
7518  let Inst{21-17} = 0b10000;
7519  let Inst{16-12} = opcode;
7520  let Inst{11-10} = 0b10;
7521  let Inst{9-5}   = Rn;
7522  let Inst{4-0}   = Rd;
7523}
7524
7525
7526let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7527class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7528                        RegisterClass regtype, string asm, string zero>
7529  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7530      "\t$Rd, $Rn, #" # zero, "", []>,
7531    Sched<[WriteVd]> {
7532  bits<5> Rd;
7533  bits<5> Rn;
7534  let Inst{31-30} = 0b01;
7535  let Inst{29}    = U;
7536  let Inst{28-24} = 0b11110;
7537  let Inst{23-22} = size;
7538  let Inst{21} = 0b1;
7539  let Inst{20-19} = size2;
7540  let Inst{18-17} = 0b00;
7541  let Inst{16-12} = opcode;
7542  let Inst{11-10} = 0b10;
7543  let Inst{9-5}   = Rn;
7544  let Inst{4-0}   = Rd;
7545}
7546
7547let mayRaiseFPException = 1, Uses = [FPCR] in
7548class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7549  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7550     [(set (f32 FPR32:$Rd), (AArch64fcvtxnsdr (f64 FPR64:$Rn)))]>,
7551    Sched<[WriteVd]> {
7552  bits<5> Rd;
7553  bits<5> Rn;
7554  let Inst{31-17} = 0b011111100110000;
7555  let Inst{16-12} = opcode;
7556  let Inst{11-10} = 0b10;
7557  let Inst{9-5}   = Rn;
7558  let Inst{4-0}   = Rd;
7559}
7560
7561multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7562                             SDPatternOperator OpNode> {
7563  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7564
7565  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7566            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7567}
7568
7569multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7570                              SDPatternOperator OpNode> {
7571  let mayRaiseFPException = 1, Uses = [FPCR] in {
7572  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7573  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7574  let Predicates = [HasNEON, HasFullFP16] in {
7575  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7576  }
7577  }
7578
7579  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7580                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7581  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7582                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7583  let Predicates = [HasNEON, HasFullFP16] in {
7584  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7585                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7586  }
7587
7588  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7589            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7590}
7591
7592multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7593                          SDPatternOperator OpNode = null_frag,
7594                          list<Predicate> preds = []> {
7595  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7596    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7597
7598  let Predicates = preds in {
7599  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7600            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7601  }
7602}
7603
7604let mayRaiseFPException = 1, Uses = [FPCR] in
7605multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm> {
7606  let Predicates = [HasNEONandIsStreamingSafe] in {
7607  def v1i64       : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,[]>;
7608  def v1i32       : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,[]>;
7609  }
7610  let Predicates = [HasNEONandIsStreamingSafe, HasFullFP16] in {
7611  def v1f16       : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,[]>;
7612  }
7613}
7614
7615let mayRaiseFPException = 1, Uses = [FPCR] in
7616multiclass SIMDFPTwoScalarCVT<bit U, bit S, bits<5> opc, string asm,
7617                              SDPatternOperator OpNode> {
7618  let Predicates = [HasNEONandIsStreamingSafe] in {
7619  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7620                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7621  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7622                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7623  }
7624  let Predicates = [HasNEONandIsStreamingSafe, HasFullFP16] in {
7625  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7626                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7627  }
7628}
7629
7630multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7631                             SDPatternOperator OpNode = null_frag> {
7632  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7633    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7634           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7635    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7636           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7637    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7638    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7639  }
7640
7641  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7642            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7643}
7644
7645multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7646                                 Intrinsic OpNode> {
7647  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7648    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7649        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7650    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7651        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7652    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7653    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7654  }
7655
7656  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7657            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7658}
7659
7660
7661
7662let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7663multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7664                                 SDPatternOperator OpNode = null_frag> {
7665  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7666        [(set (f32 FPR32:$Rd), (OpNode (f64 FPR64:$Rn)))]>;
7667  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7668  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7669}
7670
7671//----------------------------------------------------------------------------
7672// AdvSIMD scalar pairwise instructions
7673//----------------------------------------------------------------------------
7674
7675let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7676class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7677                        RegisterOperand regtype, RegisterOperand vectype,
7678                        string asm, string kind>
7679  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7680      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7681    Sched<[WriteVd]> {
7682  bits<5> Rd;
7683  bits<5> Rn;
7684  let Inst{31-30} = 0b01;
7685  let Inst{29}    = U;
7686  let Inst{28-24} = 0b11110;
7687  let Inst{23-22} = size;
7688  let Inst{21-17} = 0b11000;
7689  let Inst{16-12} = opcode;
7690  let Inst{11-10} = 0b10;
7691  let Inst{9-5}   = Rn;
7692  let Inst{4-0}   = Rd;
7693}
7694
7695multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7696  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7697                                      asm, ".2d">;
7698}
7699
7700let mayRaiseFPException = 1, Uses = [FPCR] in
7701multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7702  let Predicates = [HasNEON, HasFullFP16] in {
7703  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7704                                      asm, ".2h">;
7705  }
7706  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7707                                      asm, ".2s">;
7708  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7709                                      asm, ".2d">;
7710}
7711
7712//----------------------------------------------------------------------------
7713// AdvSIMD across lanes instructions
7714//----------------------------------------------------------------------------
7715
7716let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7717class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7718                          RegisterClass regtype, RegisterOperand vectype,
7719                          string asm, string kind, list<dag> pattern>
7720  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7721      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7722    Sched<[!if(Q, WriteVq, WriteVd)]> {
7723  bits<5> Rd;
7724  bits<5> Rn;
7725  let Inst{31}    = 0;
7726  let Inst{30}    = Q;
7727  let Inst{29}    = U;
7728  let Inst{28-24} = 0b01110;
7729  let Inst{23-22} = size;
7730  let Inst{21-17} = 0b11000;
7731  let Inst{16-12} = opcode;
7732  let Inst{11-10} = 0b10;
7733  let Inst{9-5}   = Rn;
7734  let Inst{4-0}   = Rd;
7735}
7736
7737multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7738                              string asm> {
7739  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7740                                   asm, ".8b", []>;
7741  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7742                                   asm, ".16b", []>;
7743  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7744                                   asm, ".4h", []>;
7745  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7746                                   asm, ".8h", []>;
7747  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7748                                   asm, ".4s", []>;
7749}
7750
7751multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7752  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7753                                   asm, ".8b", []>;
7754  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7755                                   asm, ".16b", []>;
7756  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7757                                   asm, ".4h", []>;
7758  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7759                                   asm, ".8h", []>;
7760  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7761                                   asm, ".4s", []>;
7762}
7763
7764let mayRaiseFPException = 1, Uses = [FPCR] in
7765multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7766                            SDPatternOperator intOp> {
7767  let Predicates = [HasNEON, HasFullFP16] in {
7768  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7769                                   asm, ".4h",
7770        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7771  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7772                                   asm, ".8h",
7773        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7774  } // Predicates = [HasNEON, HasFullFP16]
7775  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7776                                   asm, ".4s",
7777        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7778}
7779
7780//----------------------------------------------------------------------------
7781// AdvSIMD INS/DUP instructions
7782//----------------------------------------------------------------------------
7783
7784// FIXME: There has got to be a better way to factor these. ugh.
7785
7786class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7787                     string operands, string constraints, list<dag> pattern>
7788  : I<outs, ins, asm, operands, constraints, pattern>,
7789    Sched<[!if(Q, WriteVq, WriteVd)]> {
7790  bits<5> Rd;
7791  bits<5> Rn;
7792  let Inst{31} = 0;
7793  let Inst{30} = Q;
7794  let Inst{29} = op;
7795  let Inst{28-21} = 0b01110000;
7796  let Inst{15} = 0;
7797  let Inst{10} = 1;
7798  let Inst{9-5} = Rn;
7799  let Inst{4-0} = Rd;
7800}
7801
7802class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7803                      RegisterOperand vecreg, RegisterClass regtype>
7804  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7805                   "{\t$Rd" # size # ", $Rn" #
7806                   "|" # size # "\t$Rd, $Rn}", "",
7807                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7808  let Inst{20-16} = imm5;
7809  let Inst{14-11} = 0b0001;
7810}
7811
7812class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7813                         ValueType vectype, ValueType insreg,
7814                         RegisterOperand vecreg, Operand idxtype,
7815                         SDNode OpNode>
7816  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7817                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7818                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7819                 [(set (vectype vecreg:$Rd),
7820                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7821  let Inst{14-11} = 0b0000;
7822}
7823
7824class SIMDDup64FromElement
7825  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7826                       VectorIndexD, AArch64duplane64> {
7827  bits<1> idx;
7828  let Inst{20} = idx;
7829  let Inst{19-16} = 0b1000;
7830}
7831
7832class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7833                           RegisterOperand vecreg>
7834  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7835                       VectorIndexS, AArch64duplane32> {
7836  bits<2> idx;
7837  let Inst{20-19} = idx;
7838  let Inst{18-16} = 0b100;
7839}
7840
7841class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7842                           RegisterOperand vecreg>
7843  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7844                       VectorIndexH, AArch64duplane16> {
7845  bits<3> idx;
7846  let Inst{20-18} = idx;
7847  let Inst{17-16} = 0b10;
7848}
7849
7850class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7851                          RegisterOperand vecreg>
7852  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7853                       VectorIndexB, AArch64duplane8> {
7854  bits<4> idx;
7855  let Inst{20-17} = idx;
7856  let Inst{16} = 1;
7857}
7858
7859class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7860                  Operand idxtype, string asm, list<dag> pattern>
7861  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7862                   "{\t$Rd, $Rn" # size # "$idx" #
7863                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7864  let Inst{14-11} = imm4;
7865}
7866
7867class SIMDSMov<bit Q, string size, RegisterClass regtype,
7868               Operand idxtype>
7869  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7870class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7871               Operand idxtype>
7872  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7873      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7874
7875class SIMDMovAlias<string asm, string size, Instruction inst,
7876                   RegisterClass regtype, Operand idxtype>
7877    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7878                    "|" # size # "\t$dst, $src$idx}",
7879                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7880
7881multiclass SMov {
7882  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7883  // streaming mode.
7884  let Predicates = [HasNEONandIsStreamingSafe] in {
7885    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
7886      let Inst{20-16} = 0b00001;
7887    }
7888    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
7889      let Inst{20-16} = 0b00001;
7890    }
7891    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
7892      let Inst{20-16} = 0b00010;
7893    }
7894    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
7895      let Inst{20-16} = 0b00010;
7896    }
7897    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
7898      let Inst{20-16} = 0b00100;
7899    }
7900  }
7901  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7902    bits<4> idx;
7903    let Inst{20-17} = idx;
7904    let Inst{16} = 1;
7905  }
7906  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7907    bits<4> idx;
7908    let Inst{20-17} = idx;
7909    let Inst{16} = 1;
7910  }
7911  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7912    bits<3> idx;
7913    let Inst{20-18} = idx;
7914    let Inst{17-16} = 0b10;
7915  }
7916  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7917    bits<3> idx;
7918    let Inst{20-18} = idx;
7919    let Inst{17-16} = 0b10;
7920  }
7921  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7922    bits<2> idx;
7923    let Inst{20-19} = idx;
7924    let Inst{18-16} = 0b100;
7925  }
7926}
7927
7928multiclass UMov {
7929  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7930  // streaming mode.
7931  let Predicates = [HasNEONandIsStreamingSafe] in {
7932    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
7933      let Inst{20-16} = 0b00001;
7934    }
7935    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
7936      let Inst{20-16} = 0b00010;
7937    }
7938    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
7939      let Inst{20-16} = 0b00100;
7940    }
7941    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
7942      let Inst{20-16} = 0b01000;
7943    }
7944    def : SIMDMovAlias<"mov", ".s",
7945                       !cast<Instruction>(NAME # vi32_idx0),
7946                       GPR32, VectorIndex0>;
7947    def : SIMDMovAlias<"mov", ".d",
7948                       !cast<Instruction>(NAME # vi64_idx0),
7949                       GPR64, VectorIndex0>;
7950  }
7951  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7952    bits<4> idx;
7953    let Inst{20-17} = idx;
7954    let Inst{16} = 1;
7955  }
7956  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7957    bits<3> idx;
7958    let Inst{20-18} = idx;
7959    let Inst{17-16} = 0b10;
7960  }
7961  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7962    bits<2> idx;
7963    let Inst{20-19} = idx;
7964    let Inst{18-16} = 0b100;
7965  }
7966  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7967    bits<1> idx;
7968    let Inst{20} = idx;
7969    let Inst{19-16} = 0b1000;
7970  }
7971  def : SIMDMovAlias<"mov", ".s",
7972                     !cast<Instruction>(NAME#"vi32"),
7973                     GPR32, VectorIndexS>;
7974  def : SIMDMovAlias<"mov", ".d",
7975                     !cast<Instruction>(NAME#"vi64"),
7976                     GPR64, VectorIndexD>;
7977}
7978
7979class SIMDInsFromMain<string size, ValueType vectype,
7980                      RegisterClass regtype, Operand idxtype>
7981  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7982                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7983                   "{\t$Rd" # size # "$idx, $Rn" #
7984                   "|" # size # "\t$Rd$idx, $Rn}",
7985                   "$Rd = $dst",
7986            [(set V128:$dst,
7987              (vector_insert (vectype V128:$Rd), regtype:$Rn, (i64 idxtype:$idx)))]> {
7988  let Inst{14-11} = 0b0011;
7989}
7990
7991class SIMDInsFromElement<string size, ValueType vectype,
7992                         ValueType elttype, Operand idxtype>
7993  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7994                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7995                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7996                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7997                   "$Rd = $dst",
7998         [(set V128:$dst,
7999               (vector_insert
8000                 (vectype V128:$Rd),
8001                 (elttype (vector_extract (vectype V128:$Rn), (i64 idxtype:$idx2))),
8002                 (i64 idxtype:$idx)))]>;
8003
8004class SIMDInsMainMovAlias<string size, Instruction inst,
8005                          RegisterClass regtype, Operand idxtype>
8006    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
8007                        "|" # size #"\t$dst$idx, $src}",
8008                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
8009class SIMDInsElementMovAlias<string size, Instruction inst,
8010                             Operand idxtype>
8011    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
8012                      # "|" # size #"\t$dst$idx, $src$idx2}",
8013                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
8014
8015
8016multiclass SIMDIns {
8017  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
8018    bits<4> idx;
8019    let Inst{20-17} = idx;
8020    let Inst{16} = 1;
8021  }
8022  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
8023    bits<3> idx;
8024    let Inst{20-18} = idx;
8025    let Inst{17-16} = 0b10;
8026  }
8027  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
8028    bits<2> idx;
8029    let Inst{20-19} = idx;
8030    let Inst{18-16} = 0b100;
8031  }
8032  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
8033    bits<1> idx;
8034    let Inst{20} = idx;
8035    let Inst{19-16} = 0b1000;
8036  }
8037
8038  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
8039    bits<4> idx;
8040    bits<4> idx2;
8041    let Inst{20-17} = idx;
8042    let Inst{16} = 1;
8043    let Inst{14-11} = idx2;
8044  }
8045  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
8046    bits<3> idx;
8047    bits<3> idx2;
8048    let Inst{20-18} = idx;
8049    let Inst{17-16} = 0b10;
8050    let Inst{14-12} = idx2;
8051    let Inst{11} = {?};
8052  }
8053  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
8054    bits<2> idx;
8055    bits<2> idx2;
8056    let Inst{20-19} = idx;
8057    let Inst{18-16} = 0b100;
8058    let Inst{14-13} = idx2;
8059    let Inst{12-11} = {?,?};
8060  }
8061  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
8062    bits<1> idx;
8063    bits<1> idx2;
8064    let Inst{20} = idx;
8065    let Inst{19-16} = 0b1000;
8066    let Inst{14} = idx2;
8067    let Inst{13-11} = {?,?,?};
8068  }
8069
8070  // For all forms of the INS instruction, the "mov" mnemonic is the
8071  // preferred alias. Why they didn't just call the instruction "mov" in
8072  // the first place is a very good question indeed...
8073  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
8074                         GPR32, VectorIndexB>;
8075  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
8076                         GPR32, VectorIndexH>;
8077  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
8078                         GPR32, VectorIndexS>;
8079  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
8080                         GPR64, VectorIndexD>;
8081
8082  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
8083                         VectorIndexB>;
8084  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
8085                         VectorIndexH>;
8086  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
8087                         VectorIndexS>;
8088  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
8089                         VectorIndexD>;
8090}
8091
8092//----------------------------------------------------------------------------
8093// AdvSIMD TBL/TBX
8094//----------------------------------------------------------------------------
8095
8096let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8097class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
8098                          RegisterOperand listtype, string asm, string kind>
8099  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
8100       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
8101    Sched<[!if(Q, WriteVq, WriteVd)]> {
8102  bits<5> Vd;
8103  bits<5> Vn;
8104  bits<5> Vm;
8105  let Inst{31}    = 0;
8106  let Inst{30}    = Q;
8107  let Inst{29-21} = 0b001110000;
8108  let Inst{20-16} = Vm;
8109  let Inst{15}    = 0;
8110  let Inst{14-13} = len;
8111  let Inst{12}    = op;
8112  let Inst{11-10} = 0b00;
8113  let Inst{9-5}   = Vn;
8114  let Inst{4-0}   = Vd;
8115}
8116
8117let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8118class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
8119                          RegisterOperand listtype, string asm, string kind>
8120  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
8121       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
8122    Sched<[!if(Q, WriteVq, WriteVd)]> {
8123  bits<5> Vd;
8124  bits<5> Vn;
8125  bits<5> Vm;
8126  let Inst{31}    = 0;
8127  let Inst{30}    = Q;
8128  let Inst{29-21} = 0b001110000;
8129  let Inst{20-16} = Vm;
8130  let Inst{15}    = 0;
8131  let Inst{14-13} = len;
8132  let Inst{12}    = op;
8133  let Inst{11-10} = 0b00;
8134  let Inst{9-5}   = Vn;
8135  let Inst{4-0}   = Vd;
8136}
8137
8138class SIMDTableLookupAlias<string asm, Instruction inst,
8139                          RegisterOperand vectype, RegisterOperand listtype>
8140    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
8141                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
8142
8143multiclass SIMDTableLookup<bit op, string asm> {
8144  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
8145                                      asm, ".8b">;
8146  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
8147                                      asm, ".8b">;
8148  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
8149                                      asm, ".8b">;
8150  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
8151                                      asm, ".8b">;
8152  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
8153                                      asm, ".16b">;
8154  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
8155                                      asm, ".16b">;
8156  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
8157                                      asm, ".16b">;
8158  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
8159                                      asm, ".16b">;
8160
8161  def : SIMDTableLookupAlias<asm # ".8b",
8162                         !cast<Instruction>(NAME#"v8i8One"),
8163                         V64, VecListOne128>;
8164  def : SIMDTableLookupAlias<asm # ".8b",
8165                         !cast<Instruction>(NAME#"v8i8Two"),
8166                         V64, VecListTwo128>;
8167  def : SIMDTableLookupAlias<asm # ".8b",
8168                         !cast<Instruction>(NAME#"v8i8Three"),
8169                         V64, VecListThree128>;
8170  def : SIMDTableLookupAlias<asm # ".8b",
8171                         !cast<Instruction>(NAME#"v8i8Four"),
8172                         V64, VecListFour128>;
8173  def : SIMDTableLookupAlias<asm # ".16b",
8174                         !cast<Instruction>(NAME#"v16i8One"),
8175                         V128, VecListOne128>;
8176  def : SIMDTableLookupAlias<asm # ".16b",
8177                         !cast<Instruction>(NAME#"v16i8Two"),
8178                         V128, VecListTwo128>;
8179  def : SIMDTableLookupAlias<asm # ".16b",
8180                         !cast<Instruction>(NAME#"v16i8Three"),
8181                         V128, VecListThree128>;
8182  def : SIMDTableLookupAlias<asm # ".16b",
8183                         !cast<Instruction>(NAME#"v16i8Four"),
8184                         V128, VecListFour128>;
8185}
8186
8187multiclass SIMDTableLookupTied<bit op, string asm> {
8188  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
8189                                      asm, ".8b">;
8190  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
8191                                      asm, ".8b">;
8192  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
8193                                      asm, ".8b">;
8194  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
8195                                      asm, ".8b">;
8196  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
8197                                      asm, ".16b">;
8198  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
8199                                      asm, ".16b">;
8200  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
8201                                      asm, ".16b">;
8202  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
8203                                      asm, ".16b">;
8204
8205  def : SIMDTableLookupAlias<asm # ".8b",
8206                         !cast<Instruction>(NAME#"v8i8One"),
8207                         V64, VecListOne128>;
8208  def : SIMDTableLookupAlias<asm # ".8b",
8209                         !cast<Instruction>(NAME#"v8i8Two"),
8210                         V64, VecListTwo128>;
8211  def : SIMDTableLookupAlias<asm # ".8b",
8212                         !cast<Instruction>(NAME#"v8i8Three"),
8213                         V64, VecListThree128>;
8214  def : SIMDTableLookupAlias<asm # ".8b",
8215                         !cast<Instruction>(NAME#"v8i8Four"),
8216                         V64, VecListFour128>;
8217  def : SIMDTableLookupAlias<asm # ".16b",
8218                         !cast<Instruction>(NAME#"v16i8One"),
8219                         V128, VecListOne128>;
8220  def : SIMDTableLookupAlias<asm # ".16b",
8221                         !cast<Instruction>(NAME#"v16i8Two"),
8222                         V128, VecListTwo128>;
8223  def : SIMDTableLookupAlias<asm # ".16b",
8224                         !cast<Instruction>(NAME#"v16i8Three"),
8225                         V128, VecListThree128>;
8226  def : SIMDTableLookupAlias<asm # ".16b",
8227                         !cast<Instruction>(NAME#"v16i8Four"),
8228                         V128, VecListFour128>;
8229}
8230
8231//----------------------------------------------------------------------------
8232// AdvSIMD LUT
8233//----------------------------------------------------------------------------
8234let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8235class BaseSIMDTableLookupIndexed<bit Q, bits<5> opc, RegisterOperand vectype,
8236                            RegisterOperand listtype, Operand idx_type,
8237                            string asm, string kind>
8238  : I<(outs vectype:$Rd),
8239      (ins listtype:$Rn, vectype:$Rm, idx_type:$idx),
8240      asm, "\t$Rd" # kind # ", $Rn, $Rm$idx", "", []>,
8241    Sched<[]> {
8242  bits<5> Rd;
8243  bits<5> Rn;
8244  bits<5> Rm;
8245  let Inst{31}    = 0;
8246  let Inst{30}    = Q;
8247  let Inst{29-24} = 0b001110;
8248  let Inst{23-22} = opc{4-3};
8249  let Inst{21}    = 0;
8250  let Inst{20-16} = Rm;
8251  let Inst{15}    = 0;
8252  let Inst{14-12} = opc{2-0};
8253  let Inst{11-10} = 0b00;
8254  let Inst{9-5}   = Rn;
8255  let Inst{4-0}   = Rd;
8256}
8257
8258multiclass BaseSIMDTableLookupIndexed2<string asm> {
8259  def v16f8 : BaseSIMDTableLookupIndexed<0b1, {0b10,?,?,0b1}, V128, VecListOne16b, VectorIndexS, asm, ".16b"> {
8260    bits<2> idx;
8261    let Inst{14-13} = idx;
8262  }
8263  def v8f16 : BaseSIMDTableLookupIndexed<0b1, {0b11,?,?,?}, V128, VecListOne8h, VectorIndexH, asm, ".8h" > {
8264    bits<3> idx;
8265    let Inst{14-12} = idx;
8266  }
8267}
8268
8269multiclass BaseSIMDTableLookupIndexed4<string asm> {
8270  def v16f8 : BaseSIMDTableLookupIndexed<0b1, {0b01,?,0b10}, V128, VecListOne16b, VectorIndexD, asm, ".16b"> {
8271    bit idx;
8272    let Inst{14} = idx;
8273  }
8274  def v8f16 : BaseSIMDTableLookupIndexed<0b1, {0b01,?,?,0b1}, V128, VecListTwo8h, VectorIndexS, asm, ".8h" > {
8275    bits<2> idx;
8276    let Inst{14-13} = idx;
8277  }
8278}
8279
8280//----------------------------------------------------------------------------
8281// AdvSIMD scalar DUP
8282//----------------------------------------------------------------------------
8283let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8284class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
8285                        string asm, string kind, Operand idxtype>
8286  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
8287       "{\t$dst, $src" # kind # "$idx" #
8288       "|\t$dst, $src$idx}", "", []>,
8289    Sched<[WriteVd]> {
8290  bits<5> dst;
8291  bits<5> src;
8292  let Inst{31-21} = 0b01011110000;
8293  let Inst{15-10} = 0b000001;
8294  let Inst{9-5}   = src;
8295  let Inst{4-0}   = dst;
8296}
8297
8298class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
8299      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
8300    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
8301                    # "|\t$dst, $src$index}",
8302                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
8303
8304
8305multiclass SIMDScalarDUP<string asm> {
8306  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
8307    bits<4> idx;
8308    let Inst{20-17} = idx;
8309    let Inst{16} = 1;
8310  }
8311  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
8312    bits<3> idx;
8313    let Inst{20-18} = idx;
8314    let Inst{17-16} = 0b10;
8315  }
8316  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
8317    bits<2> idx;
8318    let Inst{20-19} = idx;
8319    let Inst{18-16} = 0b100;
8320  }
8321  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
8322    bits<1> idx;
8323    let Inst{20} = idx;
8324    let Inst{19-16} = 0b1000;
8325  }
8326
8327  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
8328                                                          VectorIndexD:$idx)))),
8329            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
8330
8331  // 'DUP' mnemonic aliases.
8332  def : SIMDScalarDUPAlias<"dup", ".b",
8333                           !cast<Instruction>(NAME#"i8"),
8334                           FPR8, V128, VectorIndexB>;
8335  def : SIMDScalarDUPAlias<"dup", ".h",
8336                           !cast<Instruction>(NAME#"i16"),
8337                           FPR16, V128, VectorIndexH>;
8338  def : SIMDScalarDUPAlias<"dup", ".s",
8339                           !cast<Instruction>(NAME#"i32"),
8340                           FPR32, V128, VectorIndexS>;
8341  def : SIMDScalarDUPAlias<"dup", ".d",
8342                           !cast<Instruction>(NAME#"i64"),
8343                           FPR64, V128, VectorIndexD>;
8344}
8345
8346//----------------------------------------------------------------------------
8347// AdvSIMD modified immediate instructions
8348//----------------------------------------------------------------------------
8349
8350class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
8351                          string asm, string op_string,
8352                          string cstr, list<dag> pattern>
8353  : I<oops, iops, asm, op_string, cstr, pattern>,
8354    Sched<[!if(Q, WriteVq, WriteVd)]> {
8355  bits<5> Rd;
8356  bits<8> imm8;
8357  let Inst{31}    = 0;
8358  let Inst{30}    = Q;
8359  let Inst{29}    = op;
8360  let Inst{28-19} = 0b0111100000;
8361  let Inst{18-16} = imm8{7-5};
8362  let Inst{11} = op2;
8363  let Inst{10} = 1;
8364  let Inst{9-5}   = imm8{4-0};
8365  let Inst{4-0}   = Rd;
8366}
8367
8368class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
8369                                Operand immtype, dag opt_shift_iop,
8370                                string opt_shift, string asm, string kind,
8371                                list<dag> pattern>
8372  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
8373                        !con((ins immtype:$imm8), opt_shift_iop), asm,
8374                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
8375                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8376                        "", pattern> {
8377  let DecoderMethod = "DecodeModImmInstruction";
8378}
8379
8380class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
8381                                Operand immtype, dag opt_shift_iop,
8382                                string opt_shift, string asm, string kind,
8383                                list<dag> pattern>
8384  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
8385                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
8386                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
8387                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8388                        "$Rd = $dst", pattern> {
8389  let DecoderMethod = "DecodeModImmTiedInstruction";
8390}
8391
8392class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
8393                                     RegisterOperand vectype, string asm,
8394                                     string kind, list<dag> pattern>
8395  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8396                              (ins logical_vec_shift:$shift),
8397                              "$shift", asm, kind, pattern> {
8398  bits<2> shift;
8399  let Inst{15}    = b15_b12{1};
8400  let Inst{14-13} = shift;
8401  let Inst{12}    = b15_b12{0};
8402}
8403
8404class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
8405                                     RegisterOperand vectype, string asm,
8406                                     string kind, list<dag> pattern>
8407  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8408                              (ins logical_vec_shift:$shift),
8409                              "$shift", asm, kind, pattern> {
8410  bits<2> shift;
8411  let Inst{15}    = b15_b12{1};
8412  let Inst{14-13} = shift;
8413  let Inst{12}    = b15_b12{0};
8414}
8415
8416
8417class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
8418                                         RegisterOperand vectype, string asm,
8419                                         string kind, list<dag> pattern>
8420  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8421                              (ins logical_vec_hw_shift:$shift),
8422                              "$shift", asm, kind, pattern> {
8423  bits<2> shift;
8424  let Inst{15} = b15_b12{1};
8425  let Inst{14} = 0;
8426  let Inst{13} = shift{0};
8427  let Inst{12} = b15_b12{0};
8428}
8429
8430class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
8431                                         RegisterOperand vectype, string asm,
8432                                         string kind, list<dag> pattern>
8433  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8434                              (ins logical_vec_hw_shift:$shift),
8435                              "$shift", asm, kind, pattern> {
8436  bits<2> shift;
8437  let Inst{15} = b15_b12{1};
8438  let Inst{14} = 0;
8439  let Inst{13} = shift{0};
8440  let Inst{12} = b15_b12{0};
8441}
8442
8443multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
8444                                      string asm> {
8445  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
8446                                                 asm, ".4h", []>;
8447  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
8448                                                 asm, ".8h", []>;
8449
8450  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
8451                                             asm, ".2s", []>;
8452  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
8453                                             asm, ".4s", []>;
8454}
8455
8456multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
8457                                      bits<2> w_cmode, string asm,
8458                                      SDNode OpNode> {
8459  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
8460                                                 asm, ".4h",
8461             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
8462                                             imm0_255:$imm8,
8463                                             (i32 imm:$shift)))]>;
8464  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
8465                                                 asm, ".8h",
8466             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
8467                                              imm0_255:$imm8,
8468                                              (i32 imm:$shift)))]>;
8469
8470  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
8471                                             asm, ".2s",
8472             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
8473                                             imm0_255:$imm8,
8474                                             (i32 imm:$shift)))]>;
8475  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
8476                                             asm, ".4s",
8477             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
8478                                              imm0_255:$imm8,
8479                                              (i32 imm:$shift)))]>;
8480}
8481
8482class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
8483                             RegisterOperand vectype, string asm,
8484                             string kind, list<dag> pattern>
8485  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8486                              (ins move_vec_shift:$shift),
8487                              "$shift", asm, kind, pattern> {
8488  bits<1> shift;
8489  let Inst{15-13} = cmode{3-1};
8490  let Inst{12}    = shift;
8491}
8492
8493class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
8494                                   RegisterOperand vectype,
8495                                   Operand imm_type, string asm,
8496                                   string kind, list<dag> pattern>
8497  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
8498                              asm, kind, pattern> {
8499  let Inst{15-12} = cmode;
8500}
8501
8502class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
8503                                   list<dag> pattern>
8504  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
8505                        "\t$Rd, $imm8", "", pattern> {
8506  let Inst{15-12} = cmode;
8507  let DecoderMethod = "DecodeModImmInstruction";
8508}
8509
8510//----------------------------------------------------------------------------
8511// AdvSIMD indexed element
8512//----------------------------------------------------------------------------
8513
8514let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8515class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8516                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8517                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8518                      string apple_kind, string dst_kind, string lhs_kind,
8519                      string rhs_kind, list<dag> pattern>
8520  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
8521      asm,
8522      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8523      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
8524    Sched<[WriteVd]> {
8525  bits<5> Rd;
8526  bits<5> Rn;
8527  bits<5> Rm;
8528
8529  let Inst{31}    = 0;
8530  let Inst{30}    = Q;
8531  let Inst{29}    = U;
8532  let Inst{28}    = Scalar;
8533  let Inst{27-24} = 0b1111;
8534  let Inst{23-22} = size;
8535  // Bit 21 must be set by the derived class.
8536  let Inst{20-16} = Rm;
8537  let Inst{15-12} = opc;
8538  // Bit 11 must be set by the derived class.
8539  let Inst{10}    = 0;
8540  let Inst{9-5}   = Rn;
8541  let Inst{4-0}   = Rd;
8542}
8543
8544let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8545class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8546                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8547                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8548                      string apple_kind, string dst_kind, string lhs_kind,
8549                      string rhs_kind, list<dag> pattern>
8550  : I<(outs dst_reg:$dst),
8551      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
8552      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8553      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
8554    Sched<[WriteVd]> {
8555  bits<5> Rd;
8556  bits<5> Rn;
8557  bits<5> Rm;
8558
8559  let Inst{31}    = 0;
8560  let Inst{30}    = Q;
8561  let Inst{29}    = U;
8562  let Inst{28}    = Scalar;
8563  let Inst{27-24} = 0b1111;
8564  let Inst{23-22} = size;
8565  // Bit 21 must be set by the derived class.
8566  let Inst{20-16} = Rm;
8567  let Inst{15-12} = opc;
8568  // Bit 11 must be set by the derived class.
8569  let Inst{10}    = 0;
8570  let Inst{9-5}   = Rn;
8571  let Inst{4-0}   = Rd;
8572}
8573
8574
8575//----------------------------------------------------------------------------
8576// Armv8.6 BFloat16 Extension
8577//----------------------------------------------------------------------------
8578let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8579
8580class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8581                                   string kind2, RegisterOperand RegType,
8582                                   ValueType AccumType, ValueType InputType>
8583  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8584                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8585                                            (InputType RegType:$Rn),
8586                                            (InputType RegType:$Rm)))]> {
8587  let AsmString = !strconcat(asm,
8588                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8589                               ", $Rm" # kind2 # "}");
8590}
8591
8592multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8593  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8594                                           v2f32, v4bf16>;
8595  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8596                                           v4f32, v8bf16>;
8597}
8598
8599class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
8600                                      string dst_kind, string lhs_kind,
8601                                      string rhs_kind,
8602                                      RegisterOperand RegType,
8603                                      ValueType AccumType,
8604                                      ValueType InputType>
8605  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
8606                        RegType, RegType, V128, VectorIndexS,
8607                        asm, "", dst_kind, lhs_kind, rhs_kind,
8608        [(set (AccumType RegType:$dst),
8609              (AccumType (int_aarch64_neon_bfdot
8610                                 (AccumType RegType:$Rd),
8611                                 (InputType RegType:$Rn),
8612                                 (InputType (bitconvert (AccumType
8613                                    (AArch64duplane32 (v4f32 V128:$Rm),
8614                                        VectorIndexS:$idx)))))))]> {
8615
8616  bits<2> idx;
8617  let Inst{21}    = idx{0};  // L
8618  let Inst{11}    = idx{1};  // H
8619}
8620
8621multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
8622
8623  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
8624                                               ".2h", V64, v2f32, v4bf16>;
8625  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
8626                                              ".2h", V128, v4f32, v8bf16>;
8627}
8628
8629let mayRaiseFPException = 1, Uses = [FPCR] in
8630class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
8631  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
8632              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
8633                                               (v8bf16 V128:$Rn),
8634                                               (v8bf16 V128:$Rm)))]> {
8635  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
8636}
8637
8638let mayRaiseFPException = 1, Uses = [FPCR] in
8639class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
8640  : I<(outs V128:$dst),
8641      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
8642      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
8643          [(set (v4f32 V128:$dst),
8644                (v4f32 (OpNode (v4f32 V128:$Rd),
8645                               (v8bf16 V128:$Rn),
8646                               (v8bf16
8647                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
8648                                      VectorIndexH:$idx)))))]>,
8649    Sched<[WriteVq]> {
8650  bits<5> Rd;
8651  bits<5> Rn;
8652  bits<4> Rm;
8653  bits<3> idx;
8654
8655  let Inst{31}    = 0;
8656  let Inst{30}    = Q;
8657  let Inst{29-22} = 0b00111111;
8658  let Inst{21-20} = idx{1-0};
8659  let Inst{19-16} = Rm;
8660  let Inst{15-12} = 0b1111;
8661  let Inst{11}    = idx{2};   // H
8662  let Inst{10}    = 0;
8663  let Inst{9-5}   = Rn;
8664  let Inst{4-0}   = Rd;
8665}
8666
8667class SIMDThreeSameVectorBF16MatrixMul<string asm>
8668  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
8669                                V128, asm, ".4s",
8670                          [(set (v4f32 V128:$dst),
8671                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
8672                                                         (v8bf16 V128:$Rn),
8673                                                         (v8bf16 V128:$Rm)))]> {
8674  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8675                                    ", $Rm", ".8h", "}");
8676}
8677
8678let mayRaiseFPException = 1, Uses = [FPCR] in
8679class SIMD_BFCVTN
8680  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8681                           "bfcvtn", ".4h", ".4s",
8682    [(set (v8bf16 V128:$Rd),
8683          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8684
8685let mayRaiseFPException = 1, Uses = [FPCR] in
8686class SIMD_BFCVTN2
8687  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8688                           "bfcvtn2", ".8h", ".4s",
8689    [(set (v8bf16 V128:$dst),
8690          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8691
8692let mayRaiseFPException = 1, Uses = [FPCR] in
8693class BF16ToSinglePrecision<string asm>
8694  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8695    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8696    Sched<[WriteFCvt]> {
8697  bits<5> Rd;
8698  bits<5> Rn;
8699  let Inst{31-10} = 0b0001111001100011010000;
8700  let Inst{9-5}   = Rn;
8701  let Inst{4-0}   = Rd;
8702}
8703} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8704
8705//----------------------------------------------------------------------------
8706class BaseSIMDThreeSameVectorIndexB<bit Q, bit U, bits<2> sz, bits<4> opc,
8707                                    string asm, string dst_kind,
8708                                    RegisterOperand RegType,
8709                                    RegisterOperand RegType_lo>
8710  : BaseSIMDIndexedTied<Q, U, 0b0, sz, opc,
8711                        RegType, RegType, RegType_lo, VectorIndexB,
8712                        asm, "", dst_kind, ".16b", ".b", []> {
8713
8714  // idx = H:L:M
8715  bits<4> idx;
8716  let Inst{11}    = idx{3};
8717  let Inst{21-19} = idx{2-0};
8718}
8719
8720multiclass SIMDThreeSameVectorMLAIndex<bit Q, string asm> {
8721  def v8f16 : BaseSIMDThreeSameVectorIndexB<Q, 0b0, 0b11, 0b0000, asm, ".8h",
8722                                            V128, V128_0to7>;
8723}
8724
8725multiclass SIMDThreeSameVectorMLALIndex<bit Q, bits<2> sz, string asm> {
8726  def v4f32 : BaseSIMDThreeSameVectorIndexB<Q, 0b1, sz, 0b1000, asm, ".4s",
8727                                            V128, V128_0to7>;
8728}
8729
8730//----------------------------------------------------------------------------
8731// Armv8.6 Matrix Multiply Extension
8732//----------------------------------------------------------------------------
8733
8734class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8735  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8736              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8737                                               (v16i8 V128:$Rn),
8738                                               (v16i8 V128:$Rm)))]> {
8739  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8740}
8741
8742//----------------------------------------------------------------------------
8743// ARMv8.2-A Dot Product Instructions (Indexed)
8744class BaseSIMDThreeSameVectorIndexS<bit Q, bit U, bits<2> size, bits<4> opc, string asm,
8745                                    string dst_kind, string lhs_kind, string rhs_kind,
8746                                    RegisterOperand RegType,
8747                                    ValueType AccumType, ValueType InputType,
8748                                    SDPatternOperator OpNode> :
8749        BaseSIMDIndexedTied<Q, U, 0b0, size, opc, RegType, RegType, V128,
8750                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8751        [(set (AccumType RegType:$dst),
8752              (AccumType (OpNode (AccumType RegType:$Rd),
8753                                 (InputType RegType:$Rn),
8754                                 (InputType (bitconvert (AccumType
8755                                    (AArch64duplane32 (v4i32 V128:$Rm),
8756                                        VectorIndexS:$idx)))))))]> {
8757  bits<2> idx;
8758  let Inst{21}    = idx{0};  // L
8759  let Inst{11}    = idx{1};  // H
8760}
8761
8762multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8763                                       SDPatternOperator OpNode> {
8764  def v8i8  : BaseSIMDThreeSameVectorIndexS<0, U, size, {0b111, Mixed}, asm, ".2s", ".8b", ".4b",
8765                                              V64, v2i32, v8i8, OpNode>;
8766  def v16i8 : BaseSIMDThreeSameVectorIndexS<1, U, size, {0b111, Mixed}, asm, ".4s", ".16b", ".4b",
8767                                              V128, v4i32, v16i8, OpNode>;
8768}
8769
8770// TODO: The vectors v8i8 and v16i8 should be v8f8 and v16f8
8771multiclass SIMDThreeSameVectorFP8DOT4Index<string asm> {
8772  def v8f8 : BaseSIMDThreeSameVectorIndexS<0b0, 0b0, 0b00, 0b0000, asm, ".2s", ".8b", ".4b",
8773                                           V64, v2f32, v8i8, null_frag>;
8774  def v16f8 : BaseSIMDThreeSameVectorIndexS<0b1, 0b0, 0b00, 0b0000, asm, ".4s", ".16b",".4b",
8775                                            V128, v4f32, v16i8, null_frag>;
8776}
8777
8778// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8779let mayRaiseFPException = 1, Uses = [FPCR] in
8780class BaseSIMDThreeSameVectorIndexH<bit Q, bit U, bits<2> sz, bits<4> opc, string asm,
8781                                      string dst_kind, string lhs_kind,
8782                                      string rhs_kind, RegisterOperand RegType,
8783                                      RegisterOperand RegType_lo, ValueType AccumType,
8784                                      ValueType InputType, SDPatternOperator OpNode> :
8785        BaseSIMDIndexedTied<Q, U, 0, sz, opc, RegType, RegType, RegType_lo,
8786                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8787          [(set (AccumType RegType:$dst),
8788                (AccumType (OpNode (AccumType RegType:$Rd),
8789                                   (InputType RegType:$Rn),
8790                                   (InputType (AArch64duplane16 (v8f16 V128_lo:$Rm),
8791                                                VectorIndexH:$idx)))))]> {
8792  // idx = H:L:M
8793  bits<3> idx;
8794  let Inst{11} = idx{2}; // H
8795  let Inst{21} = idx{1}; // L
8796  let Inst{20} = idx{0}; // M
8797}
8798
8799multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8800                                       SDPatternOperator OpNode> {
8801  def v4f16 : BaseSIMDThreeSameVectorIndexH<0, U, 0b10, opc, asm, ".2s", ".2h", ".h",
8802                                              V64, V128_lo, v2f32, v4f16, OpNode>;
8803  def v8f16 : BaseSIMDThreeSameVectorIndexH<1, U, 0b10, opc, asm, ".4s", ".4h", ".h",
8804                                              V128, V128_lo, v4f32, v8f16, OpNode>;
8805}
8806
8807//----------------------------------------------------------------------------
8808// FP8 Advanced SIMD vector x indexed element
8809// TODO: Replace value types v8i8 and v16i8 by v8f8 and v16f8
8810multiclass SIMDThreeSameVectorFP8DOT2Index<string asm> {
8811  def v4f16 : BaseSIMDThreeSameVectorIndexH<0b0, 0b0, 0b01, 0b0000, asm, ".4h", ".8b", ".2b",
8812                                            V64, V128_lo, v4f16, v8i8, null_frag>;
8813  def v8f16 : BaseSIMDThreeSameVectorIndexH<0b1, 0b0, 0b01, 0b0000, asm, ".8h", ".16b", ".2b",
8814                                            V128, V128_lo, v8f16, v8i16, null_frag>;
8815}
8816
8817multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8818                         SDPatternOperator OpNode> {
8819  let mayRaiseFPException = 1, Uses = [FPCR] in {
8820  let Predicates = [HasNEON, HasFullFP16] in {
8821  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8822                                      V64, V64,
8823                                      V128_lo, VectorIndexH,
8824                                      asm, ".4h", ".4h", ".4h", ".h",
8825    [(set (v4f16 V64:$Rd),
8826        (OpNode (v4f16 V64:$Rn),
8827         (dup_v8f16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8828    bits<3> idx;
8829    let Inst{11} = idx{2};
8830    let Inst{21} = idx{1};
8831    let Inst{20} = idx{0};
8832  }
8833
8834  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8835                                      V128, V128,
8836                                      V128_lo, VectorIndexH,
8837                                      asm, ".8h", ".8h", ".8h", ".h",
8838    [(set (v8f16 V128:$Rd),
8839        (OpNode (v8f16 V128:$Rn),
8840         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8841    bits<3> idx;
8842    let Inst{11} = idx{2};
8843    let Inst{21} = idx{1};
8844    let Inst{20} = idx{0};
8845  }
8846  } // Predicates = [HasNEON, HasFullFP16]
8847
8848  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8849                                      V64, V64,
8850                                      V128, VectorIndexS,
8851                                      asm, ".2s", ".2s", ".2s", ".s",
8852    [(set (v2f32 V64:$Rd),
8853        (OpNode (v2f32 V64:$Rn),
8854         (dup_v4f32 (v4f32 V128:$Rm), VectorIndexS:$idx)))]> {
8855    bits<2> idx;
8856    let Inst{11} = idx{1};
8857    let Inst{21} = idx{0};
8858  }
8859
8860  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8861                                      V128, V128,
8862                                      V128, VectorIndexS,
8863                                      asm, ".4s", ".4s", ".4s", ".s",
8864    [(set (v4f32 V128:$Rd),
8865        (OpNode (v4f32 V128:$Rn),
8866         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8867    bits<2> idx;
8868    let Inst{11} = idx{1};
8869    let Inst{21} = idx{0};
8870  }
8871
8872  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8873                                      V128, V128,
8874                                      V128, VectorIndexD,
8875                                      asm, ".2d", ".2d", ".2d", ".d",
8876    [(set (v2f64 V128:$Rd),
8877        (OpNode (v2f64 V128:$Rn),
8878         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8879    bits<1> idx;
8880    let Inst{11} = idx{0};
8881    let Inst{21} = 0;
8882  }
8883
8884  let Predicates = [HasNEON, HasFullFP16] in {
8885  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8886                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8887                                      asm, ".h", "", "", ".h",
8888    [(set (f16 FPR16Op:$Rd),
8889          (OpNode (f16 FPR16Op:$Rn),
8890                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8891                                       VectorIndexH:$idx))))]> {
8892    bits<3> idx;
8893    let Inst{11} = idx{2};
8894    let Inst{21} = idx{1};
8895    let Inst{20} = idx{0};
8896  }
8897  } // Predicates = [HasNEON, HasFullFP16]
8898
8899  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8900                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8901                                      asm, ".s", "", "", ".s",
8902    [(set (f32 FPR32Op:$Rd),
8903          (OpNode (f32 FPR32Op:$Rn),
8904                  (f32 (vector_extract (v4f32 V128:$Rm),
8905                                       VectorIndexS:$idx))))]> {
8906    bits<2> idx;
8907    let Inst{11} = idx{1};
8908    let Inst{21} = idx{0};
8909  }
8910
8911  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8912                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8913                                      asm, ".d", "", "", ".d",
8914    [(set (f64 FPR64Op:$Rd),
8915          (OpNode (f64 FPR64Op:$Rn),
8916                  (f64 (vector_extract (v2f64 V128:$Rm),
8917                                       VectorIndexD:$idx))))]> {
8918    bits<1> idx;
8919    let Inst{11} = idx{0};
8920    let Inst{21} = 0;
8921  }
8922  } // mayRaiseFPException = 1, Uses = [FPCR]
8923
8924  let Predicates = [HasNEON, HasFullFP16] in {
8925  def : Pat<(f16 (OpNode
8926                   (f16 (vector_extract (v8f16 V128:$Rn), (i64 0))),
8927                   (f16 (vector_extract (v8f16 V128:$Rm), VectorIndexH:$idx)))),
8928            (!cast<Instruction>(NAME # v1i16_indexed)
8929              (f16 (EXTRACT_SUBREG V128:$Rn, hsub)), V128:$Rm, VectorIndexH:$idx)>;
8930  }
8931
8932  let Predicates = [HasNEON] in {
8933  def : Pat<(f32 (OpNode
8934                   (f32 (vector_extract (v4f32 V128:$Rn), (i64 0))),
8935                   (f32 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx)))),
8936            (!cast<Instruction>(NAME # v1i32_indexed)
8937              (EXTRACT_SUBREG V128:$Rn, ssub), V128:$Rm, VectorIndexS:$idx)>;
8938
8939  def : Pat<(f64 (OpNode
8940                   (f64 (vector_extract (v2f64 V128:$Rn), (i64 0))),
8941                   (f64 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx)))),
8942            (!cast<Instruction>(NAME # v1i64_indexed)
8943              (EXTRACT_SUBREG V128:$Rn, dsub), V128:$Rm, VectorIndexD:$idx)>;
8944  }
8945}
8946
8947multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8948  let Predicates = [HasNEON, HasFullFP16] in {
8949  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8950  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8951                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8952                                           VectorIndexH:$idx))),
8953            (!cast<Instruction>(INST # "v8i16_indexed")
8954                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8955  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8956                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8957            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8958                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8959
8960  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8961                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8962                                           VectorIndexH:$idx))),
8963            (!cast<Instruction>(INST # "v4i16_indexed")
8964                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8965  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8966                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8967            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8968                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8969
8970  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8971                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8972            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8973                V128_lo:$Rm, VectorIndexH:$idx)>;
8974  } // Predicates = [HasNEON, HasFullFP16]
8975
8976  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8977  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8978                           (AArch64duplane32 (v4f32 V128:$Rm),
8979                                           VectorIndexS:$idx))),
8980            (!cast<Instruction>(INST # v2i32_indexed)
8981                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8982  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8983                           (AArch64dup (f32 FPR32Op:$Rm)))),
8984            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8985                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8986
8987
8988  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8989  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8990                           (AArch64duplane32 (v4f32 V128:$Rm),
8991                                           VectorIndexS:$idx))),
8992            (!cast<Instruction>(INST # "v4i32_indexed")
8993                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8994  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8995                           (AArch64dup (f32 FPR32Op:$Rm)))),
8996            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8997                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8998
8999  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
9000  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
9001                           (AArch64duplane64 (v2f64 V128:$Rm),
9002                                           VectorIndexD:$idx))),
9003            (!cast<Instruction>(INST # "v2i64_indexed")
9004                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
9005  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
9006                           (AArch64dup (f64 FPR64Op:$Rm)))),
9007            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
9008                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
9009
9010  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
9011  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
9012                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
9013            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
9014                V128:$Rm, VectorIndexS:$idx)>;
9015
9016  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
9017  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
9018                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
9019            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
9020                V128:$Rm, VectorIndexD:$idx)>;
9021}
9022
9023let mayRaiseFPException = 1, Uses = [FPCR] in
9024multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
9025  let Predicates = [HasNEON, HasFullFP16] in {
9026  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
9027                                          V128_lo, VectorIndexH,
9028                                          asm, ".4h", ".4h", ".4h", ".h", []> {
9029    bits<3> idx;
9030    let Inst{11} = idx{2};
9031    let Inst{21} = idx{1};
9032    let Inst{20} = idx{0};
9033  }
9034
9035  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
9036                                          V128, V128,
9037                                          V128_lo, VectorIndexH,
9038                                          asm, ".8h", ".8h", ".8h", ".h", []> {
9039    bits<3> idx;
9040    let Inst{11} = idx{2};
9041    let Inst{21} = idx{1};
9042    let Inst{20} = idx{0};
9043  }
9044  } // Predicates = [HasNEON, HasFullFP16]
9045
9046  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
9047                                          V128, VectorIndexS,
9048                                          asm, ".2s", ".2s", ".2s", ".s", []> {
9049    bits<2> idx;
9050    let Inst{11} = idx{1};
9051    let Inst{21} = idx{0};
9052  }
9053
9054  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9055                                      V128, V128,
9056                                      V128, VectorIndexS,
9057                                      asm, ".4s", ".4s", ".4s", ".s", []> {
9058    bits<2> idx;
9059    let Inst{11} = idx{1};
9060    let Inst{21} = idx{0};
9061  }
9062
9063  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
9064                                      V128, V128,
9065                                      V128, VectorIndexD,
9066                                      asm, ".2d", ".2d", ".2d", ".d", []> {
9067    bits<1> idx;
9068    let Inst{11} = idx{0};
9069    let Inst{21} = 0;
9070  }
9071
9072  let Predicates = [HasNEON, HasFullFP16] in {
9073  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
9074                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
9075                                      asm, ".h", "", "", ".h", []> {
9076    bits<3> idx;
9077    let Inst{11} = idx{2};
9078    let Inst{21} = idx{1};
9079    let Inst{20} = idx{0};
9080  }
9081  } // Predicates = [HasNEON, HasFullFP16]
9082
9083  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9084                                      FPR32Op, FPR32Op, V128, VectorIndexS,
9085                                      asm, ".s", "", "", ".s", []> {
9086    bits<2> idx;
9087    let Inst{11} = idx{1};
9088    let Inst{21} = idx{0};
9089  }
9090
9091  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
9092                                      FPR64Op, FPR64Op, V128, VectorIndexD,
9093                                      asm, ".d", "", "", ".d", []> {
9094    bits<1> idx;
9095    let Inst{11} = idx{0};
9096    let Inst{21} = 0;
9097  }
9098}
9099
9100multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
9101                                 SDPatternOperator OpNodeLaneQ> {
9102
9103  def : Pat<(v4i16 (OpNodeLane
9104                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
9105                     VectorIndexS32b:$idx)),
9106            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
9107              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
9108              (UImmS1XForm $idx))>;
9109
9110  def : Pat<(v4i16 (OpNodeLaneQ
9111                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
9112                     VectorIndexH32b:$idx)),
9113            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
9114              (UImmS1XForm $idx))>;
9115
9116  def : Pat<(v8i16 (OpNodeLane
9117                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
9118                     VectorIndexS32b:$idx)),
9119            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
9120              (SUBREG_TO_REG (i32 0), $Rm, dsub),
9121              (UImmS1XForm $idx))>;
9122
9123  def : Pat<(v8i16 (OpNodeLaneQ
9124                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
9125                     VectorIndexH32b:$idx)),
9126            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
9127              (UImmS1XForm $idx))>;
9128
9129  def : Pat<(v2i32 (OpNodeLane
9130                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
9131                     VectorIndexD32b:$idx)),
9132            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
9133              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
9134              (UImmS1XForm $idx))>;
9135
9136  def : Pat<(v2i32 (OpNodeLaneQ
9137                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
9138                     VectorIndexS32b:$idx)),
9139            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
9140              (UImmS1XForm $idx))>;
9141
9142  def : Pat<(v4i32 (OpNodeLane
9143                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
9144                     VectorIndexD32b:$idx)),
9145            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
9146              (SUBREG_TO_REG (i32 0), $Rm, dsub),
9147              (UImmS1XForm $idx))>;
9148
9149  def : Pat<(v4i32 (OpNodeLaneQ
9150                     (v4i32 V128:$Rn),
9151                     (v4i32 V128:$Rm),
9152                     VectorIndexS32b:$idx)),
9153            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
9154              (UImmS1XForm $idx))>;
9155
9156}
9157
9158multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
9159                         SDPatternOperator OpNode> {
9160  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
9161                                      V128_lo, VectorIndexH,
9162                                      asm, ".4h", ".4h", ".4h", ".h",
9163    [(set (v4i16 V64:$Rd),
9164        (OpNode (v4i16 V64:$Rn),
9165         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9166    bits<3> idx;
9167    let Inst{11} = idx{2};
9168    let Inst{21} = idx{1};
9169    let Inst{20} = idx{0};
9170  }
9171
9172  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9173                                      V128, V128,
9174                                      V128_lo, VectorIndexH,
9175                                      asm, ".8h", ".8h", ".8h", ".h",
9176    [(set (v8i16 V128:$Rd),
9177       (OpNode (v8i16 V128:$Rn),
9178         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9179    bits<3> idx;
9180    let Inst{11} = idx{2};
9181    let Inst{21} = idx{1};
9182    let Inst{20} = idx{0};
9183  }
9184
9185  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9186                                      V64, V64,
9187                                      V128, VectorIndexS,
9188                                      asm, ".2s", ".2s", ".2s",  ".s",
9189    [(set (v2i32 V64:$Rd),
9190       (OpNode (v2i32 V64:$Rn),
9191          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9192    bits<2> idx;
9193    let Inst{11} = idx{1};
9194    let Inst{21} = idx{0};
9195  }
9196
9197  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9198                                      V128, V128,
9199                                      V128, VectorIndexS,
9200                                      asm, ".4s", ".4s", ".4s", ".s",
9201    [(set (v4i32 V128:$Rd),
9202       (OpNode (v4i32 V128:$Rn),
9203          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9204    bits<2> idx;
9205    let Inst{11} = idx{1};
9206    let Inst{21} = idx{0};
9207  }
9208
9209  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
9210                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
9211                                      asm, ".h", "", "", ".h", []> {
9212    bits<3> idx;
9213    let Inst{11} = idx{2};
9214    let Inst{21} = idx{1};
9215    let Inst{20} = idx{0};
9216  }
9217
9218  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9219                                      FPR32Op, FPR32Op, V128, VectorIndexS,
9220                                      asm, ".s", "", "", ".s",
9221      [(set (i32 FPR32Op:$Rd),
9222            (OpNode FPR32Op:$Rn,
9223                    (i32 (vector_extract (v4i32 V128:$Rm),
9224                                         VectorIndexS:$idx))))]> {
9225    bits<2> idx;
9226    let Inst{11} = idx{1};
9227    let Inst{21} = idx{0};
9228  }
9229}
9230
9231multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
9232                               SDPatternOperator OpNode> {
9233  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9234                                      V64, V64,
9235                                      V128_lo, VectorIndexH,
9236                                      asm, ".4h", ".4h", ".4h", ".h",
9237    [(set (v4i16 V64:$Rd),
9238        (OpNode (v4i16 V64:$Rn),
9239         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9240    bits<3> idx;
9241    let Inst{11} = idx{2};
9242    let Inst{21} = idx{1};
9243    let Inst{20} = idx{0};
9244  }
9245
9246  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9247                                      V128, V128,
9248                                      V128_lo, VectorIndexH,
9249                                      asm, ".8h", ".8h", ".8h", ".h",
9250    [(set (v8i16 V128:$Rd),
9251       (OpNode (v8i16 V128:$Rn),
9252         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9253    bits<3> idx;
9254    let Inst{11} = idx{2};
9255    let Inst{21} = idx{1};
9256    let Inst{20} = idx{0};
9257  }
9258
9259  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9260                                      V64, V64,
9261                                      V128, VectorIndexS,
9262                                      asm, ".2s", ".2s", ".2s", ".s",
9263    [(set (v2i32 V64:$Rd),
9264       (OpNode (v2i32 V64:$Rn),
9265          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9266    bits<2> idx;
9267    let Inst{11} = idx{1};
9268    let Inst{21} = idx{0};
9269  }
9270
9271  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9272                                      V128, V128,
9273                                      V128, VectorIndexS,
9274                                      asm, ".4s", ".4s", ".4s", ".s",
9275    [(set (v4i32 V128:$Rd),
9276       (OpNode (v4i32 V128:$Rn),
9277          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9278    bits<2> idx;
9279    let Inst{11} = idx{1};
9280    let Inst{21} = idx{0};
9281  }
9282}
9283
9284multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
9285                                   SDPatternOperator OpNode> {
9286  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
9287                                          V128_lo, VectorIndexH,
9288                                          asm, ".4h", ".4h", ".4h", ".h",
9289    [(set (v4i16 V64:$dst),
9290        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
9291         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9292    bits<3> idx;
9293    let Inst{11} = idx{2};
9294    let Inst{21} = idx{1};
9295    let Inst{20} = idx{0};
9296  }
9297
9298  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9299                                      V128, V128,
9300                                      V128_lo, VectorIndexH,
9301                                      asm, ".8h", ".8h", ".8h", ".h",
9302    [(set (v8i16 V128:$dst),
9303       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9304         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9305    bits<3> idx;
9306    let Inst{11} = idx{2};
9307    let Inst{21} = idx{1};
9308    let Inst{20} = idx{0};
9309  }
9310
9311  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9312                                      V64, V64,
9313                                      V128, VectorIndexS,
9314                                      asm, ".2s", ".2s", ".2s", ".s",
9315    [(set (v2i32 V64:$dst),
9316       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9317          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9318    bits<2> idx;
9319    let Inst{11} = idx{1};
9320    let Inst{21} = idx{0};
9321  }
9322
9323  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9324                                      V128, V128,
9325                                      V128, VectorIndexS,
9326                                      asm, ".4s", ".4s", ".4s", ".s",
9327    [(set (v4i32 V128:$dst),
9328       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9329          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9330    bits<2> idx;
9331    let Inst{11} = idx{1};
9332    let Inst{21} = idx{0};
9333  }
9334}
9335
9336multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
9337                             SDPatternOperator OpNode> {
9338  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9339                                      V128, V64,
9340                                      V128_lo, VectorIndexH,
9341                                      asm, ".4s", ".4s", ".4h", ".h",
9342    [(set (v4i32 V128:$Rd),
9343        (OpNode (v4i16 V64:$Rn),
9344         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9345    bits<3> idx;
9346    let Inst{11} = idx{2};
9347    let Inst{21} = idx{1};
9348    let Inst{20} = idx{0};
9349  }
9350
9351  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9352                                      V128, V128,
9353                                      V128_lo, VectorIndexH,
9354                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9355    [(set (v4i32 V128:$Rd),
9356          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9357                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9358
9359    bits<3> idx;
9360    let Inst{11} = idx{2};
9361    let Inst{21} = idx{1};
9362    let Inst{20} = idx{0};
9363  }
9364
9365  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9366                                      V128, V64,
9367                                      V128, VectorIndexS,
9368                                      asm, ".2d", ".2d", ".2s", ".s",
9369    [(set (v2i64 V128:$Rd),
9370        (OpNode (v2i32 V64:$Rn),
9371         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9372    bits<2> idx;
9373    let Inst{11} = idx{1};
9374    let Inst{21} = idx{0};
9375  }
9376
9377  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9378                                      V128, V128,
9379                                      V128, VectorIndexS,
9380                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9381    [(set (v2i64 V128:$Rd),
9382          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9383                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9384    bits<2> idx;
9385    let Inst{11} = idx{1};
9386    let Inst{21} = idx{0};
9387  }
9388
9389  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
9390                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9391                                      asm, ".h", "", "", ".h", []> {
9392    bits<3> idx;
9393    let Inst{11} = idx{2};
9394    let Inst{21} = idx{1};
9395    let Inst{20} = idx{0};
9396  }
9397
9398  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9399                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9400                                      asm, ".s", "", "", ".s", []> {
9401    bits<2> idx;
9402    let Inst{11} = idx{1};
9403    let Inst{21} = idx{0};
9404  }
9405}
9406
9407multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
9408                                       SDPatternOperator Accum> {
9409  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9410                                      V128, V64,
9411                                      V128_lo, VectorIndexH,
9412                                      asm, ".4s", ".4s", ".4h", ".h",
9413    [(set (v4i32 V128:$dst),
9414          (Accum (v4i32 V128:$Rd),
9415                 (v4i32 (int_aarch64_neon_sqdmull
9416                             (v4i16 V64:$Rn),
9417                             (dup_v8i16 (v8i16 V128_lo:$Rm),
9418                                         VectorIndexH:$idx)))))]> {
9419    bits<3> idx;
9420    let Inst{11} = idx{2};
9421    let Inst{21} = idx{1};
9422    let Inst{20} = idx{0};
9423  }
9424
9425  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9426                                      V128, V128,
9427                                      V128_lo, VectorIndexH,
9428                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9429    [(set (v4i32 V128:$dst),
9430          (Accum (v4i32 V128:$Rd),
9431                 (v4i32 (int_aarch64_neon_sqdmull
9432                            (extract_high_v8i16 (v8i16 V128:$Rn)),
9433                            (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))))]> {
9434    bits<3> idx;
9435    let Inst{11} = idx{2};
9436    let Inst{21} = idx{1};
9437    let Inst{20} = idx{0};
9438  }
9439
9440  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9441                                      V128, V64,
9442                                      V128, VectorIndexS,
9443                                      asm, ".2d", ".2d", ".2s", ".s",
9444    [(set (v2i64 V128:$dst),
9445        (Accum (v2i64 V128:$Rd),
9446               (v2i64 (int_aarch64_neon_sqdmull
9447                          (v2i32 V64:$Rn),
9448                          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9449    bits<2> idx;
9450    let Inst{11} = idx{1};
9451    let Inst{21} = idx{0};
9452  }
9453
9454  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9455                                      V128, V128,
9456                                      V128, VectorIndexS,
9457                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9458    [(set (v2i64 V128:$dst),
9459          (Accum (v2i64 V128:$Rd),
9460                 (v2i64 (int_aarch64_neon_sqdmull
9461                            (extract_high_v4i32 (v4i32 V128:$Rn)),
9462                            (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9463    bits<2> idx;
9464    let Inst{11} = idx{1};
9465    let Inst{21} = idx{0};
9466  }
9467
9468  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9469                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9470                                      asm, ".h", "", "", ".h", []> {
9471    bits<3> idx;
9472    let Inst{11} = idx{2};
9473    let Inst{21} = idx{1};
9474    let Inst{20} = idx{0};
9475  }
9476
9477  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9478                        (i32 (vector_extract
9479                                    (v4i32 (int_aarch64_neon_sqdmull
9480                                                (v4i16 V64:$Rn),
9481                                                (v4i16 V64:$Rm))),
9482                                    (i64 0))))),
9483            (!cast<Instruction>(NAME # v1i32_indexed)
9484                        FPR32Op:$Rd,
9485                        (f16 (EXTRACT_SUBREG V64:$Rn, hsub)),
9486                        (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rm, dsub),
9487                        (i64 0))>;
9488
9489  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9490                        (i32 (vector_extract
9491                                    (v4i32 (int_aarch64_neon_sqdmull
9492                                                (v4i16 V64:$Rn),
9493                                                (dup_v8i16 (v8i16 V128_lo:$Rm),
9494                                                            VectorIndexH:$idx))),
9495                                    (i64 0))))),
9496            (!cast<Instruction>(NAME # v1i32_indexed)
9497                        FPR32Op:$Rd,
9498                        (f16 (EXTRACT_SUBREG V64:$Rn, hsub)),
9499                        V128_lo:$Rm,
9500                        VectorIndexH:$idx)>;
9501
9502  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9503                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9504                                      asm, ".s", "", "", ".s",
9505    [(set (i64 FPR64Op:$dst),
9506          (Accum (i64 FPR64Op:$Rd),
9507                 (i64 (int_aarch64_neon_sqdmulls_scalar
9508                            (i32 FPR32Op:$Rn),
9509                            (i32 (vector_extract (v4i32 V128:$Rm),
9510                                                 VectorIndexS:$idx))))))]> {
9511
9512    bits<2> idx;
9513    let Inst{11} = idx{1};
9514    let Inst{21} = idx{0};
9515  }
9516}
9517
9518multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
9519                                   SDPatternOperator OpNode> {
9520  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9521  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9522                                      V128, V64,
9523                                      V128_lo, VectorIndexH,
9524                                      asm, ".4s", ".4s", ".4h", ".h",
9525    [(set (v4i32 V128:$Rd),
9526        (OpNode (v4i16 V64:$Rn),
9527         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9528    bits<3> idx;
9529    let Inst{11} = idx{2};
9530    let Inst{21} = idx{1};
9531    let Inst{20} = idx{0};
9532  }
9533
9534  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9535                                      V128, V128,
9536                                      V128_lo, VectorIndexH,
9537                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9538    [(set (v4i32 V128:$Rd),
9539          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9540                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9541
9542    bits<3> idx;
9543    let Inst{11} = idx{2};
9544    let Inst{21} = idx{1};
9545    let Inst{20} = idx{0};
9546  }
9547
9548  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9549                                      V128, V64,
9550                                      V128, VectorIndexS,
9551                                      asm, ".2d", ".2d", ".2s", ".s",
9552    [(set (v2i64 V128:$Rd),
9553        (OpNode (v2i32 V64:$Rn),
9554         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9555    bits<2> idx;
9556    let Inst{11} = idx{1};
9557    let Inst{21} = idx{0};
9558  }
9559
9560  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9561                                      V128, V128,
9562                                      V128, VectorIndexS,
9563                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9564    [(set (v2i64 V128:$Rd),
9565          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9566                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9567    bits<2> idx;
9568    let Inst{11} = idx{1};
9569    let Inst{21} = idx{0};
9570  }
9571  }
9572}
9573
9574multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
9575                                       SDPatternOperator OpNode> {
9576  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9577  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9578                                      V128, V64,
9579                                      V128_lo, VectorIndexH,
9580                                      asm, ".4s", ".4s", ".4h", ".h",
9581    [(set (v4i32 V128:$dst),
9582        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
9583         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9584    bits<3> idx;
9585    let Inst{11} = idx{2};
9586    let Inst{21} = idx{1};
9587    let Inst{20} = idx{0};
9588  }
9589
9590  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9591                                      V128, V128,
9592                                      V128_lo, VectorIndexH,
9593                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9594    [(set (v4i32 V128:$dst),
9595          (OpNode (v4i32 V128:$Rd),
9596                  (extract_high_v8i16 (v8i16 V128:$Rn)),
9597                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9598    bits<3> idx;
9599    let Inst{11} = idx{2};
9600    let Inst{21} = idx{1};
9601    let Inst{20} = idx{0};
9602  }
9603
9604  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9605                                      V128, V64,
9606                                      V128, VectorIndexS,
9607                                      asm, ".2d", ".2d", ".2s", ".s",
9608    [(set (v2i64 V128:$dst),
9609        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
9610         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9611    bits<2> idx;
9612    let Inst{11} = idx{1};
9613    let Inst{21} = idx{0};
9614  }
9615
9616  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9617                                      V128, V128,
9618                                      V128, VectorIndexS,
9619                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9620    [(set (v2i64 V128:$dst),
9621          (OpNode (v2i64 V128:$Rd),
9622                  (extract_high_v4i32 (v4i32 V128:$Rn)),
9623                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9624    bits<2> idx;
9625    let Inst{11} = idx{1};
9626    let Inst{21} = idx{0};
9627  }
9628  }
9629}
9630
9631//----------------------------------------------------------------------------
9632// AdvSIMD scalar shift by immediate
9633//----------------------------------------------------------------------------
9634
9635let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9636class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
9637                     RegisterClass regtype1, RegisterClass regtype2,
9638                     Operand immtype, string asm, list<dag> pattern>
9639  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
9640      asm, "\t$Rd, $Rn, $imm", "", pattern>,
9641    Sched<[WriteVd]> {
9642  bits<5> Rd;
9643  bits<5> Rn;
9644  bits<7> imm;
9645  let Inst{31-30} = 0b01;
9646  let Inst{29}    = U;
9647  let Inst{28-23} = 0b111110;
9648  let Inst{22-16} = fixed_imm;
9649  let Inst{15-11} = opc;
9650  let Inst{10}    = 1;
9651  let Inst{9-5} = Rn;
9652  let Inst{4-0} = Rd;
9653}
9654
9655let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9656class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
9657                     RegisterClass regtype1, RegisterClass regtype2,
9658                     Operand immtype, string asm, list<dag> pattern>
9659  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
9660      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
9661    Sched<[WriteVd]> {
9662  bits<5> Rd;
9663  bits<5> Rn;
9664  bits<7> imm;
9665  let Inst{31-30} = 0b01;
9666  let Inst{29}    = U;
9667  let Inst{28-23} = 0b111110;
9668  let Inst{22-16} = fixed_imm;
9669  let Inst{15-11} = opc;
9670  let Inst{10}    = 1;
9671  let Inst{9-5} = Rn;
9672  let Inst{4-0} = Rd;
9673}
9674
9675
9676multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
9677  let Predicates = [HasNEON, HasFullFP16] in {
9678  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9679                              FPR16, FPR16, vecshiftR16, asm, []> {
9680    let Inst{19-16} = imm{3-0};
9681  }
9682  } // Predicates = [HasNEON, HasFullFP16]
9683  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9684                              FPR32, FPR32, vecshiftR32, asm, []> {
9685    let Inst{20-16} = imm{4-0};
9686  }
9687  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9688                              FPR64, FPR64, vecshiftR64, asm, []> {
9689    let Inst{21-16} = imm{5-0};
9690  }
9691}
9692
9693multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
9694                             SDPatternOperator OpNode> {
9695  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9696                              FPR64, FPR64, vecshiftR64, asm,
9697  [(set (i64 FPR64:$Rd),
9698     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
9699    let Inst{21-16} = imm{5-0};
9700  }
9701
9702  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
9703            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
9704}
9705
9706multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
9707                                 SDPatternOperator OpNode = null_frag> {
9708  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9709                              FPR64, FPR64, vecshiftR64, asm,
9710  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
9711                                                   (i32 vecshiftR64:$imm)))]> {
9712    let Inst{21-16} = imm{5-0};
9713  }
9714
9715  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
9716                           (i32 vecshiftR64:$imm))),
9717            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
9718                                            vecshiftR64:$imm)>;
9719}
9720
9721multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
9722                             SDPatternOperator OpNode> {
9723  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9724                              FPR64, FPR64, vecshiftL64, asm,
9725    [(set (i64 FPR64:$Rd),
9726       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9727    let Inst{21-16} = imm{5-0};
9728  }
9729
9730  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9731            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9732}
9733
9734let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9735multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
9736  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9737                              FPR64, FPR64, vecshiftL64, asm, []> {
9738    let Inst{21-16} = imm{5-0};
9739  }
9740}
9741
9742let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9743multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
9744                               SDPatternOperator OpNode = null_frag> {
9745  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9746                              FPR8, FPR16, vecshiftR8, asm, []> {
9747    let Inst{18-16} = imm{2-0};
9748  }
9749
9750  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9751                              FPR16, FPR32, vecshiftR16, asm, []> {
9752    let Inst{19-16} = imm{3-0};
9753  }
9754
9755  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9756                              FPR32, FPR64, vecshiftR32, asm,
9757    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9758    let Inst{20-16} = imm{4-0};
9759  }
9760}
9761
9762multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9763                                SDPatternOperator OpNode> {
9764  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9765                              FPR8, FPR8, vecshiftL8, asm, []> {
9766    let Inst{18-16} = imm{2-0};
9767  }
9768
9769  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9770                              FPR16, FPR16, vecshiftL16, asm, []> {
9771    let Inst{19-16} = imm{3-0};
9772  }
9773
9774  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9775                              FPR32, FPR32, vecshiftL32, asm,
9776    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9777    let Inst{20-16} = imm{4-0};
9778  }
9779
9780  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9781                              FPR64, FPR64, vecshiftL64, asm,
9782    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9783    let Inst{21-16} = imm{5-0};
9784  }
9785
9786  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9787            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9788}
9789
9790multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9791  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9792                              FPR8, FPR8, vecshiftR8, asm, []> {
9793    let Inst{18-16} = imm{2-0};
9794  }
9795
9796  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9797                              FPR16, FPR16, vecshiftR16, asm, []> {
9798    let Inst{19-16} = imm{3-0};
9799  }
9800
9801  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9802                              FPR32, FPR32, vecshiftR32, asm, []> {
9803    let Inst{20-16} = imm{4-0};
9804  }
9805
9806  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9807                              FPR64, FPR64, vecshiftR64, asm, []> {
9808    let Inst{21-16} = imm{5-0};
9809  }
9810}
9811
9812//----------------------------------------------------------------------------
9813// AdvSIMD vector x indexed element
9814//----------------------------------------------------------------------------
9815
9816let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9817class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9818                     RegisterOperand dst_reg, RegisterOperand src_reg,
9819                     Operand immtype,
9820                     string asm, string dst_kind, string src_kind,
9821                     list<dag> pattern>
9822  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9823      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9824           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9825    Sched<[!if(Q, WriteVq, WriteVd)]> {
9826  bits<5> Rd;
9827  bits<5> Rn;
9828  let Inst{31}    = 0;
9829  let Inst{30}    = Q;
9830  let Inst{29}    = U;
9831  let Inst{28-23} = 0b011110;
9832  let Inst{22-16} = fixed_imm;
9833  let Inst{15-11} = opc;
9834  let Inst{10}    = 1;
9835  let Inst{9-5}   = Rn;
9836  let Inst{4-0}   = Rd;
9837}
9838
9839let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9840class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9841                     RegisterOperand vectype1, RegisterOperand vectype2,
9842                     Operand immtype,
9843                     string asm, string dst_kind, string src_kind,
9844                     list<dag> pattern>
9845  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9846      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9847           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9848    Sched<[!if(Q, WriteVq, WriteVd)]> {
9849  bits<5> Rd;
9850  bits<5> Rn;
9851  let Inst{31}    = 0;
9852  let Inst{30}    = Q;
9853  let Inst{29}    = U;
9854  let Inst{28-23} = 0b011110;
9855  let Inst{22-16} = fixed_imm;
9856  let Inst{15-11} = opc;
9857  let Inst{10}    = 1;
9858  let Inst{9-5}   = Rn;
9859  let Inst{4-0}   = Rd;
9860}
9861
9862multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9863                              Intrinsic OpNode> {
9864  let Predicates = [HasNEON, HasFullFP16] in {
9865  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9866                                  V64, V64, vecshiftR16,
9867                                  asm, ".4h", ".4h",
9868      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9869    bits<4> imm;
9870    let Inst{19-16} = imm;
9871  }
9872
9873  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9874                                  V128, V128, vecshiftR16,
9875                                  asm, ".8h", ".8h",
9876      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9877    bits<4> imm;
9878    let Inst{19-16} = imm;
9879  }
9880  } // Predicates = [HasNEON, HasFullFP16]
9881  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9882                                  V64, V64, vecshiftR32,
9883                                  asm, ".2s", ".2s",
9884      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9885    bits<5> imm;
9886    let Inst{20-16} = imm;
9887  }
9888
9889  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9890                                  V128, V128, vecshiftR32,
9891                                  asm, ".4s", ".4s",
9892      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9893    bits<5> imm;
9894    let Inst{20-16} = imm;
9895  }
9896
9897  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9898                                  V128, V128, vecshiftR64,
9899                                  asm, ".2d", ".2d",
9900      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9901    bits<6> imm;
9902    let Inst{21-16} = imm;
9903  }
9904}
9905
9906multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9907                                  Intrinsic OpNode> {
9908  let Predicates = [HasNEON, HasFullFP16] in {
9909  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9910                                  V64, V64, vecshiftR16,
9911                                  asm, ".4h", ".4h",
9912      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9913    bits<4> imm;
9914    let Inst{19-16} = imm;
9915  }
9916
9917  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9918                                  V128, V128, vecshiftR16,
9919                                  asm, ".8h", ".8h",
9920      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9921    bits<4> imm;
9922    let Inst{19-16} = imm;
9923  }
9924  } // Predicates = [HasNEON, HasFullFP16]
9925
9926  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9927                                  V64, V64, vecshiftR32,
9928                                  asm, ".2s", ".2s",
9929      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9930    bits<5> imm;
9931    let Inst{20-16} = imm;
9932  }
9933
9934  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9935                                  V128, V128, vecshiftR32,
9936                                  asm, ".4s", ".4s",
9937      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9938    bits<5> imm;
9939    let Inst{20-16} = imm;
9940  }
9941
9942  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9943                                  V128, V128, vecshiftR64,
9944                                  asm, ".2d", ".2d",
9945      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9946    bits<6> imm;
9947    let Inst{21-16} = imm;
9948  }
9949}
9950
9951multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9952                                     SDPatternOperator OpNode> {
9953  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9954                                  V64, V128, vecshiftR16Narrow,
9955                                  asm, ".8b", ".8h",
9956      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9957    bits<3> imm;
9958    let Inst{18-16} = imm;
9959  }
9960
9961  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9962                                  V128, V128, vecshiftR16Narrow,
9963                                  asm#"2", ".16b", ".8h", []> {
9964    bits<3> imm;
9965    let Inst{18-16} = imm;
9966    let hasSideEffects = 0;
9967  }
9968
9969  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9970                                  V64, V128, vecshiftR32Narrow,
9971                                  asm, ".4h", ".4s",
9972      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9973    bits<4> imm;
9974    let Inst{19-16} = imm;
9975  }
9976
9977  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9978                                  V128, V128, vecshiftR32Narrow,
9979                                  asm#"2", ".8h", ".4s", []> {
9980    bits<4> imm;
9981    let Inst{19-16} = imm;
9982    let hasSideEffects = 0;
9983  }
9984
9985  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9986                                  V64, V128, vecshiftR64Narrow,
9987                                  asm, ".2s", ".2d",
9988      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9989    bits<5> imm;
9990    let Inst{20-16} = imm;
9991  }
9992
9993  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9994                                  V128, V128, vecshiftR64Narrow,
9995                                  asm#"2", ".4s", ".2d", []> {
9996    bits<5> imm;
9997    let Inst{20-16} = imm;
9998    let hasSideEffects = 0;
9999  }
10000
10001  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
10002  // themselves, so put them here instead.
10003
10004  // Patterns involving what's effectively an insert high and a normal
10005  // intrinsic, represented by CONCAT_VECTORS.
10006  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
10007                                                   vecshiftR16Narrow:$imm)),
10008            (!cast<Instruction>(NAME # "v16i8_shift")
10009                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
10010                V128:$Rn, vecshiftR16Narrow:$imm)>;
10011  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
10012                                                     vecshiftR32Narrow:$imm)),
10013            (!cast<Instruction>(NAME # "v8i16_shift")
10014                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
10015                V128:$Rn, vecshiftR32Narrow:$imm)>;
10016  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
10017                                                     vecshiftR64Narrow:$imm)),
10018            (!cast<Instruction>(NAME # "v4i32_shift")
10019                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
10020                V128:$Rn, vecshiftR64Narrow:$imm)>;
10021}
10022
10023multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
10024                                SDPatternOperator OpNode> {
10025  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10026                                  V64, V64, vecshiftL8,
10027                                  asm, ".8b", ".8b",
10028                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
10029                       (i32 vecshiftL8:$imm)))]> {
10030    bits<3> imm;
10031    let Inst{18-16} = imm;
10032  }
10033
10034  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10035                                  V128, V128, vecshiftL8,
10036                                  asm, ".16b", ".16b",
10037             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
10038                   (i32 vecshiftL8:$imm)))]> {
10039    bits<3> imm;
10040    let Inst{18-16} = imm;
10041  }
10042
10043  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10044                                  V64, V64, vecshiftL16,
10045                                  asm, ".4h", ".4h",
10046              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
10047                    (i32 vecshiftL16:$imm)))]> {
10048    bits<4> imm;
10049    let Inst{19-16} = imm;
10050  }
10051
10052  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10053                                  V128, V128, vecshiftL16,
10054                                  asm, ".8h", ".8h",
10055            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
10056                  (i32 vecshiftL16:$imm)))]> {
10057    bits<4> imm;
10058    let Inst{19-16} = imm;
10059  }
10060
10061  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10062                                  V64, V64, vecshiftL32,
10063                                  asm, ".2s", ".2s",
10064              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
10065                    (i32 vecshiftL32:$imm)))]> {
10066    bits<5> imm;
10067    let Inst{20-16} = imm;
10068  }
10069
10070  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10071                                  V128, V128, vecshiftL32,
10072                                  asm, ".4s", ".4s",
10073            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
10074                  (i32 vecshiftL32:$imm)))]> {
10075    bits<5> imm;
10076    let Inst{20-16} = imm;
10077  }
10078
10079  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10080                                  V128, V128, vecshiftL64,
10081                                  asm, ".2d", ".2d",
10082            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
10083                  (i32 vecshiftL64:$imm)))]> {
10084    bits<6> imm;
10085    let Inst{21-16} = imm;
10086  }
10087}
10088
10089multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
10090                                SDPatternOperator OpNode> {
10091  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10092                                  V64, V64, vecshiftR8,
10093                                  asm, ".8b", ".8b",
10094                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
10095                       (i32 vecshiftR8:$imm)))]> {
10096    bits<3> imm;
10097    let Inst{18-16} = imm;
10098  }
10099
10100  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10101                                  V128, V128, vecshiftR8,
10102                                  asm, ".16b", ".16b",
10103             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
10104                   (i32 vecshiftR8:$imm)))]> {
10105    bits<3> imm;
10106    let Inst{18-16} = imm;
10107  }
10108
10109  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10110                                  V64, V64, vecshiftR16,
10111                                  asm, ".4h", ".4h",
10112              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
10113                    (i32 vecshiftR16:$imm)))]> {
10114    bits<4> imm;
10115    let Inst{19-16} = imm;
10116  }
10117
10118  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10119                                  V128, V128, vecshiftR16,
10120                                  asm, ".8h", ".8h",
10121            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
10122                  (i32 vecshiftR16:$imm)))]> {
10123    bits<4> imm;
10124    let Inst{19-16} = imm;
10125  }
10126
10127  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10128                                  V64, V64, vecshiftR32,
10129                                  asm, ".2s", ".2s",
10130              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
10131                    (i32 vecshiftR32:$imm)))]> {
10132    bits<5> imm;
10133    let Inst{20-16} = imm;
10134  }
10135
10136  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10137                                  V128, V128, vecshiftR32,
10138                                  asm, ".4s", ".4s",
10139            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
10140                  (i32 vecshiftR32:$imm)))]> {
10141    bits<5> imm;
10142    let Inst{20-16} = imm;
10143  }
10144
10145  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10146                                  V128, V128, vecshiftR64,
10147                                  asm, ".2d", ".2d",
10148            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
10149                  (i32 vecshiftR64:$imm)))]> {
10150    bits<6> imm;
10151    let Inst{21-16} = imm;
10152  }
10153}
10154
10155let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10156multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
10157                                    SDPatternOperator OpNode = null_frag> {
10158  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
10159                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
10160                 [(set (v8i8 V64:$dst),
10161                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
10162                           (i32 vecshiftR8:$imm)))]> {
10163    bits<3> imm;
10164    let Inst{18-16} = imm;
10165  }
10166
10167  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
10168                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
10169             [(set (v16i8 V128:$dst),
10170               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
10171                       (i32 vecshiftR8:$imm)))]> {
10172    bits<3> imm;
10173    let Inst{18-16} = imm;
10174  }
10175
10176  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
10177                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
10178              [(set (v4i16 V64:$dst),
10179                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10180                        (i32 vecshiftR16:$imm)))]> {
10181    bits<4> imm;
10182    let Inst{19-16} = imm;
10183  }
10184
10185  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
10186                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
10187            [(set (v8i16 V128:$dst),
10188              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10189                      (i32 vecshiftR16:$imm)))]> {
10190    bits<4> imm;
10191    let Inst{19-16} = imm;
10192  }
10193
10194  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
10195                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
10196              [(set (v2i32 V64:$dst),
10197                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10198                        (i32 vecshiftR32:$imm)))]> {
10199    bits<5> imm;
10200    let Inst{20-16} = imm;
10201  }
10202
10203  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
10204                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
10205            [(set (v4i32 V128:$dst),
10206              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10207                      (i32 vecshiftR32:$imm)))]> {
10208    bits<5> imm;
10209    let Inst{20-16} = imm;
10210  }
10211
10212  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
10213                                  V128, V128, vecshiftR64,
10214                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
10215              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
10216                      (i32 vecshiftR64:$imm)))]> {
10217    bits<6> imm;
10218    let Inst{21-16} = imm;
10219  }
10220}
10221
10222multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
10223                                    SDPatternOperator OpNode = null_frag> {
10224  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
10225                                  V64, V64, vecshiftL8,
10226                                  asm, ".8b", ".8b",
10227                    [(set (v8i8 V64:$dst),
10228                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
10229                                  (i32 vecshiftL8:$imm)))]> {
10230    bits<3> imm;
10231    let Inst{18-16} = imm;
10232  }
10233
10234  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
10235                                  V128, V128, vecshiftL8,
10236                                  asm, ".16b", ".16b",
10237                    [(set (v16i8 V128:$dst),
10238                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
10239                                  (i32 vecshiftL8:$imm)))]> {
10240    bits<3> imm;
10241    let Inst{18-16} = imm;
10242  }
10243
10244  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
10245                                  V64, V64, vecshiftL16,
10246                                  asm, ".4h", ".4h",
10247                    [(set (v4i16 V64:$dst),
10248                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10249                                   (i32 vecshiftL16:$imm)))]> {
10250    bits<4> imm;
10251    let Inst{19-16} = imm;
10252  }
10253
10254  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
10255                                  V128, V128, vecshiftL16,
10256                                  asm, ".8h", ".8h",
10257                    [(set (v8i16 V128:$dst),
10258                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10259                                  (i32 vecshiftL16:$imm)))]> {
10260    bits<4> imm;
10261    let Inst{19-16} = imm;
10262  }
10263
10264  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
10265                                  V64, V64, vecshiftL32,
10266                                  asm, ".2s", ".2s",
10267                    [(set (v2i32 V64:$dst),
10268                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10269                                  (i32 vecshiftL32:$imm)))]> {
10270    bits<5> imm;
10271    let Inst{20-16} = imm;
10272  }
10273
10274  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
10275                                  V128, V128, vecshiftL32,
10276                                  asm, ".4s", ".4s",
10277                    [(set (v4i32 V128:$dst),
10278                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10279                                  (i32 vecshiftL32:$imm)))]> {
10280    bits<5> imm;
10281    let Inst{20-16} = imm;
10282  }
10283
10284  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
10285                                  V128, V128, vecshiftL64,
10286                                  asm, ".2d", ".2d",
10287                    [(set (v2i64 V128:$dst),
10288                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
10289                                  (i32 vecshiftL64:$imm)))]> {
10290    bits<6> imm;
10291    let Inst{21-16} = imm;
10292  }
10293}
10294
10295multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
10296                                   SDPatternOperator OpNode> {
10297  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10298                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
10299      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
10300    bits<3> imm;
10301    let Inst{18-16} = imm;
10302  }
10303
10304  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10305                                  V128, V128, vecshiftL8,
10306                                  asm#"2", ".8h", ".16b",
10307      [(set (v8i16 V128:$Rd),
10308            (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)), vecshiftL8:$imm))]> {
10309    bits<3> imm;
10310    let Inst{18-16} = imm;
10311  }
10312
10313  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10314                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
10315      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
10316    bits<4> imm;
10317    let Inst{19-16} = imm;
10318  }
10319
10320  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10321                                  V128, V128, vecshiftL16,
10322                                  asm#"2", ".4s", ".8h",
10323      [(set (v4i32 V128:$Rd),
10324            (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)), vecshiftL16:$imm))]> {
10325
10326    bits<4> imm;
10327    let Inst{19-16} = imm;
10328  }
10329
10330  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10331                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
10332      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
10333    bits<5> imm;
10334    let Inst{20-16} = imm;
10335  }
10336
10337  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10338                                  V128, V128, vecshiftL32,
10339                                  asm#"2", ".2d", ".4s",
10340      [(set (v2i64 V128:$Rd),
10341            (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)), vecshiftL32:$imm))]> {
10342    bits<5> imm;
10343    let Inst{20-16} = imm;
10344  }
10345}
10346
10347
10348//---
10349// Vector load/store
10350//---
10351// SIMD ldX/stX no-index memory references don't allow the optional
10352// ", #0" constant and handle post-indexing explicitly, so we use
10353// a more specialized parse method for them. Otherwise, it's the same as
10354// the general GPR64sp handling.
10355
10356class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
10357                   string asm, dag oops, dag iops, list<dag> pattern>
10358  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
10359  bits<5> Vt;
10360  bits<5> Rn;
10361  let Inst{31} = 0;
10362  let Inst{30} = Q;
10363  let Inst{29-23} = 0b0011000;
10364  let Inst{22} = L;
10365  let Inst{21-16} = 0b000000;
10366  let Inst{15-12} = opcode;
10367  let Inst{11-10} = size;
10368  let Inst{9-5} = Rn;
10369  let Inst{4-0} = Vt;
10370}
10371
10372class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
10373                       string asm, dag oops, dag iops>
10374  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
10375  bits<5> Vt;
10376  bits<5> Rn;
10377  bits<5> Xm;
10378  let Inst{31} = 0;
10379  let Inst{30} = Q;
10380  let Inst{29-23} = 0b0011001;
10381  let Inst{22} = L;
10382  let Inst{21} = 0;
10383  let Inst{20-16} = Xm;
10384  let Inst{15-12} = opcode;
10385  let Inst{11-10} = size;
10386  let Inst{9-5} = Rn;
10387  let Inst{4-0} = Vt;
10388}
10389
10390// The immediate form of AdvSIMD post-indexed addressing is encoded with
10391// register post-index addressing from the zero register.
10392multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
10393                           int Offset, int Size> {
10394  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
10395  //      "ld1\t$Vt, [$Rn], #16"
10396  // may get mapped to
10397  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
10398  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10399                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10400                      GPR64sp:$Rn,
10401                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10402                      XZR), 1>;
10403
10404  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
10405  //      "ld1.8b\t$Vt, [$Rn], #16"
10406  // may get mapped to
10407  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
10408  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10409                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10410                      GPR64sp:$Rn,
10411                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10412                      XZR), 0>;
10413
10414  // E.g. "ld1.8b { v0, v1 }, [x1]"
10415  //      "ld1\t$Vt, [$Rn]"
10416  // may get mapped to
10417  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
10418  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10419                  (!cast<Instruction>(BaseName # Count # "v" # layout)
10420                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10421                      GPR64sp:$Rn), 0>;
10422
10423  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
10424  //      "ld1\t$Vt, [$Rn], $Xm"
10425  // may get mapped to
10426  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
10427  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10428                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10429                      GPR64sp:$Rn,
10430                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10431                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10432}
10433
10434multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
10435                       int Offset128, int Offset64, bits<4> opcode> {
10436  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10437    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
10438                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
10439                           (ins GPR64sp:$Rn), []>;
10440    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
10441                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
10442                           (ins GPR64sp:$Rn), []>;
10443    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
10444                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
10445                           (ins GPR64sp:$Rn), []>;
10446    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
10447                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
10448                           (ins GPR64sp:$Rn), []>;
10449    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
10450                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
10451                           (ins GPR64sp:$Rn), []>;
10452    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
10453                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
10454                           (ins GPR64sp:$Rn), []>;
10455    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
10456                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
10457                           (ins GPR64sp:$Rn), []>;
10458
10459
10460    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
10461                       (outs GPR64sp:$wback,
10462                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
10463                       (ins GPR64sp:$Rn,
10464                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10465    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
10466                       (outs GPR64sp:$wback,
10467                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
10468                       (ins GPR64sp:$Rn,
10469                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10470    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
10471                       (outs GPR64sp:$wback,
10472                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
10473                       (ins GPR64sp:$Rn,
10474                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10475    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
10476                       (outs GPR64sp:$wback,
10477                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
10478                       (ins GPR64sp:$Rn,
10479                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10480    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
10481                       (outs GPR64sp:$wback,
10482                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
10483                       (ins GPR64sp:$Rn,
10484                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10485    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
10486                       (outs GPR64sp:$wback,
10487                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
10488                       (ins GPR64sp:$Rn,
10489                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10490    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
10491                       (outs GPR64sp:$wback,
10492                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
10493                       (ins GPR64sp:$Rn,
10494                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10495  }
10496
10497  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10498  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10499  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10500  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10501  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10502  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10503  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10504}
10505
10506// Only ld1/st1 has a v1d version.
10507multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
10508                       int Offset128, int Offset64, bits<4> opcode> {
10509  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
10510    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
10511                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10512                                 GPR64sp:$Rn), []>;
10513    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
10514                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10515                                GPR64sp:$Rn), []>;
10516    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
10517                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10518                                GPR64sp:$Rn), []>;
10519    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
10520                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10521                                GPR64sp:$Rn), []>;
10522    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
10523                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10524                                GPR64sp:$Rn), []>;
10525    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
10526                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10527                                GPR64sp:$Rn), []>;
10528    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
10529                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10530                                GPR64sp:$Rn), []>;
10531
10532    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
10533                       (outs GPR64sp:$wback),
10534                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10535                            GPR64sp:$Rn,
10536                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10537    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
10538                       (outs GPR64sp:$wback),
10539                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10540                            GPR64sp:$Rn,
10541                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10542    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
10543                       (outs GPR64sp:$wback),
10544                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10545                            GPR64sp:$Rn,
10546                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10547    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
10548                       (outs GPR64sp:$wback),
10549                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10550                            GPR64sp:$Rn,
10551                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10552    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
10553                       (outs GPR64sp:$wback),
10554                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10555                            GPR64sp:$Rn,
10556                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10557    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
10558                       (outs GPR64sp:$wback),
10559                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10560                            GPR64sp:$Rn,
10561                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10562    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
10563                       (outs GPR64sp:$wback),
10564                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10565                            GPR64sp:$Rn,
10566                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10567  }
10568
10569  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10570  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10571  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10572  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10573  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10574  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10575  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10576}
10577
10578multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
10579                       int Offset128, int Offset64, bits<4> opcode>
10580  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10581
10582  // LD1 instructions have extra "1d" variants.
10583  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10584    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
10585                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
10586                           (ins GPR64sp:$Rn), []>;
10587
10588    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
10589                       (outs GPR64sp:$wback,
10590                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
10591                       (ins GPR64sp:$Rn,
10592                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10593  }
10594
10595  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10596}
10597
10598multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
10599                       int Offset128, int Offset64, bits<4> opcode>
10600  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10601
10602  // ST1 instructions have extra "1d" variants.
10603  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
10604    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
10605                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10606                                GPR64sp:$Rn), []>;
10607
10608    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
10609                       (outs GPR64sp:$wback),
10610                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10611                            GPR64sp:$Rn,
10612                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10613  }
10614
10615  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10616}
10617
10618multiclass SIMDLd1Multiple<string asm> {
10619  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10620  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10621  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10622  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10623}
10624
10625multiclass SIMDSt1Multiple<string asm> {
10626  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10627  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10628  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10629  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10630}
10631
10632multiclass SIMDLd2Multiple<string asm> {
10633  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10634}
10635
10636multiclass SIMDSt2Multiple<string asm> {
10637  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10638}
10639
10640multiclass SIMDLd3Multiple<string asm> {
10641  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10642}
10643
10644multiclass SIMDSt3Multiple<string asm> {
10645  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10646}
10647
10648multiclass SIMDLd4Multiple<string asm> {
10649  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10650}
10651
10652multiclass SIMDSt4Multiple<string asm> {
10653  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10654}
10655
10656//---
10657// AdvSIMD Load/store single-element
10658//---
10659
10660class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
10661                         string asm, string operands, string cst,
10662                         dag oops, dag iops, list<dag> pattern>
10663  : I<oops, iops, asm, operands, cst, pattern> {
10664  bits<5> Vt;
10665  bits<5> Rn;
10666  let Inst{31} = 0;
10667  let Inst{29-24} = 0b001101;
10668  let Inst{22} = L;
10669  let Inst{21} = R;
10670  let Inst{15-13} = opcode;
10671  let Inst{9-5} = Rn;
10672  let Inst{4-0} = Vt;
10673}
10674
10675class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
10676                         string asm, string operands, string cst,
10677                         dag oops, dag iops, list<dag> pattern>
10678  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
10679  bits<5> Vt;
10680  bits<5> Rn;
10681  let Inst{31} = 0;
10682  let Inst{29-24} = 0b001101;
10683  let Inst{22} = L;
10684  let Inst{21} = R;
10685  let Inst{15-13} = opcode;
10686  let Inst{9-5} = Rn;
10687  let Inst{4-0} = Vt;
10688}
10689
10690
10691let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10692class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
10693                  DAGOperand listtype>
10694  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
10695                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
10696                       []> {
10697  let Inst{30} = Q;
10698  let Inst{23} = 0;
10699  let Inst{20-16} = 0b00000;
10700  let Inst{12} = S;
10701  let Inst{11-10} = size;
10702}
10703let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10704class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
10705                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
10706  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
10707                       "$Rn = $wback",
10708                       (outs GPR64sp:$wback, listtype:$Vt),
10709                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
10710  bits<5> Xm;
10711  let Inst{30} = Q;
10712  let Inst{23} = 1;
10713  let Inst{20-16} = Xm;
10714  let Inst{12} = S;
10715  let Inst{11-10} = size;
10716}
10717
10718multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
10719                          int Offset, int Size> {
10720  // E.g. "ld1r { v0.8b }, [x1], #1"
10721  //      "ld1r.8b\t$Vt, [$Rn], #1"
10722  // may get mapped to
10723  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10724  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10725                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10726                      GPR64sp:$Rn,
10727                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10728                      XZR), 1>;
10729
10730  // E.g. "ld1r.8b { v0 }, [x1], #1"
10731  //      "ld1r.8b\t$Vt, [$Rn], #1"
10732  // may get mapped to
10733  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10734  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10735                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10736                      GPR64sp:$Rn,
10737                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10738                      XZR), 0>;
10739
10740  // E.g. "ld1r.8b { v0 }, [x1]"
10741  //      "ld1r.8b\t$Vt, [$Rn]"
10742  // may get mapped to
10743  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10744  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10745                  (!cast<Instruction>(BaseName # "v" # layout)
10746                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10747                      GPR64sp:$Rn), 0>;
10748
10749  // E.g. "ld1r.8b { v0 }, [x1], x2"
10750  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10751  // may get mapped to
10752  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10753  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10754                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10755                      GPR64sp:$Rn,
10756                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10757                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10758}
10759
10760multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10761  int Offset1, int Offset2, int Offset4, int Offset8> {
10762  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10763                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10764  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10765                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10766  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10767                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10768  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10769                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10770  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10771                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10772  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10773                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10774  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10775                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10776  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10777                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10778
10779  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10780                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10781                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10782  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10783                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10784                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10785  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10786                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10787                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10788  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10789                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10790                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10791  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10792                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10793                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10794  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10795                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10796                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10797  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10798                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10799                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10800  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10801                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10802                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10803
10804  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10805  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10806  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10807  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10808  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10809  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10810  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10811  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10812}
10813
10814class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10815                      dag oops, dag iops, list<dag> pattern>
10816  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10817                       pattern> {
10818  // idx encoded in Q:S:size fields.
10819  bits<4> idx;
10820  let Inst{30} = idx{3};
10821  let Inst{23} = 0;
10822  let Inst{20-16} = 0b00000;
10823  let Inst{12} = idx{2};
10824  let Inst{11-10} = idx{1-0};
10825}
10826class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10827                      dag oops, dag iops, list<dag> pattern>
10828  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10829                           oops, iops, pattern> {
10830  // idx encoded in Q:S:size fields.
10831  bits<4> idx;
10832  let Inst{30} = idx{3};
10833  let Inst{23} = 0;
10834  let Inst{20-16} = 0b00000;
10835  let Inst{12} = idx{2};
10836  let Inst{11-10} = idx{1-0};
10837}
10838class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10839                          dag oops, dag iops>
10840  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10841                       "$Rn = $wback", oops, iops, []> {
10842  // idx encoded in Q:S:size fields.
10843  bits<4> idx;
10844  bits<5> Xm;
10845  let Inst{30} = idx{3};
10846  let Inst{23} = 1;
10847  let Inst{20-16} = Xm;
10848  let Inst{12} = idx{2};
10849  let Inst{11-10} = idx{1-0};
10850}
10851class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10852                          dag oops, dag iops>
10853  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10854                           "$Rn = $wback", oops, iops, []> {
10855  // idx encoded in Q:S:size fields.
10856  bits<4> idx;
10857  bits<5> Xm;
10858  let Inst{30} = idx{3};
10859  let Inst{23} = 1;
10860  let Inst{20-16} = Xm;
10861  let Inst{12} = idx{2};
10862  let Inst{11-10} = idx{1-0};
10863}
10864
10865class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10866                      dag oops, dag iops, list<dag> pattern>
10867  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10868                       pattern> {
10869  // idx encoded in Q:S:size<1> fields.
10870  bits<3> idx;
10871  let Inst{30} = idx{2};
10872  let Inst{23} = 0;
10873  let Inst{20-16} = 0b00000;
10874  let Inst{12} = idx{1};
10875  let Inst{11} = idx{0};
10876  let Inst{10} = size;
10877}
10878class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10879                      dag oops, dag iops, list<dag> pattern>
10880  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10881                           oops, iops, pattern> {
10882  // idx encoded in Q:S:size<1> fields.
10883  bits<3> idx;
10884  let Inst{30} = idx{2};
10885  let Inst{23} = 0;
10886  let Inst{20-16} = 0b00000;
10887  let Inst{12} = idx{1};
10888  let Inst{11} = idx{0};
10889  let Inst{10} = size;
10890}
10891
10892class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10893                          dag oops, dag iops>
10894  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10895                       "$Rn = $wback", oops, iops, []> {
10896  // idx encoded in Q:S:size<1> fields.
10897  bits<3> idx;
10898  bits<5> Xm;
10899  let Inst{30} = idx{2};
10900  let Inst{23} = 1;
10901  let Inst{20-16} = Xm;
10902  let Inst{12} = idx{1};
10903  let Inst{11} = idx{0};
10904  let Inst{10} = size;
10905}
10906class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10907                          dag oops, dag iops>
10908  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10909                           "$Rn = $wback", oops, iops, []> {
10910  // idx encoded in Q:S:size<1> fields.
10911  bits<3> idx;
10912  bits<5> Xm;
10913  let Inst{30} = idx{2};
10914  let Inst{23} = 1;
10915  let Inst{20-16} = Xm;
10916  let Inst{12} = idx{1};
10917  let Inst{11} = idx{0};
10918  let Inst{10} = size;
10919}
10920class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10921                      dag oops, dag iops, list<dag> pattern>
10922  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10923                       pattern> {
10924  // idx encoded in Q:S fields.
10925  bits<2> idx;
10926  let Inst{30} = idx{1};
10927  let Inst{23} = 0;
10928  let Inst{20-16} = 0b00000;
10929  let Inst{12} = idx{0};
10930  let Inst{11-10} = size;
10931}
10932class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10933                      dag oops, dag iops, list<dag> pattern>
10934  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10935                           oops, iops, pattern> {
10936  // idx encoded in Q:S fields.
10937  bits<2> idx;
10938  let Inst{30} = idx{1};
10939  let Inst{23} = 0;
10940  let Inst{20-16} = 0b00000;
10941  let Inst{12} = idx{0};
10942  let Inst{11-10} = size;
10943}
10944class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10945                          string asm, dag oops, dag iops>
10946  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10947                       "$Rn = $wback", oops, iops, []> {
10948  // idx encoded in Q:S fields.
10949  bits<2> idx;
10950  bits<5> Xm;
10951  let Inst{30} = idx{1};
10952  let Inst{23} = 1;
10953  let Inst{20-16} = Xm;
10954  let Inst{12} = idx{0};
10955  let Inst{11-10} = size;
10956}
10957class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10958                          string asm, dag oops, dag iops>
10959  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10960                           "$Rn = $wback", oops, iops, []> {
10961  // idx encoded in Q:S fields.
10962  bits<2> idx;
10963  bits<5> Xm;
10964  let Inst{30} = idx{1};
10965  let Inst{23} = 1;
10966  let Inst{20-16} = Xm;
10967  let Inst{12} = idx{0};
10968  let Inst{11-10} = size;
10969}
10970class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10971                      dag oops, dag iops, list<dag> pattern>
10972  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10973                       pattern> {
10974  // idx encoded in Q field.
10975  bits<1> idx;
10976  let Inst{30} = idx;
10977  let Inst{23} = 0;
10978  let Inst{20-16} = 0b00000;
10979  let Inst{12} = 0;
10980  let Inst{11-10} = size;
10981}
10982class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10983                      dag oops, dag iops, list<dag> pattern>
10984  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10985                           oops, iops, pattern> {
10986  // idx encoded in Q field.
10987  bits<1> idx;
10988  let Inst{30} = idx;
10989  let Inst{23} = 0;
10990  let Inst{20-16} = 0b00000;
10991  let Inst{12} = 0;
10992  let Inst{11-10} = size;
10993}
10994class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10995                          string asm, dag oops, dag iops>
10996  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10997                       "$Rn = $wback", oops, iops, []> {
10998  // idx encoded in Q field.
10999  bits<1> idx;
11000  bits<5> Xm;
11001  let Inst{30} = idx;
11002  let Inst{23} = 1;
11003  let Inst{20-16} = Xm;
11004  let Inst{12} = 0;
11005  let Inst{11-10} = size;
11006}
11007class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
11008                          string asm, dag oops, dag iops>
11009  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11010                           "$Rn = $wback", oops, iops, []> {
11011  // idx encoded in Q field.
11012  bits<1> idx;
11013  bits<5> Xm;
11014  let Inst{30} = idx;
11015  let Inst{23} = 1;
11016  let Inst{20-16} = Xm;
11017  let Inst{12} = 0;
11018  let Inst{11-10} = size;
11019}
11020
11021let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11022multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
11023                         RegisterOperand listtype,
11024                         RegisterOperand GPR64pi> {
11025  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
11026                           (outs listtype:$dst),
11027                           (ins listtype:$Vt, VectorIndexB:$idx,
11028                                GPR64sp:$Rn), []>;
11029
11030  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
11031                            (outs GPR64sp:$wback, listtype:$dst),
11032                            (ins listtype:$Vt, VectorIndexB:$idx,
11033                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11034}
11035let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11036multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
11037                         RegisterOperand listtype,
11038                         RegisterOperand GPR64pi> {
11039  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
11040                            (outs listtype:$dst),
11041                            (ins listtype:$Vt, VectorIndexH:$idx,
11042                                 GPR64sp:$Rn), []>;
11043
11044  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
11045                            (outs GPR64sp:$wback, listtype:$dst),
11046                            (ins listtype:$Vt, VectorIndexH:$idx,
11047                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11048}
11049let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11050multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
11051                         RegisterOperand listtype,
11052                         RegisterOperand GPR64pi> {
11053  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
11054                            (outs listtype:$dst),
11055                            (ins listtype:$Vt, VectorIndexS:$idx,
11056                                 GPR64sp:$Rn), []>;
11057
11058  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
11059                            (outs GPR64sp:$wback, listtype:$dst),
11060                            (ins listtype:$Vt, VectorIndexS:$idx,
11061                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11062}
11063let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11064multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
11065                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11066  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
11067                            (outs listtype:$dst),
11068                            (ins listtype:$Vt, VectorIndexD:$idx,
11069                                 GPR64sp:$Rn), []>;
11070
11071  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
11072                            (outs GPR64sp:$wback, listtype:$dst),
11073                            (ins listtype:$Vt, VectorIndexD:$idx,
11074                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11075}
11076let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11077multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
11078                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11079  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
11080                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
11081                                        GPR64sp:$Rn), []>;
11082
11083  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
11084                                    (outs GPR64sp:$wback),
11085                                    (ins listtype:$Vt, VectorIndexB:$idx,
11086                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
11087}
11088let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11089multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
11090                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11091  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
11092                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
11093                                         GPR64sp:$Rn), []>;
11094
11095  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
11096                            (outs GPR64sp:$wback),
11097                            (ins listtype:$Vt, VectorIndexH:$idx,
11098                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11099}
11100let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11101multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
11102                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11103  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
11104                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
11105                                         GPR64sp:$Rn), []>;
11106
11107  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
11108                            (outs GPR64sp:$wback),
11109                            (ins listtype:$Vt, VectorIndexS:$idx,
11110                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11111}
11112let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11113multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
11114                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11115  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
11116                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
11117                                         GPR64sp:$Rn), []>;
11118
11119  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
11120                            (outs GPR64sp:$wback),
11121                            (ins listtype:$Vt, VectorIndexD:$idx,
11122                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11123}
11124
11125multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
11126                                 string Count, int Offset, Operand idxtype> {
11127  // E.g. "ld1 { v0.8b }[0], [x1], #1"
11128  //      "ld1\t$Vt, [$Rn], #1"
11129  // may get mapped to
11130  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
11131  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
11132                  (!cast<Instruction>(NAME # Type  # "_POST")
11133                      GPR64sp:$Rn,
11134                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
11135                      idxtype:$idx, XZR), 1>;
11136
11137  // E.g. "ld1.8b { v0 }[0], [x1], #1"
11138  //      "ld1.8b\t$Vt, [$Rn], #1"
11139  // may get mapped to
11140  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
11141  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
11142                  (!cast<Instruction>(NAME # Type # "_POST")
11143                      GPR64sp:$Rn,
11144                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11145                      idxtype:$idx, XZR), 0>;
11146
11147  // E.g. "ld1.8b { v0 }[0], [x1]"
11148  //      "ld1.8b\t$Vt, [$Rn]"
11149  // may get mapped to
11150  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
11151  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
11152                      (!cast<Instruction>(NAME # Type)
11153                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11154                         idxtype:$idx, GPR64sp:$Rn), 0>;
11155
11156  // E.g. "ld1.8b { v0 }[0], [x1], x2"
11157  //      "ld1.8b\t$Vt, [$Rn], $Xm"
11158  // may get mapped to
11159  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
11160  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
11161                      (!cast<Instruction>(NAME # Type # "_POST")
11162                         GPR64sp:$Rn,
11163                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11164                         idxtype:$idx,
11165                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
11166}
11167
11168multiclass SIMDLdSt1SingleAliases<string asm> {
11169  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
11170  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
11171  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
11172  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
11173}
11174
11175multiclass SIMDLdSt2SingleAliases<string asm> {
11176  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
11177  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
11178  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
11179  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
11180}
11181
11182multiclass SIMDLdSt3SingleAliases<string asm> {
11183  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
11184  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
11185  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
11186  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
11187}
11188
11189multiclass SIMDLdSt4SingleAliases<string asm> {
11190  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
11191  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
11192  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
11193  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
11194}
11195} // end of 'let Predicates = [HasNEON]'
11196
11197//----------------------------------------------------------------------------
11198// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
11199//----------------------------------------------------------------------------
11200
11201let Predicates = [HasNEON, HasRDM] in {
11202
11203class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
11204                                    RegisterOperand regtype, string asm,
11205                                    string kind, list<dag> pattern>
11206  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
11207                                pattern> {
11208}
11209multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
11210                                             SDPatternOperator op> {
11211  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
11212    [(set (v4i16 V64:$dst),
11213          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
11214  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
11215    [(set (v8i16 V128:$dst),
11216          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
11217  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
11218    [(set (v2i32 V64:$dst),
11219          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
11220  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
11221    [(set (v4i32 V128:$dst),
11222          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
11223}
11224
11225multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
11226                                     SDPatternOperator op> {
11227  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
11228                                          V64, V64, V128_lo, VectorIndexH,
11229                                          asm, ".4h", ".4h", ".4h", ".h",
11230    [(set (v4i16 V64:$dst),
11231          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
11232                     (dup_v8i16 (v8i16 V128_lo:$Rm),
11233                                 VectorIndexH:$idx))))]> {
11234    bits<3> idx;
11235    let Inst{11} = idx{2};
11236    let Inst{21} = idx{1};
11237    let Inst{20} = idx{0};
11238  }
11239
11240  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
11241                                          V128, V128, V128_lo, VectorIndexH,
11242                                          asm, ".8h", ".8h", ".8h", ".h",
11243    [(set (v8i16 V128:$dst),
11244          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
11245                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
11246                                              VectorIndexH:$idx)))))]> {
11247    bits<3> idx;
11248    let Inst{11} = idx{2};
11249    let Inst{21} = idx{1};
11250    let Inst{20} = idx{0};
11251  }
11252
11253  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
11254                                          V64, V64, V128, VectorIndexS,
11255                                          asm, ".2s", ".2s", ".2s", ".s",
11256    [(set (v2i32 V64:$dst),
11257          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
11258                     (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
11259    bits<2> idx;
11260    let Inst{11} = idx{1};
11261    let Inst{21} = idx{0};
11262  }
11263
11264  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
11265                                          V128, V128, V128, VectorIndexS,
11266                                          asm, ".4s", ".4s", ".4s", ".s",
11267    [(set (v4i32 V128:$dst),
11268          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11269                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
11270                                              VectorIndexS:$idx)))))]> {
11271    bits<2> idx;
11272    let Inst{11} = idx{1};
11273    let Inst{21} = idx{0};
11274  }
11275
11276  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
11277                                          FPR16Op, FPR16Op, V128_lo,
11278                                          VectorIndexH, asm, ".h", "", "", ".h",
11279                                          []> {
11280    bits<3> idx;
11281    let Inst{11} = idx{2};
11282    let Inst{21} = idx{1};
11283    let Inst{20} = idx{0};
11284  }
11285
11286  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
11287                                          FPR32Op, FPR32Op, V128, VectorIndexS,
11288                                          asm, ".s", "", "", ".s",
11289    [(set (i32 FPR32Op:$dst),
11290          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
11291                   (i32 (vector_extract (v4i32 V128:$Rm),
11292                                        VectorIndexS:$idx)))))]> {
11293    bits<2> idx;
11294    let Inst{11} = idx{1};
11295    let Inst{21} = idx{0};
11296  }
11297}
11298} // let Predicates = [HasNeon, HasRDM]
11299
11300//----------------------------------------------------------------------------
11301// ARMv8.3 Complex ADD/MLA instructions
11302//----------------------------------------------------------------------------
11303
11304class ComplexRotationOperand<int Angle, int Remainder, string Type>
11305  : AsmOperandClass {
11306  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
11307  let DiagnosticType = "InvalidComplexRotation" # Type;
11308  let Name = "ComplexRotation" # Type;
11309}
11310def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
11311                                                  SDNodeXForm<imm, [{
11312  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
11313}]>> {
11314  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
11315  let PrintMethod = "printComplexRotationOp<90, 0>";
11316}
11317def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
11318                                                  SDNodeXForm<imm, [{
11319  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
11320}]>> {
11321  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
11322  let PrintMethod = "printComplexRotationOp<180, 90>";
11323}
11324let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11325class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
11326                                     RegisterOperand regtype, Operand rottype,
11327                                     string asm, string kind, list<dag> pattern>
11328  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
11329      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
11330      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
11331    Sched<[!if(Q, WriteVq, WriteVd)]> {
11332  bits<5> Rd;
11333  bits<5> Rn;
11334  bits<5> Rm;
11335  bits<1> rot;
11336  let Inst{31}    = 0;
11337  let Inst{30}    = Q;
11338  let Inst{29}    = U;
11339  let Inst{28-24} = 0b01110;
11340  let Inst{23-22} = size;
11341  let Inst{21}    = 0;
11342  let Inst{20-16} = Rm;
11343  let Inst{15-13} = opcode;
11344  // Non-tied version (FCADD) only has one rotation bit
11345  let Inst{12}    = rot;
11346  let Inst{11}    = 0;
11347  let Inst{10}    = 1;
11348  let Inst{9-5}   = Rn;
11349  let Inst{4-0}   = Rd;
11350}
11351
11352//8.3 CompNum - Floating-point complex number support
11353multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
11354                                          string asm, SDPatternOperator OpNode>{
11355  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11356  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
11357              asm, ".4h",
11358              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11359                                              (v4f16 V64:$Rn),
11360                                              (v4f16 V64:$Rm),
11361                                              (i32 rottype:$rot)))]>;
11362
11363  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
11364              asm, ".8h",
11365              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11366                                               (v8f16 V128:$Rn),
11367                                               (v8f16 V128:$Rm),
11368                                               (i32 rottype:$rot)))]>;
11369  }
11370
11371  let Predicates = [HasComplxNum, HasNEON] in {
11372  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
11373              asm, ".2s",
11374              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11375                                              (v2f32 V64:$Rn),
11376                                              (v2f32 V64:$Rm),
11377                                              (i32 rottype:$rot)))]>;
11378
11379  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
11380              asm, ".4s",
11381              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11382                                               (v4f32 V128:$Rn),
11383                                               (v4f32 V128:$Rm),
11384                                               (i32 rottype:$rot)))]>;
11385
11386  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
11387              asm, ".2d",
11388              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11389                                               (v2f64 V128:$Rn),
11390                                               (v2f64 V128:$Rm),
11391                                               (i32 rottype:$rot)))]>;
11392  }
11393}
11394
11395let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11396class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
11397                                         bits<3> opcode,
11398                                         RegisterOperand regtype,
11399                                         Operand rottype, string asm,
11400                                         string kind, list<dag> pattern>
11401  : I<(outs regtype:$dst),
11402      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
11403      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
11404      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
11405    Sched<[!if(Q, WriteVq, WriteVd)]> {
11406  bits<5> Rd;
11407  bits<5> Rn;
11408  bits<5> Rm;
11409  bits<2> rot;
11410  let Inst{31}    = 0;
11411  let Inst{30}    = Q;
11412  let Inst{29}    = U;
11413  let Inst{28-24} = 0b01110;
11414  let Inst{23-22} = size;
11415  let Inst{21}    = 0;
11416  let Inst{20-16} = Rm;
11417  let Inst{15-13} = opcode;
11418  let Inst{12-11} = rot;
11419  let Inst{10}    = 1;
11420  let Inst{9-5}   = Rn;
11421  let Inst{4-0}   = Rd;
11422}
11423
11424multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
11425                                             Operand rottype, string asm,
11426                                             SDPatternOperator OpNode> {
11427  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11428  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
11429              rottype, asm, ".4h",
11430              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11431                                              (v4f16 V64:$Rn),
11432                                              (v4f16 V64:$Rm),
11433                                              (i32 rottype:$rot)))]>;
11434
11435  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
11436              rottype, asm, ".8h",
11437              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11438                                               (v8f16 V128:$Rn),
11439                                               (v8f16 V128:$Rm),
11440                                               (i32 rottype:$rot)))]>;
11441  }
11442
11443  let Predicates = [HasComplxNum, HasNEON] in {
11444  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
11445              rottype, asm, ".2s",
11446              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11447                                              (v2f32 V64:$Rn),
11448                                              (v2f32 V64:$Rm),
11449                                              (i32 rottype:$rot)))]>;
11450
11451  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
11452              rottype, asm, ".4s",
11453              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11454                                               (v4f32 V128:$Rn),
11455                                               (v4f32 V128:$Rm),
11456                                               (i32 rottype:$rot)))]>;
11457
11458  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
11459              rottype, asm, ".2d",
11460              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11461                                               (v2f64 V128:$Rn),
11462                                               (v2f64 V128:$Rm),
11463                                               (i32 rottype:$rot)))]>;
11464  }
11465}
11466
11467let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11468class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
11469                                 bit opc1, bit opc2, RegisterOperand dst_reg,
11470                                 RegisterOperand lhs_reg,
11471                                 RegisterOperand rhs_reg, Operand vec_idx,
11472                                 Operand rottype, string asm, string apple_kind,
11473                                 string dst_kind, string lhs_kind,
11474                                 string rhs_kind, list<dag> pattern>
11475  : I<(outs dst_reg:$dst),
11476      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
11477      asm,
11478      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
11479      "$idx, $rot" # "|" # apple_kind #
11480      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
11481    Sched<[!if(Q, WriteVq, WriteVd)]> {
11482  bits<5> Rd;
11483  bits<5> Rn;
11484  bits<5> Rm;
11485  bits<2> rot;
11486
11487  let Inst{31}    = 0;
11488  let Inst{30}    = Q;
11489  let Inst{29}    = U;
11490  let Inst{28}    = Scalar;
11491  let Inst{27-24} = 0b1111;
11492  let Inst{23-22} = size;
11493  // Bit 21 must be set by the derived class.
11494  let Inst{20-16} = Rm;
11495  let Inst{15}    = opc1;
11496  let Inst{14-13} = rot;
11497  let Inst{12}    = opc2;
11498  // Bit 11 must be set by the derived class.
11499  let Inst{10}    = 0;
11500  let Inst{9-5}   = Rn;
11501  let Inst{4-0}   = Rd;
11502}
11503
11504// The complex instructions index by pairs of elements, so the VectorIndexes
11505// don't match the lane types, and the index bits are different to the other
11506// classes.
11507multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
11508                                     string asm> {
11509  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11510  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
11511                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
11512                      ".4h", ".h", []> {
11513    bits<1> idx;
11514    let Inst{11} = 0;
11515    let Inst{21} = idx{0};
11516  }
11517
11518  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
11519                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
11520                      ".8h", ".8h", ".h", []> {
11521    bits<2> idx;
11522    let Inst{11} = idx{1};
11523    let Inst{21} = idx{0};
11524  }
11525  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
11526
11527  let Predicates = [HasComplxNum, HasNEON] in {
11528  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
11529                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
11530                      ".4s", ".4s", ".s", []> {
11531    bits<1> idx;
11532    let Inst{11} = idx{0};
11533    let Inst{21} = 0;
11534  }
11535  } // Predicates = [HasComplxNum, HasNEON]
11536}
11537
11538//----------------------------------------------------------------------------
11539// Crypto extensions
11540//----------------------------------------------------------------------------
11541
11542let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11543class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
11544              list<dag> pat>
11545  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
11546    Sched<[WriteVq]>{
11547  bits<5> Rd;
11548  bits<5> Rn;
11549  let Inst{31-16} = 0b0100111000101000;
11550  let Inst{15-12} = opc;
11551  let Inst{11-10} = 0b10;
11552  let Inst{9-5}   = Rn;
11553  let Inst{4-0}   = Rd;
11554}
11555
11556class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
11557  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
11558            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
11559
11560class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
11561  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
11562            "$Rd = $dst",
11563            [(set (v16i8 V128:$dst),
11564                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
11565
11566let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11567class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
11568                     dag oops, dag iops, list<dag> pat>
11569  : I<oops, iops, asm,
11570      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
11571      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
11572    Sched<[WriteVq]>{
11573  bits<5> Rd;
11574  bits<5> Rn;
11575  bits<5> Rm;
11576  let Inst{31-21} = 0b01011110000;
11577  let Inst{20-16} = Rm;
11578  let Inst{15}    = 0;
11579  let Inst{14-12} = opc;
11580  let Inst{11-10} = 0b00;
11581  let Inst{9-5}   = Rn;
11582  let Inst{4-0}   = Rd;
11583}
11584
11585class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
11586  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11587                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
11588                   [(set (v4i32 FPR128:$dst),
11589                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
11590                                 (v4i32 V128:$Rm)))]>;
11591
11592class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
11593  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
11594                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
11595                   [(set (v4i32 V128:$dst),
11596                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11597                                 (v4i32 V128:$Rm)))]>;
11598
11599class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
11600  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11601                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
11602                   [(set (v4i32 FPR128:$dst),
11603                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
11604                                 (v4i32 V128:$Rm)))]>;
11605
11606let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11607class SHA2OpInst<bits<4> opc, string asm, string kind,
11608                 string cstr, dag oops, dag iops,
11609                 list<dag> pat>
11610  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
11611                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
11612    Sched<[WriteVq]>{
11613  bits<5> Rd;
11614  bits<5> Rn;
11615  let Inst{31-16} = 0b0101111000101000;
11616  let Inst{15-12} = opc;
11617  let Inst{11-10} = 0b10;
11618  let Inst{9-5}   = Rn;
11619  let Inst{4-0}   = Rd;
11620}
11621
11622class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
11623  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
11624               (ins V128:$Rd, V128:$Rn),
11625               [(set (v4i32 V128:$dst),
11626                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
11627
11628class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
11629  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
11630               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
11631
11632// Armv8.2-A Crypto extensions
11633class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
11634                    list<dag> pattern>
11635  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
11636  bits<5> Vd;
11637  bits<5> Vn;
11638  let Inst{31-25} = 0b1100111;
11639  let Inst{9-5}   = Vn;
11640  let Inst{4-0}   = Vd;
11641}
11642
11643class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
11644  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
11645                  "$Vd = $Vdst", []> {
11646  let Inst{31-25} = 0b1100111;
11647  let Inst{24-21} = 0b0110;
11648  let Inst{20-15} = 0b000001;
11649  let Inst{14}    = op0;
11650  let Inst{13-12} = 0b00;
11651  let Inst{11-10} = op1;
11652}
11653class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
11654  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
11655class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
11656  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
11657
11658class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
11659                string asmops, string cst>
11660  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
11661  bits<5> Vm;
11662  let Inst{24-21} = 0b0011;
11663  let Inst{20-16} = Vm;
11664  let Inst{15}    = 0b1;
11665  let Inst{14}    = op0;
11666  let Inst{13-12} = 0b00;
11667  let Inst{11-10} = op1;
11668}
11669class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
11670  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11671              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
11672class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
11673  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11674              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11675class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
11676  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11677              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
11678class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
11679  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11680              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11681class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11682  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11683              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11684
11685class CryptoRRRR<bits<2>op0, string asm, string asmops>
11686  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11687                  asmops, "", []> {
11688  bits<5> Vm;
11689  bits<5> Va;
11690  let Inst{24-23} = 0b00;
11691  let Inst{22-21} = op0;
11692  let Inst{20-16} = Vm;
11693  let Inst{15}    = 0b0;
11694  let Inst{14-10} = Va;
11695}
11696class CryptoRRRR_16B<bits<2>op0, string asm>
11697 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11698                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11699}
11700class CryptoRRRR_4S<bits<2>op0, string asm>
11701 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11702                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11703}
11704
11705class CryptoRRRi6<string asm>
11706  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11707                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11708                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11709  bits<6> imm;
11710  bits<5> Vm;
11711  let Inst{24-21} = 0b0100;
11712  let Inst{20-16} = Vm;
11713  let Inst{15-10} = imm;
11714  let Inst{9-5}   = Vn;
11715  let Inst{4-0}   = Vd;
11716}
11717
11718class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11719  : BaseCryptoV82<(outs V128:$Vdst),
11720                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11721                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11722                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11723  bits<2> imm;
11724  bits<5> Vm;
11725  let Inst{24-21} = 0b0010;
11726  let Inst{20-16} = Vm;
11727  let Inst{15}    = 0b1;
11728  let Inst{14}    = op0;
11729  let Inst{13-12} = imm;
11730  let Inst{11-10} = op1;
11731}
11732
11733//----------------------------------------------------------------------------
11734// v8.1 atomic instructions extension:
11735// * CAS
11736// * CASP
11737// * SWP
11738// * LDOPregister<OP>, and aliases STOPregister<OP>
11739
11740// Instruction encodings:
11741//
11742//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11743// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11744// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11745// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11746// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11747// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11748
11749// Instruction syntax:
11750//
11751// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11752// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11753// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11754// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11755// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11756// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11757// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11758// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11759// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11760// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11761
11762let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11763class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11764                      string cstr, list<dag> pattern>
11765      : I<oops, iops, asm, operands, cstr, pattern> {
11766  bits<2> Sz;
11767  bit NP;
11768  bit Acq;
11769  bit Rel;
11770  bits<5> Rs;
11771  bits<5> Rn;
11772  bits<5> Rt;
11773  let Inst{31-30} = Sz;
11774  let Inst{29-24} = 0b001000;
11775  let Inst{23} = NP;
11776  let Inst{22} = Acq;
11777  let Inst{21} = 0b1;
11778  let Inst{20-16} = Rs;
11779  let Inst{15} = Rel;
11780  let Inst{14-10} = 0b11111;
11781  let Inst{9-5} = Rn;
11782  let Inst{4-0} = Rt;
11783  let Predicates = [HasLSE];
11784}
11785
11786class BaseCAS<string order, string size, RegisterClass RC>
11787      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11788                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11789                        "$out = $Rs",[]>,
11790        Sched<[WriteAtomic]> {
11791  let NP = 1;
11792}
11793
11794multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11795  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11796  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11797  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11798  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11799}
11800
11801class BaseCASP<string order, string size, RegisterOperand RC>
11802      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11803                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11804                        "$out = $Rs",[]>,
11805        Sched<[WriteAtomic]> {
11806  let NP = 0;
11807}
11808
11809multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11810  let Sz = 0b00, Acq = Acq, Rel = Rel in
11811    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11812  let Sz = 0b01, Acq = Acq, Rel = Rel in
11813    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11814}
11815
11816let Predicates = [HasLSE] in
11817class BaseSWP<string order, string size, RegisterClass RC>
11818      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11819          "\t$Rs, $Rt, [$Rn]","",[]>,
11820        Sched<[WriteAtomic]> {
11821  bits<2> Sz;
11822  bit Acq;
11823  bit Rel;
11824  bits<5> Rs;
11825  bits<3> opc = 0b000;
11826  bits<5> Rn;
11827  bits<5> Rt;
11828  let Inst{31-30} = Sz;
11829  let Inst{29-24} = 0b111000;
11830  let Inst{23} = Acq;
11831  let Inst{22} = Rel;
11832  let Inst{21} = 0b1;
11833  let Inst{20-16} = Rs;
11834  let Inst{15} = 0b1;
11835  let Inst{14-12} = opc;
11836  let Inst{11-10} = 0b00;
11837  let Inst{9-5} = Rn;
11838  let Inst{4-0} = Rt;
11839  let Predicates = [HasLSE];
11840}
11841
11842multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11843  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11844  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11845  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11846  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11847}
11848
11849let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11850class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11851      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11852          "\t$Rs, $Rt, [$Rn]","",[]>,
11853        Sched<[WriteAtomic]> {
11854  bits<2> Sz;
11855  bit Acq;
11856  bit Rel;
11857  bits<5> Rs;
11858  bits<3> opc;
11859  bits<5> Rn;
11860  bits<5> Rt;
11861  let Inst{31-30} = Sz;
11862  let Inst{29-24} = 0b111000;
11863  let Inst{23} = Acq;
11864  let Inst{22} = Rel;
11865  let Inst{21} = 0b1;
11866  let Inst{20-16} = Rs;
11867  let Inst{15} = 0b0;
11868  let Inst{14-12} = opc;
11869  let Inst{11-10} = 0b00;
11870  let Inst{9-5} = Rn;
11871  let Inst{4-0} = Rt;
11872  let Predicates = [HasLSE];
11873}
11874
11875multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11876                        string order> {
11877  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11878    def B : BaseLDOPregister<op, order, "b", GPR32>;
11879  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11880    def H : BaseLDOPregister<op, order, "h", GPR32>;
11881  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11882    def W : BaseLDOPregister<op, order, "", GPR32>;
11883  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11884    def X : BaseLDOPregister<op, order, "", GPR64>;
11885}
11886
11887// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11888// complex DAG for DstRHS.
11889let Predicates = [HasLSE] in
11890multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11891                                         ValueType vt, dag SrcRHS, dag DstRHS> {
11892  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_monotonic") GPR64sp:$Rn, SrcRHS),
11893            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11894  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_acquire") GPR64sp:$Rn, SrcRHS),
11895            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11896  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_release") GPR64sp:$Rn, SrcRHS),
11897            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11898  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11899            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11900  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11901            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11902}
11903
11904multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11905                                     ValueType vt, dag RHS> {
11906  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, vt, RHS, RHS>;
11907}
11908
11909multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11910                                         ValueType vt, dag LHS, dag RHS> {
11911  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, vt, LHS, RHS>;
11912}
11913
11914multiclass LDOPregister_patterns<string inst, string op> {
11915  defm : LDOPregister_patterns_ord<inst, "X", op, i64, (i64 GPR64:$Rm)>;
11916  defm : LDOPregister_patterns_ord<inst, "W", op, i32, (i32 GPR32:$Rm)>;
11917  defm : LDOPregister_patterns_ord<inst, "H", op, i16, (i32 GPR32:$Rm)>;
11918  defm : LDOPregister_patterns_ord<inst, "B", op, i8,  (i32 GPR32:$Rm)>;
11919}
11920
11921multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11922  defm : LDOPregister_patterns_ord_mod<inst, "X", op, i64,
11923                        (i64 GPR64:$Rm),
11924                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11925  defm : LDOPregister_patterns_ord_mod<inst, "W", op, i32,
11926                        (i32 GPR32:$Rm),
11927                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11928  defm : LDOPregister_patterns_ord_mod<inst, "H", op, i16,
11929                        (i32 GPR32:$Rm),
11930                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11931  defm : LDOPregister_patterns_ord_mod<inst, "B", op, i8,
11932                        (i32 GPR32:$Rm),
11933                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11934}
11935
11936let Predicates = [HasLSE] in
11937multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11938                                        ValueType vt, dag OLD, dag NEW> {
11939  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11940            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11941  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_acquire") GPR64sp:$Rn, OLD, NEW),
11942            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11943  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_release") GPR64sp:$Rn, OLD, NEW),
11944            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11945  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11946            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11947  def : Pat<(!cast<PatFrag>(op#"_"#vt#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11948            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11949}
11950
11951multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11952                                    ValueType vt, dag OLD, dag NEW> {
11953  defm : CASregister_patterns_ord_dag<inst, suffix, op, vt, OLD, NEW>;
11954}
11955
11956multiclass CASregister_patterns<string inst, string op> {
11957  defm : CASregister_patterns_ord<inst, "X", op, i64,
11958                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11959  defm : CASregister_patterns_ord<inst, "W", op, i32,
11960                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11961  defm : CASregister_patterns_ord<inst, "H", op, i16,
11962                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11963  defm : CASregister_patterns_ord<inst, "B", op, i8,
11964                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11965}
11966
11967let Predicates = [HasLSE] in
11968class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11969                        Instruction inst> :
11970      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11971
11972multiclass STOPregister<string asm, string instr> {
11973  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11974                    !cast<Instruction>(instr # "LB")>;
11975  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11976                    !cast<Instruction>(instr # "LH")>;
11977  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11978                    !cast<Instruction>(instr # "LW")>;
11979  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11980                    !cast<Instruction>(instr # "LX")>;
11981  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11982                    !cast<Instruction>(instr # "B")>;
11983  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11984                    !cast<Instruction>(instr # "H")>;
11985  def : BaseSTOPregister<asm,        GPR32, WZR,
11986                    !cast<Instruction>(instr # "W")>;
11987  def : BaseSTOPregister<asm,        GPR64, XZR,
11988                    !cast<Instruction>(instr # "X")>;
11989}
11990
11991class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11992                        dag iops, dag oops, list<dag> pat>
11993    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11994      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11995  bits<5> Rt;
11996  bits<5> Rn;
11997  let Inst{31-21} = 0b11111000001;
11998  let Inst{15}    = 1;
11999  let Inst{14-12} = opc;
12000  let Inst{11-10} = 0b00;
12001  let Inst{9-5}   = Rn;
12002  let Inst{4-0}   = Rt;
12003
12004  let Predicates = [HasV8_7a];
12005}
12006
12007class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
12008                      list<dag> pat = []>
12009    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
12010  let Inst{20-16} = 0b11111;
12011}
12012
12013class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
12014    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
12015                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
12016  bits<5> Rs;
12017  let Inst{20-16} = Rs;
12018}
12019
12020class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
12021                             bits<2> op2, string asm>
12022  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
12023      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
12024      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
12025      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
12026    Sched<[]> {
12027  bits<5> Rd;
12028  bits<5> Rs;
12029  bits<5> Rn;
12030  let Inst{31-27} = 0b00011;
12031  let Inst{26} = isMove;
12032  let Inst{25-24} = 0b01;
12033  let Inst{23-22} = opcode;
12034  let Inst{21} = 0b0;
12035  let Inst{20-16} = Rs;
12036  let Inst{15-14} = op2;
12037  let Inst{13-12} = op1;
12038  let Inst{11-10} = 0b01;
12039  let Inst{9-5} = Rn;
12040  let Inst{4-0} = Rd;
12041
12042  let DecoderMethod = "DecodeCPYMemOpInstruction";
12043  let mayLoad = 1;
12044  let mayStore = 1;
12045}
12046
12047class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
12048  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
12049
12050class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
12051  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
12052
12053class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
12054                        string asm>
12055  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
12056      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
12057      asm, "\t[$Rd]!, $Rn!, $Rm",
12058      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
12059    Sched<[]> {
12060  bits<5> Rd;
12061  bits<5> Rn;
12062  bits<5> Rm;
12063  let Inst{31-27} = 0b00011;
12064  let Inst{26} = isTagging;
12065  let Inst{25-21} = 0b01110;
12066  let Inst{20-16} = Rm;
12067  let Inst{15-14} = opcode;
12068  let Inst{13} = op2;
12069  let Inst{12} = op1;
12070  let Inst{11-10} = 0b01;
12071  let Inst{9-5} = Rn;
12072  let Inst{4-0} = Rd;
12073
12074  let DecoderMethod = "DecodeSETMemOpInstruction";
12075  let mayLoad = 0;
12076  let mayStore = 1;
12077}
12078
12079class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
12080  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
12081
12082class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
12083  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
12084
12085multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
12086  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
12087  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
12088  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
12089  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
12090  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
12091  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
12092  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
12093  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
12094  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
12095  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
12096  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
12097  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
12098  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
12099  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
12100  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
12101  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
12102}
12103
12104multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
12105  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
12106  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
12107  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
12108  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
12109  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
12110  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
12111  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
12112  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
12113  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
12114  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
12115  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
12116  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
12117  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
12118  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
12119  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
12120  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
12121}
12122
12123multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
12124  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
12125  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
12126  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
12127  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
12128}
12129
12130multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
12131  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
12132  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
12133  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
12134  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
12135}
12136
12137//----------------------------------------------------------------------------
12138// 2022 Armv8.9/Armv9.4 Extensions
12139//----------------------------------------------------------------------------
12140
12141//---
12142// 2022 Architecture Extensions: General Data Processing (FEAT_CSSC)
12143//---
12144
12145class BaseTwoOperandRegImm<bit sf, bit Op, bit S, bits<4> opc,
12146                           RegisterClass regtype, ImmLeaf immtype, string asm,
12147                           SDPatternOperator OpNode>
12148    : I<(outs regtype:$Rd), (ins regtype:$Rn, immtype:$imm),
12149        asm, "\t$Rd, $Rn, $imm", "",
12150        [(set regtype:$Rd, (OpNode regtype:$Rn, immtype:$imm))]> {
12151  bits<5> Rd;
12152  bits<5> Rn;
12153  bits<8> imm;
12154
12155  let Inst{31}    = sf;
12156  let Inst{30}    = Op;
12157  let Inst{29}    = S;
12158  let Inst{28-22} = 0b1000111;
12159  let Inst{21-18} = opc;
12160  let Inst{17-10} = imm;
12161  let Inst{9-5}   = Rn;
12162  let Inst{4-0}   = Rd;
12163}
12164
12165class BaseComparisonOpReg<bit size, bit isUnsigned, bit isMin,
12166                          RegisterClass regtype, string asm,
12167                          SDPatternOperator OpNode>
12168    : BaseTwoOperandRegReg<size, 0b0, {0,1,1,0,?,?}, regtype, asm, OpNode>,
12169      Sched<[WriteI]> {
12170  let Inst{11} = isMin;
12171  let Inst{10} = isUnsigned;
12172  let mayLoad  = 0;
12173  let mayStore = 0;
12174  let hasSideEffects = 0;
12175}
12176
12177class BaseComparisonOpImm<bit size, bit isUnsigned, bit isMin,
12178                          RegisterClass regtype, ImmLeaf immtype, string asm,
12179                          SDPatternOperator OpNode>
12180    : BaseTwoOperandRegImm<size, 0b0, 0b0, {0,0,?,?}, regtype, immtype, asm,
12181                           OpNode>,
12182      Sched<[]> {
12183  let Inst{19} = isMin;
12184  let Inst{18} = isUnsigned;
12185  let mayLoad  = 0;
12186  let mayStore = 0;
12187  let hasSideEffects = 0;
12188}
12189
12190multiclass ComparisonOp<bit isUnsigned, bit isMin, string asm,
12191                        SDPatternOperator OpNode = null_frag> {
12192  def Wrr : BaseComparisonOpReg<0b0, isUnsigned, isMin, GPR32, asm, OpNode>;
12193
12194  def Wri : BaseComparisonOpImm<0b0, isUnsigned, isMin, GPR32,
12195                                !cond(isUnsigned : uimm8_32b,
12196                                      !not(isUnsigned) : simm8_32b), asm, OpNode>;
12197
12198  def Xrr : BaseComparisonOpReg<0b1, isUnsigned, isMin, GPR64, asm, OpNode>;
12199
12200  def Xri : BaseComparisonOpImm<0b1, isUnsigned, isMin, GPR64,
12201                                !cond(isUnsigned : uimm8_64b,
12202                                      !not(isUnsigned) : simm8_64b), asm, OpNode>;
12203}
12204
12205//---
12206// RCPC instructions (FEAT_LRCPC3)
12207//---
12208
12209class BaseLRCPC3<bits<2> size, bit V, bits<2> opc, dag oops, dag iops,
12210                 string asm, string operands, string cstr = "">
12211      : I<oops, iops, asm, operands, cstr, []>,
12212        Sched<[WriteAtomic]> {
12213  bits<5> Rt;
12214  bits<5> Rn;
12215  let Inst{31-30}    = size;
12216  let Inst{29-24}    = {0,1,1,V,0,1};
12217  let Inst{23-22}    = opc;
12218  let Inst{21}       = 0b0;
12219  //  Inst{20-12}
12220  let Inst{11-10}    = 0b10;
12221  let Inst{9-5}      = Rn;
12222  let Inst{4-0}      = Rt;
12223
12224  let mayLoad = Inst{22};
12225  let mayStore = !not(Inst{22});
12226  let hasSideEffects = 0;
12227}
12228
12229class BaseLRCPC3IntegerLoadStorePair<bits<2> size, bits<2> opc, bits<4> opc2,
12230                                     dag oops, dag iops, string asm,
12231                                     string operands, string cstr>
12232      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
12233  bits<5> Rt2;
12234  let Inst{20-16} = Rt2;
12235  let Inst{15-12} = opc2;
12236}
12237
12238class BaseLRCPC3IntegerLoadStore<bits<2> size, bits<2> opc, dag oops, dag iops,
12239                                 string asm, string operands, string cstr>
12240      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
12241  let Inst{20-12} = 0b000000000; // imm9
12242}
12243
12244multiclass LRCPC3NEONLoadStoreUnscaledOffset<bits<2> size, bits<2> opc, RegisterClass regtype,
12245                                             dag oops, dag iops, string asm> {
12246  def i : BaseLRCPC3<size, /*V*/1, opc, oops, iops, asm, "\t$Rt, [$Rn{, $simm}]", /*cstr*/""> {
12247    bits<9> simm; // signed immediate encoded in imm9=Rt2:imm4
12248    let Inst{20-12} = simm;
12249  }
12250
12251  def a : InstAlias<asm # "\t$Rt, [$Rn]",
12252                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
12253}
12254
12255class LRCPC3NEONLdStSingle<bit L, dag oops, dag iops, string asm, string cst>
12256      : BaseSIMDLdStSingle<L, /*R*/0b0, /*opcode*/0b100, asm,
12257                           "\t$Vt$Q, [$Rn]", cst, oops, iops, []>,
12258        Sched<[]> {
12259  bit Q;
12260  let Inst{31}       = 0;
12261  let Inst{30}       = Q;
12262  let Inst{23}       = 0;
12263  let Inst{20-16}    = 0b00001;
12264  let Inst{12}       = 0; // S
12265  let Inst{11-10}    = 0b01; // size
12266
12267  let mayLoad = L;
12268  let mayStore = !not(L);
12269  let hasSideEffects = 1;
12270}
12271
12272//---
12273// Instrumentation Extension (FEAT_ITE)
12274//---
12275
12276let Predicates = [HasITE] in
12277def TRCIT : RtSystemI<0b0, (outs), (ins GPR64:$Rt), "trcit", "\t$Rt"> {
12278  let Inst{20-19} = 0b01;
12279  let Inst{18-16} = 0b011;
12280  let Inst{15-12} = 0b0111;
12281  let Inst{11-8}  = 0b0010;
12282  let Inst{7-5}   = 0b111;
12283}
12284
12285// * RCWCAS family
12286// * RCW<OP> family
12287
12288//--------------------------------------------------------------------
12289// Read-Check-Write Compare And Swap family (RCWCAS[S|P|PS]?[A|L|AL]?)
12290
12291// Instruction encoding:
12292//
12293//          31 30|29  24|23|22|21|20 16|15|14 13|12 11 10|9 5|4 0
12294// RCWCAS    0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
12295// RCWSCAS   0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
12296// RCWCASP   0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
12297// RCWSCASP  0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
12298
12299// Instruction syntax:
12300//
12301// RCW[S]CAS{<order>}   <Xs>,           <Xt>,          [<Xn|SP>]
12302// RCW[S]CASP{<order>}  <Xs>, <X(s+1)>, <Xt>, <X(t+1)> [<Xn|SP>]
12303
12304class BaseRCWCASEncoding<dag oops, dag iops, string asm>
12305      : I<oops, iops, asm, "\t$Rs, $Rt, [$Rn]", "$out = $Rs", []>,
12306        Sched<[]> {
12307  bit Acq;
12308  bit Rel;
12309  bit SC;
12310  bit Pair;
12311  bits<5> Rs;
12312  bits<5> Rn;
12313  bits<5> Rt;
12314  let Inst{31} = 0b0;
12315  let Inst{30} = SC;
12316  let Inst{29-24} = 0b011001;
12317  let Inst{23} = Acq;
12318  let Inst{22} = Rel;
12319  let Inst{21} = 0b1;
12320  let Inst{20-16} = Rs;
12321  let Inst{15-13} = 0b000;
12322  let Inst{12-11} = 0b01;
12323  let Inst{10} = Pair;
12324  let Inst{9-5} = Rn;
12325  let Inst{4-0} = Rt;
12326  let mayLoad = 1;
12327  let mayStore = 1;
12328  let hasSideEffects = 1;
12329  let Defs = [NZCV];
12330}
12331
12332multiclass BaseRCWCAS<dag oops, dag iops, string prefix> {
12333  let Acq = 0b0, Rel = 0b0 in
12334    def "" : BaseRCWCASEncoding<oops, iops, prefix # "">;
12335  let Acq = 0b1, Rel = 0b0 in
12336    def A  : BaseRCWCASEncoding<oops, iops, prefix # "a">;
12337  let Acq = 0b0, Rel = 0b1 in
12338    def L  : BaseRCWCASEncoding<oops, iops, prefix # "l">;
12339  let Acq = 0b1, Rel = 0b1 in
12340    def AL : BaseRCWCASEncoding<oops, iops, prefix # "al">;
12341}
12342
12343multiclass ReadCheckWriteCompareAndSwap {
12344  let SC = 0b0, Pair = 0b0, Predicates = [HasTHE] in
12345    defm CAS  : BaseRCWCAS<(outs GPR64:$out),
12346                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwcas" >;
12347  let SC = 0b1, Pair = 0b0, Predicates = [HasTHE] in
12348    defm SCAS : BaseRCWCAS<(outs GPR64:$out),
12349                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwscas">;
12350  let SC = 0b0, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12351    defm CASP : BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12352                           (ins XSeqPairClassOperand:$Rs,
12353                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12354                           "rcwcasp">;
12355  let SC = 0b1, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12356    defm SCASP: BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12357                           (ins XSeqPairClassOperand:$Rs,
12358                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12359                           "rcwscasp">;
12360}
12361
12362//------------------------------------------------------------------
12363// Read-Check-Write <OP> family (RCW[CLR|SET|SWP][S|P|PS]?[A|L|AL]?)
12364
12365// Instruction encoding:
12366//
12367//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12368// RCWCLR    0  0|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12369// RCWSCLR   0  1|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12370// RCWSET    0  0|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12371// RCWSSET   0  1|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12372// RCWSWP    0  0|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12373// RCWSSWP   0  1|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12374
12375//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12376// RCWCLRP   0  0|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12377// RCWSCLRP  0  1|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12378// RCWSETP   0  0|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12379// RCWSSETP  0  1|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12380// RCWSWPP   0  0|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12381// RCWSSWPP  0  1|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12382
12383// Instruction syntax:
12384//
12385// RCW[S]<OP>{<order>}   <Xs>,  <Xt>, [<Xn|SP>]
12386// RCW[S]<OP>P{<order>}  <Xt1>, <Xt2>, [<Xn|SP>]
12387
12388class BaseRCWOPEncoding<string asm>
12389      : I<(outs GPR64:$Rt),(ins GPR64:$Rs, GPR64sp:$Rn), asm,
12390          "\t$Rs, $Rt, [$Rn]", "", []>,
12391        Sched<[]> {
12392  bit Acq;
12393  bit Rel;
12394  bit SC;
12395  bits<3> opc;
12396  bits<5> Rs;
12397  bits<5> Rn;
12398  bits<5> Rt;
12399  let Inst{31} = 0b0;
12400  let Inst{30} = SC;
12401  let Inst{29-24} = 0b111000;
12402  let Inst{23} = Acq;
12403  let Inst{22} = Rel;
12404  let Inst{21} = 0b1;
12405  let Inst{20-16} = Rs;
12406  let Inst{15} = 0b1;
12407  let Inst{14-12} = opc;
12408  let Inst{11-10} = 0b00;
12409  let Inst{9-5} = Rn;
12410  let Inst{4-0} = Rt;
12411  let mayLoad = 1;
12412  let mayStore = 1;
12413  let hasSideEffects = 1;
12414  let Defs = [NZCV];
12415  let Predicates = [HasTHE];
12416}
12417
12418class BaseRCWOPPEncoding<string asm>
12419      : I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12420          (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn), asm,
12421          "\t$Rt, $Rt2, [$Rn]", "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12422        Sched<[]> {
12423  bit Acq;
12424  bit Rel;
12425  bit SC;
12426  bits<3> opc;
12427  bits<5> Rt2;
12428  bits<5> Rn;
12429  bits<5> Rt;
12430  let Inst{31} = 0b0;
12431  let Inst{30} = SC;
12432  let Inst{29-24} = 0b011001;
12433  let Inst{23} = Acq;
12434  let Inst{22} = Rel;
12435  let Inst{21} = 0b1;
12436  let Inst{20-16} = Rt2;
12437  let Inst{15} = 0b1;
12438  let Inst{14-12} = opc;
12439  let Inst{11-10} = 0b00;
12440  let Inst{9-5} = Rn;
12441  let Inst{4-0} = Rt;
12442  let mayLoad = 1;
12443  let mayStore = 1;
12444  let hasSideEffects = 1;
12445  let Defs = [NZCV];
12446  let Predicates = [HasTHE, HasD128];
12447}
12448
12449multiclass BaseRCWOP<string prefix> {
12450  let Acq = 0b0, Rel = 0b0 in def "" : BaseRCWOPEncoding<prefix # "">;
12451  let Acq = 0b1, Rel = 0b0 in def A  : BaseRCWOPEncoding<prefix # "a">;
12452  let Acq = 0b0, Rel = 0b1 in def L  : BaseRCWOPEncoding<prefix # "l">;
12453  let Acq = 0b1, Rel = 0b1 in def AL : BaseRCWOPEncoding<prefix # "al">;
12454
12455  let Acq = 0b0, Rel = 0b0 in def P   : BaseRCWOPPEncoding<prefix # "p">;
12456  let Acq = 0b1, Rel = 0b0 in def PA  : BaseRCWOPPEncoding<prefix # "pa">;
12457  let Acq = 0b0, Rel = 0b1 in def PL  : BaseRCWOPPEncoding<prefix # "pl">;
12458  let Acq = 0b1, Rel = 0b1 in def PAL : BaseRCWOPPEncoding<prefix # "pal">;
12459}
12460
12461multiclass ReadCheckWriteOperation<bits<3> opc, string op> {
12462  let SC = 0b0, opc = opc in defm ""  : BaseRCWOP<"rcw" # ""  # op>;
12463  let SC = 0b1, opc = opc in defm S   : BaseRCWOP<"rcw" # "s" # op >;
12464}
12465
12466//---
12467// 128-bit atomic instructions (FEAT_LSE128)
12468//---
12469
12470let mayLoad = 1, mayStore = 1, hasSideEffects = 0 in
12471class LSE128Base<bits<3> op0, bits<2> AR, bit o3, string asm>
12472: I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12473    (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn),
12474    asm, "\t$Rt, $Rt2, [$Rn]",
12475    "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12476  Sched<[]> {
12477  bits<5> Rt;
12478  bits<5> Rt2;
12479  bits<5> Rn;
12480  let Inst{31-24} = 0b00011001;
12481  let Inst{23-22} = AR;
12482  let Inst{21} = 0b1;
12483  let Inst{20-16} = Rt2;
12484  let Inst{15} = o3;
12485  let Inst{14-12} = op0;
12486  let Inst{11-10} = 0b00;
12487  let Inst{9-5} = Rn;
12488  let Inst{4-0} = Rt;
12489}
12490
12491//---
12492// 128-bit System Instructions (FEAT_SYSINSTR128)
12493//---
12494
12495// Instruction encoding:
12496//
12497//          31          19|18 16|15 12|11 8|7 5|4 0
12498// SYSP      1101010101001|  op1|   Cn|  Cm|op2| Rt
12499
12500// Instruction syntax:
12501//
12502// SYSP #<op1>, <Cn>, <Cm>, #<op2>{, <Xt>, <Xt+1>}
12503
12504class RtSystemI128<bit L, dag oops, dag iops, string asm, string operands, list<dag> pattern = []> :
12505  RtSystemI<L, oops, iops, asm, operands, pattern> {
12506  let Inst{22}    = 0b1; // override BaseSystemI
12507}
12508
12509class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inputs>
12510  : RtSystemI128<L, outputs, inputs, asm, operands> {
12511  bits<3> op1;
12512  bits<4> Cn;
12513  bits<4> Cm;
12514  bits<3> op2;
12515  let Inst{20-19} = 0b01;
12516  let Inst{18-16} = op1;
12517  let Inst{15-12} = Cn;
12518  let Inst{11-8}  = Cm;
12519  let Inst{7-5}   = op2;
12520}
12521class SystemPXtI<bit L, string asm> :
12522  BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
12523  (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XSeqPairClassOperand:$Rt)>;
12524
12525//----------------------------------------------------------------------------
12526// 2023 Armv9.5 Extensions
12527//----------------------------------------------------------------------------
12528
12529//---
12530// Checked Pointer Arithmetic (FEAT_CPA)
12531//---
12532
12533def LSLImm3ShiftOperand : AsmOperandClass {
12534  let SuperClasses = [ExtendOperandLSL64];
12535  let Name = "LSLImm3Shift";
12536  let RenderMethod = "addLSLImm3ShifterOperands";
12537  let DiagnosticType = "AddSubLSLImm3ShiftLarge";
12538}
12539
12540def lsl_imm3_shift_operand : Operand<i32> {
12541  let PrintMethod = "printShifter";
12542  let ParserMatchClass = LSLImm3ShiftOperand;
12543}
12544
12545// Base CPA scalar add/subtract with lsl #imm3 shift
12546class BaseAddSubCPA<bit isSub, string asm> : I<(outs GPR64sp:$Rd),
12547    (ins GPR64sp:$Rn, GPR64:$Rm, lsl_imm3_shift_operand:$shift_imm),
12548    asm, "\t$Rd, $Rn, $Rm$shift_imm", "", []>, Sched<[]> {
12549  bits<5> Rd;
12550  bits<5> Rn;
12551  bits<5> Rm;
12552  bits<3> shift_imm;
12553  let Inst{31} = 0b1;
12554  let Inst{30} = isSub;
12555  let Inst{29-21} = 0b011010000;
12556  let Inst{20-16} = Rm;
12557  let Inst{15-13} = 0b001;
12558  let Inst{12-10} = shift_imm;
12559  let Inst{9-5} = Rn;
12560  let Inst{4-0} = Rd;
12561}
12562
12563// Alias for CPA scalar add/subtract with no shift
12564class AddSubCPAAlias<string asm, Instruction inst>
12565    : InstAlias<asm#"\t$Rd, $Rn, $Rm",
12566                (inst GPR64sp:$Rd, GPR64sp:$Rn, GPR64:$Rm, 0)>;
12567
12568multiclass AddSubCPA<bit isSub, string asm> {
12569  def _shift : BaseAddSubCPA<isSub, asm>;
12570  def _noshift : AddSubCPAAlias<asm, !cast<Instruction>(NAME#"_shift")>;
12571}
12572
12573class MulAccumCPA<bit isSub, string asm>
12574  : BaseMulAccum<isSub, 0b011, GPR64, GPR64, asm, []>, Sched<[]> {
12575  let Inst{31} = 0b1;
12576}
12577
12578//----------------------------------------------------------------------------
12579// Allow the size specifier tokens to be upper case, not just lower.
12580def : TokenAlias<".4B", ".4b">;  // Add dot product
12581def : TokenAlias<".8B", ".8b">;
12582def : TokenAlias<".4H", ".4h">;
12583def : TokenAlias<".2S", ".2s">;
12584def : TokenAlias<".1D", ".1d">;
12585def : TokenAlias<".16B", ".16b">;
12586def : TokenAlias<".8H", ".8h">;
12587def : TokenAlias<".4S", ".4s">;
12588def : TokenAlias<".2D", ".2d">;
12589def : TokenAlias<".1Q", ".1q">;
12590def : TokenAlias<".2H", ".2h">;
12591def : TokenAlias<".2B", ".2b">;
12592def : TokenAlias<".B", ".b">;
12593def : TokenAlias<".H", ".h">;
12594def : TokenAlias<".S", ".s">;
12595def : TokenAlias<".D", ".d">;
12596def : TokenAlias<".Q", ".q">;
12597