xref: /freebsd/contrib/llvm-project/llvm/lib/Target/AArch64/AArch64InstrFormats.td (revision 1db9f3b21e39176dd5b67cf8ac378633b172463e)
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}
2813
2814class BaseAddSubRegPseudo<RegisterClass regtype,
2815                          SDPatternOperator OpNode>
2816    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
2817             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
2818      Sched<[WriteI, ReadI, ReadI]>;
2819
2820class BaseAddSubSReg<bit isSub, bit setFlags, RegisterClass regtype,
2821                     arith_shifted_reg shifted_regtype, string asm,
2822                     SDPatternOperator OpNode>
2823    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
2824        asm, "\t$Rd, $Rn, $Rm_and_shift", "",
2825        [(set regtype:$Rd, (OpNode regtype:$Rn, shifted_regtype:$Rm_and_shift))]>,
2826      Sched<[WriteISReg, ReadI, ReadISReg]> {
2827  bits<5> Rd;
2828  bits<5> Rn;
2829  bits<5> Rm;
2830  bits<8> shift;
2831  let Inst{30}    = isSub;
2832  let Inst{29}    = setFlags;
2833  let Inst{28-24} = 0b01011;
2834  let Inst{23-22} = shift{7-6};
2835  let Inst{21}    = 0;
2836  let Inst{20-16} = Rm;
2837  let Inst{15-10} = shift{5-0};
2838  let Inst{9-5}   = Rn;
2839  let Inst{4-0}   = Rd;
2840
2841  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
2842}
2843
2844class BaseAddSubEReg<bit isSub, bit setFlags, RegisterClass dstRegtype,
2845                     RegisterClass src1Regtype, Operand src2Regtype,
2846                     string asm, SDPatternOperator OpNode>
2847    : I<(outs dstRegtype:$Rd),
2848        (ins src1Regtype:$Rn, (src2Regtype $Rm, $extend):$Rm_and_extend),
2849        asm, "\t$Rd, $Rn, $Rm_and_extend", "",
2850        [(set dstRegtype:$Rd, (OpNode src1Regtype:$Rn, src2Regtype:$Rm_and_extend))]>,
2851      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2852  bits<5> Rd;
2853  bits<5> Rn;
2854  bits<5> Rm;
2855  bits<6> extend;
2856  let Inst{30}    = isSub;
2857  let Inst{29}    = setFlags;
2858  let Inst{28-24} = 0b01011;
2859  let Inst{23-21} = 0b001;
2860  let Inst{20-16} = Rm;
2861  let Inst{15-13} = extend{5-3};
2862  let Inst{12-10} = extend{2-0};
2863  let Inst{9-5}   = Rn;
2864  let Inst{4-0}   = Rd;
2865
2866  let DecoderMethod = "DecodeAddSubERegInstruction";
2867}
2868
2869let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
2870class BaseAddSubEReg64<bit isSub, bit setFlags, RegisterClass dstRegtype,
2871                       RegisterClass src1Regtype, RegisterClass src2Regtype,
2872                       Operand ext_op, string asm>
2873    : I<(outs dstRegtype:$Rd),
2874        (ins src1Regtype:$Rn, src2Regtype:$Rm, ext_op:$ext),
2875        asm, "\t$Rd, $Rn, $Rm$ext", "", []>,
2876      Sched<[WriteIEReg, ReadI, ReadIEReg]> {
2877  bits<5> Rd;
2878  bits<5> Rn;
2879  bits<5> Rm;
2880  bits<6> ext;
2881  let Inst{30}    = isSub;
2882  let Inst{29}    = setFlags;
2883  let Inst{28-24} = 0b01011;
2884  let Inst{23-21} = 0b001;
2885  let Inst{20-16} = Rm;
2886  let Inst{15}    = ext{5};
2887  let Inst{12-10} = ext{2-0};
2888  let Inst{9-5}   = Rn;
2889  let Inst{4-0}   = Rd;
2890
2891  let DecoderMethod = "DecodeAddSubERegInstruction";
2892}
2893
2894// Aliases for register+register add/subtract.
2895class AddSubRegAlias<string asm, Instruction inst, RegisterClass dstRegtype,
2896                     RegisterClass src1Regtype, RegisterClass src2Regtype,
2897                     int shiftExt>
2898    : InstAlias<asm#"\t$dst, $src1, $src2",
2899                (inst dstRegtype:$dst, src1Regtype:$src1, src2Regtype:$src2,
2900                      shiftExt)>;
2901
2902multiclass AddSub<bit isSub, string mnemonic, string alias,
2903                  SDPatternOperator OpNode = null_frag> {
2904  let hasSideEffects = 0, isReMaterializable = 1, isAsCheapAsAMove = 1 in {
2905  // Add/Subtract immediate
2906  // Increase the weight of the immediate variant to try to match it before
2907  // the extended register variant.
2908  // We used to match the register variant before the immediate when the
2909  // register argument could be implicitly zero-extended.
2910  let AddedComplexity = 6 in
2911  def Wri  : AddSubImmShift<isSub, 0, GPR32sp, GPR32sp, addsub_shifted_imm32,
2912                           mnemonic, OpNode> {
2913    let Inst{31} = 0;
2914  }
2915  let AddedComplexity = 6 in
2916  def Xri  : AddSubImmShift<isSub, 0, GPR64sp, GPR64sp, addsub_shifted_imm64,
2917                           mnemonic, OpNode> {
2918    let Inst{31} = 1;
2919  }
2920
2921  // Add/Subtract register - Only used for CodeGen
2922  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2923  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2924
2925  // Add/Subtract shifted register
2926  def Wrs : BaseAddSubSReg<isSub, 0, GPR32, arith_shifted_reg32, mnemonic,
2927                           OpNode> {
2928    let Inst{31} = 0;
2929  }
2930  def Xrs : BaseAddSubSReg<isSub, 0, GPR64, arith_shifted_reg64, mnemonic,
2931                           OpNode> {
2932    let Inst{31} = 1;
2933  }
2934  }
2935
2936  // Add/Subtract extended register
2937  let AddedComplexity = 1, hasSideEffects = 0 in {
2938  def Wrx : BaseAddSubEReg<isSub, 0, GPR32sp, GPR32sp,
2939                           arith_extended_reg32_i32, mnemonic, OpNode> {
2940    let Inst{31} = 0;
2941  }
2942  def Xrx : BaseAddSubEReg<isSub, 0, GPR64sp, GPR64sp,
2943                           arith_extended_reg32to64_i64, mnemonic, OpNode> {
2944    let Inst{31} = 1;
2945  }
2946  }
2947
2948  def Xrx64 : BaseAddSubEReg64<isSub, 0, GPR64sp, GPR64sp, GPR64,
2949                               arith_extendlsl64, mnemonic> {
2950    // UXTX and SXTX only.
2951    let Inst{14-13} = 0b11;
2952    let Inst{31} = 1;
2953  }
2954
2955  // add Rd, Rb, -imm -> sub Rd, Rn, imm
2956  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2957                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32sp:$Rn,
2958                      addsub_shifted_imm32_neg:$imm), 0>;
2959  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
2960                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64sp:$Rn,
2961                       addsub_shifted_imm64_neg:$imm), 0>;
2962
2963  // Register/register aliases with no shift when SP is not used.
2964  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
2965                       GPR32, GPR32, GPR32, 0>;
2966  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
2967                       GPR64, GPR64, GPR64, 0>;
2968
2969  // Register/register aliases with no shift when either the destination or
2970  // first source register is SP.
2971  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2972                       GPR32sponly, GPR32sp, GPR32, 16>; // UXTW #0
2973  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
2974                       GPR32sp, GPR32sponly, GPR32, 16>; // UXTW #0
2975  def : AddSubRegAlias<mnemonic,
2976                       !cast<Instruction>(NAME#"Xrx64"),
2977                       GPR64sponly, GPR64sp, GPR64, 24>; // UXTX #0
2978  def : AddSubRegAlias<mnemonic,
2979                       !cast<Instruction>(NAME#"Xrx64"),
2980                       GPR64sp, GPR64sponly, GPR64, 24>; // UXTX #0
2981}
2982
2983multiclass AddSubS<bit isSub, string mnemonic, SDNode OpNode, string cmp,
2984                   string alias, string cmpAlias> {
2985  let isCompare = 1, Defs = [NZCV] in {
2986  // Add/Subtract immediate
2987  def Wri  : AddSubImmShift<isSub, 1, GPR32, GPR32sp, addsub_shifted_imm32,
2988                           mnemonic, OpNode> {
2989    let Inst{31} = 0;
2990  }
2991  def Xri  : AddSubImmShift<isSub, 1, GPR64, GPR64sp, addsub_shifted_imm64,
2992                           mnemonic, OpNode> {
2993    let Inst{31} = 1;
2994  }
2995
2996  // Add/Subtract register
2997  def Wrr : BaseAddSubRegPseudo<GPR32, OpNode>;
2998  def Xrr : BaseAddSubRegPseudo<GPR64, OpNode>;
2999
3000  // Add/Subtract shifted register
3001  def Wrs : BaseAddSubSReg<isSub, 1, GPR32, arith_shifted_reg32, mnemonic,
3002                           OpNode> {
3003    let Inst{31} = 0;
3004  }
3005  def Xrs : BaseAddSubSReg<isSub, 1, GPR64, arith_shifted_reg64, mnemonic,
3006                           OpNode> {
3007    let Inst{31} = 1;
3008  }
3009
3010  // Add/Subtract extended register
3011  let AddedComplexity = 1 in {
3012  def Wrx : BaseAddSubEReg<isSub, 1, GPR32, GPR32sp,
3013                           arith_extended_reg32_i32, mnemonic, OpNode> {
3014    let Inst{31} = 0;
3015  }
3016  def Xrx : BaseAddSubEReg<isSub, 1, GPR64, GPR64sp,
3017                           arith_extended_reg32_i64, mnemonic, OpNode> {
3018    let Inst{31} = 1;
3019  }
3020  }
3021
3022  def Xrx64 : BaseAddSubEReg64<isSub, 1, GPR64, GPR64sp, GPR64,
3023                               arith_extendlsl64, mnemonic> {
3024    // UXTX and SXTX only.
3025    let Inst{14-13} = 0b11;
3026    let Inst{31} = 1;
3027  }
3028  } // Defs = [NZCV]
3029
3030  // Support negative immediates, e.g. adds Rd, Rn, -imm -> subs Rd, Rn, imm
3031  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
3032                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32sp:$Rn,
3033                      addsub_shifted_imm32_neg:$imm), 0>;
3034  def : InstSubst<alias#"\t$Rd, $Rn, $imm",
3035                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64sp:$Rn,
3036                       addsub_shifted_imm64_neg:$imm), 0>;
3037
3038  // Compare aliases
3039  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
3040                  WZR, GPR32sp:$src, addsub_shifted_imm32:$imm), 5>;
3041  def : InstAlias<cmp#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
3042                  XZR, GPR64sp:$src, addsub_shifted_imm64:$imm), 5>;
3043  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrx")
3044                  WZR, GPR32sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
3045  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx")
3046                  XZR, GPR64sp:$src1, GPR32:$src2, arith_extend:$sh), 4>;
3047  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrx64")
3048                  XZR, GPR64sp:$src1, GPR64:$src2, arith_extendlsl64:$sh), 4>;
3049  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Wrs")
3050                  WZR, GPR32:$src1, GPR32:$src2, arith_shift32:$sh), 4>;
3051  def : InstAlias<cmp#"\t$src1, $src2$sh", (!cast<Instruction>(NAME#"Xrs")
3052                  XZR, GPR64:$src1, GPR64:$src2, arith_shift64:$sh), 4>;
3053
3054  // Support negative immediates, e.g. cmp Rn, -imm -> cmn Rn, imm
3055  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Wri")
3056                  WZR, GPR32sp:$src, addsub_shifted_imm32_neg:$imm), 0>;
3057  def : InstSubst<cmpAlias#"\t$src, $imm", (!cast<Instruction>(NAME#"Xri")
3058                  XZR, GPR64sp:$src, addsub_shifted_imm64_neg:$imm), 0>;
3059
3060  // Compare shorthands
3061  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrs")
3062                  WZR, GPR32:$src1, GPR32:$src2, 0), 5>;
3063  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrs")
3064                  XZR, GPR64:$src1, GPR64:$src2, 0), 5>;
3065  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Wrx")
3066                  WZR, GPR32sponly:$src1, GPR32:$src2, 16), 5>;
3067  def : InstAlias<cmp#"\t$src1, $src2", (!cast<Instruction>(NAME#"Xrx64")
3068                  XZR, GPR64sponly:$src1, GPR64:$src2, 24), 5>;
3069
3070  // Register/register aliases with no shift when SP is not used.
3071  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrs"),
3072                       GPR32, GPR32, GPR32, 0>;
3073  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Xrs"),
3074                       GPR64, GPR64, GPR64, 0>;
3075
3076  // Register/register aliases with no shift when the first source register
3077  // is SP.
3078  def : AddSubRegAlias<mnemonic, !cast<Instruction>(NAME#"Wrx"),
3079                       GPR32, GPR32sponly, GPR32, 16>; // UXTW #0
3080  def : AddSubRegAlias<mnemonic,
3081                       !cast<Instruction>(NAME#"Xrx64"),
3082                       GPR64, GPR64sponly, GPR64, 24>; // UXTX #0
3083}
3084
3085class AddSubG<bit isSub, string asm_inst, SDPatternOperator OpNode>
3086      : BaseAddSubImm<
3087          isSub, 0, GPR64sp, asm_inst, "\t$Rd, $Rn, $imm6, $imm4",
3088          (ins GPR64sp:$Rn, uimm6s16:$imm6, imm0_15:$imm4),
3089          (set GPR64sp:$Rd, (OpNode GPR64sp:$Rn, imm0_63:$imm6, imm0_15:$imm4))> {
3090  bits<6> imm6;
3091  bits<4> imm4;
3092  let Inst{31} = 1;
3093  let Inst{23-22} = 0b10;
3094  let Inst{21-16} = imm6;
3095  let Inst{15-14} = 0b00;
3096  let Inst{13-10} = imm4;
3097  let Unpredictable{15-14} = 0b11;
3098}
3099
3100class SUBP<bit setsFlags, string asm_instr, SDPatternOperator OpNode>
3101      : BaseTwoOperandRegReg<0b1, setsFlags, 0b000000, GPR64, asm_instr, OpNode,
3102                             GPR64sp, GPR64sp>;
3103
3104//---
3105// Extract
3106//---
3107def SDTA64EXTR : SDTypeProfile<1, 3, [SDTCisSameAs<0, 1>, SDTCisSameAs<0, 2>,
3108                                      SDTCisPtrTy<3>]>;
3109def AArch64Extr : SDNode<"AArch64ISD::EXTR", SDTA64EXTR>;
3110
3111class BaseExtractImm<RegisterClass regtype, Operand imm_type, string asm,
3112                     list<dag> patterns>
3113    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, imm_type:$imm),
3114         asm, "\t$Rd, $Rn, $Rm, $imm", "", patterns>,
3115      Sched<[WriteExtr, ReadExtrHi]> {
3116  bits<5> Rd;
3117  bits<5> Rn;
3118  bits<5> Rm;
3119  bits<6> imm;
3120
3121  let Inst{30-23} = 0b00100111;
3122  let Inst{21}    = 0;
3123  let Inst{20-16} = Rm;
3124  let Inst{15-10} = imm;
3125  let Inst{9-5}   = Rn;
3126  let Inst{4-0}   = Rd;
3127}
3128
3129multiclass ExtractImm<string asm> {
3130  def Wrri : BaseExtractImm<GPR32, imm0_31, asm,
3131                      [(set GPR32:$Rd,
3132                        (fshr GPR32:$Rn, GPR32:$Rm, imm0_31:$imm))]> {
3133    let Inst{31} = 0;
3134    let Inst{22} = 0;
3135    // imm<5> must be zero.
3136    let imm{5}   = 0;
3137  }
3138  def Xrri : BaseExtractImm<GPR64, imm0_63, asm,
3139                      [(set GPR64:$Rd,
3140                        (fshr GPR64:$Rn, GPR64:$Rm, imm0_63:$imm))]> {
3141
3142    let Inst{31} = 1;
3143    let Inst{22} = 1;
3144  }
3145}
3146
3147//---
3148// Bitfield
3149//---
3150
3151let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3152class BaseBitfieldImm<bits<2> opc,
3153                      RegisterClass regtype, Operand imm_type, string asm>
3154    : I<(outs regtype:$Rd), (ins regtype:$Rn, imm_type:$immr, imm_type:$imms),
3155         asm, "\t$Rd, $Rn, $immr, $imms", "", []>,
3156      Sched<[WriteIS, ReadI]> {
3157  bits<5> Rd;
3158  bits<5> Rn;
3159  bits<6> immr;
3160  bits<6> imms;
3161
3162  let Inst{30-29} = opc;
3163  let Inst{28-23} = 0b100110;
3164  let Inst{21-16} = immr;
3165  let Inst{15-10} = imms;
3166  let Inst{9-5}   = Rn;
3167  let Inst{4-0}   = Rd;
3168}
3169
3170multiclass BitfieldImm<bits<2> opc, string asm> {
3171  def Wri : BaseBitfieldImm<opc, GPR32, imm0_31, asm> {
3172    let Inst{31} = 0;
3173    let Inst{22} = 0;
3174    // imms<5> and immr<5> must be zero, else ReservedValue().
3175    let Inst{21} = 0;
3176    let Inst{15} = 0;
3177  }
3178  def Xri : BaseBitfieldImm<opc, GPR64, imm0_63, asm> {
3179    let Inst{31} = 1;
3180    let Inst{22} = 1;
3181  }
3182}
3183
3184let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3185class BaseBitfieldImmWith2RegArgs<bits<2> opc,
3186                      RegisterClass regtype, Operand imm_type, string asm>
3187    : I<(outs regtype:$Rd), (ins regtype:$src, regtype:$Rn, imm_type:$immr,
3188                             imm_type:$imms),
3189         asm, "\t$Rd, $Rn, $immr, $imms", "$src = $Rd", []>,
3190      Sched<[WriteIS, ReadI]> {
3191  bits<5> Rd;
3192  bits<5> Rn;
3193  bits<6> immr;
3194  bits<6> imms;
3195
3196  let Inst{30-29} = opc;
3197  let Inst{28-23} = 0b100110;
3198  let Inst{21-16} = immr;
3199  let Inst{15-10} = imms;
3200  let Inst{9-5}   = Rn;
3201  let Inst{4-0}   = Rd;
3202}
3203
3204multiclass BitfieldImmWith2RegArgs<bits<2> opc, string asm> {
3205  def Wri : BaseBitfieldImmWith2RegArgs<opc, GPR32, imm0_31, asm> {
3206    let Inst{31} = 0;
3207    let Inst{22} = 0;
3208    // imms<5> and immr<5> must be zero, else ReservedValue().
3209    let Inst{21} = 0;
3210    let Inst{15} = 0;
3211  }
3212  def Xri : BaseBitfieldImmWith2RegArgs<opc, GPR64, imm0_63, asm> {
3213    let Inst{31} = 1;
3214    let Inst{22} = 1;
3215  }
3216}
3217
3218//---
3219// Logical
3220//---
3221
3222// Logical (immediate)
3223class BaseLogicalImm<bits<2> opc, RegisterClass dregtype,
3224                     RegisterClass sregtype, Operand imm_type, string asm,
3225                     list<dag> pattern>
3226    : I<(outs dregtype:$Rd), (ins sregtype:$Rn, imm_type:$imm),
3227         asm, "\t$Rd, $Rn, $imm", "", pattern>,
3228      Sched<[WriteI, ReadI]> {
3229  bits<5>  Rd;
3230  bits<5>  Rn;
3231  bits<13> imm;
3232  let Inst{30-29} = opc;
3233  let Inst{28-23} = 0b100100;
3234  let Inst{22}    = imm{12};
3235  let Inst{21-16} = imm{11-6};
3236  let Inst{15-10} = imm{5-0};
3237  let Inst{9-5}   = Rn;
3238  let Inst{4-0}   = Rd;
3239
3240  let DecoderMethod = "DecodeLogicalImmInstruction";
3241}
3242
3243// Logical (shifted register)
3244class BaseLogicalSReg<bits<2> opc, bit N, RegisterClass regtype,
3245                      logical_shifted_reg shifted_regtype, string asm,
3246                      list<dag> pattern>
3247    : I<(outs regtype:$Rd), (ins regtype:$Rn, (shifted_regtype $Rm, $shift):$Rm_and_shift),
3248        asm, "\t$Rd, $Rn, $Rm_and_shift", "", pattern>,
3249      Sched<[WriteISReg, ReadI, ReadISReg]> {
3250  bits<5> Rd;
3251  bits<5> Rn;
3252  bits<5> Rm;
3253  bits<8> shift;
3254  let Inst{30-29} = opc;
3255  let Inst{28-24} = 0b01010;
3256  let Inst{23-22} = shift{7-6};
3257  let Inst{21}    = N;
3258  let Inst{20-16} = Rm;
3259  let Inst{15-10} = shift{5-0};
3260  let Inst{9-5}   = Rn;
3261  let Inst{4-0}   = Rd;
3262
3263  let DecoderMethod = "DecodeThreeAddrSRegInstruction";
3264}
3265
3266// Aliases for register+register logical instructions.
3267class LogicalRegAlias<string asm, Instruction inst, RegisterClass regtype>
3268    : InstAlias<asm#"\t$dst, $src1, $src2",
3269                (inst regtype:$dst, regtype:$src1, regtype:$src2, 0)>;
3270
3271multiclass LogicalImm<bits<2> opc, string mnemonic, SDNode OpNode,
3272                      string Alias> {
3273  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3274  def Wri : BaseLogicalImm<opc, GPR32sp, GPR32, logical_imm32, mnemonic,
3275                           [(set GPR32sp:$Rd, (OpNode GPR32:$Rn,
3276                                               logical_imm32:$imm))]> {
3277    let Inst{31} = 0;
3278    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3279  }
3280  let AddedComplexity = 6, isReMaterializable = 1, isAsCheapAsAMove = 1 in
3281  def Xri : BaseLogicalImm<opc, GPR64sp, GPR64, logical_imm64, mnemonic,
3282                           [(set GPR64sp:$Rd, (OpNode GPR64:$Rn,
3283                                               logical_imm64:$imm))]> {
3284    let Inst{31} = 1;
3285  }
3286
3287  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3288                  (!cast<Instruction>(NAME # "Wri") GPR32sp:$Rd, GPR32:$Rn,
3289                      logical_imm32_not:$imm), 0>;
3290  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3291                  (!cast<Instruction>(NAME # "Xri") GPR64sp:$Rd, GPR64:$Rn,
3292                       logical_imm64_not:$imm), 0>;
3293}
3294
3295multiclass LogicalImmS<bits<2> opc, string mnemonic, SDNode OpNode,
3296                       string Alias> {
3297  let isCompare = 1, Defs = [NZCV] in {
3298  def Wri  : BaseLogicalImm<opc, GPR32, GPR32, logical_imm32, mnemonic,
3299      [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_imm32:$imm))]> {
3300    let Inst{31} = 0;
3301    let Inst{22} = 0; // 64-bit version has an additional bit of immediate.
3302  }
3303  def Xri  : BaseLogicalImm<opc, GPR64, GPR64, logical_imm64, mnemonic,
3304      [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_imm64:$imm))]> {
3305    let Inst{31} = 1;
3306  }
3307  } // end Defs = [NZCV]
3308
3309  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3310                  (!cast<Instruction>(NAME # "Wri") GPR32:$Rd, GPR32:$Rn,
3311                      logical_imm32_not:$imm), 0>;
3312  def : InstSubst<Alias # "\t$Rd, $Rn, $imm",
3313                  (!cast<Instruction>(NAME # "Xri") GPR64:$Rd, GPR64:$Rn,
3314                       logical_imm64_not:$imm), 0>;
3315}
3316
3317class BaseLogicalRegPseudo<RegisterClass regtype, SDPatternOperator OpNode>
3318    : Pseudo<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
3319             [(set regtype:$Rd, (OpNode regtype:$Rn, regtype:$Rm))]>,
3320      Sched<[WriteI, ReadI, ReadI]>;
3321
3322// Split from LogicalImm as not all instructions have both.
3323multiclass LogicalReg<bits<2> opc, bit N, string mnemonic,
3324                      SDPatternOperator OpNode, int AddedComplexityVal = 0> {
3325  let isReMaterializable = 1, isAsCheapAsAMove = 1, AddedComplexity = AddedComplexityVal in {
3326  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3327  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3328  }
3329
3330  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3331                            [(set GPR32:$Rd, (OpNode GPR32:$Rn,
3332                                                 logical_shifted_reg32:$Rm_and_shift))]> {
3333    let Inst{31} = 0;
3334  }
3335  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3336                            [(set GPR64:$Rd, (OpNode GPR64:$Rn,
3337                                                 logical_shifted_reg64:$Rm_and_shift))]> {
3338    let Inst{31} = 1;
3339  }
3340
3341  def : LogicalRegAlias<mnemonic,
3342                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3343  def : LogicalRegAlias<mnemonic,
3344                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3345}
3346
3347// Split from LogicalReg to allow setting NZCV Defs
3348multiclass LogicalRegS<bits<2> opc, bit N, string mnemonic,
3349                       SDPatternOperator OpNode = null_frag> {
3350  let Defs = [NZCV], mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
3351  def Wrr : BaseLogicalRegPseudo<GPR32, OpNode>;
3352  def Xrr : BaseLogicalRegPseudo<GPR64, OpNode>;
3353
3354  def Wrs : BaseLogicalSReg<opc, N, GPR32, logical_shifted_reg32, mnemonic,
3355            [(set GPR32:$Rd, (OpNode GPR32:$Rn, logical_shifted_reg32:$Rm_and_shift))]> {
3356    let Inst{31} = 0;
3357  }
3358  def Xrs : BaseLogicalSReg<opc, N, GPR64, logical_shifted_reg64, mnemonic,
3359            [(set GPR64:$Rd, (OpNode GPR64:$Rn, logical_shifted_reg64:$Rm_and_shift))]> {
3360    let Inst{31} = 1;
3361  }
3362  } // Defs = [NZCV]
3363
3364  def : LogicalRegAlias<mnemonic,
3365                        !cast<Instruction>(NAME#"Wrs"), GPR32>;
3366  def : LogicalRegAlias<mnemonic,
3367                        !cast<Instruction>(NAME#"Xrs"), GPR64>;
3368}
3369
3370//---
3371// Conditionally set flags
3372//---
3373
3374let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3375class BaseCondComparisonImm<bit op, RegisterClass regtype, ImmLeaf immtype,
3376                            string mnemonic, SDNode OpNode>
3377    : I<(outs), (ins regtype:$Rn, immtype:$imm, imm32_0_15:$nzcv, ccode:$cond),
3378         mnemonic, "\t$Rn, $imm, $nzcv, $cond", "",
3379         [(set NZCV, (OpNode regtype:$Rn, immtype:$imm, (i32 imm:$nzcv),
3380                             (i32 imm:$cond), NZCV))]>,
3381      Sched<[WriteI, ReadI]> {
3382  let Uses = [NZCV];
3383  let Defs = [NZCV];
3384
3385  bits<5> Rn;
3386  bits<5> imm;
3387  bits<4> nzcv;
3388  bits<4> cond;
3389
3390  let Inst{30}    = op;
3391  let Inst{29-21} = 0b111010010;
3392  let Inst{20-16} = imm;
3393  let Inst{15-12} = cond;
3394  let Inst{11-10} = 0b10;
3395  let Inst{9-5}   = Rn;
3396  let Inst{4}     = 0b0;
3397  let Inst{3-0}   = nzcv;
3398}
3399
3400let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
3401class BaseCondComparisonReg<bit op, RegisterClass regtype, string mnemonic,
3402                            SDNode OpNode>
3403    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
3404         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "",
3405         [(set NZCV, (OpNode regtype:$Rn, regtype:$Rm, (i32 imm:$nzcv),
3406                             (i32 imm:$cond), NZCV))]>,
3407      Sched<[WriteI, ReadI, ReadI]> {
3408  let Uses = [NZCV];
3409  let Defs = [NZCV];
3410
3411  bits<5> Rn;
3412  bits<5> Rm;
3413  bits<4> nzcv;
3414  bits<4> cond;
3415
3416  let Inst{30}    = op;
3417  let Inst{29-21} = 0b111010010;
3418  let Inst{20-16} = Rm;
3419  let Inst{15-12} = cond;
3420  let Inst{11-10} = 0b00;
3421  let Inst{9-5}   = Rn;
3422  let Inst{4}     = 0b0;
3423  let Inst{3-0}   = nzcv;
3424}
3425
3426multiclass CondComparison<bit op, string mnemonic, SDNode OpNode> {
3427  // immediate operand variants
3428  def Wi : BaseCondComparisonImm<op, GPR32, imm32_0_31, mnemonic, OpNode> {
3429    let Inst{31} = 0;
3430  }
3431  def Xi : BaseCondComparisonImm<op, GPR64, imm0_31, mnemonic, OpNode> {
3432    let Inst{31} = 1;
3433  }
3434  // register operand variants
3435  def Wr : BaseCondComparisonReg<op, GPR32, mnemonic, OpNode> {
3436    let Inst{31} = 0;
3437  }
3438  def Xr : BaseCondComparisonReg<op, GPR64, mnemonic, OpNode> {
3439    let Inst{31} = 1;
3440  }
3441}
3442
3443//---
3444// Conditional select
3445//---
3446
3447class BaseCondSelect<bit op, bits<2> op2, RegisterClass regtype, string asm>
3448    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3449         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3450         [(set regtype:$Rd,
3451               (AArch64csel regtype:$Rn, regtype:$Rm, (i32 imm:$cond), NZCV))]>,
3452      Sched<[WriteI, ReadI, ReadI]> {
3453  let Uses = [NZCV];
3454
3455  bits<5> Rd;
3456  bits<5> Rn;
3457  bits<5> Rm;
3458  bits<4> cond;
3459
3460  let Inst{30}    = op;
3461  let Inst{29-21} = 0b011010100;
3462  let Inst{20-16} = Rm;
3463  let Inst{15-12} = cond;
3464  let Inst{11-10} = op2;
3465  let Inst{9-5}   = Rn;
3466  let Inst{4-0}   = Rd;
3467}
3468
3469multiclass CondSelect<bit op, bits<2> op2, string asm> {
3470  def Wr : BaseCondSelect<op, op2, GPR32, asm> {
3471    let Inst{31} = 0;
3472  }
3473  def Xr : BaseCondSelect<op, op2, GPR64, asm> {
3474    let Inst{31} = 1;
3475  }
3476}
3477
3478class BaseCondSelectOp<bit op, bits<2> op2, RegisterClass regtype, string asm,
3479                       PatFrag frag>
3480    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
3481         asm, "\t$Rd, $Rn, $Rm, $cond", "",
3482         [(set regtype:$Rd,
3483               (AArch64csel regtype:$Rn, (frag regtype:$Rm),
3484               (i32 imm:$cond), NZCV))]>,
3485      Sched<[WriteI, ReadI, ReadI]> {
3486  let Uses = [NZCV];
3487
3488  bits<5> Rd;
3489  bits<5> Rn;
3490  bits<5> Rm;
3491  bits<4> cond;
3492
3493  let Inst{30}    = op;
3494  let Inst{29-21} = 0b011010100;
3495  let Inst{20-16} = Rm;
3496  let Inst{15-12} = cond;
3497  let Inst{11-10} = op2;
3498  let Inst{9-5}   = Rn;
3499  let Inst{4-0}   = Rd;
3500}
3501
3502def inv_cond_XFORM : SDNodeXForm<imm, [{
3503  AArch64CC::CondCode CC = static_cast<AArch64CC::CondCode>(N->getZExtValue());
3504  return CurDAG->getTargetConstant(AArch64CC::getInvertedCondCode(CC), SDLoc(N),
3505                                   MVT::i32);
3506}]>;
3507
3508multiclass CondSelectOp<bit op, bits<2> op2, string asm, PatFrag frag> {
3509  def Wr : BaseCondSelectOp<op, op2, GPR32, asm, frag> {
3510    let Inst{31} = 0;
3511  }
3512  def Xr : BaseCondSelectOp<op, op2, GPR64, asm, frag> {
3513    let Inst{31} = 1;
3514  }
3515
3516  def : Pat<(AArch64csel (frag GPR32:$Rm), GPR32:$Rn, (i32 imm:$cond), NZCV),
3517            (!cast<Instruction>(NAME # Wr) GPR32:$Rn, GPR32:$Rm,
3518                                           (inv_cond_XFORM imm:$cond))>;
3519
3520  def : Pat<(AArch64csel (frag GPR64:$Rm), GPR64:$Rn, (i32 imm:$cond), NZCV),
3521            (!cast<Instruction>(NAME # Xr) GPR64:$Rn, GPR64:$Rm,
3522                                           (inv_cond_XFORM imm:$cond))>;
3523}
3524
3525//---
3526// Special Mask Value
3527//---
3528def maski8_or_more : Operand<i32>,
3529  ImmLeaf<i32, [{ return (Imm & 0xff) == 0xff; }]> {
3530}
3531def maski16_or_more : Operand<i32>,
3532  ImmLeaf<i32, [{ return (Imm & 0xffff) == 0xffff; }]> {
3533}
3534
3535
3536//---
3537// Load/store
3538//---
3539
3540// (unsigned immediate)
3541// Indexed for 8-bit registers. offset is in range [0,4095].
3542def am_indexed8 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed8", []>;
3543def am_indexed16 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed16", []>;
3544def am_indexed32 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed32", []>;
3545def am_indexed64 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed64", []>;
3546def am_indexed128 : ComplexPattern<iPTR, 2, "SelectAddrModeIndexed128", []>;
3547
3548// (unsigned immediate)
3549// Indexed for 8-bit registers. offset is in range [0,63].
3550def am_indexed8_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<1,63>", []>;
3551def am_indexed16_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<2,63>", []>;
3552def am_indexed32_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<4,63>", []>;
3553def am_indexed64_6b : ComplexPattern<iPTR, 2, "SelectAddrModeIndexedUImm<8,63>", []>;
3554
3555def gi_am_indexed8 :
3556    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<8>">,
3557    GIComplexPatternEquiv<am_indexed8>;
3558def gi_am_indexed16 :
3559    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<16>">,
3560    GIComplexPatternEquiv<am_indexed16>;
3561def gi_am_indexed32 :
3562    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<32>">,
3563    GIComplexPatternEquiv<am_indexed32>;
3564def gi_am_indexed64 :
3565    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<64>">,
3566    GIComplexPatternEquiv<am_indexed64>;
3567def gi_am_indexed128 :
3568    GIComplexOperandMatcher<s64, "selectAddrModeIndexed<128>">,
3569    GIComplexPatternEquiv<am_indexed128>;
3570
3571class UImm12OffsetOperand<int Scale> : AsmOperandClass {
3572  let Name = "UImm12Offset" # Scale;
3573  let RenderMethod = "addUImm12OffsetOperands<" # Scale # ">";
3574  let PredicateMethod = "isUImm12Offset<" # Scale # ">";
3575  let DiagnosticType = "InvalidMemoryIndexed" # Scale;
3576}
3577
3578def UImm12OffsetScale1Operand : UImm12OffsetOperand<1>;
3579def UImm12OffsetScale2Operand : UImm12OffsetOperand<2>;
3580def UImm12OffsetScale4Operand : UImm12OffsetOperand<4>;
3581def UImm12OffsetScale8Operand : UImm12OffsetOperand<8>;
3582def UImm12OffsetScale16Operand : UImm12OffsetOperand<16>;
3583
3584class uimm12_scaled<int Scale> : Operand<i64> {
3585  let ParserMatchClass
3586   = !cast<AsmOperandClass>("UImm12OffsetScale" # Scale # "Operand");
3587  let EncoderMethod
3588   = "getLdStUImm12OpValue<AArch64::fixup_aarch64_ldst_imm12_scale" # Scale # ">";
3589  let PrintMethod = "printUImm12Offset<" # Scale # ">";
3590}
3591
3592def uimm12s1 : uimm12_scaled<1>;
3593def uimm12s2 : uimm12_scaled<2>;
3594def uimm12s4 : uimm12_scaled<4>;
3595def uimm12s8 : uimm12_scaled<8>;
3596def uimm12s16 : uimm12_scaled<16>;
3597
3598class BaseLoadStoreUI<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
3599                      string asm, list<dag> pattern>
3600    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
3601  bits<5> Rt;
3602
3603  bits<5> Rn;
3604  bits<12> offset;
3605
3606  let Inst{31-30} = sz;
3607  let Inst{29-27} = 0b111;
3608  let Inst{26}    = V;
3609  let Inst{25-24} = 0b01;
3610  let Inst{23-22} = opc;
3611  let Inst{21-10} = offset;
3612  let Inst{9-5}   = Rn;
3613  let Inst{4-0}   = Rt;
3614
3615  let DecoderMethod = "DecodeUnsignedLdStInstruction";
3616}
3617
3618multiclass LoadUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3619                  Operand indextype, string asm, list<dag> pattern> {
3620  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
3621  def ui : BaseLoadStoreUI<sz, V, opc, (outs regtype:$Rt),
3622                           (ins GPR64sp:$Rn, indextype:$offset),
3623                           asm, pattern>,
3624           Sched<[WriteLD]>;
3625
3626  def : InstAlias<asm # "\t$Rt, [$Rn]",
3627                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3628}
3629
3630multiclass StoreUI<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3631             Operand indextype, string asm, list<dag> pattern> {
3632  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3633  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3634                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3635                           asm, pattern>,
3636           Sched<[WriteST]>;
3637
3638  def : InstAlias<asm # "\t$Rt, [$Rn]",
3639                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3640}
3641
3642// Same as StoreUI, but take a RegisterOperand. This is used by GlobalISel to
3643// substitute zero-registers automatically.
3644//
3645// TODO: Roll out zero-register subtitution to GPR32/GPR64 and fold this back
3646//       into StoreUI.
3647multiclass StoreUIz<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
3648             Operand indextype, string asm, list<dag> pattern> {
3649  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
3650  def ui : BaseLoadStoreUI<sz, V, opc, (outs),
3651                           (ins regtype:$Rt, GPR64sp:$Rn, indextype:$offset),
3652                           asm, pattern>,
3653           Sched<[WriteST]>;
3654
3655  def : InstAlias<asm # "\t$Rt, [$Rn]",
3656                  (!cast<Instruction>(NAME # "ui") regtype:$Rt, GPR64sp:$Rn, 0)>;
3657}
3658
3659def PrefetchOperand : AsmOperandClass {
3660  let Name = "Prefetch";
3661  let ParserMethod = "tryParsePrefetch";
3662}
3663def prfop : Operand<i32> {
3664  let PrintMethod = "printPrefetchOp";
3665  let ParserMatchClass = PrefetchOperand;
3666}
3667
3668let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3669class PrefetchUI<bits<2> sz, bit V, bits<2> opc, string asm, list<dag> pat>
3670    : BaseLoadStoreUI<sz, V, opc,
3671                      (outs), (ins prfop:$Rt, GPR64sp:$Rn, uimm12s8:$offset),
3672                      asm, pat>,
3673      Sched<[WriteLD]>;
3674
3675//---
3676// Load literal
3677//---
3678
3679// Load literal address: 19-bit immediate. The low two bits of the target
3680// offset are implied zero and so are not part of the immediate.
3681def am_ldrlit : Operand<iPTR> {
3682  let EncoderMethod = "getLoadLiteralOpValue";
3683  let DecoderMethod = "DecodePCRelLabel19";
3684  let PrintMethod = "printAlignedLabel";
3685  let ParserMatchClass = PCRelLabel19Operand;
3686  let OperandType = "OPERAND_PCREL";
3687}
3688
3689let mayLoad = 1, mayStore = 0, hasSideEffects = 0, AddedComplexity = 20 in
3690class LoadLiteral<bits<2> opc, bit V, RegisterOperand regtype, string asm, list<dag> pat>
3691    : I<(outs regtype:$Rt), (ins am_ldrlit:$label),
3692        asm, "\t$Rt, $label", "", pat>,
3693      Sched<[WriteLD]> {
3694  bits<5> Rt;
3695  bits<19> label;
3696  let Inst{31-30} = opc;
3697  let Inst{29-27} = 0b011;
3698  let Inst{26}    = V;
3699  let Inst{25-24} = 0b00;
3700  let Inst{23-5}  = label;
3701  let Inst{4-0}   = Rt;
3702}
3703
3704let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
3705class PrefetchLiteral<bits<2> opc, bit V, string asm, list<dag> pat>
3706    : I<(outs), (ins prfop:$Rt, am_ldrlit:$label),
3707        asm, "\t$Rt, $label", "", pat>,
3708      Sched<[WriteLD]> {
3709  bits<5> Rt;
3710  bits<19> label;
3711  let Inst{31-30} = opc;
3712  let Inst{29-27} = 0b011;
3713  let Inst{26}    = V;
3714  let Inst{25-24} = 0b00;
3715  let Inst{23-5}  = label;
3716  let Inst{4-0}   = Rt;
3717}
3718
3719//---
3720// Load/store register offset
3721//---
3722
3723def ro_Xindexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<8>", []>;
3724def ro_Xindexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<16>", []>;
3725def ro_Xindexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<32>", []>;
3726def ro_Xindexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<64>", []>;
3727def ro_Xindexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeXRO<128>", []>;
3728
3729def gi_ro_Xindexed8 :
3730    GIComplexOperandMatcher<s64, "selectAddrModeXRO<8>">,
3731    GIComplexPatternEquiv<ro_Xindexed8>;
3732def gi_ro_Xindexed16 :
3733    GIComplexOperandMatcher<s64, "selectAddrModeXRO<16>">,
3734    GIComplexPatternEquiv<ro_Xindexed16>;
3735def gi_ro_Xindexed32 :
3736    GIComplexOperandMatcher<s64, "selectAddrModeXRO<32>">,
3737    GIComplexPatternEquiv<ro_Xindexed32>;
3738def gi_ro_Xindexed64 :
3739    GIComplexOperandMatcher<s64, "selectAddrModeXRO<64>">,
3740    GIComplexPatternEquiv<ro_Xindexed64>;
3741def gi_ro_Xindexed128 :
3742    GIComplexOperandMatcher<s64, "selectAddrModeXRO<128>">,
3743    GIComplexPatternEquiv<ro_Xindexed128>;
3744
3745def ro_Windexed8 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<8>", []>;
3746def ro_Windexed16 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<16>", []>;
3747def ro_Windexed32 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<32>", []>;
3748def ro_Windexed64 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<64>", []>;
3749def ro_Windexed128 : ComplexPattern<iPTR, 4, "SelectAddrModeWRO<128>", []>;
3750
3751def gi_ro_Windexed8 :
3752    GIComplexOperandMatcher<s64, "selectAddrModeWRO<8>">,
3753    GIComplexPatternEquiv<ro_Windexed8>;
3754def gi_ro_Windexed16 :
3755    GIComplexOperandMatcher<s64, "selectAddrModeWRO<16>">,
3756    GIComplexPatternEquiv<ro_Windexed16>;
3757def gi_ro_Windexed32 :
3758    GIComplexOperandMatcher<s64, "selectAddrModeWRO<32>">,
3759    GIComplexPatternEquiv<ro_Windexed32>;
3760def gi_ro_Windexed64 :
3761    GIComplexOperandMatcher<s64, "selectAddrModeWRO<64>">,
3762    GIComplexPatternEquiv<ro_Windexed64>;
3763def gi_ro_Windexed128 :
3764    GIComplexOperandMatcher<s64, "selectAddrModeWRO<128>">,
3765    GIComplexPatternEquiv<ro_Windexed128>;
3766
3767class MemExtendOperand<string Reg, int Width> : AsmOperandClass {
3768  let Name = "Mem" # Reg # "Extend" # Width;
3769  let PredicateMethod = "isMem" # Reg # "Extend<" # Width # ">";
3770  let RenderMethod = "addMemExtendOperands";
3771  let DiagnosticType = "InvalidMemory" # Reg # "Extend" # Width;
3772}
3773
3774def MemWExtend8Operand : MemExtendOperand<"W", 8> {
3775  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3776  // the trivial shift.
3777  let RenderMethod = "addMemExtend8Operands";
3778}
3779def MemWExtend16Operand : MemExtendOperand<"W", 16>;
3780def MemWExtend32Operand : MemExtendOperand<"W", 32>;
3781def MemWExtend64Operand : MemExtendOperand<"W", 64>;
3782def MemWExtend128Operand : MemExtendOperand<"W", 128>;
3783
3784def MemXExtend8Operand : MemExtendOperand<"X", 8> {
3785  // The address "[x0, x1, lsl #0]" actually maps to the variant which performs
3786  // the trivial shift.
3787  let RenderMethod = "addMemExtend8Operands";
3788}
3789def MemXExtend16Operand : MemExtendOperand<"X", 16>;
3790def MemXExtend32Operand : MemExtendOperand<"X", 32>;
3791def MemXExtend64Operand : MemExtendOperand<"X", 64>;
3792def MemXExtend128Operand : MemExtendOperand<"X", 128>;
3793
3794class ro_extend<AsmOperandClass ParserClass, string Reg, int Width>
3795        : Operand<i32> {
3796  let ParserMatchClass = ParserClass;
3797  let PrintMethod = "printMemExtend<'" # Reg # "', " # Width # ">";
3798  let DecoderMethod = "DecodeMemExtend";
3799  let EncoderMethod = "getMemExtendOpValue";
3800  let MIOperandInfo = (ops i32imm:$signed, i32imm:$doshift);
3801}
3802
3803def ro_Wextend8   : ro_extend<MemWExtend8Operand,   "w", 8>;
3804def ro_Wextend16  : ro_extend<MemWExtend16Operand,  "w", 16>;
3805def ro_Wextend32  : ro_extend<MemWExtend32Operand,  "w", 32>;
3806def ro_Wextend64  : ro_extend<MemWExtend64Operand,  "w", 64>;
3807def ro_Wextend128 : ro_extend<MemWExtend128Operand, "w", 128>;
3808
3809def ro_Xextend8   : ro_extend<MemXExtend8Operand,   "x", 8>;
3810def ro_Xextend16  : ro_extend<MemXExtend16Operand,  "x", 16>;
3811def ro_Xextend32  : ro_extend<MemXExtend32Operand,  "x", 32>;
3812def ro_Xextend64  : ro_extend<MemXExtend64Operand,  "x", 64>;
3813def ro_Xextend128 : ro_extend<MemXExtend128Operand, "x", 128>;
3814
3815class ROAddrMode<ComplexPattern windex, ComplexPattern xindex,
3816                  Operand wextend, Operand xextend>  {
3817  // CodeGen-level pattern covering the entire addressing mode.
3818  ComplexPattern Wpat = windex;
3819  ComplexPattern Xpat = xindex;
3820
3821  // Asm-level Operand covering the valid "uxtw #3" style syntax.
3822  Operand Wext = wextend;
3823  Operand Xext = xextend;
3824}
3825
3826def ro8 : ROAddrMode<ro_Windexed8, ro_Xindexed8, ro_Wextend8, ro_Xextend8>;
3827def ro16 : ROAddrMode<ro_Windexed16, ro_Xindexed16, ro_Wextend16, ro_Xextend16>;
3828def ro32 : ROAddrMode<ro_Windexed32, ro_Xindexed32, ro_Wextend32, ro_Xextend32>;
3829def ro64 : ROAddrMode<ro_Windexed64, ro_Xindexed64, ro_Wextend64, ro_Xextend64>;
3830def ro128 : ROAddrMode<ro_Windexed128, ro_Xindexed128, ro_Wextend128,
3831                       ro_Xextend128>;
3832
3833class LoadStore8RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3834                   dag outs, list<dag> pat>
3835    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3836  bits<5> Rt;
3837  bits<5> Rn;
3838  bits<5> Rm;
3839  bits<2> extend;
3840  let Inst{31-30} = sz;
3841  let Inst{29-27} = 0b111;
3842  let Inst{26}    = V;
3843  let Inst{25-24} = 0b00;
3844  let Inst{23-22} = opc;
3845  let Inst{21}    = 1;
3846  let Inst{20-16} = Rm;
3847  let Inst{15}    = extend{1}; // sign extend Rm?
3848  let Inst{14}    = 1;
3849  let Inst{12}    = extend{0}; // do shift?
3850  let Inst{11-10} = 0b10;
3851  let Inst{9-5}   = Rn;
3852  let Inst{4-0}   = Rt;
3853}
3854
3855class ROInstAlias<string asm, DAGOperand regtype, Instruction INST>
3856  : InstAlias<asm # "\t$Rt, [$Rn, $Rm]",
3857              (INST regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
3858
3859multiclass Load8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3860                   string asm, ValueType Ty, SDPatternOperator loadop> {
3861  let AddedComplexity = 10 in
3862  def roW : LoadStore8RO<sz, V, opc, asm,
3863                 (outs regtype:$Rt),
3864                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3865                 [(set (Ty regtype:$Rt),
3866                       (loadop (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3867                                             ro_Wextend8:$extend)))]>,
3868           Sched<[WriteLDIdx, ReadAdrBase]> {
3869    let Inst{13} = 0b0;
3870  }
3871
3872  let AddedComplexity = 10 in
3873  def roX : LoadStore8RO<sz, V, opc, asm,
3874                 (outs regtype:$Rt),
3875                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3876                 [(set (Ty regtype:$Rt),
3877                       (loadop (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3878                                             ro_Xextend8:$extend)))]>,
3879           Sched<[WriteLDIdx, ReadAdrBase]> {
3880    let Inst{13} = 0b1;
3881  }
3882
3883  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3884}
3885
3886multiclass Store8RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3887                    string asm, ValueType Ty, SDPatternOperator storeop> {
3888  let AddedComplexity = 10 in
3889  def roW : LoadStore8RO<sz, V, opc, asm, (outs),
3890                 (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend8:$extend),
3891                 [(storeop (Ty regtype:$Rt),
3892                           (ro_Windexed8 GPR64sp:$Rn, GPR32:$Rm,
3893                                         ro_Wextend8:$extend))]>,
3894            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3895    let Inst{13} = 0b0;
3896  }
3897
3898  let AddedComplexity = 10 in
3899  def roX : LoadStore8RO<sz, V, opc, asm, (outs),
3900                 (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend8:$extend),
3901                 [(storeop (Ty regtype:$Rt),
3902                           (ro_Xindexed8 GPR64sp:$Rn, GPR64:$Rm,
3903                                         ro_Xextend8:$extend))]>,
3904            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3905    let Inst{13} = 0b1;
3906  }
3907
3908  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3909}
3910
3911class LoadStore16RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3912                    dag outs, list<dag> pat>
3913    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3914  bits<5> Rt;
3915  bits<5> Rn;
3916  bits<5> Rm;
3917  bits<2> extend;
3918  let Inst{31-30} = sz;
3919  let Inst{29-27} = 0b111;
3920  let Inst{26}    = V;
3921  let Inst{25-24} = 0b00;
3922  let Inst{23-22} = opc;
3923  let Inst{21}    = 1;
3924  let Inst{20-16} = Rm;
3925  let Inst{15}    = extend{1}; // sign extend Rm?
3926  let Inst{14}    = 1;
3927  let Inst{12}    = extend{0}; // do shift?
3928  let Inst{11-10} = 0b10;
3929  let Inst{9-5}   = Rn;
3930  let Inst{4-0}   = Rt;
3931}
3932
3933multiclass Load16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3934                    string asm, ValueType Ty, SDPatternOperator loadop> {
3935  let AddedComplexity = 10 in
3936  def roW : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3937                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3938                 [(set (Ty regtype:$Rt),
3939                       (loadop (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3940                                              ro_Wextend16:$extend)))]>,
3941            Sched<[WriteLDIdx, ReadAdrBase]> {
3942    let Inst{13} = 0b0;
3943  }
3944
3945  let AddedComplexity = 10 in
3946  def roX : LoadStore16RO<sz, V, opc, asm, (outs regtype:$Rt),
3947                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3948                 [(set (Ty regtype:$Rt),
3949                       (loadop (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3950                                             ro_Xextend16:$extend)))]>,
3951            Sched<[WriteLDIdx, ReadAdrBase]> {
3952    let Inst{13} = 0b1;
3953  }
3954
3955  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3956}
3957
3958multiclass Store16RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
3959                     string asm, ValueType Ty, SDPatternOperator storeop> {
3960  let AddedComplexity = 10 in
3961  def roW : LoadStore16RO<sz, V, opc, asm, (outs),
3962                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend16:$extend),
3963                [(storeop (Ty regtype:$Rt),
3964                          (ro_Windexed16 GPR64sp:$Rn, GPR32:$Rm,
3965                                         ro_Wextend16:$extend))]>,
3966           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3967    let Inst{13} = 0b0;
3968  }
3969
3970  let AddedComplexity = 10 in
3971  def roX : LoadStore16RO<sz, V, opc, asm, (outs),
3972                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend16:$extend),
3973                [(storeop (Ty regtype:$Rt),
3974                          (ro_Xindexed16 GPR64sp:$Rn, GPR64:$Rm,
3975                                         ro_Xextend16:$extend))]>,
3976           Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
3977    let Inst{13} = 0b1;
3978  }
3979
3980  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
3981}
3982
3983class LoadStore32RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
3984                    dag outs, list<dag> pat>
3985    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
3986  bits<5> Rt;
3987  bits<5> Rn;
3988  bits<5> Rm;
3989  bits<2> extend;
3990  let Inst{31-30} = sz;
3991  let Inst{29-27} = 0b111;
3992  let Inst{26}    = V;
3993  let Inst{25-24} = 0b00;
3994  let Inst{23-22} = opc;
3995  let Inst{21}    = 1;
3996  let Inst{20-16} = Rm;
3997  let Inst{15}    = extend{1}; // sign extend Rm?
3998  let Inst{14}    = 1;
3999  let Inst{12}    = extend{0}; // do shift?
4000  let Inst{11-10} = 0b10;
4001  let Inst{9-5}   = Rn;
4002  let Inst{4-0}   = Rt;
4003}
4004
4005multiclass Load32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4006                    string asm, ValueType Ty, SDPatternOperator loadop> {
4007  let AddedComplexity = 10 in
4008  def roW : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
4009                 (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
4010                 [(set (Ty regtype:$Rt),
4011                       (loadop (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
4012                                              ro_Wextend32:$extend)))]>,
4013           Sched<[WriteLDIdx, ReadAdrBase]> {
4014    let Inst{13} = 0b0;
4015  }
4016
4017  let AddedComplexity = 10 in
4018  def roX : LoadStore32RO<sz, V, opc, asm, (outs regtype:$Rt),
4019                 (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
4020                 [(set (Ty regtype:$Rt),
4021                       (loadop (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
4022                                              ro_Xextend32:$extend)))]>,
4023           Sched<[WriteLDIdx, ReadAdrBase]> {
4024    let Inst{13} = 0b1;
4025  }
4026
4027  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4028}
4029
4030multiclass Store32RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4031                     string asm, ValueType Ty, SDPatternOperator storeop> {
4032  let AddedComplexity = 10 in
4033  def roW : LoadStore32RO<sz, V, opc, asm, (outs),
4034                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend32:$extend),
4035                [(storeop (Ty regtype:$Rt),
4036                          (ro_Windexed32 GPR64sp:$Rn, GPR32:$Rm,
4037                                         ro_Wextend32:$extend))]>,
4038            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4039    let Inst{13} = 0b0;
4040  }
4041
4042  let AddedComplexity = 10 in
4043  def roX : LoadStore32RO<sz, V, opc, asm, (outs),
4044                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend32:$extend),
4045                [(storeop (Ty regtype:$Rt),
4046                          (ro_Xindexed32 GPR64sp:$Rn, GPR64:$Rm,
4047                                        ro_Xextend32:$extend))]>,
4048            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4049    let Inst{13} = 0b1;
4050  }
4051
4052  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4053}
4054
4055class LoadStore64RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
4056                    dag outs, list<dag> pat>
4057    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
4058  bits<5> Rt;
4059  bits<5> Rn;
4060  bits<5> Rm;
4061  bits<2> extend;
4062  let Inst{31-30} = sz;
4063  let Inst{29-27} = 0b111;
4064  let Inst{26}    = V;
4065  let Inst{25-24} = 0b00;
4066  let Inst{23-22} = opc;
4067  let Inst{21}    = 1;
4068  let Inst{20-16} = Rm;
4069  let Inst{15}    = extend{1}; // sign extend Rm?
4070  let Inst{14}    = 1;
4071  let Inst{12}    = extend{0}; // do shift?
4072  let Inst{11-10} = 0b10;
4073  let Inst{9-5}   = Rn;
4074  let Inst{4-0}   = Rt;
4075}
4076
4077multiclass Load64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4078                    string asm, ValueType Ty, SDPatternOperator loadop> {
4079  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4080  def roW : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
4081                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4082                [(set (Ty regtype:$Rt),
4083                      (loadop (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4084                                             ro_Wextend64:$extend)))]>,
4085           Sched<[WriteLDIdx, ReadAdrBase]> {
4086    let Inst{13} = 0b0;
4087  }
4088
4089  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4090  def roX : LoadStore64RO<sz, V, opc, asm, (outs regtype:$Rt),
4091                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4092                 [(set (Ty regtype:$Rt),
4093                       (loadop (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4094                                              ro_Xextend64:$extend)))]>,
4095           Sched<[WriteLDIdx, ReadAdrBase]> {
4096    let Inst{13} = 0b1;
4097  }
4098
4099  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4100}
4101
4102multiclass Store64RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4103                     string asm, ValueType Ty, SDPatternOperator storeop> {
4104  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4105  def roW : LoadStore64RO<sz, V, opc, asm, (outs),
4106                (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4107                [(storeop (Ty regtype:$Rt),
4108                          (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4109                                         ro_Wextend64:$extend))]>,
4110            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4111    let Inst{13} = 0b0;
4112  }
4113
4114  let AddedComplexity = 10, mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4115  def roX : LoadStore64RO<sz, V, opc, asm, (outs),
4116                (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4117                [(storeop (Ty regtype:$Rt),
4118                          (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4119                                         ro_Xextend64:$extend))]>,
4120            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4121    let Inst{13} = 0b1;
4122  }
4123
4124  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4125}
4126
4127class LoadStore128RO<bits<2> sz, bit V, bits<2> opc, string asm, dag ins,
4128                     dag outs, list<dag> pat>
4129    : I<ins, outs, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat> {
4130  bits<5> Rt;
4131  bits<5> Rn;
4132  bits<5> Rm;
4133  bits<2> extend;
4134  let Inst{31-30} = sz;
4135  let Inst{29-27} = 0b111;
4136  let Inst{26}    = V;
4137  let Inst{25-24} = 0b00;
4138  let Inst{23-22} = opc;
4139  let Inst{21}    = 1;
4140  let Inst{20-16} = Rm;
4141  let Inst{15}    = extend{1}; // sign extend Rm?
4142  let Inst{14}    = 1;
4143  let Inst{12}    = extend{0}; // do shift?
4144  let Inst{11-10} = 0b10;
4145  let Inst{9-5}   = Rn;
4146  let Inst{4-0}   = Rt;
4147}
4148
4149multiclass Load128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4150                     string asm, ValueType Ty, SDPatternOperator loadop> {
4151  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4152  def roW : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4153                (ins GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4154                 [(set (Ty regtype:$Rt),
4155                       (loadop (ro_Windexed128 GPR64sp:$Rn, GPR32:$Rm,
4156                                               ro_Wextend128:$extend)))]>,
4157            Sched<[WriteLDIdx, ReadAdrBase]> {
4158    let Inst{13} = 0b0;
4159  }
4160
4161  let AddedComplexity = 10, mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
4162  def roX : LoadStore128RO<sz, V, opc, asm, (outs regtype:$Rt),
4163                (ins GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4164                 [(set (Ty regtype:$Rt),
4165                       (loadop (ro_Xindexed128 GPR64sp:$Rn, GPR64:$Rm,
4166                                               ro_Xextend128:$extend)))]>,
4167            Sched<[WriteLDIdx, ReadAdrBase]> {
4168    let Inst{13} = 0b1;
4169  }
4170
4171  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4172}
4173
4174multiclass Store128RO<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4175                      string asm> {
4176  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4177  def roW : LoadStore128RO<sz, V, opc, asm, (outs),
4178               (ins regtype:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend128:$extend),
4179                []>,
4180            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4181    let Inst{13} = 0b0;
4182  }
4183
4184  let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
4185  def roX : LoadStore128RO<sz, V, opc, asm, (outs),
4186               (ins regtype:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend128:$extend),
4187                []>,
4188            Sched<[WriteSTIdx, ReadST, ReadAdrBase]> {
4189    let Inst{13} = 0b1;
4190  }
4191
4192  def : ROInstAlias<asm, regtype, !cast<Instruction>(NAME # "roX")>;
4193}
4194
4195let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4196class BasePrefetchRO<bits<2> sz, bit V, bits<2> opc, dag outs, dag ins,
4197                     string asm, list<dag> pat>
4198    : I<outs, ins, asm, "\t$Rt, [$Rn, $Rm, $extend]", "", pat>,
4199      Sched<[WriteLD]> {
4200  bits<5> Rt;
4201  bits<5> Rn;
4202  bits<5> Rm;
4203  bits<2> extend;
4204  let Inst{31-30} = sz;
4205  let Inst{29-27} = 0b111;
4206  let Inst{26}    = V;
4207  let Inst{25-24} = 0b00;
4208  let Inst{23-22} = opc;
4209  let Inst{21}    = 1;
4210  let Inst{20-16} = Rm;
4211  let Inst{15}    = extend{1}; // sign extend Rm?
4212  let Inst{14}    = 1;
4213  let Inst{12}    = extend{0}; // do shift?
4214  let Inst{11-10} = 0b10;
4215  let Inst{9-5}   = Rn;
4216  let Inst{4-0}   = Rt;
4217  let DecoderMethod = "DecodePRFMRegInstruction";
4218  // PRFM (reg) aliases with RPRFM added to the base A64 instruction set. When
4219  // the decoder method returns Fail, the decoder should attempt to decode the
4220  // instruction as RPRFM.
4221  let hasCompleteDecoder = 0;
4222}
4223
4224multiclass PrefetchRO<bits<2> sz, bit V, bits<2> opc, string asm> {
4225  def roW : BasePrefetchRO<sz, V, opc, (outs),
4226                (ins prfop:$Rt, GPR64sp:$Rn, GPR32:$Rm, ro_Wextend64:$extend),
4227                asm, [(AArch64Prefetch timm:$Rt,
4228                                     (ro_Windexed64 GPR64sp:$Rn, GPR32:$Rm,
4229                                                    ro_Wextend64:$extend))]> {
4230    let Inst{13} = 0b0;
4231  }
4232
4233  def roX : BasePrefetchRO<sz, V, opc, (outs),
4234                (ins prfop:$Rt, GPR64sp:$Rn, GPR64:$Rm, ro_Xextend64:$extend),
4235                asm,  [(AArch64Prefetch timm:$Rt,
4236                                      (ro_Xindexed64 GPR64sp:$Rn, GPR64:$Rm,
4237                                                     ro_Xextend64:$extend))]> {
4238    let Inst{13} = 0b1;
4239  }
4240
4241  def : InstAlias<"prfm $Rt, [$Rn, $Rm]",
4242               (!cast<Instruction>(NAME # "roX") prfop:$Rt,
4243                                                 GPR64sp:$Rn, GPR64:$Rm, 0, 0)>;
4244}
4245
4246//---
4247// Load/store unscaled immediate
4248//---
4249
4250def am_unscaled8 :  ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled8", []>;
4251def am_unscaled16 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled16", []>;
4252def am_unscaled32 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled32", []>;
4253def am_unscaled64 : ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled64", []>;
4254def am_unscaled128 :ComplexPattern<iPTR, 2, "SelectAddrModeUnscaled128", []>;
4255
4256def gi_am_unscaled8 :
4257    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled8">,
4258    GIComplexPatternEquiv<am_unscaled8>;
4259def gi_am_unscaled16 :
4260    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled16">,
4261    GIComplexPatternEquiv<am_unscaled16>;
4262def gi_am_unscaled32 :
4263    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled32">,
4264    GIComplexPatternEquiv<am_unscaled32>;
4265def gi_am_unscaled64 :
4266    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled64">,
4267    GIComplexPatternEquiv<am_unscaled64>;
4268def gi_am_unscaled128 :
4269    GIComplexOperandMatcher<s64, "selectAddrModeUnscaled128">,
4270    GIComplexPatternEquiv<am_unscaled128>;
4271
4272
4273class BaseLoadStoreUnscale<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4274                           string asm, list<dag> pattern>
4275    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", pattern> {
4276  bits<5> Rt;
4277  bits<5> Rn;
4278  bits<9> offset;
4279  let Inst{31-30} = sz;
4280  let Inst{29-27} = 0b111;
4281  let Inst{26}    = V;
4282  let Inst{25-24} = 0b00;
4283  let Inst{23-22} = opc;
4284  let Inst{21}    = 0;
4285  let Inst{20-12} = offset;
4286  let Inst{11-10} = 0b00;
4287  let Inst{9-5}   = Rn;
4288  let Inst{4-0}   = Rt;
4289
4290  let DecoderMethod = "DecodeSignedLdStInstruction";
4291}
4292
4293// Armv8.4 LDAPR & STLR with Immediate Offset instruction
4294multiclass BaseLoadUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4295                              DAGOperand regtype > {
4296  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs regtype:$Rt),
4297                               (ins GPR64sp:$Rn, simm9:$offset), asm, []>,
4298          Sched<[WriteST]> {
4299    let Inst{29} = 0;
4300    let Inst{24} = 1;
4301  }
4302  def : InstAlias<asm # "\t$Rt, [$Rn]",
4303                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4304}
4305
4306multiclass BaseStoreUnscaleV84<string asm, bits<2> sz, bits<2> opc,
4307                               DAGOperand regtype > {
4308  def i : BaseLoadStoreUnscale<sz, 0, opc, (outs),
4309                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4310                               asm, []>,
4311          Sched<[WriteST]> {
4312    let Inst{29} = 0;
4313    let Inst{24} = 1;
4314  }
4315  def : InstAlias<asm # "\t$Rt, [$Rn]",
4316                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4317}
4318
4319multiclass LoadUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4320                   string asm, list<dag> pattern> {
4321  let AddedComplexity = 1 in // try this before LoadUI
4322  def i : BaseLoadStoreUnscale<sz, V, opc, (outs regtype:$Rt),
4323                               (ins GPR64sp:$Rn, simm9:$offset), asm, pattern>,
4324          Sched<[WriteLD]>;
4325
4326  def : InstAlias<asm # "\t$Rt, [$Rn]",
4327                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4328}
4329
4330multiclass StoreUnscaled<bits<2> sz, bit V, bits<2> opc, DAGOperand regtype,
4331                         string asm, list<dag> pattern> {
4332  let AddedComplexity = 1 in // try this before StoreUI
4333  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4334                               (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4335                               asm, pattern>,
4336          Sched<[WriteST]>;
4337
4338  def : InstAlias<asm # "\t$Rt, [$Rn]",
4339                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4340}
4341
4342multiclass PrefetchUnscaled<bits<2> sz, bit V, bits<2> opc, string asm,
4343                            list<dag> pat> {
4344  let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4345  def i : BaseLoadStoreUnscale<sz, V, opc, (outs),
4346                               (ins prfop:$Rt, GPR64sp:$Rn, simm9:$offset),
4347                               asm, pat>,
4348          Sched<[WriteLD]>;
4349
4350  def : InstAlias<asm # "\t$Rt, [$Rn]",
4351                  (!cast<Instruction>(NAME # "i") prfop:$Rt, GPR64sp:$Rn, 0)>;
4352}
4353
4354//---
4355// Load/store unscaled immediate, unprivileged
4356//---
4357
4358class BaseLoadStoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4359                                dag oops, dag iops, string asm>
4360    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]", "", []> {
4361  bits<5> Rt;
4362  bits<5> Rn;
4363  bits<9> offset;
4364  let Inst{31-30} = sz;
4365  let Inst{29-27} = 0b111;
4366  let Inst{26}    = V;
4367  let Inst{25-24} = 0b00;
4368  let Inst{23-22} = opc;
4369  let Inst{21}    = 0;
4370  let Inst{20-12} = offset;
4371  let Inst{11-10} = 0b10;
4372  let Inst{9-5}   = Rn;
4373  let Inst{4-0}   = Rt;
4374
4375  let DecoderMethod = "DecodeSignedLdStInstruction";
4376}
4377
4378multiclass LoadUnprivileged<bits<2> sz, bit V, bits<2> opc,
4379                            RegisterClass regtype, string asm> {
4380  let mayStore = 0, mayLoad = 1, hasSideEffects = 0 in
4381  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs regtype:$Rt),
4382                                    (ins GPR64sp:$Rn, simm9:$offset), asm>,
4383          Sched<[WriteLD]>;
4384
4385  def : InstAlias<asm # "\t$Rt, [$Rn]",
4386                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4387}
4388
4389multiclass StoreUnprivileged<bits<2> sz, bit V, bits<2> opc,
4390                             RegisterClass regtype, string asm> {
4391  let mayStore = 1, mayLoad = 0, hasSideEffects = 0 in
4392  def i : BaseLoadStoreUnprivileged<sz, V, opc, (outs),
4393                                 (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4394                                 asm>,
4395          Sched<[WriteST]>;
4396
4397  def : InstAlias<asm # "\t$Rt, [$Rn]",
4398                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
4399}
4400
4401//---
4402// Load/store pre-indexed
4403//---
4404
4405class BaseLoadStorePreIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4406                          string asm, string cstr, list<dag> pat>
4407    : I<oops, iops, asm, "\t$Rt, [$Rn, $offset]!", cstr, pat> {
4408  bits<5> Rt;
4409  bits<5> Rn;
4410  bits<9> offset;
4411  let Inst{31-30} = sz;
4412  let Inst{29-27} = 0b111;
4413  let Inst{26}    = V;
4414  let Inst{25-24} = 0;
4415  let Inst{23-22} = opc;
4416  let Inst{21}    = 0;
4417  let Inst{20-12} = offset;
4418  let Inst{11-10} = 0b11;
4419  let Inst{9-5}   = Rn;
4420  let Inst{4-0}   = Rt;
4421
4422  let DecoderMethod = "DecodeSignedLdStInstruction";
4423}
4424
4425let hasSideEffects = 0 in {
4426let mayStore = 0, mayLoad = 1 in
4427class LoadPreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4428             string asm>
4429    : BaseLoadStorePreIdx<sz, V, opc,
4430                     (outs GPR64sp:$wback, regtype:$Rt),
4431                     (ins GPR64sp:$Rn, simm9:$offset), asm,
4432                     "$Rn = $wback,@earlyclobber $wback", []>,
4433      Sched<[WriteAdr, WriteLD]>;
4434
4435let mayStore = 1, mayLoad = 0 in
4436class StorePreIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4437                  string asm, SDPatternOperator storeop, ValueType Ty>
4438    : BaseLoadStorePreIdx<sz, V, opc,
4439                      (outs GPR64sp:$wback),
4440                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4441                      asm, "$Rn = $wback,@earlyclobber $wback",
4442      [(set GPR64sp:$wback,
4443            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4444      Sched<[WriteAdr, WriteST]>;
4445} // hasSideEffects = 0
4446
4447//---
4448// Load/store post-indexed
4449//---
4450
4451class BaseLoadStorePostIdx<bits<2> sz, bit V, bits<2> opc, dag oops, dag iops,
4452                          string asm, string cstr, list<dag> pat>
4453    : I<oops, iops, asm, "\t$Rt, [$Rn], $offset", cstr, pat> {
4454  bits<5> Rt;
4455  bits<5> Rn;
4456  bits<9> offset;
4457  let Inst{31-30} = sz;
4458  let Inst{29-27} = 0b111;
4459  let Inst{26}    = V;
4460  let Inst{25-24} = 0b00;
4461  let Inst{23-22} = opc;
4462  let Inst{21}    = 0b0;
4463  let Inst{20-12} = offset;
4464  let Inst{11-10} = 0b01;
4465  let Inst{9-5}   = Rn;
4466  let Inst{4-0}   = Rt;
4467
4468  let DecoderMethod = "DecodeSignedLdStInstruction";
4469}
4470
4471let hasSideEffects = 0 in {
4472let mayStore = 0, mayLoad = 1 in
4473class LoadPostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4474             string asm>
4475    : BaseLoadStorePostIdx<sz, V, opc,
4476                      (outs GPR64sp:$wback, regtype:$Rt),
4477                      (ins GPR64sp:$Rn, simm9:$offset),
4478                      asm, "$Rn = $wback,@earlyclobber $wback", []>,
4479      Sched<[WriteAdr, WriteLD]>;
4480
4481let mayStore = 1, mayLoad = 0 in
4482class StorePostIdx<bits<2> sz, bit V, bits<2> opc, RegisterOperand regtype,
4483                   string asm, SDPatternOperator storeop, ValueType Ty>
4484    : BaseLoadStorePostIdx<sz, V, opc,
4485                      (outs GPR64sp:$wback),
4486                      (ins regtype:$Rt, GPR64sp:$Rn, simm9:$offset),
4487                       asm, "$Rn = $wback,@earlyclobber $wback",
4488      [(set GPR64sp:$wback,
4489            (storeop (Ty regtype:$Rt), GPR64sp:$Rn, simm9:$offset))]>,
4490    Sched<[WriteAdr, WriteST]>;
4491} // hasSideEffects = 0
4492
4493
4494//---
4495// Load/store pair
4496//---
4497
4498// (indexed, offset)
4499
4500class BaseLoadStorePairOffset<bits<2> opc, bit V, bit L, dag oops, dag iops,
4501                              string asm>
4502    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4503  bits<5> Rt;
4504  bits<5> Rt2;
4505  bits<5> Rn;
4506  bits<7> offset;
4507  let Inst{31-30} = opc;
4508  let Inst{29-27} = 0b101;
4509  let Inst{26}    = V;
4510  let Inst{25-23} = 0b010;
4511  let Inst{22}    = L;
4512  let Inst{21-15} = offset;
4513  let Inst{14-10} = Rt2;
4514  let Inst{9-5}   = Rn;
4515  let Inst{4-0}   = Rt;
4516
4517  let DecoderMethod = "DecodePairLdStInstruction";
4518}
4519
4520multiclass LoadPairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4521                          Operand indextype, string asm> {
4522  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4523  def i : BaseLoadStorePairOffset<opc, V, 1,
4524                                  (outs regtype:$Rt, regtype:$Rt2),
4525                                  (ins GPR64sp:$Rn, indextype:$offset), asm>,
4526          Sched<[WriteLD, WriteLDHi]>;
4527
4528  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4529                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4530                                                  GPR64sp:$Rn, 0)>;
4531}
4532
4533
4534multiclass StorePairOffset<bits<2> opc, bit V, RegisterOperand regtype,
4535                           Operand indextype, string asm> {
4536  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in
4537  def i : BaseLoadStorePairOffset<opc, V, 0, (outs),
4538                                  (ins regtype:$Rt, regtype:$Rt2,
4539                                       GPR64sp:$Rn, indextype:$offset),
4540                                  asm>,
4541          Sched<[WriteSTP]>;
4542
4543  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4544                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4545                                                  GPR64sp:$Rn, 0)>;
4546}
4547
4548// (pre-indexed)
4549class BaseLoadStorePairPreIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4550                              string asm>
4551    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]!", "$Rn = $wback,@earlyclobber $wback", []> {
4552  bits<5> Rt;
4553  bits<5> Rt2;
4554  bits<5> Rn;
4555  bits<7> offset;
4556  let Inst{31-30} = opc;
4557  let Inst{29-27} = 0b101;
4558  let Inst{26}    = V;
4559  let Inst{25-23} = 0b011;
4560  let Inst{22}    = L;
4561  let Inst{21-15} = offset;
4562  let Inst{14-10} = Rt2;
4563  let Inst{9-5}   = Rn;
4564  let Inst{4-0}   = Rt;
4565
4566  let DecoderMethod = "DecodePairLdStInstruction";
4567}
4568
4569let hasSideEffects = 0 in {
4570let mayStore = 0, mayLoad = 1 in
4571class LoadPairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4572                     Operand indextype, string asm>
4573    : BaseLoadStorePairPreIdx<opc, V, 1,
4574                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4575                              (ins GPR64sp:$Rn, indextype:$offset), asm>,
4576      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4577
4578let mayStore = 1, mayLoad = 0 in
4579class StorePairPreIdx<bits<2> opc, bit V, RegisterOperand regtype,
4580                      Operand indextype, string asm>
4581    : BaseLoadStorePairPreIdx<opc, V, 0, (outs GPR64sp:$wback),
4582                             (ins regtype:$Rt, regtype:$Rt2,
4583                                  GPR64sp:$Rn, indextype:$offset),
4584                             asm>,
4585      Sched<[WriteAdr, WriteSTP]>;
4586} // hasSideEffects = 0
4587
4588// (post-indexed)
4589
4590class BaseLoadStorePairPostIdx<bits<2> opc, bit V, bit L, dag oops, dag iops,
4591                              string asm>
4592    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn], $offset", "$Rn = $wback,@earlyclobber $wback", []> {
4593  bits<5> Rt;
4594  bits<5> Rt2;
4595  bits<5> Rn;
4596  bits<7> offset;
4597  let Inst{31-30} = opc;
4598  let Inst{29-27} = 0b101;
4599  let Inst{26}    = V;
4600  let Inst{25-23} = 0b001;
4601  let Inst{22}    = L;
4602  let Inst{21-15} = offset;
4603  let Inst{14-10} = Rt2;
4604  let Inst{9-5}   = Rn;
4605  let Inst{4-0}   = Rt;
4606
4607  let DecoderMethod = "DecodePairLdStInstruction";
4608}
4609
4610let hasSideEffects = 0 in {
4611let mayStore = 0, mayLoad = 1 in
4612class LoadPairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4613                      Operand idxtype, string asm>
4614    : BaseLoadStorePairPostIdx<opc, V, 1,
4615                              (outs GPR64sp:$wback, regtype:$Rt, regtype:$Rt2),
4616                              (ins GPR64sp:$Rn, idxtype:$offset), asm>,
4617      Sched<[WriteAdr, WriteLD, WriteLDHi]>;
4618
4619let mayStore = 1, mayLoad = 0 in
4620class StorePairPostIdx<bits<2> opc, bit V, RegisterOperand regtype,
4621                       Operand idxtype, string asm>
4622    : BaseLoadStorePairPostIdx<opc, V, 0, (outs GPR64sp:$wback),
4623                             (ins regtype:$Rt, regtype:$Rt2,
4624                                  GPR64sp:$Rn, idxtype:$offset),
4625                             asm>,
4626      Sched<[WriteAdr, WriteSTP]>;
4627} // hasSideEffects = 0
4628
4629//  (no-allocate)
4630
4631class BaseLoadStorePairNoAlloc<bits<2> opc, bit V, bit L, dag oops, dag iops,
4632                              string asm>
4633    : I<oops, iops, asm, "\t$Rt, $Rt2, [$Rn, $offset]", "", []> {
4634  bits<5> Rt;
4635  bits<5> Rt2;
4636  bits<5> Rn;
4637  bits<7> offset;
4638  let Inst{31-30} = opc;
4639  let Inst{29-27} = 0b101;
4640  let Inst{26}    = V;
4641  let Inst{25-23} = 0b000;
4642  let Inst{22}    = L;
4643  let Inst{21-15} = offset;
4644  let Inst{14-10} = Rt2;
4645  let Inst{9-5}   = Rn;
4646  let Inst{4-0}   = Rt;
4647
4648  let DecoderMethod = "DecodePairLdStInstruction";
4649}
4650
4651multiclass LoadPairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4652                           Operand indextype, string asm> {
4653  let hasSideEffects = 0, mayStore = 0, mayLoad = 1 in
4654  def i : BaseLoadStorePairNoAlloc<opc, V, 1,
4655                                   (outs regtype:$Rt, regtype:$Rt2),
4656                                   (ins GPR64sp:$Rn, indextype:$offset), asm>,
4657          Sched<[WriteLD, WriteLDHi]>;
4658
4659
4660  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4661                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4662                                                  GPR64sp:$Rn, 0)>;
4663}
4664
4665multiclass StorePairNoAlloc<bits<2> opc, bit V, DAGOperand regtype,
4666                      Operand indextype, string asm> {
4667  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in
4668  def i : BaseLoadStorePairNoAlloc<opc, V, 0, (outs),
4669                                   (ins regtype:$Rt, regtype:$Rt2,
4670                                        GPR64sp:$Rn, indextype:$offset),
4671                                   asm>,
4672          Sched<[WriteSTP]>;
4673
4674  def : InstAlias<asm # "\t$Rt, $Rt2, [$Rn]",
4675                  (!cast<Instruction>(NAME # "i") regtype:$Rt, regtype:$Rt2,
4676                                                  GPR64sp:$Rn, 0)>;
4677}
4678
4679//---
4680// Load/store exclusive
4681//---
4682
4683// True exclusive operations write to and/or read from the system's exclusive
4684// monitors, which as far as a compiler is concerned can be modelled as a
4685// random shared memory address. Hence LoadExclusive mayStore.
4686//
4687// Since these instructions have the undefined register bits set to 1 in
4688// their canonical form, we need a post encoder method to set those bits
4689// to 1 when encoding these instructions. We do this using the
4690// fixLoadStoreExclusive function. This function has template parameters:
4691//
4692// fixLoadStoreExclusive<int hasRs, int hasRt2>
4693//
4694// hasRs indicates that the instruction uses the Rs field, so we won't set
4695// it to 1 (and the same for Rt2). We don't need template parameters for
4696// the other register fields since Rt and Rn are always used.
4697//
4698let hasSideEffects = 1, mayLoad = 1, mayStore = 1 in
4699class BaseLoadStoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4700                             dag oops, dag iops, string asm, string operands>
4701    : I<oops, iops, asm, operands, "", []> {
4702  let Inst{31-30} = sz;
4703  let Inst{29-24} = 0b001000;
4704  let Inst{23}    = o2;
4705  let Inst{22}    = L;
4706  let Inst{21}    = o1;
4707  let Inst{15}    = o0;
4708
4709  let DecoderMethod = "DecodeExclusiveLdStInstruction";
4710}
4711
4712// Neither Rs nor Rt2 operands.
4713class LoadStoreExclusiveSimple<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4714                               dag oops, dag iops, string asm, string operands>
4715    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, oops, iops, asm, operands> {
4716  bits<5> Rt;
4717  bits<5> Rn;
4718  let Inst{20-16} = 0b11111;
4719  let Unpredictable{20-16} = 0b11111;
4720  let Inst{14-10} = 0b11111;
4721  let Unpredictable{14-10} = 0b11111;
4722  let Inst{9-5} = Rn;
4723  let Inst{4-0} = Rt;
4724
4725  let PostEncoderMethod = "fixLoadStoreExclusive<0,0>";
4726}
4727
4728// Simple load acquires don't set the exclusive monitor
4729let mayLoad = 1, mayStore = 0 in
4730class LoadAcquire<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4731                  RegisterClass regtype, string asm>
4732    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4733                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4734      Sched<[WriteLD]>;
4735
4736class LoadExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4737                    RegisterClass regtype, string asm>
4738    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs regtype:$Rt),
4739                               (ins GPR64sp0:$Rn), asm, "\t$Rt, [$Rn]">,
4740      Sched<[WriteLD]>;
4741
4742class LoadExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4743                       RegisterClass regtype, string asm>
4744    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4745                             (outs regtype:$Rt, regtype:$Rt2),
4746                             (ins GPR64sp0:$Rn), asm,
4747                             "\t$Rt, $Rt2, [$Rn]">,
4748      Sched<[WriteLD, WriteLDHi]> {
4749  bits<5> Rt;
4750  bits<5> Rt2;
4751  bits<5> Rn;
4752  let Inst{14-10} = Rt2;
4753  let Inst{9-5} = Rn;
4754  let Inst{4-0} = Rt;
4755
4756  let PostEncoderMethod = "fixLoadStoreExclusive<0,1>";
4757}
4758
4759// Simple store release operations do not check the exclusive monitor.
4760let mayLoad = 0, mayStore = 1 in
4761class StoreRelease<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4762                   RegisterClass regtype, string asm>
4763    : LoadStoreExclusiveSimple<sz, o2, L, o1, o0, (outs),
4764                               (ins regtype:$Rt, GPR64sp:$Rn),
4765                               asm, "\t$Rt, [$Rn]">,
4766      Sched<[WriteST]>;
4767
4768let mayLoad = 1, mayStore = 1 in
4769class StoreExclusive<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4770                     RegisterClass regtype, string asm>
4771    : BaseLoadStoreExclusive<sz, o2, L, o1, o0, (outs GPR32:$Ws),
4772                             (ins regtype:$Rt, GPR64sp0:$Rn),
4773                             asm, "\t$Ws, $Rt, [$Rn]">,
4774      Sched<[WriteSTX]> {
4775  bits<5> Ws;
4776  bits<5> Rt;
4777  bits<5> Rn;
4778  let Inst{20-16} = Ws;
4779  let Inst{9-5} = Rn;
4780  let Inst{4-0} = Rt;
4781
4782  let Constraints = "@earlyclobber $Ws";
4783  let PostEncoderMethod = "fixLoadStoreExclusive<1,0>";
4784}
4785
4786class StoreExclusivePair<bits<2> sz, bit o2, bit L, bit o1, bit o0,
4787                         RegisterClass regtype, string asm>
4788    : BaseLoadStoreExclusive<sz, o2, L, o1, o0,
4789                             (outs GPR32:$Ws),
4790                             (ins regtype:$Rt, regtype:$Rt2, GPR64sp0:$Rn),
4791                              asm, "\t$Ws, $Rt, $Rt2, [$Rn]">,
4792      Sched<[WriteSTX]> {
4793  bits<5> Ws;
4794  bits<5> Rt;
4795  bits<5> Rt2;
4796  bits<5> Rn;
4797  let Inst{20-16} = Ws;
4798  let Inst{14-10} = Rt2;
4799  let Inst{9-5} = Rn;
4800  let Inst{4-0} = Rt;
4801
4802  let Constraints = "@earlyclobber $Ws";
4803}
4804
4805// Armv8.5-A Memory Tagging Extension
4806class BaseMemTag<bits<2> opc1, bits<2> opc2, string asm_insn,
4807                 string asm_opnds, string cstr, dag oops, dag iops>
4808    : I<oops, iops, asm_insn, asm_opnds, cstr, []>,
4809      Sched<[]> {
4810  bits<5> Rn;
4811
4812  let Inst{31-24} = 0b11011001;
4813  let Inst{23-22} = opc1;
4814  let Inst{21}    = 1;
4815  // Inst{20-12} defined by subclass
4816  let Inst{11-10} = opc2;
4817  let Inst{9-5}   = Rn;
4818  // Inst{4-0} defined by subclass
4819}
4820
4821class MemTagVector<bit Load, string asm_insn, string asm_opnds,
4822                   dag oops, dag iops>
4823    : BaseMemTag<{0b1, Load}, 0b00, asm_insn, asm_opnds,
4824                  "", oops, iops> {
4825  bits<5> Rt;
4826
4827  let Inst{20-12} = 0b000000000;
4828  let Inst{4-0}   = Rt;
4829
4830  let mayLoad = Load;
4831}
4832
4833class MemTagLoad<string asm_insn, string asm_opnds>
4834    : BaseMemTag<0b01, 0b00, asm_insn, asm_opnds, "$Rt = $wback",
4835                 (outs GPR64:$wback),
4836                 (ins GPR64:$Rt, GPR64sp:$Rn, simm9s16:$offset)> {
4837  bits<5> Rt;
4838  bits<9> offset;
4839
4840  let Inst{20-12} = offset;
4841  let Inst{4-0}   = Rt;
4842
4843  let mayLoad = 1;
4844}
4845
4846class BaseMemTagStore<bits<2> opc1, bits<2> opc2, string asm_insn,
4847                     string asm_opnds, string cstr, dag oops, dag iops>
4848    : BaseMemTag<opc1, opc2, asm_insn, asm_opnds, cstr, oops, iops> {
4849  bits<5> Rt;
4850  bits<9> offset;
4851
4852  let Inst{20-12} = offset;
4853  let Inst{4-0}   = Rt;
4854
4855  let mayStore = 1;
4856}
4857
4858multiclass MemTagStore<bits<2> opc1, string insn> {
4859  def i :
4860    BaseMemTagStore<opc1, 0b10, insn, "\t$Rt, [$Rn, $offset]", "",
4861                    (outs), (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4862  def PreIndex :
4863    BaseMemTagStore<opc1, 0b11, insn, "\t$Rt, [$Rn, $offset]!",
4864                    "$Rn = $wback",
4865                    (outs GPR64sp:$wback),
4866                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4867  def PostIndex :
4868    BaseMemTagStore<opc1, 0b01, insn, "\t$Rt, [$Rn], $offset",
4869                    "$Rn = $wback",
4870                    (outs GPR64sp:$wback),
4871                    (ins GPR64sp:$Rt, GPR64sp:$Rn, simm9s16:$offset)>;
4872
4873  def : InstAlias<insn # "\t$Rt, [$Rn]",
4874                  (!cast<Instruction>(NAME # "i") GPR64sp:$Rt, GPR64sp:$Rn, 0)>;
4875}
4876
4877//---
4878// Exception generation
4879//---
4880
4881let mayLoad = 0, mayStore = 0, hasSideEffects = 1 in
4882class ExceptionGeneration<bits<3> op1, bits<2> ll, string asm,
4883                          list<dag> pattern = []>
4884    : I<(outs), (ins timm32_0_65535:$imm), asm, "\t$imm", "", pattern>,
4885      Sched<[WriteSys]> {
4886  bits<16> imm;
4887  let Inst{31-24} = 0b11010100;
4888  let Inst{23-21} = op1;
4889  let Inst{20-5}  = imm;
4890  let Inst{4-2}   = 0b000;
4891  let Inst{1-0}   = ll;
4892}
4893
4894//---
4895// UDF : Permanently UNDEFINED instructions.  Format: Opc = 0x0000, 16 bit imm.
4896//--
4897let hasSideEffects = 1, isTrap = 1, mayLoad = 0, mayStore = 0 in {
4898class UDFType<bits<16> opc, string asm>
4899  : I<(outs), (ins uimm16:$imm),
4900       asm, "\t$imm", "", []>,
4901    Sched<[]> {
4902  bits<16> imm;
4903  let Inst{31-16} = opc;
4904  let Inst{15-0} = imm;
4905}
4906}
4907let Predicates = [HasFPARMv8] in {
4908
4909//---
4910// Floating point to integer conversion
4911//---
4912
4913let mayRaiseFPException = 1, Uses = [FPCR] in
4914class BaseFPToIntegerUnscaled<bits<2> type, bits<2> rmode, bits<3> opcode,
4915                      RegisterClass srcType, RegisterClass dstType,
4916                      string asm, list<dag> pattern>
4917    : I<(outs dstType:$Rd), (ins srcType:$Rn),
4918         asm, "\t$Rd, $Rn", "", pattern>,
4919      Sched<[WriteFCvt]> {
4920  bits<5> Rd;
4921  bits<5> Rn;
4922  let Inst{30-29} = 0b00;
4923  let Inst{28-24} = 0b11110;
4924  let Inst{23-22} = type;
4925  let Inst{21}    = 1;
4926  let Inst{20-19} = rmode;
4927  let Inst{18-16} = opcode;
4928  let Inst{15-10} = 0;
4929  let Inst{9-5}   = Rn;
4930  let Inst{4-0}   = Rd;
4931}
4932
4933let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
4934class BaseFPToInteger<bits<2> type, bits<2> rmode, bits<3> opcode,
4935                      RegisterClass srcType, RegisterClass dstType,
4936                      Operand immType, string asm, list<dag> pattern>
4937    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
4938         asm, "\t$Rd, $Rn, $scale", "", pattern>,
4939      Sched<[WriteFCvt]> {
4940  bits<5> Rd;
4941  bits<5> Rn;
4942  bits<6> scale;
4943  let Inst{30-29} = 0b00;
4944  let Inst{28-24} = 0b11110;
4945  let Inst{23-22} = type;
4946  let Inst{21}    = 0;
4947  let Inst{20-19} = rmode;
4948  let Inst{18-16} = opcode;
4949  let Inst{15-10} = scale;
4950  let Inst{9-5}   = Rn;
4951  let Inst{4-0}   = Rd;
4952}
4953
4954multiclass FPToIntegerUnscaled<bits<2> rmode, bits<3> opcode, string asm,
4955           SDPatternOperator OpN> {
4956  // Unscaled half-precision to 32-bit
4957  def UWHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR32, asm,
4958                                     [(set GPR32:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4959    let Inst{31} = 0; // 32-bit GPR flag
4960    let Predicates = [HasFullFP16];
4961  }
4962
4963  // Unscaled half-precision to 64-bit
4964  def UXHr : BaseFPToIntegerUnscaled<0b11, rmode, opcode, FPR16, GPR64, asm,
4965                                     [(set GPR64:$Rd, (OpN (f16 FPR16:$Rn)))]> {
4966    let Inst{31} = 1; // 64-bit GPR flag
4967    let Predicates = [HasFullFP16];
4968  }
4969
4970  // Unscaled single-precision to 32-bit
4971  def UWSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR32, asm,
4972                                     [(set GPR32:$Rd, (OpN FPR32:$Rn))]> {
4973    let Inst{31} = 0; // 32-bit GPR flag
4974  }
4975
4976  // Unscaled single-precision to 64-bit
4977  def UXSr : BaseFPToIntegerUnscaled<0b00, rmode, opcode, FPR32, GPR64, asm,
4978                                     [(set GPR64:$Rd, (OpN FPR32:$Rn))]> {
4979    let Inst{31} = 1; // 64-bit GPR flag
4980  }
4981
4982  // Unscaled double-precision to 32-bit
4983  def UWDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR32, asm,
4984                                     [(set GPR32:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4985    let Inst{31} = 0; // 32-bit GPR flag
4986  }
4987
4988  // Unscaled double-precision to 64-bit
4989  def UXDr : BaseFPToIntegerUnscaled<0b01, rmode, opcode, FPR64, GPR64, asm,
4990                                     [(set GPR64:$Rd, (OpN (f64 FPR64:$Rn)))]> {
4991    let Inst{31} = 1; // 64-bit GPR flag
4992  }
4993}
4994
4995multiclass FPToIntegerScaled<bits<2> rmode, bits<3> opcode, string asm,
4996                             SDPatternOperator OpN> {
4997  // Scaled half-precision to 32-bit
4998  def SWHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR32,
4999                              fixedpoint_f16_i32, asm,
5000              [(set GPR32:$Rd, (OpN (fmul (f16 FPR16:$Rn),
5001                                          fixedpoint_f16_i32:$scale)))]> {
5002    let Inst{31} = 0; // 32-bit GPR flag
5003    let scale{5} = 1;
5004    let Predicates = [HasFullFP16];
5005  }
5006
5007  // Scaled half-precision to 64-bit
5008  def SXHri : BaseFPToInteger<0b11, rmode, opcode, FPR16, GPR64,
5009                              fixedpoint_f16_i64, asm,
5010              [(set GPR64:$Rd, (OpN (fmul (f16 FPR16:$Rn),
5011                                          fixedpoint_f16_i64:$scale)))]> {
5012    let Inst{31} = 1; // 64-bit GPR flag
5013    let Predicates = [HasFullFP16];
5014  }
5015
5016  // Scaled single-precision to 32-bit
5017  def SWSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR32,
5018                              fixedpoint_f32_i32, asm,
5019              [(set GPR32:$Rd, (OpN (fmul FPR32:$Rn,
5020                                          fixedpoint_f32_i32:$scale)))]> {
5021    let Inst{31} = 0; // 32-bit GPR flag
5022    let scale{5} = 1;
5023  }
5024
5025  // Scaled single-precision to 64-bit
5026  def SXSri : BaseFPToInteger<0b00, rmode, opcode, FPR32, GPR64,
5027                              fixedpoint_f32_i64, asm,
5028              [(set GPR64:$Rd, (OpN (fmul FPR32:$Rn,
5029                                          fixedpoint_f32_i64:$scale)))]> {
5030    let Inst{31} = 1; // 64-bit GPR flag
5031  }
5032
5033  // Scaled double-precision to 32-bit
5034  def SWDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR32,
5035                              fixedpoint_f64_i32, asm,
5036              [(set GPR32:$Rd, (OpN (fmul FPR64:$Rn,
5037                                          fixedpoint_f64_i32:$scale)))]> {
5038    let Inst{31} = 0; // 32-bit GPR flag
5039    let scale{5} = 1;
5040  }
5041
5042  // Scaled double-precision to 64-bit
5043  def SXDri : BaseFPToInteger<0b01, rmode, opcode, FPR64, GPR64,
5044                              fixedpoint_f64_i64, asm,
5045              [(set GPR64:$Rd, (OpN (fmul FPR64:$Rn,
5046                                          fixedpoint_f64_i64:$scale)))]> {
5047    let Inst{31} = 1; // 64-bit GPR flag
5048  }
5049}
5050
5051//---
5052// Integer to floating point conversion
5053//---
5054
5055let mayStore = 0, mayLoad = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5056class BaseIntegerToFP<bit isUnsigned,
5057                      RegisterClass srcType, RegisterClass dstType,
5058                      Operand immType, string asm, list<dag> pattern>
5059    : I<(outs dstType:$Rd), (ins srcType:$Rn, immType:$scale),
5060         asm, "\t$Rd, $Rn, $scale", "", pattern>,
5061      Sched<[WriteFCvt]> {
5062  bits<5> Rd;
5063  bits<5> Rn;
5064  bits<6> scale;
5065  let Inst{30-24} = 0b0011110;
5066  let Inst{21-17} = 0b00001;
5067  let Inst{16}    = isUnsigned;
5068  let Inst{15-10} = scale;
5069  let Inst{9-5}   = Rn;
5070  let Inst{4-0}   = Rd;
5071}
5072
5073let mayRaiseFPException = 1, Uses = [FPCR] in
5074class BaseIntegerToFPUnscaled<bit isUnsigned,
5075                      RegisterClass srcType, RegisterClass dstType,
5076                      ValueType dvt, string asm, SDPatternOperator node>
5077    : I<(outs dstType:$Rd), (ins srcType:$Rn),
5078         asm, "\t$Rd, $Rn", "", [(set (dvt dstType:$Rd), (node srcType:$Rn))]>,
5079      Sched<[WriteFCvt]> {
5080  bits<5> Rd;
5081  bits<5> Rn;
5082  bits<6> scale;
5083  let Inst{30-24} = 0b0011110;
5084  let Inst{21-17} = 0b10001;
5085  let Inst{16}    = isUnsigned;
5086  let Inst{15-10} = 0b000000;
5087  let Inst{9-5}   = Rn;
5088  let Inst{4-0}   = Rd;
5089}
5090
5091multiclass IntegerToFP<bit isUnsigned, string asm, SDPatternOperator node> {
5092  // Unscaled
5093  def UWHri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR16, f16, asm, node> {
5094    let Inst{31} = 0; // 32-bit GPR flag
5095    let Inst{23-22} = 0b11; // 16-bit FPR flag
5096    let Predicates = [HasFullFP16];
5097  }
5098
5099  def UWSri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR32, f32, asm, node> {
5100    let Inst{31} = 0; // 32-bit GPR flag
5101    let Inst{23-22} = 0b00; // 32-bit FPR flag
5102  }
5103
5104  def UWDri: BaseIntegerToFPUnscaled<isUnsigned, GPR32, FPR64, f64, asm, node> {
5105    let Inst{31} = 0; // 32-bit GPR flag
5106    let Inst{23-22} = 0b01; // 64-bit FPR flag
5107  }
5108
5109  def UXHri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR16, f16, asm, node> {
5110    let Inst{31} = 1; // 64-bit GPR flag
5111    let Inst{23-22} = 0b11; // 16-bit FPR flag
5112    let Predicates = [HasFullFP16];
5113  }
5114
5115  def UXSri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR32, f32, asm, node> {
5116    let Inst{31} = 1; // 64-bit GPR flag
5117    let Inst{23-22} = 0b00; // 32-bit FPR flag
5118  }
5119
5120  def UXDri: BaseIntegerToFPUnscaled<isUnsigned, GPR64, FPR64, f64, asm, node> {
5121    let Inst{31} = 1; // 64-bit GPR flag
5122    let Inst{23-22} = 0b01; // 64-bit FPR flag
5123  }
5124
5125  // Scaled
5126  def SWHri: BaseIntegerToFP<isUnsigned, GPR32, FPR16, fixedpoint_recip_f16_i32, asm,
5127                             [(set (f16 FPR16:$Rd),
5128                                   (fmul (node GPR32:$Rn),
5129                                         fixedpoint_recip_f16_i32:$scale))]> {
5130    let Inst{31} = 0; // 32-bit GPR flag
5131    let Inst{23-22} = 0b11; // 16-bit FPR flag
5132    let scale{5} = 1;
5133    let Predicates = [HasFullFP16];
5134  }
5135
5136  def SWSri: BaseIntegerToFP<isUnsigned, GPR32, FPR32, fixedpoint_recip_f32_i32, asm,
5137                             [(set FPR32:$Rd,
5138                                   (fmul (node GPR32:$Rn),
5139                                         fixedpoint_recip_f32_i32:$scale))]> {
5140    let Inst{31} = 0; // 32-bit GPR flag
5141    let Inst{23-22} = 0b00; // 32-bit FPR flag
5142    let scale{5} = 1;
5143  }
5144
5145  def SWDri: BaseIntegerToFP<isUnsigned, GPR32, FPR64, fixedpoint_recip_f64_i32, asm,
5146                             [(set FPR64:$Rd,
5147                                   (fmul (node GPR32:$Rn),
5148                                         fixedpoint_recip_f64_i32:$scale))]> {
5149    let Inst{31} = 0; // 32-bit GPR flag
5150    let Inst{23-22} = 0b01; // 64-bit FPR flag
5151    let scale{5} = 1;
5152  }
5153
5154  def SXHri: BaseIntegerToFP<isUnsigned, GPR64, FPR16, fixedpoint_recip_f16_i64, asm,
5155                             [(set (f16 FPR16:$Rd),
5156                                   (fmul (node GPR64:$Rn),
5157                                         fixedpoint_recip_f16_i64:$scale))]> {
5158    let Inst{31} = 1; // 64-bit GPR flag
5159    let Inst{23-22} = 0b11; // 16-bit FPR flag
5160    let Predicates = [HasFullFP16];
5161  }
5162
5163  def SXSri: BaseIntegerToFP<isUnsigned, GPR64, FPR32, fixedpoint_recip_f32_i64, asm,
5164                             [(set FPR32:$Rd,
5165                                   (fmul (node GPR64:$Rn),
5166                                         fixedpoint_recip_f32_i64:$scale))]> {
5167    let Inst{31} = 1; // 64-bit GPR flag
5168    let Inst{23-22} = 0b00; // 32-bit FPR flag
5169  }
5170
5171  def SXDri: BaseIntegerToFP<isUnsigned, GPR64, FPR64, fixedpoint_recip_f64_i64, asm,
5172                             [(set FPR64:$Rd,
5173                                   (fmul (node GPR64:$Rn),
5174                                         fixedpoint_recip_f64_i64:$scale))]> {
5175    let Inst{31} = 1; // 64-bit GPR flag
5176    let Inst{23-22} = 0b01; // 64-bit FPR flag
5177  }
5178}
5179
5180//---
5181// Unscaled integer <-> floating point conversion (i.e. FMOV)
5182//---
5183
5184let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5185class BaseUnscaledConversion<bits<2> rmode, bits<3> opcode,
5186                      RegisterClass srcType, RegisterClass dstType,
5187                      string asm>
5188    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "",
5189        // We use COPY_TO_REGCLASS for these bitconvert operations.
5190        // copyPhysReg() expands the resultant COPY instructions after
5191        // regalloc is done. This gives greater freedom for the allocator
5192        // and related passes (coalescing, copy propagation, et. al.) to
5193        // be more effective.
5194        [/*(set (dvt dstType:$Rd), (bitconvert (svt srcType:$Rn)))*/]>,
5195      Sched<[WriteFCopy]> {
5196  bits<5> Rd;
5197  bits<5> Rn;
5198  let Inst{30-24} = 0b0011110;
5199  let Inst{21}    = 1;
5200  let Inst{20-19} = rmode;
5201  let Inst{18-16} = opcode;
5202  let Inst{15-10} = 0b000000;
5203  let Inst{9-5}   = Rn;
5204  let Inst{4-0}   = Rd;
5205}
5206
5207let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5208class BaseUnscaledConversionToHigh<bits<2> rmode, bits<3> opcode,
5209                     RegisterClass srcType, RegisterOperand dstType, string asm,
5210                     string kind>
5211    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5212        "{\t$Rd"#kind#"$idx, $Rn|"#kind#"\t$Rd$idx, $Rn}", "", []>,
5213      Sched<[WriteFCopy]> {
5214  bits<5> Rd;
5215  bits<5> Rn;
5216  let Inst{30-23} = 0b00111101;
5217  let Inst{21}    = 1;
5218  let Inst{20-19} = rmode;
5219  let Inst{18-16} = opcode;
5220  let Inst{15-10} = 0b000000;
5221  let Inst{9-5}   = Rn;
5222  let Inst{4-0}   = Rd;
5223
5224  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5225}
5226
5227let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5228class BaseUnscaledConversionFromHigh<bits<2> rmode, bits<3> opcode,
5229                     RegisterOperand srcType, RegisterClass dstType, string asm,
5230                     string kind>
5231    : I<(outs dstType:$Rd), (ins srcType:$Rn, VectorIndex1:$idx), asm,
5232        "{\t$Rd, $Rn"#kind#"$idx|"#kind#"\t$Rd, $Rn$idx}", "", []>,
5233      Sched<[WriteFCopy]> {
5234  bits<5> Rd;
5235  bits<5> Rn;
5236  let Inst{30-23} = 0b00111101;
5237  let Inst{21}    = 1;
5238  let Inst{20-19} = rmode;
5239  let Inst{18-16} = opcode;
5240  let Inst{15-10} = 0b000000;
5241  let Inst{9-5}   = Rn;
5242  let Inst{4-0}   = Rd;
5243
5244  let DecoderMethod =  "DecodeFMOVLaneInstruction";
5245}
5246
5247
5248multiclass UnscaledConversion<string asm> {
5249  def WHr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR16, asm> {
5250    let Inst{31} = 0; // 32-bit GPR flag
5251    let Inst{23-22} = 0b11; // 16-bit FPR flag
5252    let Predicates = [HasFullFP16];
5253  }
5254
5255  def XHr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR16, asm> {
5256    let Inst{31} = 1; // 64-bit GPR flag
5257    let Inst{23-22} = 0b11; // 16-bit FPR flag
5258    let Predicates = [HasFullFP16];
5259  }
5260
5261  def WSr : BaseUnscaledConversion<0b00, 0b111, GPR32, FPR32, asm> {
5262    let Inst{31} = 0; // 32-bit GPR flag
5263    let Inst{23-22} = 0b00; // 32-bit FPR flag
5264  }
5265
5266  def XDr : BaseUnscaledConversion<0b00, 0b111, GPR64, FPR64, asm> {
5267    let Inst{31} = 1; // 64-bit GPR flag
5268    let Inst{23-22} = 0b01; // 64-bit FPR flag
5269  }
5270
5271  def HWr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR32, asm> {
5272    let Inst{31} = 0; // 32-bit GPR flag
5273    let Inst{23-22} = 0b11; // 16-bit FPR flag
5274    let Predicates = [HasFullFP16];
5275  }
5276
5277  def HXr : BaseUnscaledConversion<0b00, 0b110, FPR16, GPR64, asm> {
5278    let Inst{31} = 1; // 64-bit GPR flag
5279    let Inst{23-22} = 0b11; // 16-bit FPR flag
5280    let Predicates = [HasFullFP16];
5281  }
5282
5283  def SWr : BaseUnscaledConversion<0b00, 0b110, FPR32, GPR32, asm> {
5284    let Inst{31} = 0; // 32-bit GPR flag
5285    let Inst{23-22} = 0b00; // 32-bit FPR flag
5286  }
5287
5288  def DXr : BaseUnscaledConversion<0b00, 0b110, FPR64, GPR64, asm> {
5289    let Inst{31} = 1; // 64-bit GPR flag
5290    let Inst{23-22} = 0b01; // 64-bit FPR flag
5291  }
5292
5293  def XDHighr : BaseUnscaledConversionToHigh<0b01, 0b111, GPR64, V128,
5294                                             asm, ".d"> {
5295    let Inst{31} = 1;
5296    let Inst{22} = 0;
5297  }
5298
5299  def DXHighr : BaseUnscaledConversionFromHigh<0b01, 0b110, V128, GPR64,
5300                                               asm, ".d"> {
5301    let Inst{31} = 1;
5302    let Inst{22} = 0;
5303  }
5304}
5305
5306//---
5307// Floating point conversion
5308//---
5309
5310let mayRaiseFPException = 1, Uses = [FPCR] in
5311class BaseFPConversion<bits<2> type, bits<2> opcode, RegisterClass dstType,
5312                       RegisterClass srcType, string asm, list<dag> pattern>
5313    : I<(outs dstType:$Rd), (ins srcType:$Rn), asm, "\t$Rd, $Rn", "", pattern>,
5314      Sched<[WriteFCvt]> {
5315  bits<5> Rd;
5316  bits<5> Rn;
5317  let Inst{31-24} = 0b00011110;
5318  let Inst{23-22} = type;
5319  let Inst{21-17} = 0b10001;
5320  let Inst{16-15} = opcode;
5321  let Inst{14-10} = 0b10000;
5322  let Inst{9-5}   = Rn;
5323  let Inst{4-0}   = Rd;
5324}
5325
5326multiclass FPConversion<string asm> {
5327  // Double-precision to Half-precision
5328  def HDr : BaseFPConversion<0b01, 0b11, FPR16, FPR64, asm,
5329                             [(set (f16 FPR16:$Rd), (any_fpround FPR64:$Rn))]>;
5330
5331  // Double-precision to Single-precision
5332  def SDr : BaseFPConversion<0b01, 0b00, FPR32, FPR64, asm,
5333                             [(set FPR32:$Rd, (any_fpround FPR64:$Rn))]>;
5334
5335  // Half-precision to Double-precision
5336  def DHr : BaseFPConversion<0b11, 0b01, FPR64, FPR16, asm,
5337                             [(set FPR64:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5338
5339  // Half-precision to Single-precision
5340  def SHr : BaseFPConversion<0b11, 0b00, FPR32, FPR16, asm,
5341                             [(set FPR32:$Rd, (any_fpextend (f16 FPR16:$Rn)))]>;
5342
5343  // Single-precision to Double-precision
5344  def DSr : BaseFPConversion<0b00, 0b01, FPR64, FPR32, asm,
5345                             [(set FPR64:$Rd, (any_fpextend FPR32:$Rn))]>;
5346
5347  // Single-precision to Half-precision
5348  def HSr : BaseFPConversion<0b00, 0b11, FPR16, FPR32, asm,
5349                             [(set (f16 FPR16:$Rd), (any_fpround FPR32:$Rn))]>;
5350}
5351
5352//---
5353// Single operand floating point data processing
5354//---
5355
5356let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5357class BaseSingleOperandFPData<bits<6> opcode, RegisterClass regtype,
5358                              ValueType vt, string asm, SDPatternOperator node>
5359    : I<(outs regtype:$Rd), (ins regtype:$Rn), asm, "\t$Rd, $Rn", "",
5360         [(set (vt regtype:$Rd), (node (vt regtype:$Rn)))]>,
5361      Sched<[WriteF]> {
5362  bits<5> Rd;
5363  bits<5> Rn;
5364  let Inst{31-24} = 0b00011110;
5365  let Inst{21}    = 0b1;
5366  let Inst{20-15} = opcode;
5367  let Inst{14-10} = 0b10000;
5368  let Inst{9-5}   = Rn;
5369  let Inst{4-0}   = Rd;
5370}
5371
5372multiclass SingleOperandFPData<bits<4> opcode, string asm,
5373                               SDPatternOperator node = null_frag,
5374                               int fpexceptions = 1> {
5375  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
5376  def Hr : BaseSingleOperandFPData<{0b00,opcode}, FPR16, f16, asm, node> {
5377    let Inst{23-22} = 0b11; // 16-bit size flag
5378    let Predicates = [HasFullFP16];
5379  }
5380
5381  def Sr : BaseSingleOperandFPData<{0b00,opcode}, FPR32, f32, asm, node> {
5382    let Inst{23-22} = 0b00; // 32-bit size flag
5383  }
5384
5385  def Dr : BaseSingleOperandFPData<{0b00,opcode}, FPR64, f64, asm, node> {
5386    let Inst{23-22} = 0b01; // 64-bit size flag
5387  }
5388  }
5389}
5390
5391multiclass SingleOperandFPDataNoException<bits<4> opcode, string asm,
5392                                       SDPatternOperator node = null_frag>
5393    : SingleOperandFPData<opcode, asm, node, 0>;
5394
5395let mayRaiseFPException = 1, Uses = [FPCR] in
5396multiclass SingleOperandFPNo16<bits<6> opcode, string asm,
5397                  SDPatternOperator node = null_frag>{
5398
5399  def Sr : BaseSingleOperandFPData<opcode, FPR32, f32, asm, node> {
5400    let Inst{23-22} = 0b00; // 32-bit registers
5401  }
5402
5403  def Dr : BaseSingleOperandFPData<opcode, FPR64, f64, asm, node> {
5404    let Inst{23-22} = 0b01; // 64-bit registers
5405  }
5406}
5407
5408// FRInt[32|64][Z|N] instructions
5409multiclass FRIntNNT<bits<2> opcode, string asm, SDPatternOperator node = null_frag> :
5410      SingleOperandFPNo16<{0b0100,opcode}, asm, node>;
5411
5412//---
5413// Two operand floating point data processing
5414//---
5415
5416let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5417class BaseTwoOperandFPData<bits<4> opcode, RegisterClass regtype,
5418                           string asm, list<dag> pat>
5419    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm),
5420         asm, "\t$Rd, $Rn, $Rm", "", pat>,
5421      Sched<[WriteF]> {
5422  bits<5> Rd;
5423  bits<5> Rn;
5424  bits<5> Rm;
5425  let Inst{31-24} = 0b00011110;
5426  let Inst{21}    = 1;
5427  let Inst{20-16} = Rm;
5428  let Inst{15-12} = opcode;
5429  let Inst{11-10} = 0b10;
5430  let Inst{9-5}   = Rn;
5431  let Inst{4-0}   = Rd;
5432}
5433
5434multiclass TwoOperandFPData<bits<4> opcode, string asm,
5435                            SDPatternOperator node = null_frag> {
5436  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5437                         [(set (f16 FPR16:$Rd),
5438                               (node (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]> {
5439    let Inst{23-22} = 0b11; // 16-bit size flag
5440    let Predicates = [HasFullFP16];
5441  }
5442
5443  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5444                         [(set (f32 FPR32:$Rd),
5445                               (node (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]> {
5446    let Inst{23-22} = 0b00; // 32-bit size flag
5447  }
5448
5449  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5450                         [(set (f64 FPR64:$Rd),
5451                               (node (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]> {
5452    let Inst{23-22} = 0b01; // 64-bit size flag
5453  }
5454}
5455
5456multiclass TwoOperandFPDataNeg<bits<4> opcode, string asm,
5457                               SDPatternOperator node> {
5458  def Hrr : BaseTwoOperandFPData<opcode, FPR16, asm,
5459                  [(set (f16 FPR16:$Rd), (fneg (node (f16 FPR16:$Rn), (f16 FPR16:$Rm))))]> {
5460    let Inst{23-22} = 0b11; // 16-bit size flag
5461    let Predicates = [HasFullFP16];
5462  }
5463
5464  def Srr : BaseTwoOperandFPData<opcode, FPR32, asm,
5465                  [(set FPR32:$Rd, (fneg (node FPR32:$Rn, (f32 FPR32:$Rm))))]> {
5466    let Inst{23-22} = 0b00; // 32-bit size flag
5467  }
5468
5469  def Drr : BaseTwoOperandFPData<opcode, FPR64, asm,
5470                  [(set FPR64:$Rd, (fneg (node FPR64:$Rn, (f64 FPR64:$Rm))))]> {
5471    let Inst{23-22} = 0b01; // 64-bit size flag
5472  }
5473}
5474
5475
5476//---
5477// Three operand floating point data processing
5478//---
5479
5480let mayRaiseFPException = 1, Uses = [FPCR] in
5481class BaseThreeOperandFPData<bit isNegated, bit isSub,
5482                             RegisterClass regtype, string asm, list<dag> pat>
5483    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, regtype: $Ra),
5484         asm, "\t$Rd, $Rn, $Rm, $Ra", "", pat>,
5485      Sched<[WriteFMul]> {
5486  bits<5> Rd;
5487  bits<5> Rn;
5488  bits<5> Rm;
5489  bits<5> Ra;
5490  let Inst{31-24} = 0b00011111;
5491  let Inst{21}    = isNegated;
5492  let Inst{20-16} = Rm;
5493  let Inst{15}    = isSub;
5494  let Inst{14-10} = Ra;
5495  let Inst{9-5}   = Rn;
5496  let Inst{4-0}   = Rd;
5497}
5498
5499multiclass ThreeOperandFPData<bit isNegated, bit isSub,string asm,
5500                              SDPatternOperator node> {
5501  def Hrrr : BaseThreeOperandFPData<isNegated, isSub, FPR16, asm,
5502            [(set (f16 FPR16:$Rd),
5503                  (node (f16 FPR16:$Rn), (f16 FPR16:$Rm), (f16 FPR16:$Ra)))]> {
5504    let Inst{23-22} = 0b11; // 16-bit size flag
5505    let Predicates = [HasFullFP16];
5506  }
5507
5508  def Srrr : BaseThreeOperandFPData<isNegated, isSub, FPR32, asm,
5509            [(set FPR32:$Rd,
5510                  (node (f32 FPR32:$Rn), (f32 FPR32:$Rm), (f32 FPR32:$Ra)))]> {
5511    let Inst{23-22} = 0b00; // 32-bit size flag
5512  }
5513
5514  def Drrr : BaseThreeOperandFPData<isNegated, isSub, FPR64, asm,
5515            [(set FPR64:$Rd,
5516                  (node (f64 FPR64:$Rn), (f64 FPR64:$Rm), (f64 FPR64:$Ra)))]> {
5517    let Inst{23-22} = 0b01; // 64-bit size flag
5518  }
5519
5520  let Predicates = [HasFullFP16] in {
5521  def : Pat<(f16 (node (f16 FPR16:$Rn),
5522                       (f16 (extractelt (v8f16 V128:$Rm), (i64 0))),
5523                       (f16 FPR16:$Ra))),
5524            (!cast<Instruction>(NAME # Hrrr)
5525              FPR16:$Rn, (f16 (EXTRACT_SUBREG V128:$Rm, hsub)), FPR16:$Ra)>;
5526
5527  def : Pat<(f16 (node (f16 (extractelt (v8f16 V128:$Rn), (i64 0))),
5528                       (f16 FPR16:$Rm),
5529                       (f16 FPR16:$Ra))),
5530            (!cast<Instruction>(NAME # Hrrr)
5531              (f16 (EXTRACT_SUBREG V128:$Rn, hsub)), FPR16:$Rm, FPR16:$Ra)>;
5532  }
5533
5534  def : Pat<(f32 (node (f32 FPR32:$Rn),
5535                       (f32 (extractelt (v4f32 V128:$Rm), (i64 0))),
5536                       (f32 FPR32:$Ra))),
5537            (!cast<Instruction>(NAME # Srrr)
5538              FPR32:$Rn, (EXTRACT_SUBREG V128:$Rm, ssub), FPR32:$Ra)>;
5539
5540  def : Pat<(f32 (node (f32 (extractelt (v4f32 V128:$Rn), (i64 0))),
5541                       (f32 FPR32:$Rm),
5542                       (f32 FPR32:$Ra))),
5543            (!cast<Instruction>(NAME # Srrr)
5544              (EXTRACT_SUBREG V128:$Rn, ssub), FPR32:$Rm, FPR32:$Ra)>;
5545
5546  def : Pat<(f64 (node (f64 FPR64:$Rn),
5547                       (f64 (extractelt (v2f64 V128:$Rm), (i64 0))),
5548                       (f64 FPR64:$Ra))),
5549            (!cast<Instruction>(NAME # Drrr)
5550              FPR64:$Rn, (EXTRACT_SUBREG V128:$Rm, dsub), FPR64:$Ra)>;
5551
5552  def : Pat<(f64 (node (f64 (extractelt (v2f64 V128:$Rn), (i64 0))),
5553                       (f64 FPR64:$Rm),
5554                       (f64 FPR64:$Ra))),
5555            (!cast<Instruction>(NAME # Drrr)
5556              (EXTRACT_SUBREG V128:$Rn, dsub), FPR64:$Rm, FPR64:$Ra)>;
5557}
5558
5559//---
5560// Floating point data comparisons
5561//---
5562
5563let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5564class BaseOneOperandFPComparison<bit signalAllNans,
5565                                 RegisterClass regtype, string asm,
5566                                 list<dag> pat>
5567    : I<(outs), (ins regtype:$Rn), asm, "\t$Rn, #0.0", "", pat>,
5568      Sched<[WriteFCmp]> {
5569  bits<5> Rn;
5570  let Inst{31-24} = 0b00011110;
5571  let Inst{21}    = 1;
5572
5573  let Inst{15-10} = 0b001000;
5574  let Inst{9-5}   = Rn;
5575  let Inst{4}     = signalAllNans;
5576  let Inst{3-0}   = 0b1000;
5577
5578  // Rm should be 0b00000 canonically, but we need to accept any value.
5579  let PostEncoderMethod = "fixOneOperandFPComparison";
5580}
5581
5582let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5583class BaseTwoOperandFPComparison<bit signalAllNans, RegisterClass regtype,
5584                                string asm, list<dag> pat>
5585    : I<(outs), (ins regtype:$Rn, regtype:$Rm), asm, "\t$Rn, $Rm", "", pat>,
5586      Sched<[WriteFCmp]> {
5587  bits<5> Rm;
5588  bits<5> Rn;
5589  let Inst{31-24} = 0b00011110;
5590  let Inst{21}    = 1;
5591  let Inst{20-16} = Rm;
5592  let Inst{15-10} = 0b001000;
5593  let Inst{9-5}   = Rn;
5594  let Inst{4}     = signalAllNans;
5595  let Inst{3-0}   = 0b0000;
5596}
5597
5598multiclass FPComparison<bit signalAllNans, string asm,
5599                        SDPatternOperator OpNode = null_frag> {
5600  let Defs = [NZCV] in {
5601  def Hrr : BaseTwoOperandFPComparison<signalAllNans, FPR16, asm,
5602      [(OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)), (implicit NZCV)]> {
5603    let Inst{23-22} = 0b11;
5604    let Predicates = [HasFullFP16];
5605  }
5606
5607  def Hri : BaseOneOperandFPComparison<signalAllNans, FPR16, asm,
5608      [(OpNode (f16 FPR16:$Rn), fpimm0), (implicit NZCV)]> {
5609    let Inst{23-22} = 0b11;
5610    let Predicates = [HasFullFP16];
5611  }
5612
5613  def Srr : BaseTwoOperandFPComparison<signalAllNans, FPR32, asm,
5614      [(OpNode FPR32:$Rn, (f32 FPR32:$Rm)), (implicit NZCV)]> {
5615    let Inst{23-22} = 0b00;
5616  }
5617
5618  def Sri : BaseOneOperandFPComparison<signalAllNans, FPR32, asm,
5619      [(OpNode (f32 FPR32:$Rn), fpimm0), (implicit NZCV)]> {
5620    let Inst{23-22} = 0b00;
5621  }
5622
5623  def Drr : BaseTwoOperandFPComparison<signalAllNans, FPR64, asm,
5624      [(OpNode FPR64:$Rn, (f64 FPR64:$Rm)), (implicit NZCV)]> {
5625    let Inst{23-22} = 0b01;
5626  }
5627
5628  def Dri : BaseOneOperandFPComparison<signalAllNans, FPR64, asm,
5629      [(OpNode (f64 FPR64:$Rn), fpimm0), (implicit NZCV)]> {
5630    let Inst{23-22} = 0b01;
5631  }
5632  } // Defs = [NZCV]
5633}
5634
5635//---
5636// Floating point conditional comparisons
5637//---
5638
5639let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
5640class BaseFPCondComparison<bit signalAllNans, RegisterClass regtype,
5641                           string mnemonic, list<dag> pat>
5642    : I<(outs), (ins regtype:$Rn, regtype:$Rm, imm32_0_15:$nzcv, ccode:$cond),
5643         mnemonic, "\t$Rn, $Rm, $nzcv, $cond", "", pat>,
5644      Sched<[WriteFCmp]> {
5645  let Uses = [NZCV];
5646  let Defs = [NZCV];
5647
5648  bits<5> Rn;
5649  bits<5> Rm;
5650  bits<4> nzcv;
5651  bits<4> cond;
5652
5653  let Inst{31-24} = 0b00011110;
5654  let Inst{21}    = 1;
5655  let Inst{20-16} = Rm;
5656  let Inst{15-12} = cond;
5657  let Inst{11-10} = 0b01;
5658  let Inst{9-5}   = Rn;
5659  let Inst{4}     = signalAllNans;
5660  let Inst{3-0}   = nzcv;
5661}
5662
5663multiclass FPCondComparison<bit signalAllNans, string mnemonic,
5664                            SDPatternOperator OpNode = null_frag> {
5665  def Hrr : BaseFPCondComparison<signalAllNans, FPR16, mnemonic,
5666      [(set NZCV, (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm), (i32 imm:$nzcv),
5667                          (i32 imm:$cond), NZCV))]> {
5668    let Inst{23-22} = 0b11;
5669    let Predicates = [HasFullFP16];
5670  }
5671
5672  def Srr : BaseFPCondComparison<signalAllNans, FPR32, mnemonic,
5673      [(set NZCV, (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm), (i32 imm:$nzcv),
5674                          (i32 imm:$cond), NZCV))]> {
5675    let Inst{23-22} = 0b00;
5676  }
5677
5678  def Drr : BaseFPCondComparison<signalAllNans, FPR64, mnemonic,
5679      [(set NZCV, (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm), (i32 imm:$nzcv),
5680                          (i32 imm:$cond), NZCV))]> {
5681    let Inst{23-22} = 0b01;
5682  }
5683}
5684
5685//---
5686// Floating point conditional select
5687//---
5688
5689class BaseFPCondSelect<RegisterClass regtype, ValueType vt, string asm>
5690    : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, ccode:$cond),
5691         asm, "\t$Rd, $Rn, $Rm, $cond", "",
5692         [(set regtype:$Rd,
5693               (AArch64csel (vt regtype:$Rn), regtype:$Rm,
5694                          (i32 imm:$cond), NZCV))]>,
5695      Sched<[WriteF]> {
5696  bits<5> Rd;
5697  bits<5> Rn;
5698  bits<5> Rm;
5699  bits<4> cond;
5700
5701  let Inst{31-24} = 0b00011110;
5702  let Inst{21}    = 1;
5703  let Inst{20-16} = Rm;
5704  let Inst{15-12} = cond;
5705  let Inst{11-10} = 0b11;
5706  let Inst{9-5}   = Rn;
5707  let Inst{4-0}   = Rd;
5708}
5709
5710multiclass FPCondSelect<string asm> {
5711  let Uses = [NZCV] in {
5712  def Hrrr : BaseFPCondSelect<FPR16, f16, asm> {
5713    let Inst{23-22} = 0b11;
5714    let Predicates = [HasFullFP16];
5715  }
5716
5717  def Srrr : BaseFPCondSelect<FPR32, f32, asm> {
5718    let Inst{23-22} = 0b00;
5719  }
5720
5721  def Drrr : BaseFPCondSelect<FPR64, f64, asm> {
5722    let Inst{23-22} = 0b01;
5723  }
5724  } // Uses = [NZCV]
5725}
5726
5727//---
5728// Floating move immediate
5729//---
5730
5731class BaseFPMoveImmediate<RegisterClass regtype, Operand fpimmtype, string asm>
5732  : I<(outs regtype:$Rd), (ins fpimmtype:$imm), asm, "\t$Rd, $imm", "",
5733      [(set regtype:$Rd, fpimmtype:$imm)]>,
5734    Sched<[WriteFImm]> {
5735  bits<5> Rd;
5736  bits<8> imm;
5737  let Inst{31-24} = 0b00011110;
5738  let Inst{21}    = 1;
5739  let Inst{20-13} = imm;
5740  let Inst{12-5}  = 0b10000000;
5741  let Inst{4-0}   = Rd;
5742}
5743
5744multiclass FPMoveImmediate<string asm> {
5745  def Hi : BaseFPMoveImmediate<FPR16, fpimm16, asm> {
5746    let Inst{23-22} = 0b11;
5747    let Predicates = [HasFullFP16];
5748  }
5749
5750  def Si : BaseFPMoveImmediate<FPR32, fpimm32, asm> {
5751    let Inst{23-22} = 0b00;
5752  }
5753
5754  def Di : BaseFPMoveImmediate<FPR64, fpimm64, asm> {
5755    let Inst{23-22} = 0b01;
5756  }
5757}
5758} // end of 'let Predicates = [HasFPARMv8]'
5759
5760//----------------------------------------------------------------------------
5761// AdvSIMD
5762//----------------------------------------------------------------------------
5763
5764let Predicates = [HasNEON] in {
5765
5766//----------------------------------------------------------------------------
5767// AdvSIMD three register vector instructions
5768//----------------------------------------------------------------------------
5769
5770let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5771class BaseSIMDThreeSameVector<bit Q, bit U, bits<3> size, bits<5> opcode,
5772                        RegisterOperand regtype, string asm, string kind,
5773                        list<dag> pattern>
5774  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
5775      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5776      "|" # kind # "\t$Rd, $Rn, $Rm|}", "", pattern>,
5777    Sched<[!if(Q, WriteVq, WriteVd)]> {
5778  bits<5> Rd;
5779  bits<5> Rn;
5780  bits<5> Rm;
5781  let Inst{31}    = 0;
5782  let Inst{30}    = Q;
5783  let Inst{29}    = U;
5784  let Inst{28-24} = 0b01110;
5785  let Inst{23-21} = size;
5786  let Inst{20-16} = Rm;
5787  let Inst{15-11} = opcode;
5788  let Inst{10}    = 1;
5789  let Inst{9-5}   = Rn;
5790  let Inst{4-0}   = Rd;
5791}
5792
5793let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5794class BaseSIMDThreeSameVectorTied<bit Q, bit U, bits<3> size, bits<5> opcode,
5795                        RegisterOperand regtype, string asm, string kind,
5796                        list<dag> pattern>
5797  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), asm,
5798      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
5799      "|" # kind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
5800    Sched<[!if(Q, WriteVq, WriteVd)]> {
5801  bits<5> Rd;
5802  bits<5> Rn;
5803  bits<5> Rm;
5804  let Inst{31}    = 0;
5805  let Inst{30}    = Q;
5806  let Inst{29}    = U;
5807  let Inst{28-24} = 0b01110;
5808  let Inst{23-21} = size;
5809  let Inst{20-16} = Rm;
5810  let Inst{15-11} = opcode;
5811  let Inst{10}    = 1;
5812  let Inst{9-5}   = Rn;
5813  let Inst{4-0}   = Rd;
5814}
5815
5816let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
5817class BaseSIMDThreeSameVectorPseudo<RegisterOperand regtype, list<dag> pattern>
5818  : Pseudo<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn, regtype:$Rm), pattern>,
5819    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]>;
5820
5821multiclass SIMDLogicalThreeVectorPseudo<SDPatternOperator OpNode> {
5822  def v8i8  : BaseSIMDThreeSameVectorPseudo<V64,
5823             [(set (v8i8 V64:$dst),
5824                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5825  def v16i8  : BaseSIMDThreeSameVectorPseudo<V128,
5826             [(set (v16i8 V128:$dst),
5827                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
5828                           (v16i8 V128:$Rm)))]>;
5829
5830  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
5831                           (v4i16 V64:$RHS))),
5832          (!cast<Instruction>(NAME#"v8i8")
5833            V64:$LHS, V64:$MHS, V64:$RHS)>;
5834  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
5835                           (v2i32 V64:$RHS))),
5836          (!cast<Instruction>(NAME#"v8i8")
5837            V64:$LHS, V64:$MHS, V64:$RHS)>;
5838  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
5839                           (v1i64 V64:$RHS))),
5840          (!cast<Instruction>(NAME#"v8i8")
5841            V64:$LHS, V64:$MHS, V64:$RHS)>;
5842
5843  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
5844                           (v8i16 V128:$RHS))),
5845      (!cast<Instruction>(NAME#"v16i8")
5846        V128:$LHS, V128:$MHS, V128:$RHS)>;
5847  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
5848                           (v4i32 V128:$RHS))),
5849      (!cast<Instruction>(NAME#"v16i8")
5850        V128:$LHS, V128:$MHS, V128:$RHS)>;
5851  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
5852                           (v2i64 V128:$RHS))),
5853      (!cast<Instruction>(NAME#"v16i8")
5854        V128:$LHS, V128:$MHS, V128:$RHS)>;
5855}
5856
5857// All operand sizes distinguished in the encoding.
5858multiclass SIMDThreeSameVector<bit U, bits<5> opc, string asm,
5859                               SDPatternOperator OpNode> {
5860  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5861                                      asm, ".8b",
5862         [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5863  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5864                                      asm, ".16b",
5865         [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5866  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5867                                      asm, ".4h",
5868         [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5869  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5870                                      asm, ".8h",
5871         [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5872  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5873                                      asm, ".2s",
5874         [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5875  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5876                                      asm, ".4s",
5877         [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5878  def v2i64 : BaseSIMDThreeSameVector<1, U, 0b111, opc, V128,
5879                                      asm, ".2d",
5880         [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
5881}
5882
5883multiclass SIMDThreeSameVectorExtraPatterns<string inst, SDPatternOperator OpNode> {
5884  def : Pat<(v8i8 (OpNode V64:$LHS, V64:$RHS)),
5885          (!cast<Instruction>(inst#"v8i8") V64:$LHS, V64:$RHS)>;
5886  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
5887          (!cast<Instruction>(inst#"v4i16") V64:$LHS, V64:$RHS)>;
5888  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
5889          (!cast<Instruction>(inst#"v2i32") V64:$LHS, V64:$RHS)>;
5890
5891  def : Pat<(v16i8 (OpNode V128:$LHS, V128:$RHS)),
5892          (!cast<Instruction>(inst#"v16i8") V128:$LHS, V128:$RHS)>;
5893  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
5894          (!cast<Instruction>(inst#"v8i16") V128:$LHS, V128:$RHS)>;
5895  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
5896          (!cast<Instruction>(inst#"v4i32") V128:$LHS, V128:$RHS)>;
5897  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
5898          (!cast<Instruction>(inst#"v2i64") V128:$LHS, V128:$RHS)>;
5899}
5900
5901// As above, but D sized elements unsupported.
5902multiclass SIMDThreeSameVectorBHS<bit U, bits<5> opc, string asm,
5903                                  SDPatternOperator OpNode> {
5904  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5905                                      asm, ".8b",
5906        [(set V64:$Rd, (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))]>;
5907  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5908                                      asm, ".16b",
5909        [(set V128:$Rd, (v16i8 (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm))))]>;
5910  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
5911                                      asm, ".4h",
5912        [(set V64:$Rd, (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
5913  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
5914                                      asm, ".8h",
5915        [(set V128:$Rd, (v8i16 (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
5916  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
5917                                      asm, ".2s",
5918        [(set V64:$Rd, (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
5919  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
5920                                      asm, ".4s",
5921        [(set V128:$Rd, (v4i32 (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
5922}
5923
5924multiclass SIMDThreeSameVectorBHSTied<bit U, bits<5> opc, string asm,
5925                                  SDPatternOperator OpNode> {
5926  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, 0b001, opc, V64,
5927                                      asm, ".8b",
5928      [(set (v8i8 V64:$dst),
5929            (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5930  def v16i8 : BaseSIMDThreeSameVectorTied<1, U, 0b001, opc, V128,
5931                                      asm, ".16b",
5932      [(set (v16i8 V128:$dst),
5933            (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5934  def v4i16 : BaseSIMDThreeSameVectorTied<0, U, 0b011, opc, V64,
5935                                      asm, ".4h",
5936      [(set (v4i16 V64:$dst),
5937            (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
5938  def v8i16 : BaseSIMDThreeSameVectorTied<1, U, 0b011, opc, V128,
5939                                      asm, ".8h",
5940      [(set (v8i16 V128:$dst),
5941            (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
5942  def v2i32 : BaseSIMDThreeSameVectorTied<0, U, 0b101, opc, V64,
5943                                      asm, ".2s",
5944      [(set (v2i32 V64:$dst),
5945            (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
5946  def v4i32 : BaseSIMDThreeSameVectorTied<1, U, 0b101, opc, V128,
5947                                      asm, ".4s",
5948      [(set (v4i32 V128:$dst),
5949            (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
5950}
5951
5952// As above, but only B sized elements supported.
5953multiclass SIMDThreeSameVectorB<bit U, bits<5> opc, string asm,
5954                                SDPatternOperator OpNode> {
5955  def v8i8  : BaseSIMDThreeSameVector<0, U, 0b001, opc, V64,
5956                                      asm, ".8b",
5957    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
5958  def v16i8 : BaseSIMDThreeSameVector<1, U, 0b001, opc, V128,
5959                                      asm, ".16b",
5960    [(set (v16i8 V128:$Rd),
5961          (OpNode (v16i8 V128:$Rn), (v16i8 V128:$Rm)))]>;
5962}
5963
5964// As above, but only floating point elements supported.
5965let mayRaiseFPException = 1, Uses = [FPCR] in
5966multiclass SIMDThreeSameVectorFP<bit U, bit S, bits<3> opc,
5967                                 string asm, SDPatternOperator OpNode> {
5968  let Predicates = [HasNEON, HasFullFP16] in {
5969  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5970                                      asm, ".4h",
5971        [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5972  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5973                                      asm, ".8h",
5974        [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5975  } // Predicates = [HasNEON, HasFullFP16]
5976  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
5977                                      asm, ".2s",
5978        [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
5979  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
5980                                      asm, ".4s",
5981        [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
5982  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
5983                                      asm, ".2d",
5984        [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
5985}
5986
5987let mayRaiseFPException = 1, Uses = [FPCR] in
5988multiclass SIMDThreeSameVectorFPCmp<bit U, bit S, bits<3> opc,
5989                                    string asm,
5990                                    SDPatternOperator OpNode> {
5991  let Predicates = [HasNEON, HasFullFP16] in {
5992  def v4f16 : BaseSIMDThreeSameVector<0, U, {S,0b10}, {0b00,opc}, V64,
5993                                      asm, ".4h",
5994        [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
5995  def v8f16 : BaseSIMDThreeSameVector<1, U, {S,0b10}, {0b00,opc}, V128,
5996                                      asm, ".8h",
5997        [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
5998  } // Predicates = [HasNEON, HasFullFP16]
5999  def v2f32 : BaseSIMDThreeSameVector<0, U, {S,0b01}, {0b11,opc}, V64,
6000                                      asm, ".2s",
6001        [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
6002  def v4f32 : BaseSIMDThreeSameVector<1, U, {S,0b01}, {0b11,opc}, V128,
6003                                      asm, ".4s",
6004        [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
6005  def v2f64 : BaseSIMDThreeSameVector<1, U, {S,0b11}, {0b11,opc}, V128,
6006                                      asm, ".2d",
6007        [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
6008}
6009
6010let mayRaiseFPException = 1, Uses = [FPCR] in
6011multiclass SIMDThreeSameVectorFPTied<bit U, bit S, bits<3> opc,
6012                                 string asm, SDPatternOperator OpNode> {
6013  let Predicates = [HasNEON, HasFullFP16] in {
6014  def v4f16 : BaseSIMDThreeSameVectorTied<0, U, {S,0b10}, {0b00,opc}, V64,
6015                                      asm, ".4h",
6016     [(set (v4f16 V64:$dst),
6017           (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), (v4f16 V64:$Rm)))]>;
6018  def v8f16 : BaseSIMDThreeSameVectorTied<1, U, {S,0b10}, {0b00,opc}, V128,
6019                                      asm, ".8h",
6020     [(set (v8f16 V128:$dst),
6021           (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn), (v8f16 V128:$Rm)))]>;
6022  } // Predicates = [HasNEON, HasFullFP16]
6023  def v2f32 : BaseSIMDThreeSameVectorTied<0, U, {S,0b01}, {0b11,opc}, V64,
6024                                      asm, ".2s",
6025     [(set (v2f32 V64:$dst),
6026           (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), (v2f32 V64:$Rm)))]>;
6027  def v4f32 : BaseSIMDThreeSameVectorTied<1, U, {S,0b01}, {0b11,opc}, V128,
6028                                      asm, ".4s",
6029     [(set (v4f32 V128:$dst),
6030           (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn), (v4f32 V128:$Rm)))]>;
6031  def v2f64 : BaseSIMDThreeSameVectorTied<1, U, {S,0b11}, {0b11,opc}, V128,
6032                                      asm, ".2d",
6033     [(set (v2f64 V128:$dst),
6034           (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn), (v2f64 V128:$Rm)))]>;
6035}
6036
6037// As above, but D and B sized elements unsupported.
6038let mayRaiseFPException = 1, Uses = [FPCR] in
6039multiclass SIMDThreeSameVectorHS<bit U, bits<5> opc, string asm,
6040                                SDPatternOperator OpNode> {
6041  def v4i16 : BaseSIMDThreeSameVector<0, U, 0b011, opc, V64,
6042                                      asm, ".4h",
6043        [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6044  def v8i16 : BaseSIMDThreeSameVector<1, U, 0b011, opc, V128,
6045                                      asm, ".8h",
6046        [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6047  def v2i32 : BaseSIMDThreeSameVector<0, U, 0b101, opc, V64,
6048                                      asm, ".2s",
6049        [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6050  def v4i32 : BaseSIMDThreeSameVector<1, U, 0b101, opc, V128,
6051                                      asm, ".4s",
6052        [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6053}
6054
6055// Logical three vector ops share opcode bits, and only use B sized elements.
6056multiclass SIMDLogicalThreeVector<bit U, bits<2> size, string asm,
6057                                  SDPatternOperator OpNode = null_frag> {
6058  def v8i8  : BaseSIMDThreeSameVector<0, U, {size,1}, 0b00011, V64,
6059                                     asm, ".8b",
6060                         [(set (v8i8 V64:$Rd), (OpNode V64:$Rn, V64:$Rm))]>;
6061  def v16i8  : BaseSIMDThreeSameVector<1, U, {size,1}, 0b00011, V128,
6062                                     asm, ".16b",
6063                         [(set (v16i8 V128:$Rd), (OpNode V128:$Rn, V128:$Rm))]>;
6064
6065  def : Pat<(v4i16 (OpNode V64:$LHS, V64:$RHS)),
6066          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
6067  def : Pat<(v2i32 (OpNode V64:$LHS, V64:$RHS)),
6068          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
6069  def : Pat<(v1i64 (OpNode V64:$LHS, V64:$RHS)),
6070          (!cast<Instruction>(NAME#"v8i8") V64:$LHS, V64:$RHS)>;
6071
6072  def : Pat<(v8i16 (OpNode V128:$LHS, V128:$RHS)),
6073      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6074  def : Pat<(v4i32 (OpNode V128:$LHS, V128:$RHS)),
6075      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6076  def : Pat<(v2i64 (OpNode V128:$LHS, V128:$RHS)),
6077      (!cast<Instruction>(NAME#"v16i8") V128:$LHS, V128:$RHS)>;
6078}
6079
6080multiclass SIMDLogicalThreeVectorTied<bit U, bits<2> size,
6081                                  string asm, SDPatternOperator OpNode = null_frag> {
6082  def v8i8  : BaseSIMDThreeSameVectorTied<0, U, {size,1}, 0b00011, V64,
6083                                     asm, ".8b",
6084             [(set (v8i8 V64:$dst),
6085                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6086  def v16i8  : BaseSIMDThreeSameVectorTied<1, U, {size,1}, 0b00011, V128,
6087                                     asm, ".16b",
6088             [(set (v16i8 V128:$dst),
6089                   (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
6090                           (v16i8 V128:$Rm)))]>;
6091
6092  def : Pat<(v4i16 (OpNode (v4i16 V64:$LHS), (v4i16 V64:$MHS),
6093                           (v4i16 V64:$RHS))),
6094          (!cast<Instruction>(NAME#"v8i8")
6095            V64:$LHS, V64:$MHS, V64:$RHS)>;
6096  def : Pat<(v2i32 (OpNode (v2i32 V64:$LHS), (v2i32 V64:$MHS),
6097                           (v2i32 V64:$RHS))),
6098          (!cast<Instruction>(NAME#"v8i8")
6099            V64:$LHS, V64:$MHS, V64:$RHS)>;
6100  def : Pat<(v1i64 (OpNode (v1i64 V64:$LHS), (v1i64 V64:$MHS),
6101                           (v1i64 V64:$RHS))),
6102          (!cast<Instruction>(NAME#"v8i8")
6103            V64:$LHS, V64:$MHS, V64:$RHS)>;
6104
6105  def : Pat<(v8i16 (OpNode (v8i16 V128:$LHS), (v8i16 V128:$MHS),
6106                           (v8i16 V128:$RHS))),
6107      (!cast<Instruction>(NAME#"v16i8")
6108        V128:$LHS, V128:$MHS, V128:$RHS)>;
6109  def : Pat<(v4i32 (OpNode (v4i32 V128:$LHS), (v4i32 V128:$MHS),
6110                           (v4i32 V128:$RHS))),
6111      (!cast<Instruction>(NAME#"v16i8")
6112        V128:$LHS, V128:$MHS, V128:$RHS)>;
6113  def : Pat<(v2i64 (OpNode (v2i64 V128:$LHS), (v2i64 V128:$MHS),
6114                           (v2i64 V128:$RHS))),
6115      (!cast<Instruction>(NAME#"v16i8")
6116        V128:$LHS, V128:$MHS, V128:$RHS)>;
6117}
6118
6119// ARMv8.2-A Dot Product Instructions (Vector): These instructions extract
6120// bytes from S-sized elements.
6121class BaseSIMDThreeSameVectorDot<bit Q, bit U, bits<2> sz, bits<4> opc, string asm,
6122                                 string kind1, string kind2, RegisterOperand RegType,
6123                                 ValueType AccumType, ValueType InputType,
6124                                 SDPatternOperator OpNode> :
6125        BaseSIMDThreeSameVectorTied<Q, U, {sz, 0b0}, {0b1, opc}, RegType, asm, kind1,
6126        [(set (AccumType RegType:$dst),
6127              (OpNode (AccumType RegType:$Rd),
6128                      (InputType RegType:$Rn),
6129                      (InputType RegType:$Rm)))]> {
6130  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
6131}
6132
6133multiclass SIMDThreeSameVectorDot<bit U, bit Mixed, string asm, SDPatternOperator OpNode> {
6134  def v8i8  : BaseSIMDThreeSameVectorDot<0, U, 0b10, {0b001, Mixed}, asm, ".2s", ".8b", V64,
6135                                         v2i32, v8i8, OpNode>;
6136  def v16i8 : BaseSIMDThreeSameVectorDot<1, U, 0b10, {0b001, Mixed}, asm, ".4s", ".16b", V128,
6137                                         v4i32, v16i8, OpNode>;
6138}
6139
6140// ARMv8.2-A Fused Multiply Add-Long Instructions (Vector): These instructions
6141// select inputs from 4H vectors and accumulate outputs to a 2S vector (or from
6142// 8H to 4S, when Q=1).
6143let mayRaiseFPException = 1, Uses = [FPCR] in
6144class BaseSIMDThreeSameVectorFML<bit Q, bit U, bit b13, bits<3> size, string asm, string kind1,
6145                                 string kind2, RegisterOperand RegType,
6146                                 ValueType AccumType, ValueType InputType,
6147                                 SDPatternOperator OpNode> :
6148        BaseSIMDThreeSameVectorTied<Q, U, size, 0b11101, RegType, asm, kind1,
6149		[(set (AccumType RegType:$dst),
6150              (OpNode (AccumType RegType:$Rd),
6151                      (InputType RegType:$Rn),
6152                      (InputType RegType:$Rm)))]> {
6153  let AsmString = !strconcat(asm, "{\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2 # "}");
6154  let Inst{13} = b13;
6155}
6156
6157multiclass SIMDThreeSameVectorFML<bit U, bit b13, bits<3> size, string asm,
6158                                  SDPatternOperator OpNode> {
6159  def v4f16 : BaseSIMDThreeSameVectorFML<0, U, b13, size, asm, ".2s", ".2h", V64,
6160                                         v2f32, v4f16, OpNode>;
6161  def v8f16 : BaseSIMDThreeSameVectorFML<1, U, b13, size, asm, ".4s", ".4h", V128,
6162                                         v4f32, v8f16, OpNode>;
6163}
6164
6165multiclass SIMDThreeSameVectorMLA<bit Q, string asm>{
6166  def v8f16 : BaseSIMDThreeSameVectorDot<Q, 0b0, 0b11, 0b1111, asm, ".8h", ".16b",
6167                                         V128, v8f16, v16i8, null_frag>;
6168}
6169
6170multiclass SIMDThreeSameVectorMLAL<bit Q, bits<2> sz, string asm>{
6171  def v4f32 : BaseSIMDThreeSameVectorDot<Q, 0b0, sz, 0b1000, asm, ".4s", ".16b",
6172                                         V128, v4f32, v16i8, null_frag>;
6173}
6174
6175// FP8 assembly/disassembly classes
6176
6177//----------------------------------------------------------------------------
6178// FP8 Advanced SIMD three-register extension
6179//----------------------------------------------------------------------------
6180class BaseSIMDThreeVectors<bit Q, bit U, bits<2> size, bits<4> op,
6181                           RegisterOperand regtype1,
6182                           RegisterOperand regtype2, string asm,
6183                           string kind1, string kind2>
6184  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, regtype2:$Rm), asm,
6185      "\t$Rd" # kind1 # ", $Rn" # kind2 # ", $Rm" # kind2, "", []>, Sched<[]> {
6186  bits<5> Rd;
6187  bits<5> Rn;
6188  bits<5> Rm;
6189  let Inst{31}    = 0;
6190  let Inst{30}    = Q;
6191  let Inst{29}    = U;
6192  let Inst{28-24} = 0b01110;
6193  let Inst{23-22} = size;
6194  let Inst{21}    = 0b0;
6195  let Inst{20-16} = Rm;
6196  let Inst{15}    = 0b1;
6197  let Inst{14-11} = op;
6198  let Inst{10}    = 0b1;
6199  let Inst{9-5}   = Rn;
6200  let Inst{4-0}   = Rd;
6201}
6202
6203
6204// FCVTN (FP16 to FP8)
6205multiclass SIMDThreeSameSizeVectorCvt<string asm> {
6206   def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b01, 0b1110, V64, V64, asm, ".8b",".4h">;
6207   def v16f8 : BaseSIMDThreeVectors<0b1, 0b0, 0b01, 0b1110,  V128, V128, asm, ".16b", ".8h">;
6208}
6209
6210// TODO : Create v16f8 value type
6211// FCVTN, FCVTN2 (FP32 to FP8)
6212multiclass SIMDThreeVectorCvt<string asm> {
6213   def v8f8 : BaseSIMDThreeVectors<0b0, 0b0, 0b00, 0b1110, V64, V128, asm, ".8b", ".4s">;
6214   def 2v16f8 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b00, 0b1110, asm#2, ".16b", ".4s",
6215                                           V128, v16i8, v4f32, null_frag>;
6216}
6217
6218// TODO: Create a new Value Type v8f8 and v16f8
6219multiclass SIMDThreeSameVectorDOT2<string asm> {
6220   def v4f16 : BaseSIMDThreeSameVectorDot<0b0, 0b0, 0b01, 0b1111, asm, ".4h", ".8b",
6221                                          V64, v4f16, v8i8, null_frag>;
6222   def v8f16 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b01, 0b1111, asm, ".8h", ".16b",
6223                                          V128, v8f16, v16i8, null_frag>;
6224}
6225
6226multiclass SIMDThreeSameVectorDOT4<string asm> {
6227   def v2f32 : BaseSIMDThreeSameVectorDot<0b0, 0b0, 0b00, 0b1111, asm, ".2s", ".8b",
6228                                          V64, v2f32, v8i8, null_frag>;
6229   def v4f32 : BaseSIMDThreeSameVectorDot<0b1, 0b0, 0b00, 0b1111, asm, ".4s", ".16b",
6230                                          V128, v4f32, v16i8, null_frag>;
6231}
6232
6233//----------------------------------------------------------------------------
6234// AdvSIMD two register vector instructions.
6235//----------------------------------------------------------------------------
6236
6237let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6238class BaseSIMDTwoSameVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6239                            bits<2> size2, RegisterOperand regtype, string asm,
6240                            string dstkind, string srckind, list<dag> pattern>
6241  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6242      "{\t$Rd" # dstkind # ", $Rn" # srckind #
6243      "|" # dstkind # "\t$Rd, $Rn}", "", pattern>,
6244    Sched<[!if(Q, WriteVq, WriteVd)]> {
6245  bits<5> Rd;
6246  bits<5> Rn;
6247  let Inst{31}    = 0;
6248  let Inst{30}    = Q;
6249  let Inst{29}    = U;
6250  let Inst{28-24} = 0b01110;
6251  let Inst{23-22} = size;
6252  let Inst{21} = 0b1;
6253  let Inst{20-19} = size2;
6254  let Inst{18-17} = 0b00;
6255  let Inst{16-12} = opcode;
6256  let Inst{11-10} = 0b10;
6257  let Inst{9-5}   = Rn;
6258  let Inst{4-0}   = Rd;
6259}
6260
6261let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6262class BaseSIMDTwoSameVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6263                                bits<2> size2, RegisterOperand regtype,
6264                                string asm, string dstkind, string srckind,
6265                                list<dag> pattern>
6266  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype:$Rn), asm,
6267      "{\t$Rd" # dstkind # ", $Rn" # srckind #
6268      "|" # dstkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6269    Sched<[!if(Q, WriteVq, WriteVd)]> {
6270  bits<5> Rd;
6271  bits<5> Rn;
6272  let Inst{31}    = 0;
6273  let Inst{30}    = Q;
6274  let Inst{29}    = U;
6275  let Inst{28-24} = 0b01110;
6276  let Inst{23-22} = size;
6277  let Inst{21} = 0b1;
6278  let Inst{20-19} = size2;
6279  let Inst{18-17} = 0b00;
6280  let Inst{16-12} = opcode;
6281  let Inst{11-10} = 0b10;
6282  let Inst{9-5}   = Rn;
6283  let Inst{4-0}   = Rd;
6284}
6285
6286// Supports B, H, and S element sizes.
6287multiclass SIMDTwoVectorBHS<bit U, bits<5> opc, string asm,
6288                            SDPatternOperator OpNode> {
6289  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6290                                      asm, ".8b", ".8b",
6291                          [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6292  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6293                                      asm, ".16b", ".16b",
6294                          [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6295  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6296                                      asm, ".4h", ".4h",
6297                          [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6298  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6299                                      asm, ".8h", ".8h",
6300                          [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6301  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6302                                      asm, ".2s", ".2s",
6303                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6304  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6305                                      asm, ".4s", ".4s",
6306                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6307}
6308
6309class BaseSIMDVectorLShiftLongBySize<bit Q, bits<2> size,
6310                            RegisterOperand regtype, string asm, string dstkind,
6311                            string srckind, string amount>
6312  : I<(outs V128:$Rd), (ins regtype:$Rn), asm,
6313      "{\t$Rd" # dstkind # ", $Rn" # srckind # ", #" # amount #
6314      "|" # dstkind # "\t$Rd, $Rn, #" #  amount # "}", "", []>,
6315    Sched<[WriteVq]> {
6316  bits<5> Rd;
6317  bits<5> Rn;
6318  let Inst{31}    = 0;
6319  let Inst{30}    = Q;
6320  let Inst{29-24} = 0b101110;
6321  let Inst{23-22} = size;
6322  let Inst{21-10} = 0b100001001110;
6323  let Inst{9-5}   = Rn;
6324  let Inst{4-0}   = Rd;
6325}
6326
6327multiclass SIMDVectorLShiftLongBySizeBHS {
6328  let hasSideEffects = 0 in {
6329  def v8i8  : BaseSIMDVectorLShiftLongBySize<0, 0b00, V64,
6330                                             "shll", ".8h",  ".8b", "8">;
6331  def v16i8 : BaseSIMDVectorLShiftLongBySize<1, 0b00, V128,
6332                                             "shll2", ".8h", ".16b", "8">;
6333  def v4i16 : BaseSIMDVectorLShiftLongBySize<0, 0b01, V64,
6334                                             "shll", ".4s",  ".4h", "16">;
6335  def v8i16 : BaseSIMDVectorLShiftLongBySize<1, 0b01, V128,
6336                                             "shll2", ".4s", ".8h", "16">;
6337  def v2i32 : BaseSIMDVectorLShiftLongBySize<0, 0b10, V64,
6338                                             "shll", ".2d",  ".2s", "32">;
6339  def v4i32 : BaseSIMDVectorLShiftLongBySize<1, 0b10, V128,
6340                                             "shll2", ".2d", ".4s", "32">;
6341  }
6342}
6343
6344// Supports all element sizes.
6345multiclass SIMDLongTwoVector<bit U, bits<5> opc, string asm,
6346                             SDPatternOperator OpNode> {
6347  def v8i8_v4i16  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6348                                      asm, ".4h", ".8b",
6349               [(set (v4i16 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6350  def v16i8_v8i16 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6351                                      asm, ".8h", ".16b",
6352               [(set (v8i16 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6353  def v4i16_v2i32 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6354                                      asm, ".2s", ".4h",
6355               [(set (v2i32 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6356  def v8i16_v4i32 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6357                                      asm, ".4s", ".8h",
6358               [(set (v4i32 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6359  def v2i32_v1i64 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6360                                      asm, ".1d", ".2s",
6361               [(set (v1i64 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6362  def v4i32_v2i64 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6363                                      asm, ".2d", ".4s",
6364               [(set (v2i64 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6365}
6366
6367multiclass SIMDLongTwoVectorTied<bit U, bits<5> opc, string asm,
6368                                 SDPatternOperator OpNode> {
6369  def v8i8_v4i16  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6370                                          asm, ".4h", ".8b",
6371      [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd),
6372                                      (v8i8 V64:$Rn)))]>;
6373  def v16i8_v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6374                                          asm, ".8h", ".16b",
6375      [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd),
6376                                      (v16i8 V128:$Rn)))]>;
6377  def v4i16_v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6378                                          asm, ".2s", ".4h",
6379      [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd),
6380                                      (v4i16 V64:$Rn)))]>;
6381  def v8i16_v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6382                                          asm, ".4s", ".8h",
6383      [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
6384                                      (v8i16 V128:$Rn)))]>;
6385  def v2i32_v1i64 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6386                                          asm, ".1d", ".2s",
6387      [(set (v1i64 V64:$dst), (OpNode (v1i64 V64:$Rd),
6388                                      (v2i32 V64:$Rn)))]>;
6389  def v4i32_v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6390                                          asm, ".2d", ".4s",
6391      [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd),
6392                                      (v4i32 V128:$Rn)))]>;
6393}
6394
6395// Supports all element sizes, except 1xD.
6396multiclass SIMDTwoVectorBHSDTied<bit U, bits<5> opc, string asm,
6397                                  SDPatternOperator OpNode> {
6398  def v8i8  : BaseSIMDTwoSameVectorTied<0, U, 0b00, opc, 0b00, V64,
6399                                    asm, ".8b", ".8b",
6400    [(set (v8i8 V64:$dst), (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn)))]>;
6401  def v16i8 : BaseSIMDTwoSameVectorTied<1, U, 0b00, opc, 0b00, V128,
6402                                    asm, ".16b", ".16b",
6403    [(set (v16i8 V128:$dst), (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
6404  def v4i16 : BaseSIMDTwoSameVectorTied<0, U, 0b01, opc, 0b00, V64,
6405                                    asm, ".4h", ".4h",
6406    [(set (v4i16 V64:$dst), (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn)))]>;
6407  def v8i16 : BaseSIMDTwoSameVectorTied<1, U, 0b01, opc, 0b00, V128,
6408                                    asm, ".8h", ".8h",
6409    [(set (v8i16 V128:$dst), (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn)))]>;
6410  def v2i32 : BaseSIMDTwoSameVectorTied<0, U, 0b10, opc, 0b00, V64,
6411                                    asm, ".2s", ".2s",
6412    [(set (v2i32 V64:$dst), (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn)))]>;
6413  def v4i32 : BaseSIMDTwoSameVectorTied<1, U, 0b10, opc, 0b00, V128,
6414                                    asm, ".4s", ".4s",
6415    [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
6416  def v2i64 : BaseSIMDTwoSameVectorTied<1, U, 0b11, opc, 0b00, V128,
6417                                    asm, ".2d", ".2d",
6418    [(set (v2i64 V128:$dst), (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn)))]>;
6419}
6420
6421multiclass SIMDTwoVectorBHSD<bit U, bits<5> opc, string asm,
6422                             SDPatternOperator OpNode = null_frag> {
6423  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6424                                asm, ".8b", ".8b",
6425    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6426  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6427                                asm, ".16b", ".16b",
6428    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6429  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6430                                asm, ".4h", ".4h",
6431    [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6432  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6433                                asm, ".8h", ".8h",
6434    [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6435  def v2i32 : BaseSIMDTwoSameVector<0, U, 0b10, opc, 0b00, V64,
6436                                asm, ".2s", ".2s",
6437    [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6438  def v4i32 : BaseSIMDTwoSameVector<1, U, 0b10, opc, 0b00, V128,
6439                                asm, ".4s", ".4s",
6440    [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6441  def v2i64 : BaseSIMDTwoSameVector<1, U, 0b11, opc, 0b00, V128,
6442                                asm, ".2d", ".2d",
6443    [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6444}
6445
6446
6447// Supports only B element sizes.
6448multiclass SIMDTwoVectorB<bit U, bits<2> size, bits<5> opc, string asm,
6449                          SDPatternOperator OpNode> {
6450  def v8i8  : BaseSIMDTwoSameVector<0, U, size, opc, 0b00, V64,
6451                                asm, ".8b", ".8b",
6452                    [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn)))]>;
6453  def v16i8 : BaseSIMDTwoSameVector<1, U, size, opc, 0b00, V128,
6454                                asm, ".16b", ".16b",
6455                    [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
6456
6457}
6458
6459// Supports only B and H element sizes.
6460multiclass SIMDTwoVectorBH<bit U, bits<5> opc, string asm,
6461                                SDPatternOperator OpNode> {
6462  def v8i8  : BaseSIMDTwoSameVector<0, U, 0b00, opc, 0b00, V64,
6463                                asm, ".8b", ".8b",
6464                    [(set (v8i8 V64:$Rd), (OpNode V64:$Rn))]>;
6465  def v16i8 : BaseSIMDTwoSameVector<1, U, 0b00, opc, 0b00, V128,
6466                                asm, ".16b", ".16b",
6467                    [(set (v16i8 V128:$Rd), (OpNode V128:$Rn))]>;
6468  def v4i16 : BaseSIMDTwoSameVector<0, U, 0b01, opc, 0b00, V64,
6469                                asm, ".4h", ".4h",
6470                    [(set (v4i16 V64:$Rd), (OpNode V64:$Rn))]>;
6471  def v8i16 : BaseSIMDTwoSameVector<1, U, 0b01, opc, 0b00, V128,
6472                                asm, ".8h", ".8h",
6473                    [(set (v8i16 V128:$Rd), (OpNode V128:$Rn))]>;
6474}
6475
6476// Supports H, S and D element sizes, uses high bit of the size field
6477// as an extra opcode bit.
6478multiclass SIMDTwoVectorFP<bit U, bit S, bits<5> opc, string asm,
6479                           SDPatternOperator OpNode,
6480                           int fpexceptions = 1> {
6481  let mayRaiseFPException = fpexceptions, Uses = !if(fpexceptions,[FPCR],[]<Register>) in {
6482  let Predicates = [HasNEON, HasFullFP16] in {
6483  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6484                                asm, ".4h", ".4h",
6485                          [(set (v4f16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6486  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6487                                asm, ".8h", ".8h",
6488                          [(set (v8f16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6489  } // Predicates = [HasNEON, HasFullFP16]
6490  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6491                                asm, ".2s", ".2s",
6492                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6493  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6494                                asm, ".4s", ".4s",
6495                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6496  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6497                                asm, ".2d", ".2d",
6498                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6499  }
6500}
6501
6502multiclass SIMDTwoVectorFPNoException<bit U, bit S, bits<5> opc, string asm,
6503                                      SDPatternOperator OpNode>
6504    : SIMDTwoVectorFP<U, S, opc, asm, OpNode, 0>;
6505
6506// Supports only S and D element sizes
6507let mayRaiseFPException = 1, Uses = [FPCR] in
6508multiclass SIMDTwoVectorSD<bit U, bits<5> opc, string asm,
6509                           SDPatternOperator OpNode = null_frag> {
6510
6511  def v2f32 : BaseSIMDTwoSameVector<0, U, 00, opc, 0b00, V64,
6512                                asm, ".2s", ".2s",
6513                          [(set (v2f32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6514  def v4f32 : BaseSIMDTwoSameVector<1, U, 00, opc, 0b00, V128,
6515                                asm, ".4s", ".4s",
6516                          [(set (v4f32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6517  def v2f64 : BaseSIMDTwoSameVector<1, U, 01, opc, 0b00, V128,
6518                                asm, ".2d", ".2d",
6519                          [(set (v2f64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6520}
6521
6522multiclass FRIntNNTVector<bit U, bit op, string asm,
6523                          SDPatternOperator OpNode = null_frag> :
6524           SIMDTwoVectorSD<U, {0b1111,op}, asm, OpNode>;
6525
6526// Supports only S element size.
6527multiclass SIMDTwoVectorS<bit U, bit S, bits<5> opc, string asm,
6528                           SDPatternOperator OpNode> {
6529  def v2i32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6530                                asm, ".2s", ".2s",
6531                          [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6532  def v4i32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6533                                asm, ".4s", ".4s",
6534                          [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6535}
6536
6537let mayRaiseFPException = 1, Uses = [FPCR] in
6538multiclass SIMDTwoVectorFPToInt<bit U, bit S, bits<5> opc, string asm,
6539                           SDPatternOperator OpNode> {
6540  let Predicates = [HasNEON, HasFullFP16] in {
6541  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6542                                asm, ".4h", ".4h",
6543                          [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn)))]>;
6544  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6545                                asm, ".8h", ".8h",
6546                          [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn)))]>;
6547  } // Predicates = [HasNEON, HasFullFP16]
6548  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6549                                asm, ".2s", ".2s",
6550                          [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn)))]>;
6551  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6552                                asm, ".4s", ".4s",
6553                          [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn)))]>;
6554  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6555                                asm, ".2d", ".2d",
6556                          [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6557}
6558
6559let mayRaiseFPException = 1, Uses = [FPCR] in
6560multiclass SIMDTwoVectorIntToFP<bit U, bit S, bits<5> opc, string asm,
6561                           SDPatternOperator OpNode> {
6562  let Predicates = [HasNEON, HasFullFP16] in {
6563  def v4f16 : BaseSIMDTwoSameVector<0, U, {S,1}, opc, 0b11, V64,
6564                                asm, ".4h", ".4h",
6565                          [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn)))]>;
6566  def v8f16 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b11, V128,
6567                                asm, ".8h", ".8h",
6568                          [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6569  } // Predicates = [HasNEON, HasFullFP16]
6570  def v2f32 : BaseSIMDTwoSameVector<0, U, {S,0}, opc, 0b00, V64,
6571                                asm, ".2s", ".2s",
6572                          [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn)))]>;
6573  def v4f32 : BaseSIMDTwoSameVector<1, U, {S,0}, opc, 0b00, V128,
6574                                asm, ".4s", ".4s",
6575                          [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6576  def v2f64 : BaseSIMDTwoSameVector<1, U, {S,1}, opc, 0b00, V128,
6577                                asm, ".2d", ".2d",
6578                          [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6579}
6580
6581let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6582class BaseSIMDMixedTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6583                           RegisterOperand inreg, RegisterOperand outreg,
6584                           string asm, string outkind, string inkind,
6585                           list<dag> pattern>
6586  : I<(outs outreg:$Rd), (ins inreg:$Rn), asm,
6587      "{\t$Rd" # outkind # ", $Rn" # inkind #
6588      "|" # outkind # "\t$Rd, $Rn}", "", pattern>,
6589    Sched<[WriteVq]> {
6590  bits<5> Rd;
6591  bits<5> Rn;
6592  let Inst{31}    = 0;
6593  let Inst{30}    = Q;
6594  let Inst{29}    = U;
6595  let Inst{28-24} = 0b01110;
6596  let Inst{23-22} = size;
6597  let Inst{21-17} = 0b10000;
6598  let Inst{16-12} = opcode;
6599  let Inst{11-10} = 0b10;
6600  let Inst{9-5}   = Rn;
6601  let Inst{4-0}   = Rd;
6602}
6603
6604let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6605class BaseSIMDMixedTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6606                           RegisterOperand inreg, RegisterOperand outreg,
6607                           string asm, string outkind, string inkind,
6608                           list<dag> pattern>
6609  : I<(outs outreg:$dst), (ins outreg:$Rd, inreg:$Rn), asm,
6610      "{\t$Rd" # outkind # ", $Rn" # inkind #
6611      "|" # outkind # "\t$Rd, $Rn}", "$Rd = $dst", pattern>,
6612    Sched<[WriteVq]> {
6613  bits<5> Rd;
6614  bits<5> Rn;
6615  let Inst{31}    = 0;
6616  let Inst{30}    = Q;
6617  let Inst{29}    = U;
6618  let Inst{28-24} = 0b01110;
6619  let Inst{23-22} = size;
6620  let Inst{21-17} = 0b10000;
6621  let Inst{16-12} = opcode;
6622  let Inst{11-10} = 0b10;
6623  let Inst{9-5}   = Rn;
6624  let Inst{4-0}   = Rd;
6625}
6626
6627multiclass SIMDMixedTwoVector<bit U, bits<5> opc, string asm,
6628                              SDPatternOperator OpNode> {
6629  def v8i8  : BaseSIMDMixedTwoVector<0, U, 0b00, opc, V128, V64,
6630                                      asm, ".8b", ".8h",
6631        [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn)))]>;
6632  def v16i8 : BaseSIMDMixedTwoVectorTied<1, U, 0b00, opc, V128, V128,
6633                                      asm#"2", ".16b", ".8h", []>;
6634  def v4i16 : BaseSIMDMixedTwoVector<0, U, 0b01, opc, V128, V64,
6635                                      asm, ".4h", ".4s",
6636        [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn)))]>;
6637  def v8i16 : BaseSIMDMixedTwoVectorTied<1, U, 0b01, opc, V128, V128,
6638                                      asm#"2", ".8h", ".4s", []>;
6639  def v2i32 : BaseSIMDMixedTwoVector<0, U, 0b10, opc, V128, V64,
6640                                      asm, ".2s", ".2d",
6641        [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn)))]>;
6642  def v4i32 : BaseSIMDMixedTwoVectorTied<1, U, 0b10, opc, V128, V128,
6643                                      asm#"2", ".4s", ".2d", []>;
6644
6645  def : Pat<(concat_vectors (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn))),
6646            (!cast<Instruction>(NAME # "v16i8")
6647                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6648  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn))),
6649            (!cast<Instruction>(NAME # "v8i16")
6650                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6651  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn))),
6652            (!cast<Instruction>(NAME # "v4i32")
6653                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6654}
6655
6656//----------------------------------------------------------------------------
6657// FP8 Advanced SIMD two-register miscellaneous
6658//----------------------------------------------------------------------------
6659multiclass SIMDMixedTwoVectorFP8<bits<2>sz, string asm> {
6660  def v8f16 : BaseSIMDMixedTwoVector<0b0, 0b1, sz, 0b10111, V64, V128,
6661                                     asm, ".8h", ".8b", []>;
6662  def 2v8f16 : BaseSIMDMixedTwoVector<0b1, 0b1, sz, 0b10111, V128, V128,
6663                                     asm#2, ".8h", ".16b", []>;
6664}
6665
6666class BaseSIMDCmpTwoVector<bit Q, bit U, bits<2> size, bits<2> size2,
6667                           bits<5> opcode, RegisterOperand regtype, string asm,
6668                           string kind, string zero, ValueType dty,
6669                           ValueType sty, SDNode OpNode>
6670  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
6671      "{\t$Rd" # kind # ", $Rn" # kind # ", #" # zero #
6672      "|" # kind # "\t$Rd, $Rn, #" # zero # "}", "",
6673      [(set (dty regtype:$Rd), (OpNode (sty regtype:$Rn)))]>,
6674    Sched<[!if(Q, WriteVq, WriteVd)]> {
6675  bits<5> Rd;
6676  bits<5> Rn;
6677  let Inst{31}    = 0;
6678  let Inst{30}    = Q;
6679  let Inst{29}    = U;
6680  let Inst{28-24} = 0b01110;
6681  let Inst{23-22} = size;
6682  let Inst{21} = 0b1;
6683  let Inst{20-19} = size2;
6684  let Inst{18-17} = 0b00;
6685  let Inst{16-12} = opcode;
6686  let Inst{11-10} = 0b10;
6687  let Inst{9-5}   = Rn;
6688  let Inst{4-0}   = Rd;
6689}
6690
6691// Comparisons support all element sizes, except 1xD.
6692multiclass SIMDCmpTwoVector<bit U, bits<5> opc, string asm,
6693                            SDNode OpNode> {
6694  def v8i8rz  : BaseSIMDCmpTwoVector<0, U, 0b00, 0b00, opc, V64,
6695                                     asm, ".8b", "0",
6696                                     v8i8, v8i8, OpNode>;
6697  def v16i8rz : BaseSIMDCmpTwoVector<1, U, 0b00, 0b00, opc, V128,
6698                                     asm, ".16b", "0",
6699                                     v16i8, v16i8, OpNode>;
6700  def v4i16rz : BaseSIMDCmpTwoVector<0, U, 0b01, 0b00, opc, V64,
6701                                     asm, ".4h", "0",
6702                                     v4i16, v4i16, OpNode>;
6703  def v8i16rz : BaseSIMDCmpTwoVector<1, U, 0b01, 0b00, opc, V128,
6704                                     asm, ".8h", "0",
6705                                     v8i16, v8i16, OpNode>;
6706  def v2i32rz : BaseSIMDCmpTwoVector<0, U, 0b10, 0b00, opc, V64,
6707                                     asm, ".2s", "0",
6708                                     v2i32, v2i32, OpNode>;
6709  def v4i32rz : BaseSIMDCmpTwoVector<1, U, 0b10, 0b00, opc, V128,
6710                                     asm, ".4s", "0",
6711                                     v4i32, v4i32, OpNode>;
6712  def v2i64rz : BaseSIMDCmpTwoVector<1, U, 0b11, 0b00, opc, V128,
6713                                     asm, ".2d", "0",
6714                                     v2i64, v2i64, OpNode>;
6715}
6716
6717// FP Comparisons support only S and D element sizes (and H for v8.2a).
6718multiclass SIMDFPCmpTwoVector<bit U, bit S, bits<5> opc,
6719                              string asm, SDNode OpNode> {
6720
6721  let mayRaiseFPException = 1, Uses = [FPCR] in {
6722  let Predicates = [HasNEON, HasFullFP16] in {
6723  def v4i16rz : BaseSIMDCmpTwoVector<0, U, {S,1}, 0b11, opc, V64,
6724                                     asm, ".4h", "0.0",
6725                                     v4i16, v4f16, OpNode>;
6726  def v8i16rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b11, opc, V128,
6727                                     asm, ".8h", "0.0",
6728                                     v8i16, v8f16, OpNode>;
6729  } // Predicates = [HasNEON, HasFullFP16]
6730  def v2i32rz : BaseSIMDCmpTwoVector<0, U, {S,0}, 0b00, opc, V64,
6731                                     asm, ".2s", "0.0",
6732                                     v2i32, v2f32, OpNode>;
6733  def v4i32rz : BaseSIMDCmpTwoVector<1, U, {S,0}, 0b00, opc, V128,
6734                                     asm, ".4s", "0.0",
6735                                     v4i32, v4f32, OpNode>;
6736  def v2i64rz : BaseSIMDCmpTwoVector<1, U, {S,1}, 0b00, opc, V128,
6737                                     asm, ".2d", "0.0",
6738                                     v2i64, v2f64, OpNode>;
6739  }
6740
6741  let Predicates = [HasNEON, HasFullFP16] in {
6742  def : InstAlias<asm # "\t$Vd.4h, $Vn.4h, #0",
6743                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6744  def : InstAlias<asm # "\t$Vd.8h, $Vn.8h, #0",
6745                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6746  }
6747  def : InstAlias<asm # "\t$Vd.2s, $Vn.2s, #0",
6748                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6749  def : InstAlias<asm # "\t$Vd.4s, $Vn.4s, #0",
6750                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6751  def : InstAlias<asm # "\t$Vd.2d, $Vn.2d, #0",
6752                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6753  let Predicates = [HasNEON, HasFullFP16] in {
6754  def : InstAlias<asm # ".4h\t$Vd, $Vn, #0",
6755                  (!cast<Instruction>(NAME # v4i16rz) V64:$Vd, V64:$Vn), 0>;
6756  def : InstAlias<asm # ".8h\t$Vd, $Vn, #0",
6757                  (!cast<Instruction>(NAME # v8i16rz) V128:$Vd, V128:$Vn), 0>;
6758  }
6759  def : InstAlias<asm # ".2s\t$Vd, $Vn, #0",
6760                  (!cast<Instruction>(NAME # v2i32rz) V64:$Vd, V64:$Vn), 0>;
6761  def : InstAlias<asm # ".4s\t$Vd, $Vn, #0",
6762                  (!cast<Instruction>(NAME # v4i32rz) V128:$Vd, V128:$Vn), 0>;
6763  def : InstAlias<asm # ".2d\t$Vd, $Vn, #0",
6764                  (!cast<Instruction>(NAME # v2i64rz) V128:$Vd, V128:$Vn), 0>;
6765}
6766
6767let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6768class BaseSIMDFPCvtTwoVector<bit Q, bit U, bits<2> size, bits<5> opcode,
6769                             RegisterOperand outtype, RegisterOperand intype,
6770                             string asm, string VdTy, string VnTy,
6771                             list<dag> pattern>
6772  : I<(outs outtype:$Rd), (ins intype:$Rn), asm,
6773      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "", pattern>,
6774    Sched<[WriteVq]> {
6775  bits<5> Rd;
6776  bits<5> Rn;
6777  let Inst{31}    = 0;
6778  let Inst{30}    = Q;
6779  let Inst{29}    = U;
6780  let Inst{28-24} = 0b01110;
6781  let Inst{23-22} = size;
6782  let Inst{21-17} = 0b10000;
6783  let Inst{16-12} = opcode;
6784  let Inst{11-10} = 0b10;
6785  let Inst{9-5}   = Rn;
6786  let Inst{4-0}   = Rd;
6787}
6788
6789let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
6790class BaseSIMDFPCvtTwoVectorTied<bit Q, bit U, bits<2> size, bits<5> opcode,
6791                             RegisterOperand outtype, RegisterOperand intype,
6792                             string asm, string VdTy, string VnTy,
6793                             list<dag> pattern>
6794  : I<(outs outtype:$dst), (ins outtype:$Rd, intype:$Rn), asm,
6795      !strconcat("\t$Rd", VdTy, ", $Rn", VnTy), "$Rd = $dst", pattern>,
6796    Sched<[WriteVq]> {
6797  bits<5> Rd;
6798  bits<5> Rn;
6799  let Inst{31}    = 0;
6800  let Inst{30}    = Q;
6801  let Inst{29}    = U;
6802  let Inst{28-24} = 0b01110;
6803  let Inst{23-22} = size;
6804  let Inst{21-17} = 0b10000;
6805  let Inst{16-12} = opcode;
6806  let Inst{11-10} = 0b10;
6807  let Inst{9-5}   = Rn;
6808  let Inst{4-0}   = Rd;
6809}
6810
6811multiclass SIMDFPWidenTwoVector<bit U, bit S, bits<5> opc, string asm> {
6812  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V128, V64,
6813                                    asm, ".4s", ".4h", []>;
6814  def v8i16 : BaseSIMDFPCvtTwoVector<1, U, {S,0}, opc, V128, V128,
6815                                    asm#"2", ".4s", ".8h", []>;
6816  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V128, V64,
6817                                    asm, ".2d", ".2s", []>;
6818  def v4i32 : BaseSIMDFPCvtTwoVector<1, U, {S,1}, opc, V128, V128,
6819                                    asm#"2", ".2d", ".4s", []>;
6820}
6821
6822multiclass SIMDFPNarrowTwoVector<bit U, bit S, bits<5> opc, string asm> {
6823  def v4i16 : BaseSIMDFPCvtTwoVector<0, U, {S,0}, opc, V64, V128,
6824                                    asm, ".4h", ".4s", []>;
6825  def v8i16 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,0}, opc, V128, V128,
6826                                    asm#"2", ".8h", ".4s", []>;
6827  def v2i32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6828                                    asm, ".2s", ".2d", []>;
6829  def v4i32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6830                                    asm#"2", ".4s", ".2d", []>;
6831}
6832
6833multiclass SIMDFPInexactCvtTwoVector<bit U, bit S, bits<5> opc, string asm,
6834                                     Intrinsic OpNode> {
6835  def v2f32 : BaseSIMDFPCvtTwoVector<0, U, {S,1}, opc, V64, V128,
6836                                     asm, ".2s", ".2d",
6837                          [(set (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn)))]>;
6838  def v4f32 : BaseSIMDFPCvtTwoVectorTied<1, U, {S,1}, opc, V128, V128,
6839                                    asm#"2", ".4s", ".2d", []>;
6840
6841  def : Pat<(concat_vectors (v2f32 V64:$Rd), (OpNode (v2f64 V128:$Rn))),
6842            (!cast<Instruction>(NAME # "v4f32")
6843                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub), V128:$Rn)>;
6844}
6845
6846//----------------------------------------------------------------------------
6847// AdvSIMD three register different-size vector instructions.
6848//----------------------------------------------------------------------------
6849
6850let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6851class BaseSIMDDifferentThreeVector<bit U, bits<3> size, bits<4> opcode,
6852                      RegisterOperand outtype, RegisterOperand intype1,
6853                      RegisterOperand intype2, string asm,
6854                      string outkind, string inkind1, string inkind2,
6855                      list<dag> pattern>
6856  : I<(outs outtype:$Rd), (ins intype1:$Rn, intype2:$Rm), asm,
6857      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6858      "|" # outkind # "\t$Rd, $Rn, $Rm}", "", pattern>,
6859    Sched<[WriteVq]> {
6860  bits<5> Rd;
6861  bits<5> Rn;
6862  bits<5> Rm;
6863  let Inst{31}    = 0;
6864  let Inst{30}    = size{0};
6865  let Inst{29}    = U;
6866  let Inst{28-24} = 0b01110;
6867  let Inst{23-22} = size{2-1};
6868  let Inst{21}    = 1;
6869  let Inst{20-16} = Rm;
6870  let Inst{15-12} = opcode;
6871  let Inst{11-10} = 0b00;
6872  let Inst{9-5}   = Rn;
6873  let Inst{4-0}   = Rd;
6874}
6875
6876let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
6877class BaseSIMDDifferentThreeVectorTied<bit U, bits<3> size, bits<4> opcode,
6878                      RegisterOperand outtype, RegisterOperand intype1,
6879                      RegisterOperand intype2, string asm,
6880                      string outkind, string inkind1, string inkind2,
6881                      list<dag> pattern>
6882  : I<(outs outtype:$dst), (ins outtype:$Rd, intype1:$Rn, intype2:$Rm), asm,
6883      "{\t$Rd" # outkind # ", $Rn" # inkind1 # ", $Rm" # inkind2 #
6884      "|" # outkind # "\t$Rd, $Rn, $Rm}", "$Rd = $dst", pattern>,
6885    Sched<[WriteVq]> {
6886  bits<5> Rd;
6887  bits<5> Rn;
6888  bits<5> Rm;
6889  let Inst{31}    = 0;
6890  let Inst{30}    = size{0};
6891  let Inst{29}    = U;
6892  let Inst{28-24} = 0b01110;
6893  let Inst{23-22} = size{2-1};
6894  let Inst{21}    = 1;
6895  let Inst{20-16} = Rm;
6896  let Inst{15-12} = opcode;
6897  let Inst{11-10} = 0b00;
6898  let Inst{9-5}   = Rn;
6899  let Inst{4-0}   = Rd;
6900}
6901
6902// FIXME: TableGen doesn't know how to deal with expanded types that also
6903//        change the element count (in this case, placing the results in
6904//        the high elements of the result register rather than the low
6905//        elements). Until that's fixed, we can't code-gen those.
6906multiclass SIMDNarrowThreeVectorBHS<bit U, bits<4> opc, string asm,
6907                                    Intrinsic IntOp> {
6908  def v8i16_v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6909                                                  V64, V128, V128,
6910                                                  asm, ".8b", ".8h", ".8h",
6911     [(set (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn), (v8i16 V128:$Rm)))]>;
6912  def v8i16_v16i8  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
6913                                                  V128, V128, V128,
6914                                                  asm#"2", ".16b", ".8h", ".8h",
6915     []>;
6916  def v4i32_v4i16  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6917                                                  V64, V128, V128,
6918                                                  asm, ".4h", ".4s", ".4s",
6919     [(set (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn), (v4i32 V128:$Rm)))]>;
6920  def v4i32_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
6921                                                  V128, V128, V128,
6922                                                  asm#"2", ".8h", ".4s", ".4s",
6923     []>;
6924  def v2i64_v2i32  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6925                                                  V64, V128, V128,
6926                                                  asm, ".2s", ".2d", ".2d",
6927     [(set (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn), (v2i64 V128:$Rm)))]>;
6928  def v2i64_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
6929                                                  V128, V128, V128,
6930                                                  asm#"2", ".4s", ".2d", ".2d",
6931     []>;
6932
6933
6934  // Patterns for the '2' variants involve INSERT_SUBREG, which you can't put in
6935  // a version attached to an instruction.
6936  def : Pat<(concat_vectors (v8i8 V64:$Rd), (IntOp (v8i16 V128:$Rn),
6937                                                   (v8i16 V128:$Rm))),
6938            (!cast<Instruction>(NAME # "v8i16_v16i8")
6939                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6940                V128:$Rn, V128:$Rm)>;
6941  def : Pat<(concat_vectors (v4i16 V64:$Rd), (IntOp (v4i32 V128:$Rn),
6942                                                    (v4i32 V128:$Rm))),
6943            (!cast<Instruction>(NAME # "v4i32_v8i16")
6944                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6945                V128:$Rn, V128:$Rm)>;
6946  def : Pat<(concat_vectors (v2i32 V64:$Rd), (IntOp (v2i64 V128:$Rn),
6947                                                    (v2i64 V128:$Rm))),
6948            (!cast<Instruction>(NAME # "v2i64_v4i32")
6949                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
6950                V128:$Rn, V128:$Rm)>;
6951}
6952
6953multiclass SIMDDifferentThreeVectorBD<bit U, bits<4> opc, string asm,
6954                                      SDPatternOperator OpNode> {
6955  def v8i8   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
6956                                            V128, V64, V64,
6957                                            asm, ".8h", ".8b", ".8b",
6958      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
6959  def v16i8  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
6960                                            V128, V128, V128,
6961                                            asm#"2", ".8h", ".16b", ".16b", []>;
6962  let Predicates = [HasAES] in {
6963    def v1i64  : BaseSIMDDifferentThreeVector<U, 0b110, opc,
6964                                              V128, V64, V64,
6965                                              asm, ".1q", ".1d", ".1d",
6966        [(set (v16i8 V128:$Rd), (OpNode (v1i64 V64:$Rn), (v1i64 V64:$Rm)))]>;
6967    def v2i64  : BaseSIMDDifferentThreeVector<U, 0b111, opc,
6968                                              V128, V128, V128,
6969                                              asm#"2", ".1q", ".2d", ".2d",
6970        [(set (v16i8 V128:$Rd), (OpNode (extract_high_v2i64 (v2i64 V128:$Rn)),
6971                                        (extract_high_v2i64 (v2i64 V128:$Rm))))]>;
6972  }
6973
6974  def : Pat<(v8i16 (OpNode (v8i8 (extract_high_v16i8 (v16i8 V128:$Rn))),
6975                          (v8i8 (extract_high_v16i8 (v16i8 V128:$Rm))))),
6976      (!cast<Instruction>(NAME#"v16i8") V128:$Rn, V128:$Rm)>;
6977}
6978
6979multiclass SIMDLongThreeVectorHS<bit U, bits<4> opc, string asm,
6980                                 SDPatternOperator OpNode> {
6981  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
6982                                                  V128, V64, V64,
6983                                                  asm, ".4s", ".4h", ".4h",
6984      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
6985  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
6986                                                  V128, V128, V128,
6987                                                  asm#"2", ".4s", ".8h", ".8h",
6988      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
6989                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
6990  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
6991                                                  V128, V64, V64,
6992                                                  asm, ".2d", ".2s", ".2s",
6993      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
6994  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
6995                                                  V128, V128, V128,
6996                                                  asm#"2", ".2d", ".4s", ".4s",
6997      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
6998                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
6999}
7000
7001multiclass SIMDLongThreeVectorBHSabdl<bit U, bits<4> opc, string asm,
7002                                  SDPatternOperator OpNode = null_frag> {
7003  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7004                                                  V128, V64, V64,
7005                                                  asm, ".8h", ".8b", ".8b",
7006      [(set (v8i16 V128:$Rd),
7007            (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))))]>;
7008  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7009                                                 V128, V128, V128,
7010                                                 asm#"2", ".8h", ".16b", ".16b",
7011      [(set (v8i16 V128:$Rd),
7012            (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7013                                (extract_high_v16i8 (v16i8 V128:$Rm))))))]>;
7014  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7015                                                  V128, V64, V64,
7016                                                  asm, ".4s", ".4h", ".4h",
7017      [(set (v4i32 V128:$Rd),
7018            (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))))]>;
7019  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7020                                                  V128, V128, V128,
7021                                                  asm#"2", ".4s", ".8h", ".8h",
7022      [(set (v4i32 V128:$Rd),
7023            (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7024                                  (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
7025  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7026                                                  V128, V64, V64,
7027                                                  asm, ".2d", ".2s", ".2s",
7028      [(set (v2i64 V128:$Rd),
7029            (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))))]>;
7030  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7031                                                  V128, V128, V128,
7032                                                  asm#"2", ".2d", ".4s", ".4s",
7033      [(set (v2i64 V128:$Rd),
7034            (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7035                                 (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
7036}
7037
7038multiclass SIMDLongThreeVectorTiedBHSabal<bit U, bits<4> opc,
7039                                          string asm,
7040                                          SDPatternOperator OpNode> {
7041  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
7042                                                  V128, V64, V64,
7043                                                  asm, ".8h", ".8b", ".8b",
7044    [(set (v8i16 V128:$dst),
7045          (add (v8i16 V128:$Rd),
7046               (zext (v8i8 (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm))))))]>;
7047  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
7048                                                 V128, V128, V128,
7049                                                 asm#"2", ".8h", ".16b", ".16b",
7050    [(set (v8i16 V128:$dst),
7051          (add (v8i16 V128:$Rd),
7052               (zext (v8i8 (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7053                                   (extract_high_v16i8 (v16i8 V128:$Rm)))))))]>;
7054  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7055                                                  V128, V64, V64,
7056                                                  asm, ".4s", ".4h", ".4h",
7057    [(set (v4i32 V128:$dst),
7058          (add (v4i32 V128:$Rd),
7059               (zext (v4i16 (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm))))))]>;
7060  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7061                                                  V128, V128, V128,
7062                                                  asm#"2", ".4s", ".8h", ".8h",
7063    [(set (v4i32 V128:$dst),
7064          (add (v4i32 V128:$Rd),
7065               (zext (v4i16 (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7066                                    (extract_high_v8i16 (v8i16 V128:$Rm)))))))]>;
7067  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7068                                                  V128, V64, V64,
7069                                                  asm, ".2d", ".2s", ".2s",
7070    [(set (v2i64 V128:$dst),
7071          (add (v2i64 V128:$Rd),
7072               (zext (v2i32 (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm))))))]>;
7073  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7074                                                  V128, V128, V128,
7075                                                  asm#"2", ".2d", ".4s", ".4s",
7076    [(set (v2i64 V128:$dst),
7077          (add (v2i64 V128:$Rd),
7078               (zext (v2i32 (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7079                                    (extract_high_v4i32 (v4i32 V128:$Rm)))))))]>;
7080}
7081
7082multiclass SIMDLongThreeVectorBHS<bit U, bits<4> opc, string asm,
7083                                  SDPatternOperator OpNode = null_frag> {
7084  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7085                                                  V128, V64, V64,
7086                                                  asm, ".8h", ".8b", ".8b",
7087      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
7088  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7089                                                 V128, V128, V128,
7090                                                 asm#"2", ".8h", ".16b", ".16b",
7091      [(set (v8i16 V128:$Rd), (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)),
7092                                      (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7093  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7094                                                  V128, V64, V64,
7095                                                  asm, ".4s", ".4h", ".4h",
7096      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
7097  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7098                                                  V128, V128, V128,
7099                                                  asm#"2", ".4s", ".8h", ".8h",
7100      [(set (v4i32 V128:$Rd), (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
7101                                      (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7102  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7103                                                  V128, V64, V64,
7104                                                  asm, ".2d", ".2s", ".2s",
7105      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
7106  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7107                                                  V128, V128, V128,
7108                                                  asm#"2", ".2d", ".4s", ".4s",
7109      [(set (v2i64 V128:$Rd), (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
7110                                      (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7111}
7112
7113multiclass SIMDLongThreeVectorTiedBHS<bit U, bits<4> opc,
7114                                      string asm,
7115                                      SDPatternOperator OpNode> {
7116  def v8i8_v8i16   : BaseSIMDDifferentThreeVectorTied<U, 0b000, opc,
7117                                                  V128, V64, V64,
7118                                                  asm, ".8h", ".8b", ".8b",
7119    [(set (v8i16 V128:$dst),
7120          (OpNode (v8i16 V128:$Rd), (v8i8 V64:$Rn), (v8i8 V64:$Rm)))]>;
7121  def v16i8_v8i16  : BaseSIMDDifferentThreeVectorTied<U, 0b001, opc,
7122                                                 V128, V128, V128,
7123                                                 asm#"2", ".8h", ".16b", ".16b",
7124    [(set (v8i16 V128:$dst),
7125          (OpNode (v8i16 V128:$Rd),
7126                  (extract_high_v16i8 (v16i8 V128:$Rn)),
7127                  (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7128  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7129                                                  V128, V64, V64,
7130                                                  asm, ".4s", ".4h", ".4h",
7131    [(set (v4i32 V128:$dst),
7132          (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm)))]>;
7133  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7134                                                  V128, V128, V128,
7135                                                  asm#"2", ".4s", ".8h", ".8h",
7136    [(set (v4i32 V128:$dst),
7137          (OpNode (v4i32 V128:$Rd),
7138                  (extract_high_v8i16 (v8i16 V128:$Rn)),
7139                  (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7140  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7141                                                  V128, V64, V64,
7142                                                  asm, ".2d", ".2s", ".2s",
7143    [(set (v2i64 V128:$dst),
7144          (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm)))]>;
7145  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7146                                                  V128, V128, V128,
7147                                                  asm#"2", ".2d", ".4s", ".4s",
7148    [(set (v2i64 V128:$dst),
7149          (OpNode (v2i64 V128:$Rd),
7150                  (extract_high_v4i32 (v4i32 V128:$Rn)),
7151                  (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7152}
7153
7154multiclass SIMDLongThreeVectorSQDMLXTiedHS<bit U, bits<4> opc, string asm,
7155                                           SDPatternOperator Accum> {
7156  def v4i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b010, opc,
7157                                                  V128, V64, V64,
7158                                                  asm, ".4s", ".4h", ".4h",
7159    [(set (v4i32 V128:$dst),
7160          (Accum (v4i32 V128:$Rd),
7161                 (v4i32 (int_aarch64_neon_sqdmull (v4i16 V64:$Rn),
7162                                                (v4i16 V64:$Rm)))))]>;
7163  def v8i16_v4i32  : BaseSIMDDifferentThreeVectorTied<U, 0b011, opc,
7164                                                  V128, V128, V128,
7165                                                  asm#"2", ".4s", ".8h", ".8h",
7166    [(set (v4i32 V128:$dst),
7167          (Accum (v4i32 V128:$Rd),
7168                 (v4i32 (int_aarch64_neon_sqdmull (extract_high_v8i16 (v8i16 V128:$Rn)),
7169                                            (extract_high_v8i16 (v8i16 V128:$Rm))))))]>;
7170  def v2i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b100, opc,
7171                                                  V128, V64, V64,
7172                                                  asm, ".2d", ".2s", ".2s",
7173    [(set (v2i64 V128:$dst),
7174          (Accum (v2i64 V128:$Rd),
7175                 (v2i64 (int_aarch64_neon_sqdmull (v2i32 V64:$Rn),
7176                                                (v2i32 V64:$Rm)))))]>;
7177  def v4i32_v2i64  : BaseSIMDDifferentThreeVectorTied<U, 0b101, opc,
7178                                                  V128, V128, V128,
7179                                                  asm#"2", ".2d", ".4s", ".4s",
7180    [(set (v2i64 V128:$dst),
7181          (Accum (v2i64 V128:$Rd),
7182                 (v2i64 (int_aarch64_neon_sqdmull (extract_high_v4i32 (v4i32 V128:$Rn)),
7183                                            (extract_high_v4i32 (v4i32 V128:$Rm))))))]>;
7184}
7185
7186multiclass SIMDWideThreeVectorBHS<bit U, bits<4> opc, string asm,
7187                                  SDPatternOperator OpNode> {
7188  def v8i8_v8i16   : BaseSIMDDifferentThreeVector<U, 0b000, opc,
7189                                                  V128, V128, V64,
7190                                                  asm, ".8h", ".8h", ".8b",
7191       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (v8i8 V64:$Rm)))]>;
7192  def v16i8_v8i16  : BaseSIMDDifferentThreeVector<U, 0b001, opc,
7193                                                  V128, V128, V128,
7194                                                  asm#"2", ".8h", ".8h", ".16b",
7195       [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
7196                                       (extract_high_v16i8 (v16i8 V128:$Rm))))]>;
7197  def v4i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b010, opc,
7198                                                  V128, V128, V64,
7199                                                  asm, ".4s", ".4s", ".4h",
7200       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (v4i16 V64:$Rm)))]>;
7201  def v8i16_v4i32  : BaseSIMDDifferentThreeVector<U, 0b011, opc,
7202                                                  V128, V128, V128,
7203                                                  asm#"2", ".4s", ".4s", ".8h",
7204       [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
7205                                       (extract_high_v8i16 (v8i16 V128:$Rm))))]>;
7206  def v2i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b100, opc,
7207                                                  V128, V128, V64,
7208                                                  asm, ".2d", ".2d", ".2s",
7209       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (v2i32 V64:$Rm)))]>;
7210  def v4i32_v2i64  : BaseSIMDDifferentThreeVector<U, 0b101, opc,
7211                                                  V128, V128, V128,
7212                                                  asm#"2", ".2d", ".2d", ".4s",
7213       [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
7214                                       (extract_high_v4i32 (v4i32 V128:$Rm))))]>;
7215}
7216
7217//----------------------------------------------------------------------------
7218// AdvSIMD bitwise extract from vector
7219//----------------------------------------------------------------------------
7220
7221class BaseSIMDBitwiseExtract<bit size, RegisterOperand regtype, ValueType vty,
7222                             string asm, string kind>
7223  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, i32imm:$imm), asm,
7224      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $imm" #
7225      "|" # kind # "\t$Rd, $Rn, $Rm, $imm}", "",
7226      [(set (vty regtype:$Rd),
7227            (AArch64ext regtype:$Rn, regtype:$Rm, (i32 imm:$imm)))]>,
7228    Sched<[!if(size, WriteVq, WriteVd)]> {
7229  bits<5> Rd;
7230  bits<5> Rn;
7231  bits<5> Rm;
7232  bits<4> imm;
7233  let Inst{31}    = 0;
7234  let Inst{30}    = size;
7235  let Inst{29-21} = 0b101110000;
7236  let Inst{20-16} = Rm;
7237  let Inst{15}    = 0;
7238  let Inst{14-11} = imm;
7239  let Inst{10}    = 0;
7240  let Inst{9-5}   = Rn;
7241  let Inst{4-0}   = Rd;
7242}
7243
7244
7245multiclass SIMDBitwiseExtract<string asm> {
7246  def v8i8  : BaseSIMDBitwiseExtract<0, V64, v8i8, asm, ".8b"> {
7247    let imm{3} = 0;
7248  }
7249  def v16i8 : BaseSIMDBitwiseExtract<1, V128, v16i8, asm, ".16b">;
7250}
7251
7252//----------------------------------------------------------------------------
7253// AdvSIMD zip vector
7254//----------------------------------------------------------------------------
7255
7256class BaseSIMDZipVector<bits<3> size, bits<3> opc, RegisterOperand regtype,
7257                        string asm, string kind, SDNode OpNode, ValueType valty>
7258  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7259      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind #
7260      "|" # kind # "\t$Rd, $Rn, $Rm}", "",
7261      [(set (valty regtype:$Rd), (OpNode regtype:$Rn, regtype:$Rm))]>,
7262    Sched<[!if(!eq(regtype, V128), WriteVq, WriteVd)]> {
7263  bits<5> Rd;
7264  bits<5> Rn;
7265  bits<5> Rm;
7266  let Inst{31}    = 0;
7267  let Inst{30}    = size{0};
7268  let Inst{29-24} = 0b001110;
7269  let Inst{23-22} = size{2-1};
7270  let Inst{21}    = 0;
7271  let Inst{20-16} = Rm;
7272  let Inst{15}    = 0;
7273  let Inst{14-12} = opc;
7274  let Inst{11-10} = 0b10;
7275  let Inst{9-5}   = Rn;
7276  let Inst{4-0}   = Rd;
7277}
7278
7279multiclass SIMDZipVector<bits<3>opc, string asm,
7280                         SDNode OpNode> {
7281  def v8i8   : BaseSIMDZipVector<0b000, opc, V64,
7282      asm, ".8b", OpNode, v8i8>;
7283  def v16i8  : BaseSIMDZipVector<0b001, opc, V128,
7284      asm, ".16b", OpNode, v16i8>;
7285  def v4i16  : BaseSIMDZipVector<0b010, opc, V64,
7286      asm, ".4h", OpNode, v4i16>;
7287  def v8i16  : BaseSIMDZipVector<0b011, opc, V128,
7288      asm, ".8h", OpNode, v8i16>;
7289  def v2i32  : BaseSIMDZipVector<0b100, opc, V64,
7290      asm, ".2s", OpNode, v2i32>;
7291  def v4i32  : BaseSIMDZipVector<0b101, opc, V128,
7292      asm, ".4s", OpNode, v4i32>;
7293  def v2i64  : BaseSIMDZipVector<0b111, opc, V128,
7294      asm, ".2d", OpNode, v2i64>;
7295
7296  def : Pat<(v4f16 (OpNode V64:$Rn, V64:$Rm)),
7297        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7298  def : Pat<(v4bf16 (OpNode V64:$Rn, V64:$Rm)),
7299        (!cast<Instruction>(NAME#"v4i16") V64:$Rn, V64:$Rm)>;
7300  def : Pat<(v8f16 (OpNode V128:$Rn, V128:$Rm)),
7301        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7302  def : Pat<(v8bf16 (OpNode V128:$Rn, V128:$Rm)),
7303        (!cast<Instruction>(NAME#"v8i16") V128:$Rn, V128:$Rm)>;
7304  def : Pat<(v2f32 (OpNode V64:$Rn, V64:$Rm)),
7305        (!cast<Instruction>(NAME#"v2i32") V64:$Rn, V64:$Rm)>;
7306  def : Pat<(v4f32 (OpNode V128:$Rn, V128:$Rm)),
7307        (!cast<Instruction>(NAME#"v4i32") V128:$Rn, V128:$Rm)>;
7308  def : Pat<(v2f64 (OpNode V128:$Rn, V128:$Rm)),
7309        (!cast<Instruction>(NAME#"v2i64") V128:$Rn, V128:$Rm)>;
7310}
7311
7312//----------------------------------------------------------------------------
7313// AdvSIMD three register scalar instructions
7314//----------------------------------------------------------------------------
7315
7316let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7317class BaseSIMDThreeScalar<bit U, bits<3> size, bits<5> opcode,
7318                        RegisterClass regtype, string asm,
7319                        list<dag> pattern>
7320  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm), asm,
7321      "\t$Rd, $Rn, $Rm", "", pattern>,
7322    Sched<[WriteVd]> {
7323  bits<5> Rd;
7324  bits<5> Rn;
7325  bits<5> Rm;
7326  let Inst{31-30} = 0b01;
7327  let Inst{29}    = U;
7328  let Inst{28-24} = 0b11110;
7329  let Inst{23-21} = size;
7330  let Inst{20-16} = Rm;
7331  let Inst{15-11} = opcode;
7332  let Inst{10}    = 1;
7333  let Inst{9-5}   = Rn;
7334  let Inst{4-0}   = Rd;
7335}
7336
7337let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
7338class BaseSIMDThreeScalarTied<bit U, bits<2> size, bit R, bits<5> opcode,
7339                        dag oops, dag iops, string asm,
7340            list<dag> pattern>
7341  : I<oops, iops, asm, "\t$Rd, $Rn, $Rm", "$Rd = $dst", pattern>,
7342    Sched<[WriteVd]> {
7343  bits<5> Rd;
7344  bits<5> Rn;
7345  bits<5> Rm;
7346  let Inst{31-30} = 0b01;
7347  let Inst{29}    = U;
7348  let Inst{28-24} = 0b11110;
7349  let Inst{23-22} = size;
7350  let Inst{21}    = R;
7351  let Inst{20-16} = Rm;
7352  let Inst{15-11} = opcode;
7353  let Inst{10}    = 1;
7354  let Inst{9-5}   = Rn;
7355  let Inst{4-0}   = Rd;
7356}
7357
7358multiclass SIMDThreeScalarD<bit U, bits<5> opc, string asm,
7359                            SDPatternOperator OpNode> {
7360  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7361    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7362}
7363
7364multiclass SIMDThreeScalarBHSD<bit U, bits<5> opc, string asm,
7365                               SDPatternOperator OpNode> {
7366  def v1i64  : BaseSIMDThreeScalar<U, 0b111, opc, FPR64, asm,
7367    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn), (v1i64 FPR64:$Rm)))]>;
7368  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm, []>;
7369  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7370  def v1i8   : BaseSIMDThreeScalar<U, 0b001, opc, FPR8 , asm, []>;
7371
7372  def : Pat<(i64 (OpNode (i64 FPR64:$Rn), (i64 FPR64:$Rm))),
7373            (!cast<Instruction>(NAME#"v1i64") FPR64:$Rn, FPR64:$Rm)>;
7374  def : Pat<(i32 (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm))),
7375            (!cast<Instruction>(NAME#"v1i32") FPR32:$Rn, FPR32:$Rm)>;
7376}
7377
7378multiclass SIMDThreeScalarHS<bit U, bits<5> opc, string asm,
7379                             SDPatternOperator OpNode> {
7380  def v1i32  : BaseSIMDThreeScalar<U, 0b101, opc, FPR32, asm,
7381                             [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7382  def v1i16  : BaseSIMDThreeScalar<U, 0b011, opc, FPR16, asm, []>;
7383}
7384
7385multiclass SIMDThreeScalarHSTied<bit U, bit R, bits<5> opc, string asm> {
7386  def v1i32: BaseSIMDThreeScalarTied<U, 0b10, R, opc, (outs FPR32:$dst),
7387                                     (ins FPR32:$Rd, FPR32:$Rn, FPR32:$Rm),
7388                                     asm, []>;
7389  def v1i16: BaseSIMDThreeScalarTied<U, 0b01, R, opc, (outs FPR16:$dst),
7390                                     (ins FPR16:$Rd, FPR16:$Rn, FPR16:$Rm),
7391                                     asm, []>;
7392}
7393
7394multiclass SIMDFPThreeScalar<bit U, bit S, bits<3> opc, string asm,
7395                             SDPatternOperator OpNode = null_frag,
7396                             Predicate pred = HasNEON> {
7397  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7398    let Predicates = [pred] in {
7399    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7400      [(set (f64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7401    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7402      [(set FPR32:$Rd, (OpNode FPR32:$Rn, FPR32:$Rm))]>;
7403    }
7404    let Predicates = [pred, HasFullFP16] in {
7405    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7406      [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn), (f16 FPR16:$Rm)))]>;
7407    }
7408  }
7409
7410  def : Pat<(v1f64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7411            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7412}
7413
7414multiclass SIMDThreeScalarFPCmp<bit U, bit S, bits<3> opc, string asm,
7415                                SDPatternOperator OpNode = null_frag> {
7416  let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in {
7417    def NAME#64 : BaseSIMDThreeScalar<U, {S,0b11}, {0b11,opc}, FPR64, asm,
7418      [(set (i64 FPR64:$Rd), (OpNode (f64 FPR64:$Rn), (f64 FPR64:$Rm)))]>;
7419    def NAME#32 : BaseSIMDThreeScalar<U, {S,0b01}, {0b11,opc}, FPR32, asm,
7420      [(set (i32 FPR32:$Rd), (OpNode (f32 FPR32:$Rn), (f32 FPR32:$Rm)))]>;
7421    let Predicates = [HasNEON, HasFullFP16] in {
7422    def NAME#16 : BaseSIMDThreeScalar<U, {S,0b10}, {0b00,opc}, FPR16, asm,
7423      []>;
7424    } // Predicates = [HasNEON, HasFullFP16]
7425  }
7426
7427  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn), (v1f64 FPR64:$Rm))),
7428            (!cast<Instruction>(NAME # "64") FPR64:$Rn, FPR64:$Rm)>;
7429}
7430
7431class BaseSIMDThreeScalarMixed<bit U, bits<2> size, bits<5> opcode,
7432              dag oops, dag iops, string asm, string cstr, list<dag> pat>
7433  : I<oops, iops, asm,
7434      "\t$Rd, $Rn, $Rm", cstr, pat>,
7435    Sched<[WriteVd]> {
7436  bits<5> Rd;
7437  bits<5> Rn;
7438  bits<5> Rm;
7439  let Inst{31-30} = 0b01;
7440  let Inst{29}    = U;
7441  let Inst{28-24} = 0b11110;
7442  let Inst{23-22} = size;
7443  let Inst{21}    = 1;
7444  let Inst{20-16} = Rm;
7445  let Inst{15-11} = opcode;
7446  let Inst{10}    = 0;
7447  let Inst{9-5}   = Rn;
7448  let Inst{4-0}   = Rd;
7449}
7450
7451let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7452multiclass SIMDThreeScalarMixedHS<bit U, bits<5> opc, string asm,
7453                                  SDPatternOperator OpNode = null_frag> {
7454  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7455                                      (outs FPR32:$Rd),
7456                                      (ins FPR16:$Rn, FPR16:$Rm), asm, "", []>;
7457  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7458                                      (outs FPR64:$Rd),
7459                                      (ins FPR32:$Rn, FPR32:$Rm), asm, "",
7460            [(set (i64 FPR64:$Rd), (OpNode (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7461}
7462
7463let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7464multiclass SIMDThreeScalarMixedTiedHS<bit U, bits<5> opc, string asm,
7465                                  SDPatternOperator OpNode = null_frag> {
7466  def i16  : BaseSIMDThreeScalarMixed<U, 0b01, opc,
7467                                      (outs FPR32:$dst),
7468                                      (ins FPR32:$Rd, FPR16:$Rn, FPR16:$Rm),
7469                                      asm, "$Rd = $dst", []>;
7470  def i32  : BaseSIMDThreeScalarMixed<U, 0b10, opc,
7471                                      (outs FPR64:$dst),
7472                                      (ins FPR64:$Rd, FPR32:$Rn, FPR32:$Rm),
7473                                      asm, "$Rd = $dst",
7474            [(set (i64 FPR64:$dst),
7475                  (OpNode (i64 FPR64:$Rd), (i32 FPR32:$Rn), (i32 FPR32:$Rm)))]>;
7476}
7477
7478//----------------------------------------------------------------------------
7479// AdvSIMD two register scalar instructions
7480//----------------------------------------------------------------------------
7481
7482let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7483class BaseSIMDTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7484                        RegisterClass regtype, RegisterClass regtype2,
7485                        string asm, list<dag> pat>
7486  : I<(outs regtype:$Rd), (ins regtype2:$Rn), asm,
7487      "\t$Rd, $Rn", "", pat>,
7488    Sched<[WriteVd]> {
7489  bits<5> Rd;
7490  bits<5> Rn;
7491  let Inst{31-30} = 0b01;
7492  let Inst{29}    = U;
7493  let Inst{28-24} = 0b11110;
7494  let Inst{23-22} = size;
7495  let Inst{21} = 0b1;
7496  let Inst{20-19} = size2;
7497  let Inst{18-17} = 0b00;
7498  let Inst{16-12} = opcode;
7499  let Inst{11-10} = 0b10;
7500  let Inst{9-5}   = Rn;
7501  let Inst{4-0}   = Rd;
7502}
7503
7504let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7505class BaseSIMDTwoScalarTied<bit U, bits<2> size, bits<5> opcode,
7506                        RegisterClass regtype, RegisterClass regtype2,
7507                        string asm, list<dag> pat>
7508  : I<(outs regtype:$dst), (ins regtype:$Rd, regtype2:$Rn), asm,
7509      "\t$Rd, $Rn", "$Rd = $dst", pat>,
7510    Sched<[WriteVd]> {
7511  bits<5> Rd;
7512  bits<5> Rn;
7513  let Inst{31-30} = 0b01;
7514  let Inst{29}    = U;
7515  let Inst{28-24} = 0b11110;
7516  let Inst{23-22} = size;
7517  let Inst{21-17} = 0b10000;
7518  let Inst{16-12} = opcode;
7519  let Inst{11-10} = 0b10;
7520  let Inst{9-5}   = Rn;
7521  let Inst{4-0}   = Rd;
7522}
7523
7524
7525let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7526class BaseSIMDCmpTwoScalar<bit U, bits<2> size, bits<2> size2, bits<5> opcode,
7527                        RegisterClass regtype, string asm, string zero>
7528  : I<(outs regtype:$Rd), (ins regtype:$Rn), asm,
7529      "\t$Rd, $Rn, #" # zero, "", []>,
7530    Sched<[WriteVd]> {
7531  bits<5> Rd;
7532  bits<5> Rn;
7533  let Inst{31-30} = 0b01;
7534  let Inst{29}    = U;
7535  let Inst{28-24} = 0b11110;
7536  let Inst{23-22} = size;
7537  let Inst{21} = 0b1;
7538  let Inst{20-19} = size2;
7539  let Inst{18-17} = 0b00;
7540  let Inst{16-12} = opcode;
7541  let Inst{11-10} = 0b10;
7542  let Inst{9-5}   = Rn;
7543  let Inst{4-0}   = Rd;
7544}
7545
7546let mayRaiseFPException = 1, Uses = [FPCR] in
7547class SIMDInexactCvtTwoScalar<bits<5> opcode, string asm>
7548  : I<(outs FPR32:$Rd), (ins FPR64:$Rn), asm, "\t$Rd, $Rn", "",
7549     [(set (f32 FPR32:$Rd), (int_aarch64_sisd_fcvtxn (f64 FPR64:$Rn)))]>,
7550    Sched<[WriteVd]> {
7551  bits<5> Rd;
7552  bits<5> Rn;
7553  let Inst{31-17} = 0b011111100110000;
7554  let Inst{16-12} = opcode;
7555  let Inst{11-10} = 0b10;
7556  let Inst{9-5}   = Rn;
7557  let Inst{4-0}   = Rd;
7558}
7559
7560multiclass SIMDCmpTwoScalarD<bit U, bits<5> opc, string asm,
7561                             SDPatternOperator OpNode> {
7562  def v1i64rz  : BaseSIMDCmpTwoScalar<U, 0b11, 0b00, opc, FPR64, asm, "0">;
7563
7564  def : Pat<(v1i64 (OpNode FPR64:$Rn)),
7565            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7566}
7567
7568multiclass SIMDFPCmpTwoScalar<bit U, bit S, bits<5> opc, string asm,
7569                              SDPatternOperator OpNode> {
7570  let mayRaiseFPException = 1, Uses = [FPCR] in {
7571  def v1i64rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b00, opc, FPR64, asm, "0.0">;
7572  def v1i32rz  : BaseSIMDCmpTwoScalar<U, {S,0}, 0b00, opc, FPR32, asm, "0.0">;
7573  let Predicates = [HasNEON, HasFullFP16] in {
7574  def v1i16rz  : BaseSIMDCmpTwoScalar<U, {S,1}, 0b11, opc, FPR16, asm, "0.0">;
7575  }
7576  }
7577
7578  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7579                  (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rd, FPR64:$Rn), 0>;
7580  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7581                  (!cast<Instruction>(NAME # v1i32rz) FPR32:$Rd, FPR32:$Rn), 0>;
7582  let Predicates = [HasNEON, HasFullFP16] in {
7583  def : InstAlias<asm # "\t$Rd, $Rn, #0",
7584                  (!cast<Instruction>(NAME # v1i16rz) FPR16:$Rd, FPR16:$Rn), 0>;
7585  }
7586
7587  def : Pat<(v1i64 (OpNode (v1f64 FPR64:$Rn))),
7588            (!cast<Instruction>(NAME # v1i64rz) FPR64:$Rn)>;
7589}
7590
7591multiclass SIMDTwoScalarD<bit U, bits<5> opc, string asm,
7592                          SDPatternOperator OpNode = null_frag,
7593                          list<Predicate> preds = []> {
7594  def v1i64       : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7595    [(set (v1i64 FPR64:$Rd), (OpNode (v1i64 FPR64:$Rn)))]>;
7596
7597  let Predicates = preds in {
7598  def : Pat<(i64 (OpNode (i64 FPR64:$Rn))),
7599            (!cast<Instruction>(NAME # "v1i64") FPR64:$Rn)>;
7600  }
7601}
7602
7603let mayRaiseFPException = 1, Uses = [FPCR] in
7604multiclass SIMDFPTwoScalar<bit U, bit S, bits<5> opc, string asm,
7605                           Predicate pred = HasNEON> {
7606  let Predicates = [pred] 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 = [pred, 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  def v1i64 : BaseSIMDTwoScalar<U, {S,1}, 0b00, opc, FPR64, FPR64, asm,
7619                                [(set FPR64:$Rd, (OpNode (f64 FPR64:$Rn)))]>;
7620  def v1i32 : BaseSIMDTwoScalar<U, {S,0}, 0b00, opc, FPR32, FPR32, asm,
7621                                [(set FPR32:$Rd, (OpNode (f32 FPR32:$Rn)))]>;
7622  let Predicates = [HasNEON, HasFullFP16] in {
7623  def v1i16 : BaseSIMDTwoScalar<U, {S,1}, 0b11, opc, FPR16, FPR16, asm,
7624                                [(set (f16 FPR16:$Rd), (OpNode (f16 FPR16:$Rn)))]>;
7625  }
7626}
7627
7628multiclass SIMDTwoScalarBHSD<bit U, bits<5> opc, string asm,
7629                             SDPatternOperator OpNode = null_frag> {
7630  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7631    def v1i64  : BaseSIMDTwoScalar<U, 0b11, 0b00, opc, FPR64, FPR64, asm,
7632           [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn)))]>;
7633    def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR32, asm,
7634           [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
7635    def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR16, asm, []>;
7636    def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR8 , asm, []>;
7637  }
7638
7639  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn))),
7640            (!cast<Instruction>(NAME # v1i64) FPR64:$Rn)>;
7641}
7642
7643multiclass SIMDTwoScalarBHSDTied<bit U, bits<5> opc, string asm,
7644                                 Intrinsic OpNode> {
7645  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
7646    def v1i64  : BaseSIMDTwoScalarTied<U, 0b11, opc, FPR64, FPR64, asm,
7647        [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn)))]>;
7648    def v1i32  : BaseSIMDTwoScalarTied<U, 0b10, opc, FPR32, FPR32, asm,
7649        [(set (i32 FPR32:$dst), (OpNode (i32 FPR32:$Rd), (i32 FPR32:$Rn)))]>;
7650    def v1i16  : BaseSIMDTwoScalarTied<U, 0b01, opc, FPR16, FPR16, asm, []>;
7651    def v1i8   : BaseSIMDTwoScalarTied<U, 0b00, opc, FPR8 , FPR8 , asm, []>;
7652  }
7653
7654  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn))),
7655            (!cast<Instruction>(NAME # v1i64) FPR64:$Rd, FPR64:$Rn)>;
7656}
7657
7658
7659
7660let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7661multiclass SIMDTwoScalarMixedBHS<bit U, bits<5> opc, string asm,
7662                                 SDPatternOperator OpNode = null_frag> {
7663  def v1i32  : BaseSIMDTwoScalar<U, 0b10, 0b00, opc, FPR32, FPR64, asm,
7664        [(set (f32 FPR32:$Rd), (OpNode (f64 FPR64:$Rn)))]>;
7665  def v1i16  : BaseSIMDTwoScalar<U, 0b01, 0b00, opc, FPR16, FPR32, asm, []>;
7666  def v1i8   : BaseSIMDTwoScalar<U, 0b00, 0b00, opc, FPR8 , FPR16, asm, []>;
7667}
7668
7669//----------------------------------------------------------------------------
7670// AdvSIMD scalar pairwise instructions
7671//----------------------------------------------------------------------------
7672
7673let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7674class BaseSIMDPairwiseScalar<bit U, bits<2> size, bits<5> opcode,
7675                        RegisterOperand regtype, RegisterOperand vectype,
7676                        string asm, string kind>
7677  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7678      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", []>,
7679    Sched<[WriteVd]> {
7680  bits<5> Rd;
7681  bits<5> Rn;
7682  let Inst{31-30} = 0b01;
7683  let Inst{29}    = U;
7684  let Inst{28-24} = 0b11110;
7685  let Inst{23-22} = size;
7686  let Inst{21-17} = 0b11000;
7687  let Inst{16-12} = opcode;
7688  let Inst{11-10} = 0b10;
7689  let Inst{9-5}   = Rn;
7690  let Inst{4-0}   = Rd;
7691}
7692
7693multiclass SIMDPairwiseScalarD<bit U, bits<5> opc, string asm> {
7694  def v2i64p : BaseSIMDPairwiseScalar<U, 0b11, opc, FPR64Op, V128,
7695                                      asm, ".2d">;
7696}
7697
7698let mayRaiseFPException = 1, Uses = [FPCR] in
7699multiclass SIMDFPPairwiseScalar<bit S, bits<5> opc, string asm> {
7700  let Predicates = [HasNEON, HasFullFP16] in {
7701  def v2i16p : BaseSIMDPairwiseScalar<0, {S,0}, opc, FPR16Op, V64,
7702                                      asm, ".2h">;
7703  }
7704  def v2i32p : BaseSIMDPairwiseScalar<1, {S,0}, opc, FPR32Op, V64,
7705                                      asm, ".2s">;
7706  def v2i64p : BaseSIMDPairwiseScalar<1, {S,1}, opc, FPR64Op, V128,
7707                                      asm, ".2d">;
7708}
7709
7710//----------------------------------------------------------------------------
7711// AdvSIMD across lanes instructions
7712//----------------------------------------------------------------------------
7713
7714let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
7715class BaseSIMDAcrossLanes<bit Q, bit U, bits<2> size, bits<5> opcode,
7716                          RegisterClass regtype, RegisterOperand vectype,
7717                          string asm, string kind, list<dag> pattern>
7718  : I<(outs regtype:$Rd), (ins vectype:$Rn), asm,
7719      "{\t$Rd, $Rn" # kind # "|" # kind # "\t$Rd, $Rn}", "", pattern>,
7720    Sched<[!if(Q, WriteVq, WriteVd)]> {
7721  bits<5> Rd;
7722  bits<5> Rn;
7723  let Inst{31}    = 0;
7724  let Inst{30}    = Q;
7725  let Inst{29}    = U;
7726  let Inst{28-24} = 0b01110;
7727  let Inst{23-22} = size;
7728  let Inst{21-17} = 0b11000;
7729  let Inst{16-12} = opcode;
7730  let Inst{11-10} = 0b10;
7731  let Inst{9-5}   = Rn;
7732  let Inst{4-0}   = Rd;
7733}
7734
7735multiclass SIMDAcrossLanesBHS<bit U, bits<5> opcode,
7736                              string asm> {
7737  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR8,  V64,
7738                                   asm, ".8b", []>;
7739  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR8,  V128,
7740                                   asm, ".16b", []>;
7741  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR16, V64,
7742                                   asm, ".4h", []>;
7743  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR16, V128,
7744                                   asm, ".8h", []>;
7745  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR32, V128,
7746                                   asm, ".4s", []>;
7747}
7748
7749multiclass SIMDAcrossLanesHSD<bit U, bits<5> opcode, string asm> {
7750  def v8i8v  : BaseSIMDAcrossLanes<0, U, 0b00, opcode, FPR16, V64,
7751                                   asm, ".8b", []>;
7752  def v16i8v : BaseSIMDAcrossLanes<1, U, 0b00, opcode, FPR16, V128,
7753                                   asm, ".16b", []>;
7754  def v4i16v : BaseSIMDAcrossLanes<0, U, 0b01, opcode, FPR32, V64,
7755                                   asm, ".4h", []>;
7756  def v8i16v : BaseSIMDAcrossLanes<1, U, 0b01, opcode, FPR32, V128,
7757                                   asm, ".8h", []>;
7758  def v4i32v : BaseSIMDAcrossLanes<1, U, 0b10, opcode, FPR64, V128,
7759                                   asm, ".4s", []>;
7760}
7761
7762let mayRaiseFPException = 1, Uses = [FPCR] in
7763multiclass SIMDFPAcrossLanes<bits<5> opcode, bit sz1, string asm,
7764                            SDPatternOperator intOp> {
7765  let Predicates = [HasNEON, HasFullFP16] in {
7766  def v4i16v : BaseSIMDAcrossLanes<0, 0, {sz1, 0}, opcode, FPR16, V64,
7767                                   asm, ".4h",
7768        [(set (f16 FPR16:$Rd), (intOp (v4f16 V64:$Rn)))]>;
7769  def v8i16v : BaseSIMDAcrossLanes<1, 0, {sz1, 0}, opcode, FPR16, V128,
7770                                   asm, ".8h",
7771        [(set (f16 FPR16:$Rd), (intOp (v8f16 V128:$Rn)))]>;
7772  } // Predicates = [HasNEON, HasFullFP16]
7773  def v4i32v : BaseSIMDAcrossLanes<1, 1, {sz1, 0}, opcode, FPR32, V128,
7774                                   asm, ".4s",
7775        [(set FPR32:$Rd, (intOp (v4f32 V128:$Rn)))]>;
7776}
7777
7778//----------------------------------------------------------------------------
7779// AdvSIMD INS/DUP instructions
7780//----------------------------------------------------------------------------
7781
7782// FIXME: There has got to be a better way to factor these. ugh.
7783
7784class BaseSIMDInsDup<bit Q, bit op, dag outs, dag ins, string asm,
7785                     string operands, string constraints, list<dag> pattern>
7786  : I<outs, ins, asm, operands, constraints, pattern>,
7787    Sched<[!if(Q, WriteVq, WriteVd)]> {
7788  bits<5> Rd;
7789  bits<5> Rn;
7790  let Inst{31} = 0;
7791  let Inst{30} = Q;
7792  let Inst{29} = op;
7793  let Inst{28-21} = 0b01110000;
7794  let Inst{15} = 0;
7795  let Inst{10} = 1;
7796  let Inst{9-5} = Rn;
7797  let Inst{4-0} = Rd;
7798}
7799
7800class SIMDDupFromMain<bit Q, bits<5> imm5, string size, ValueType vectype,
7801                      RegisterOperand vecreg, RegisterClass regtype>
7802  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins regtype:$Rn), "dup",
7803                   "{\t$Rd" # size # ", $Rn" #
7804                   "|" # size # "\t$Rd, $Rn}", "",
7805                   [(set (vectype vecreg:$Rd), (AArch64dup regtype:$Rn))]> {
7806  let Inst{20-16} = imm5;
7807  let Inst{14-11} = 0b0001;
7808}
7809
7810class SIMDDupFromElement<bit Q, string dstkind, string srckind,
7811                         ValueType vectype, ValueType insreg,
7812                         RegisterOperand vecreg, Operand idxtype,
7813                         SDNode OpNode>
7814  : BaseSIMDInsDup<Q, 0, (outs vecreg:$Rd), (ins V128:$Rn, idxtype:$idx), "dup",
7815                   "{\t$Rd" # dstkind # ", $Rn" # srckind # "$idx" #
7816                   "|" # dstkind # "\t$Rd, $Rn$idx}", "",
7817                 [(set (vectype vecreg:$Rd),
7818                       (OpNode (insreg V128:$Rn), idxtype:$idx))]> {
7819  let Inst{14-11} = 0b0000;
7820}
7821
7822class SIMDDup64FromElement
7823  : SIMDDupFromElement<1, ".2d", ".d", v2i64, v2i64, V128,
7824                       VectorIndexD, AArch64duplane64> {
7825  bits<1> idx;
7826  let Inst{20} = idx;
7827  let Inst{19-16} = 0b1000;
7828}
7829
7830class SIMDDup32FromElement<bit Q, string size, ValueType vectype,
7831                           RegisterOperand vecreg>
7832  : SIMDDupFromElement<Q, size, ".s", vectype, v4i32, vecreg,
7833                       VectorIndexS, AArch64duplane32> {
7834  bits<2> idx;
7835  let Inst{20-19} = idx;
7836  let Inst{18-16} = 0b100;
7837}
7838
7839class SIMDDup16FromElement<bit Q, string size, ValueType vectype,
7840                           RegisterOperand vecreg>
7841  : SIMDDupFromElement<Q, size, ".h", vectype, v8i16, vecreg,
7842                       VectorIndexH, AArch64duplane16> {
7843  bits<3> idx;
7844  let Inst{20-18} = idx;
7845  let Inst{17-16} = 0b10;
7846}
7847
7848class SIMDDup8FromElement<bit Q, string size, ValueType vectype,
7849                          RegisterOperand vecreg>
7850  : SIMDDupFromElement<Q, size, ".b", vectype, v16i8, vecreg,
7851                       VectorIndexB, AArch64duplane8> {
7852  bits<4> idx;
7853  let Inst{20-17} = idx;
7854  let Inst{16} = 1;
7855}
7856
7857class BaseSIMDMov<bit Q, string size, bits<4> imm4, RegisterClass regtype,
7858                  Operand idxtype, string asm, list<dag> pattern>
7859  : BaseSIMDInsDup<Q, 0, (outs regtype:$Rd), (ins V128:$Rn, idxtype:$idx), asm,
7860                   "{\t$Rd, $Rn" # size # "$idx" #
7861                   "|" # size # "\t$Rd, $Rn$idx}", "", pattern> {
7862  let Inst{14-11} = imm4;
7863}
7864
7865class SIMDSMov<bit Q, string size, RegisterClass regtype,
7866               Operand idxtype>
7867  : BaseSIMDMov<Q, size, 0b0101, regtype, idxtype, "smov", []>;
7868class SIMDUMov<bit Q, string size, ValueType vectype, RegisterClass regtype,
7869               Operand idxtype>
7870  : BaseSIMDMov<Q, size, 0b0111, regtype, idxtype, "umov",
7871      [(set regtype:$Rd, (vector_extract (vectype V128:$Rn), idxtype:$idx))]>;
7872
7873class SIMDMovAlias<string asm, string size, Instruction inst,
7874                   RegisterClass regtype, Operand idxtype>
7875    : InstAlias<asm#"{\t$dst, $src"#size#"$idx" #
7876                    "|" # size # "\t$dst, $src$idx}",
7877                (inst regtype:$dst, V128:$src, idxtype:$idx)>;
7878
7879multiclass SMov {
7880  // SMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7881  // streaming mode.
7882  let Predicates = [HasNEONorSME] in {
7883    def vi8to32_idx0 : SIMDSMov<0, ".b", GPR32, VectorIndex0> {
7884      let Inst{20-16} = 0b00001;
7885    }
7886    def vi8to64_idx0 : SIMDSMov<1, ".b", GPR64, VectorIndex0> {
7887      let Inst{20-16} = 0b00001;
7888    }
7889    def vi16to32_idx0 : SIMDSMov<0, ".h", GPR32, VectorIndex0> {
7890      let Inst{20-16} = 0b00010;
7891    }
7892    def vi16to64_idx0 : SIMDSMov<1, ".h", GPR64, VectorIndex0> {
7893      let Inst{20-16} = 0b00010;
7894    }
7895    def vi32to64_idx0 : SIMDSMov<1, ".s", GPR64, VectorIndex0> {
7896      let Inst{20-16} = 0b00100;
7897    }
7898  }
7899  def vi8to32 : SIMDSMov<0, ".b", GPR32, VectorIndexB> {
7900    bits<4> idx;
7901    let Inst{20-17} = idx;
7902    let Inst{16} = 1;
7903  }
7904  def vi8to64 : SIMDSMov<1, ".b", GPR64, VectorIndexB> {
7905    bits<4> idx;
7906    let Inst{20-17} = idx;
7907    let Inst{16} = 1;
7908  }
7909  def vi16to32 : SIMDSMov<0, ".h", GPR32, VectorIndexH> {
7910    bits<3> idx;
7911    let Inst{20-18} = idx;
7912    let Inst{17-16} = 0b10;
7913  }
7914  def vi16to64 : SIMDSMov<1, ".h", GPR64, VectorIndexH> {
7915    bits<3> idx;
7916    let Inst{20-18} = idx;
7917    let Inst{17-16} = 0b10;
7918  }
7919  def vi32to64 : SIMDSMov<1, ".s", GPR64, VectorIndexS> {
7920    bits<2> idx;
7921    let Inst{20-19} = idx;
7922    let Inst{18-16} = 0b100;
7923  }
7924}
7925
7926multiclass UMov {
7927  // UMOV with vector index of 0 are legal in Scalable Matrix Extension (SME)
7928  // streaming mode.
7929  let Predicates = [HasNEONorSME] in {
7930    def vi8_idx0 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndex0> {
7931      let Inst{20-16} = 0b00001;
7932    }
7933    def vi16_idx0 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndex0> {
7934      let Inst{20-16} = 0b00010;
7935    }
7936    def vi32_idx0 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndex0> {
7937      let Inst{20-16} = 0b00100;
7938    }
7939    def vi64_idx0 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndex0> {
7940      let Inst{20-16} = 0b01000;
7941    }
7942    def : SIMDMovAlias<"mov", ".s",
7943                       !cast<Instruction>(NAME # vi32_idx0),
7944                       GPR32, VectorIndex0>;
7945    def : SIMDMovAlias<"mov", ".d",
7946                       !cast<Instruction>(NAME # vi64_idx0),
7947                       GPR64, VectorIndex0>;
7948  }
7949  def vi8 : SIMDUMov<0, ".b", v16i8, GPR32, VectorIndexB> {
7950    bits<4> idx;
7951    let Inst{20-17} = idx;
7952    let Inst{16} = 1;
7953  }
7954  def vi16 : SIMDUMov<0, ".h", v8i16, GPR32, VectorIndexH> {
7955    bits<3> idx;
7956    let Inst{20-18} = idx;
7957    let Inst{17-16} = 0b10;
7958  }
7959  def vi32 : SIMDUMov<0, ".s", v4i32, GPR32, VectorIndexS> {
7960    bits<2> idx;
7961    let Inst{20-19} = idx;
7962    let Inst{18-16} = 0b100;
7963  }
7964  def vi64 : SIMDUMov<1, ".d", v2i64, GPR64, VectorIndexD> {
7965    bits<1> idx;
7966    let Inst{20} = idx;
7967    let Inst{19-16} = 0b1000;
7968  }
7969  def : SIMDMovAlias<"mov", ".s",
7970                     !cast<Instruction>(NAME#"vi32"),
7971                     GPR32, VectorIndexS>;
7972  def : SIMDMovAlias<"mov", ".d",
7973                     !cast<Instruction>(NAME#"vi64"),
7974                     GPR64, VectorIndexD>;
7975}
7976
7977class SIMDInsFromMain<string size, ValueType vectype,
7978                      RegisterClass regtype, Operand idxtype>
7979  : BaseSIMDInsDup<1, 0, (outs V128:$dst),
7980                   (ins V128:$Rd, idxtype:$idx, regtype:$Rn), "ins",
7981                   "{\t$Rd" # size # "$idx, $Rn" #
7982                   "|" # size # "\t$Rd$idx, $Rn}",
7983                   "$Rd = $dst",
7984            [(set V128:$dst,
7985              (vector_insert (vectype V128:$Rd), regtype:$Rn, idxtype:$idx))]> {
7986  let Inst{14-11} = 0b0011;
7987}
7988
7989class SIMDInsFromElement<string size, ValueType vectype,
7990                         ValueType elttype, Operand idxtype>
7991  : BaseSIMDInsDup<1, 1, (outs V128:$dst),
7992                   (ins V128:$Rd, idxtype:$idx, V128:$Rn, idxtype:$idx2), "ins",
7993                   "{\t$Rd" # size # "$idx, $Rn" # size # "$idx2" #
7994                   "|" # size # "\t$Rd$idx, $Rn$idx2}",
7995                   "$Rd = $dst",
7996         [(set V128:$dst,
7997               (vector_insert
7998                 (vectype V128:$Rd),
7999                 (elttype (vector_extract (vectype V128:$Rn), idxtype:$idx2)),
8000                 idxtype:$idx))]>;
8001
8002class SIMDInsMainMovAlias<string size, Instruction inst,
8003                          RegisterClass regtype, Operand idxtype>
8004    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" #
8005                        "|" # size #"\t$dst$idx, $src}",
8006                (inst V128:$dst, idxtype:$idx, regtype:$src)>;
8007class SIMDInsElementMovAlias<string size, Instruction inst,
8008                             Operand idxtype>
8009    : InstAlias<"mov" # "{\t$dst" # size # "$idx, $src" # size # "$idx2"
8010                      # "|" # size #"\t$dst$idx, $src$idx2}",
8011                (inst V128:$dst, idxtype:$idx, V128:$src, idxtype:$idx2)>;
8012
8013
8014multiclass SIMDIns {
8015  def vi8gpr : SIMDInsFromMain<".b", v16i8, GPR32, VectorIndexB> {
8016    bits<4> idx;
8017    let Inst{20-17} = idx;
8018    let Inst{16} = 1;
8019  }
8020  def vi16gpr : SIMDInsFromMain<".h", v8i16, GPR32, VectorIndexH> {
8021    bits<3> idx;
8022    let Inst{20-18} = idx;
8023    let Inst{17-16} = 0b10;
8024  }
8025  def vi32gpr : SIMDInsFromMain<".s", v4i32, GPR32, VectorIndexS> {
8026    bits<2> idx;
8027    let Inst{20-19} = idx;
8028    let Inst{18-16} = 0b100;
8029  }
8030  def vi64gpr : SIMDInsFromMain<".d", v2i64, GPR64, VectorIndexD> {
8031    bits<1> idx;
8032    let Inst{20} = idx;
8033    let Inst{19-16} = 0b1000;
8034  }
8035
8036  def vi8lane : SIMDInsFromElement<".b", v16i8, i32, VectorIndexB> {
8037    bits<4> idx;
8038    bits<4> idx2;
8039    let Inst{20-17} = idx;
8040    let Inst{16} = 1;
8041    let Inst{14-11} = idx2;
8042  }
8043  def vi16lane : SIMDInsFromElement<".h", v8i16, i32, VectorIndexH> {
8044    bits<3> idx;
8045    bits<3> idx2;
8046    let Inst{20-18} = idx;
8047    let Inst{17-16} = 0b10;
8048    let Inst{14-12} = idx2;
8049    let Inst{11} = {?};
8050  }
8051  def vi32lane : SIMDInsFromElement<".s", v4i32, i32, VectorIndexS> {
8052    bits<2> idx;
8053    bits<2> idx2;
8054    let Inst{20-19} = idx;
8055    let Inst{18-16} = 0b100;
8056    let Inst{14-13} = idx2;
8057    let Inst{12-11} = {?,?};
8058  }
8059  def vi64lane : SIMDInsFromElement<".d", v2i64, i64, VectorIndexD> {
8060    bits<1> idx;
8061    bits<1> idx2;
8062    let Inst{20} = idx;
8063    let Inst{19-16} = 0b1000;
8064    let Inst{14} = idx2;
8065    let Inst{13-11} = {?,?,?};
8066  }
8067
8068  // For all forms of the INS instruction, the "mov" mnemonic is the
8069  // preferred alias. Why they didn't just call the instruction "mov" in
8070  // the first place is a very good question indeed...
8071  def : SIMDInsMainMovAlias<".b", !cast<Instruction>(NAME#"vi8gpr"),
8072                         GPR32, VectorIndexB>;
8073  def : SIMDInsMainMovAlias<".h", !cast<Instruction>(NAME#"vi16gpr"),
8074                         GPR32, VectorIndexH>;
8075  def : SIMDInsMainMovAlias<".s", !cast<Instruction>(NAME#"vi32gpr"),
8076                         GPR32, VectorIndexS>;
8077  def : SIMDInsMainMovAlias<".d", !cast<Instruction>(NAME#"vi64gpr"),
8078                         GPR64, VectorIndexD>;
8079
8080  def : SIMDInsElementMovAlias<".b", !cast<Instruction>(NAME#"vi8lane"),
8081                         VectorIndexB>;
8082  def : SIMDInsElementMovAlias<".h", !cast<Instruction>(NAME#"vi16lane"),
8083                         VectorIndexH>;
8084  def : SIMDInsElementMovAlias<".s", !cast<Instruction>(NAME#"vi32lane"),
8085                         VectorIndexS>;
8086  def : SIMDInsElementMovAlias<".d", !cast<Instruction>(NAME#"vi64lane"),
8087                         VectorIndexD>;
8088}
8089
8090//----------------------------------------------------------------------------
8091// AdvSIMD TBL/TBX
8092//----------------------------------------------------------------------------
8093
8094let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8095class BaseSIMDTableLookup<bit Q, bits<2> len, bit op, RegisterOperand vectype,
8096                          RegisterOperand listtype, string asm, string kind>
8097  : I<(outs vectype:$Vd), (ins listtype:$Vn, vectype:$Vm), asm,
8098       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "", []>,
8099    Sched<[!if(Q, WriteVq, WriteVd)]> {
8100  bits<5> Vd;
8101  bits<5> Vn;
8102  bits<5> Vm;
8103  let Inst{31}    = 0;
8104  let Inst{30}    = Q;
8105  let Inst{29-21} = 0b001110000;
8106  let Inst{20-16} = Vm;
8107  let Inst{15}    = 0;
8108  let Inst{14-13} = len;
8109  let Inst{12}    = op;
8110  let Inst{11-10} = 0b00;
8111  let Inst{9-5}   = Vn;
8112  let Inst{4-0}   = Vd;
8113}
8114
8115let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
8116class BaseSIMDTableLookupTied<bit Q, bits<2> len, bit op, RegisterOperand vectype,
8117                          RegisterOperand listtype, string asm, string kind>
8118  : I<(outs vectype:$dst), (ins vectype:$Vd, listtype:$Vn, vectype:$Vm), asm,
8119       "\t$Vd" # kind # ", $Vn, $Vm" # kind, "$Vd = $dst", []>,
8120    Sched<[!if(Q, WriteVq, WriteVd)]> {
8121  bits<5> Vd;
8122  bits<5> Vn;
8123  bits<5> Vm;
8124  let Inst{31}    = 0;
8125  let Inst{30}    = Q;
8126  let Inst{29-21} = 0b001110000;
8127  let Inst{20-16} = Vm;
8128  let Inst{15}    = 0;
8129  let Inst{14-13} = len;
8130  let Inst{12}    = op;
8131  let Inst{11-10} = 0b00;
8132  let Inst{9-5}   = Vn;
8133  let Inst{4-0}   = Vd;
8134}
8135
8136class SIMDTableLookupAlias<string asm, Instruction inst,
8137                          RegisterOperand vectype, RegisterOperand listtype>
8138    : InstAlias<!strconcat(asm, "\t$dst, $lst, $index"),
8139                (inst vectype:$dst, listtype:$lst, vectype:$index), 0>;
8140
8141multiclass SIMDTableLookup<bit op, string asm> {
8142  def v8i8One   : BaseSIMDTableLookup<0, 0b00, op, V64, VecListOne16b,
8143                                      asm, ".8b">;
8144  def v8i8Two   : BaseSIMDTableLookup<0, 0b01, op, V64, VecListTwo16b,
8145                                      asm, ".8b">;
8146  def v8i8Three : BaseSIMDTableLookup<0, 0b10, op, V64, VecListThree16b,
8147                                      asm, ".8b">;
8148  def v8i8Four  : BaseSIMDTableLookup<0, 0b11, op, V64, VecListFour16b,
8149                                      asm, ".8b">;
8150  def v16i8One  : BaseSIMDTableLookup<1, 0b00, op, V128, VecListOne16b,
8151                                      asm, ".16b">;
8152  def v16i8Two  : BaseSIMDTableLookup<1, 0b01, op, V128, VecListTwo16b,
8153                                      asm, ".16b">;
8154  def v16i8Three: BaseSIMDTableLookup<1, 0b10, op, V128, VecListThree16b,
8155                                      asm, ".16b">;
8156  def v16i8Four : BaseSIMDTableLookup<1, 0b11, op, V128, VecListFour16b,
8157                                      asm, ".16b">;
8158
8159  def : SIMDTableLookupAlias<asm # ".8b",
8160                         !cast<Instruction>(NAME#"v8i8One"),
8161                         V64, VecListOne128>;
8162  def : SIMDTableLookupAlias<asm # ".8b",
8163                         !cast<Instruction>(NAME#"v8i8Two"),
8164                         V64, VecListTwo128>;
8165  def : SIMDTableLookupAlias<asm # ".8b",
8166                         !cast<Instruction>(NAME#"v8i8Three"),
8167                         V64, VecListThree128>;
8168  def : SIMDTableLookupAlias<asm # ".8b",
8169                         !cast<Instruction>(NAME#"v8i8Four"),
8170                         V64, VecListFour128>;
8171  def : SIMDTableLookupAlias<asm # ".16b",
8172                         !cast<Instruction>(NAME#"v16i8One"),
8173                         V128, VecListOne128>;
8174  def : SIMDTableLookupAlias<asm # ".16b",
8175                         !cast<Instruction>(NAME#"v16i8Two"),
8176                         V128, VecListTwo128>;
8177  def : SIMDTableLookupAlias<asm # ".16b",
8178                         !cast<Instruction>(NAME#"v16i8Three"),
8179                         V128, VecListThree128>;
8180  def : SIMDTableLookupAlias<asm # ".16b",
8181                         !cast<Instruction>(NAME#"v16i8Four"),
8182                         V128, VecListFour128>;
8183}
8184
8185multiclass SIMDTableLookupTied<bit op, string asm> {
8186  def v8i8One   : BaseSIMDTableLookupTied<0, 0b00, op, V64, VecListOne16b,
8187                                      asm, ".8b">;
8188  def v8i8Two   : BaseSIMDTableLookupTied<0, 0b01, op, V64, VecListTwo16b,
8189                                      asm, ".8b">;
8190  def v8i8Three : BaseSIMDTableLookupTied<0, 0b10, op, V64, VecListThree16b,
8191                                      asm, ".8b">;
8192  def v8i8Four  : BaseSIMDTableLookupTied<0, 0b11, op, V64, VecListFour16b,
8193                                      asm, ".8b">;
8194  def v16i8One  : BaseSIMDTableLookupTied<1, 0b00, op, V128, VecListOne16b,
8195                                      asm, ".16b">;
8196  def v16i8Two  : BaseSIMDTableLookupTied<1, 0b01, op, V128, VecListTwo16b,
8197                                      asm, ".16b">;
8198  def v16i8Three: BaseSIMDTableLookupTied<1, 0b10, op, V128, VecListThree16b,
8199                                      asm, ".16b">;
8200  def v16i8Four : BaseSIMDTableLookupTied<1, 0b11, op, V128, VecListFour16b,
8201                                      asm, ".16b">;
8202
8203  def : SIMDTableLookupAlias<asm # ".8b",
8204                         !cast<Instruction>(NAME#"v8i8One"),
8205                         V64, VecListOne128>;
8206  def : SIMDTableLookupAlias<asm # ".8b",
8207                         !cast<Instruction>(NAME#"v8i8Two"),
8208                         V64, VecListTwo128>;
8209  def : SIMDTableLookupAlias<asm # ".8b",
8210                         !cast<Instruction>(NAME#"v8i8Three"),
8211                         V64, VecListThree128>;
8212  def : SIMDTableLookupAlias<asm # ".8b",
8213                         !cast<Instruction>(NAME#"v8i8Four"),
8214                         V64, VecListFour128>;
8215  def : SIMDTableLookupAlias<asm # ".16b",
8216                         !cast<Instruction>(NAME#"v16i8One"),
8217                         V128, VecListOne128>;
8218  def : SIMDTableLookupAlias<asm # ".16b",
8219                         !cast<Instruction>(NAME#"v16i8Two"),
8220                         V128, VecListTwo128>;
8221  def : SIMDTableLookupAlias<asm # ".16b",
8222                         !cast<Instruction>(NAME#"v16i8Three"),
8223                         V128, VecListThree128>;
8224  def : SIMDTableLookupAlias<asm # ".16b",
8225                         !cast<Instruction>(NAME#"v16i8Four"),
8226                         V128, VecListFour128>;
8227}
8228
8229//----------------------------------------------------------------------------
8230// AdvSIMD LUT
8231//----------------------------------------------------------------------------
8232let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8233class BaseSIMDTableLookupIndexed<bit Q, bits<5> opc, RegisterOperand vectype,
8234                            RegisterOperand listtype, Operand idx_type,
8235                            string asm, string kind>
8236  : I<(outs vectype:$Rd),
8237      (ins listtype:$Rn, vectype:$Rm, idx_type:$idx),
8238      asm, "\t$Rd" # kind # ", $Rn, $Rm$idx", "", []>,
8239    Sched<[]> {
8240  bits<5> Rd;
8241  bits<5> Rn;
8242  bits<5> Rm;
8243  let Inst{31}    = 0;
8244  let Inst{30}    = Q;
8245  let Inst{29-24} = 0b001110;
8246  let Inst{23-22} = opc{4-3};
8247  let Inst{21}    = 0;
8248  let Inst{20-16} = Rm;
8249  let Inst{15}    = 0;
8250  let Inst{14-12} = opc{2-0};
8251  let Inst{11-10} = 0b00;
8252  let Inst{9-5}   = Rn;
8253  let Inst{4-0}   = Rd;
8254}
8255
8256multiclass BaseSIMDTableLookupIndexed2<string asm> {
8257  def v16f8 : BaseSIMDTableLookupIndexed<0b1, {0b10,?,?,0b1}, V128, VecListOne16b, VectorIndexS, asm, ".16b"> {
8258    bits<2> idx;
8259    let Inst{14-13} = idx;
8260  }
8261  def v8f16 : BaseSIMDTableLookupIndexed<0b1, {0b11,?,?,?}, V128, VecListOne8h, VectorIndexH, asm, ".8h" > {
8262    bits<3> idx;
8263    let Inst{14-12} = idx;
8264  }
8265}
8266
8267multiclass BaseSIMDTableLookupIndexed4<string asm> {
8268  def v16f8 : BaseSIMDTableLookupIndexed<0b1, {0b01,?,0b10}, V128, VecListOne16b, VectorIndexD, asm, ".16b"> {
8269    bit idx;
8270    let Inst{14} = idx;
8271  }
8272  def v8f16 : BaseSIMDTableLookupIndexed<0b1, {0b01,?,?,0b1}, V128, VecListTwo8h, VectorIndexS, asm, ".8h" > {
8273    bits<2> idx;
8274    let Inst{14-13} = idx;
8275  }
8276}
8277
8278//----------------------------------------------------------------------------
8279// AdvSIMD scalar DUP
8280//----------------------------------------------------------------------------
8281let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8282class BaseSIMDScalarDUP<RegisterClass regtype, RegisterOperand vectype,
8283                        string asm, string kind, Operand idxtype>
8284  : I<(outs regtype:$dst), (ins vectype:$src, idxtype:$idx), asm,
8285       "{\t$dst, $src" # kind # "$idx" #
8286       "|\t$dst, $src$idx}", "", []>,
8287    Sched<[WriteVd]> {
8288  bits<5> dst;
8289  bits<5> src;
8290  let Inst{31-21} = 0b01011110000;
8291  let Inst{15-10} = 0b000001;
8292  let Inst{9-5}   = src;
8293  let Inst{4-0}   = dst;
8294}
8295
8296class SIMDScalarDUPAlias<string asm, string size, Instruction inst,
8297      RegisterClass regtype, RegisterOperand vectype, Operand idxtype>
8298    : InstAlias<asm # "{\t$dst, $src" # size # "$index"
8299                    # "|\t$dst, $src$index}",
8300                (inst regtype:$dst, vectype:$src, idxtype:$index), 0>;
8301
8302
8303multiclass SIMDScalarDUP<string asm> {
8304  def i8  : BaseSIMDScalarDUP<FPR8,  V128, asm, ".b", VectorIndexB> {
8305    bits<4> idx;
8306    let Inst{20-17} = idx;
8307    let Inst{16} = 1;
8308  }
8309  def i16 : BaseSIMDScalarDUP<FPR16, V128, asm, ".h", VectorIndexH> {
8310    bits<3> idx;
8311    let Inst{20-18} = idx;
8312    let Inst{17-16} = 0b10;
8313  }
8314  def i32 : BaseSIMDScalarDUP<FPR32, V128, asm, ".s", VectorIndexS> {
8315    bits<2> idx;
8316    let Inst{20-19} = idx;
8317    let Inst{18-16} = 0b100;
8318  }
8319  def i64 : BaseSIMDScalarDUP<FPR64, V128, asm, ".d", VectorIndexD> {
8320    bits<1> idx;
8321    let Inst{20} = idx;
8322    let Inst{19-16} = 0b1000;
8323  }
8324
8325  def : Pat<(v1i64 (scalar_to_vector (i64 (vector_extract (v2i64 V128:$src),
8326                                                          VectorIndexD:$idx)))),
8327            (!cast<Instruction>(NAME # i64) V128:$src, VectorIndexD:$idx)>;
8328
8329  // 'DUP' mnemonic aliases.
8330  def : SIMDScalarDUPAlias<"dup", ".b",
8331                           !cast<Instruction>(NAME#"i8"),
8332                           FPR8, V128, VectorIndexB>;
8333  def : SIMDScalarDUPAlias<"dup", ".h",
8334                           !cast<Instruction>(NAME#"i16"),
8335                           FPR16, V128, VectorIndexH>;
8336  def : SIMDScalarDUPAlias<"dup", ".s",
8337                           !cast<Instruction>(NAME#"i32"),
8338                           FPR32, V128, VectorIndexS>;
8339  def : SIMDScalarDUPAlias<"dup", ".d",
8340                           !cast<Instruction>(NAME#"i64"),
8341                           FPR64, V128, VectorIndexD>;
8342}
8343
8344//----------------------------------------------------------------------------
8345// AdvSIMD modified immediate instructions
8346//----------------------------------------------------------------------------
8347
8348class BaseSIMDModifiedImm<bit Q, bit op, bit op2, dag oops, dag iops,
8349                          string asm, string op_string,
8350                          string cstr, list<dag> pattern>
8351  : I<oops, iops, asm, op_string, cstr, pattern>,
8352    Sched<[!if(Q, WriteVq, WriteVd)]> {
8353  bits<5> Rd;
8354  bits<8> imm8;
8355  let Inst{31}    = 0;
8356  let Inst{30}    = Q;
8357  let Inst{29}    = op;
8358  let Inst{28-19} = 0b0111100000;
8359  let Inst{18-16} = imm8{7-5};
8360  let Inst{11} = op2;
8361  let Inst{10} = 1;
8362  let Inst{9-5}   = imm8{4-0};
8363  let Inst{4-0}   = Rd;
8364}
8365
8366class BaseSIMDModifiedImmVector<bit Q, bit op, bit op2, RegisterOperand vectype,
8367                                Operand immtype, dag opt_shift_iop,
8368                                string opt_shift, string asm, string kind,
8369                                list<dag> pattern>
8370  : BaseSIMDModifiedImm<Q, op, op2, (outs vectype:$Rd),
8371                        !con((ins immtype:$imm8), opt_shift_iop), asm,
8372                        "{\t$Rd" # kind # ", $imm8" # opt_shift #
8373                        "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8374                        "", pattern> {
8375  let DecoderMethod = "DecodeModImmInstruction";
8376}
8377
8378class BaseSIMDModifiedImmVectorTied<bit Q, bit op, RegisterOperand vectype,
8379                                Operand immtype, dag opt_shift_iop,
8380                                string opt_shift, string asm, string kind,
8381                                list<dag> pattern>
8382  : BaseSIMDModifiedImm<Q, op, 0, (outs vectype:$dst),
8383                        !con((ins vectype:$Rd, immtype:$imm8), opt_shift_iop),
8384                        asm, "{\t$Rd" # kind # ", $imm8" # opt_shift #
8385                             "|" # kind # "\t$Rd, $imm8" # opt_shift # "}",
8386                        "$Rd = $dst", pattern> {
8387  let DecoderMethod = "DecodeModImmTiedInstruction";
8388}
8389
8390class BaseSIMDModifiedImmVectorShift<bit Q, bit op, bits<2> b15_b12,
8391                                     RegisterOperand vectype, string asm,
8392                                     string kind, list<dag> pattern>
8393  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8394                              (ins logical_vec_shift:$shift),
8395                              "$shift", asm, kind, pattern> {
8396  bits<2> shift;
8397  let Inst{15}    = b15_b12{1};
8398  let Inst{14-13} = shift;
8399  let Inst{12}    = b15_b12{0};
8400}
8401
8402class BaseSIMDModifiedImmVectorShiftTied<bit Q, bit op, bits<2> b15_b12,
8403                                     RegisterOperand vectype, string asm,
8404                                     string kind, list<dag> pattern>
8405  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8406                              (ins logical_vec_shift:$shift),
8407                              "$shift", asm, kind, pattern> {
8408  bits<2> shift;
8409  let Inst{15}    = b15_b12{1};
8410  let Inst{14-13} = shift;
8411  let Inst{12}    = b15_b12{0};
8412}
8413
8414
8415class BaseSIMDModifiedImmVectorShiftHalf<bit Q, bit op, bits<2> b15_b12,
8416                                         RegisterOperand vectype, string asm,
8417                                         string kind, list<dag> pattern>
8418  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8419                              (ins logical_vec_hw_shift:$shift),
8420                              "$shift", asm, kind, pattern> {
8421  bits<2> shift;
8422  let Inst{15} = b15_b12{1};
8423  let Inst{14} = 0;
8424  let Inst{13} = shift{0};
8425  let Inst{12} = b15_b12{0};
8426}
8427
8428class BaseSIMDModifiedImmVectorShiftHalfTied<bit Q, bit op, bits<2> b15_b12,
8429                                         RegisterOperand vectype, string asm,
8430                                         string kind, list<dag> pattern>
8431  : BaseSIMDModifiedImmVectorTied<Q, op, vectype, imm0_255,
8432                              (ins logical_vec_hw_shift:$shift),
8433                              "$shift", asm, kind, pattern> {
8434  bits<2> shift;
8435  let Inst{15} = b15_b12{1};
8436  let Inst{14} = 0;
8437  let Inst{13} = shift{0};
8438  let Inst{12} = b15_b12{0};
8439}
8440
8441multiclass SIMDModifiedImmVectorShift<bit op, bits<2> hw_cmode, bits<2> w_cmode,
8442                                      string asm> {
8443  def v4i16 : BaseSIMDModifiedImmVectorShiftHalf<0, op, hw_cmode, V64,
8444                                                 asm, ".4h", []>;
8445  def v8i16 : BaseSIMDModifiedImmVectorShiftHalf<1, op, hw_cmode, V128,
8446                                                 asm, ".8h", []>;
8447
8448  def v2i32 : BaseSIMDModifiedImmVectorShift<0, op, w_cmode, V64,
8449                                             asm, ".2s", []>;
8450  def v4i32 : BaseSIMDModifiedImmVectorShift<1, op, w_cmode, V128,
8451                                             asm, ".4s", []>;
8452}
8453
8454multiclass SIMDModifiedImmVectorShiftTied<bit op, bits<2> hw_cmode,
8455                                      bits<2> w_cmode, string asm,
8456                                      SDNode OpNode> {
8457  def v4i16 : BaseSIMDModifiedImmVectorShiftHalfTied<0, op, hw_cmode, V64,
8458                                                 asm, ".4h",
8459             [(set (v4i16 V64:$dst), (OpNode V64:$Rd,
8460                                             imm0_255:$imm8,
8461                                             (i32 imm:$shift)))]>;
8462  def v8i16 : BaseSIMDModifiedImmVectorShiftHalfTied<1, op, hw_cmode, V128,
8463                                                 asm, ".8h",
8464             [(set (v8i16 V128:$dst), (OpNode V128:$Rd,
8465                                              imm0_255:$imm8,
8466                                              (i32 imm:$shift)))]>;
8467
8468  def v2i32 : BaseSIMDModifiedImmVectorShiftTied<0, op, w_cmode, V64,
8469                                             asm, ".2s",
8470             [(set (v2i32 V64:$dst), (OpNode V64:$Rd,
8471                                             imm0_255:$imm8,
8472                                             (i32 imm:$shift)))]>;
8473  def v4i32 : BaseSIMDModifiedImmVectorShiftTied<1, op, w_cmode, V128,
8474                                             asm, ".4s",
8475             [(set (v4i32 V128:$dst), (OpNode V128:$Rd,
8476                                              imm0_255:$imm8,
8477                                              (i32 imm:$shift)))]>;
8478}
8479
8480class SIMDModifiedImmMoveMSL<bit Q, bit op, bits<4> cmode,
8481                             RegisterOperand vectype, string asm,
8482                             string kind, list<dag> pattern>
8483  : BaseSIMDModifiedImmVector<Q, op, 0, vectype, imm0_255,
8484                              (ins move_vec_shift:$shift),
8485                              "$shift", asm, kind, pattern> {
8486  bits<1> shift;
8487  let Inst{15-13} = cmode{3-1};
8488  let Inst{12}    = shift;
8489}
8490
8491class SIMDModifiedImmVectorNoShift<bit Q, bit op, bit op2, bits<4> cmode,
8492                                   RegisterOperand vectype,
8493                                   Operand imm_type, string asm,
8494                                   string kind, list<dag> pattern>
8495  : BaseSIMDModifiedImmVector<Q, op, op2, vectype, imm_type, (ins), "",
8496                              asm, kind, pattern> {
8497  let Inst{15-12} = cmode;
8498}
8499
8500class SIMDModifiedImmScalarNoShift<bit Q, bit op, bits<4> cmode, string asm,
8501                                   list<dag> pattern>
8502  : BaseSIMDModifiedImm<Q, op, 0, (outs FPR64:$Rd), (ins simdimmtype10:$imm8), asm,
8503                        "\t$Rd, $imm8", "", pattern> {
8504  let Inst{15-12} = cmode;
8505  let DecoderMethod = "DecodeModImmInstruction";
8506}
8507
8508//----------------------------------------------------------------------------
8509// AdvSIMD indexed element
8510//----------------------------------------------------------------------------
8511
8512let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8513class BaseSIMDIndexed<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8514                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8515                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8516                      string apple_kind, string dst_kind, string lhs_kind,
8517                      string rhs_kind, list<dag> pattern>
8518  : I<(outs dst_reg:$Rd), (ins lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx),
8519      asm,
8520      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8521      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "", pattern>,
8522    Sched<[WriteVd]> {
8523  bits<5> Rd;
8524  bits<5> Rn;
8525  bits<5> Rm;
8526
8527  let Inst{31}    = 0;
8528  let Inst{30}    = Q;
8529  let Inst{29}    = U;
8530  let Inst{28}    = Scalar;
8531  let Inst{27-24} = 0b1111;
8532  let Inst{23-22} = size;
8533  // Bit 21 must be set by the derived class.
8534  let Inst{20-16} = Rm;
8535  let Inst{15-12} = opc;
8536  // Bit 11 must be set by the derived class.
8537  let Inst{10}    = 0;
8538  let Inst{9-5}   = Rn;
8539  let Inst{4-0}   = Rd;
8540}
8541
8542let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
8543class BaseSIMDIndexedTied<bit Q, bit U, bit Scalar, bits<2> size, bits<4> opc,
8544                      RegisterOperand dst_reg, RegisterOperand lhs_reg,
8545                      RegisterOperand rhs_reg, Operand vec_idx, string asm,
8546                      string apple_kind, string dst_kind, string lhs_kind,
8547                      string rhs_kind, list<dag> pattern>
8548  : I<(outs dst_reg:$dst),
8549      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx), asm,
8550      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx" #
8551      "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx}", "$Rd = $dst", pattern>,
8552    Sched<[WriteVd]> {
8553  bits<5> Rd;
8554  bits<5> Rn;
8555  bits<5> Rm;
8556
8557  let Inst{31}    = 0;
8558  let Inst{30}    = Q;
8559  let Inst{29}    = U;
8560  let Inst{28}    = Scalar;
8561  let Inst{27-24} = 0b1111;
8562  let Inst{23-22} = size;
8563  // Bit 21 must be set by the derived class.
8564  let Inst{20-16} = Rm;
8565  let Inst{15-12} = opc;
8566  // Bit 11 must be set by the derived class.
8567  let Inst{10}    = 0;
8568  let Inst{9-5}   = Rn;
8569  let Inst{4-0}   = Rd;
8570}
8571
8572
8573//----------------------------------------------------------------------------
8574// Armv8.6 BFloat16 Extension
8575//----------------------------------------------------------------------------
8576let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in {
8577
8578class BaseSIMDThreeSameVectorBFDot<bit Q, bit U, string asm, string kind1,
8579                                   string kind2, RegisterOperand RegType,
8580                                   ValueType AccumType, ValueType InputType>
8581  : BaseSIMDThreeSameVectorTied<Q, U, 0b010, 0b11111, RegType, asm, kind1, [(set (AccumType RegType:$dst),
8582                    (int_aarch64_neon_bfdot (AccumType RegType:$Rd),
8583                                            (InputType RegType:$Rn),
8584                                            (InputType RegType:$Rm)))]> {
8585  let AsmString = !strconcat(asm,
8586                             "{\t$Rd" # kind1 # ", $Rn" # kind2 #
8587                               ", $Rm" # kind2 # "}");
8588}
8589
8590multiclass SIMDThreeSameVectorBFDot<bit U, string asm> {
8591  def v4bf16 : BaseSIMDThreeSameVectorBFDot<0, U, asm, ".2s", ".4h", V64,
8592                                           v2f32, v4bf16>;
8593  def v8bf16 : BaseSIMDThreeSameVectorBFDot<1, U, asm, ".4s", ".8h", V128,
8594                                           v4f32, v8bf16>;
8595}
8596
8597class BaseSIMDThreeSameVectorBF16DotI<bit Q, bit U, string asm,
8598                                      string dst_kind, string lhs_kind,
8599                                      string rhs_kind,
8600                                      RegisterOperand RegType,
8601                                      ValueType AccumType,
8602                                      ValueType InputType>
8603  : BaseSIMDIndexedTied<Q, U, 0b0, 0b01, 0b1111,
8604                        RegType, RegType, V128, VectorIndexS,
8605                        asm, "", dst_kind, lhs_kind, rhs_kind,
8606        [(set (AccumType RegType:$dst),
8607              (AccumType (int_aarch64_neon_bfdot
8608                                 (AccumType RegType:$Rd),
8609                                 (InputType RegType:$Rn),
8610                                 (InputType (bitconvert (AccumType
8611                                    (AArch64duplane32 (v4f32 V128:$Rm),
8612                                        VectorIndexS:$idx)))))))]> {
8613
8614  bits<2> idx;
8615  let Inst{21}    = idx{0};  // L
8616  let Inst{11}    = idx{1};  // H
8617}
8618
8619multiclass SIMDThreeSameVectorBF16DotI<bit U, string asm> {
8620
8621  def v4bf16  : BaseSIMDThreeSameVectorBF16DotI<0, U, asm, ".2s", ".4h",
8622                                               ".2h", V64, v2f32, v4bf16>;
8623  def v8bf16 : BaseSIMDThreeSameVectorBF16DotI<1, U, asm, ".4s", ".8h",
8624                                              ".2h", V128, v4f32, v8bf16>;
8625}
8626
8627let mayRaiseFPException = 1, Uses = [FPCR] in
8628class SIMDBF16MLAL<bit Q, string asm, SDPatternOperator OpNode>
8629  : BaseSIMDThreeSameVectorTied<Q, 0b1, 0b110, 0b11111, V128, asm, ".4s",
8630              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
8631                                               (v8bf16 V128:$Rn),
8632                                               (v8bf16 V128:$Rm)))]> {
8633  let AsmString = !strconcat(asm, "{\t$Rd.4s, $Rn.8h, $Rm.8h}");
8634}
8635
8636let mayRaiseFPException = 1, Uses = [FPCR] in
8637class SIMDBF16MLALIndex<bit Q, string asm, SDPatternOperator OpNode>
8638  : I<(outs V128:$dst),
8639      (ins V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx), asm,
8640      "{\t$Rd.4s, $Rn.8h, $Rm.h$idx}", "$Rd = $dst",
8641          [(set (v4f32 V128:$dst),
8642                (v4f32 (OpNode (v4f32 V128:$Rd),
8643                               (v8bf16 V128:$Rn),
8644                               (v8bf16
8645                                  (AArch64duplane16 (v8bf16 V128_lo:$Rm),
8646                                      VectorIndexH:$idx)))))]>,
8647    Sched<[WriteVq]> {
8648  bits<5> Rd;
8649  bits<5> Rn;
8650  bits<4> Rm;
8651  bits<3> idx;
8652
8653  let Inst{31}    = 0;
8654  let Inst{30}    = Q;
8655  let Inst{29-22} = 0b00111111;
8656  let Inst{21-20} = idx{1-0};
8657  let Inst{19-16} = Rm;
8658  let Inst{15-12} = 0b1111;
8659  let Inst{11}    = idx{2};   // H
8660  let Inst{10}    = 0;
8661  let Inst{9-5}   = Rn;
8662  let Inst{4-0}   = Rd;
8663}
8664
8665class SIMDThreeSameVectorBF16MatrixMul<string asm>
8666  : BaseSIMDThreeSameVectorTied<1, 1, 0b010, 0b11101,
8667                                V128, asm, ".4s",
8668                          [(set (v4f32 V128:$dst),
8669                                (int_aarch64_neon_bfmmla (v4f32 V128:$Rd),
8670                                                         (v8bf16 V128:$Rn),
8671                                                         (v8bf16 V128:$Rm)))]> {
8672  let AsmString = !strconcat(asm, "{\t$Rd", ".4s", ", $Rn", ".8h",
8673                                    ", $Rm", ".8h", "}");
8674}
8675
8676let mayRaiseFPException = 1, Uses = [FPCR] in
8677class SIMD_BFCVTN
8678  : BaseSIMDMixedTwoVector<0, 0, 0b10, 0b10110, V128, V128,
8679                           "bfcvtn", ".4h", ".4s",
8680    [(set (v8bf16 V128:$Rd),
8681          (int_aarch64_neon_bfcvtn (v4f32 V128:$Rn)))]>;
8682
8683let mayRaiseFPException = 1, Uses = [FPCR] in
8684class SIMD_BFCVTN2
8685  : BaseSIMDMixedTwoVectorTied<1, 0, 0b10, 0b10110, V128, V128,
8686                           "bfcvtn2", ".8h", ".4s",
8687    [(set (v8bf16 V128:$dst),
8688          (int_aarch64_neon_bfcvtn2 (v8bf16 V128:$Rd), (v4f32 V128:$Rn)))]>;
8689
8690let mayRaiseFPException = 1, Uses = [FPCR] in
8691class BF16ToSinglePrecision<string asm>
8692  : I<(outs FPR16:$Rd), (ins FPR32:$Rn), asm, "\t$Rd, $Rn", "",
8693    [(set (bf16 FPR16:$Rd), (int_aarch64_neon_bfcvt (f32 FPR32:$Rn)))]>,
8694    Sched<[WriteFCvt]> {
8695  bits<5> Rd;
8696  bits<5> Rn;
8697  let Inst{31-10} = 0b0001111001100011010000;
8698  let Inst{9-5}   = Rn;
8699  let Inst{4-0}   = Rd;
8700}
8701} // End of let mayStore = 0, mayLoad = 0, hasSideEffects = 0
8702
8703//----------------------------------------------------------------------------
8704class BaseSIMDThreeSameVectorIndexB<bit Q, bit U, bits<2> sz, bits<4> opc,
8705                                    string asm, string dst_kind,
8706                                    RegisterOperand RegType,
8707                                    RegisterOperand RegType_lo>
8708  : BaseSIMDIndexedTied<Q, U, 0b0, sz, opc,
8709                        RegType, RegType, RegType_lo, VectorIndexB,
8710                        asm, "", dst_kind, ".16b", ".b", []> {
8711
8712  // idx = H:L:M
8713  bits<4> idx;
8714  let Inst{11}    = idx{3};
8715  let Inst{21-19} = idx{2-0};
8716}
8717
8718multiclass SIMDThreeSameVectorMLAIndex<bit Q, string asm> {
8719  def v8f16 : BaseSIMDThreeSameVectorIndexB<Q, 0b0, 0b11, 0b0000, asm, ".8h",
8720                                            V128, V128_0to7>;
8721}
8722
8723multiclass SIMDThreeSameVectorMLALIndex<bit Q, bits<2> sz, string asm> {
8724  def v4f32 : BaseSIMDThreeSameVectorIndexB<Q, 0b1, sz, 0b1000, asm, ".4s",
8725                                            V128, V128_0to7>;
8726}
8727
8728//----------------------------------------------------------------------------
8729// Armv8.6 Matrix Multiply Extension
8730//----------------------------------------------------------------------------
8731
8732class SIMDThreeSameVectorMatMul<bit B, bit U, string asm, SDPatternOperator OpNode>
8733  : BaseSIMDThreeSameVectorTied<1, U, 0b100, {0b1010, B}, V128, asm, ".4s",
8734              [(set (v4i32 V128:$dst), (OpNode (v4i32 V128:$Rd),
8735                                               (v16i8 V128:$Rn),
8736                                               (v16i8 V128:$Rm)))]> {
8737  let AsmString = asm # "{\t$Rd.4s, $Rn.16b, $Rm.16b}";
8738}
8739
8740//----------------------------------------------------------------------------
8741// ARMv8.2-A Dot Product Instructions (Indexed)
8742class BaseSIMDThreeSameVectorIndexS<bit Q, bit U, bits<2> size, bits<4> opc, string asm,
8743                                    string dst_kind, string lhs_kind, string rhs_kind,
8744                                    RegisterOperand RegType,
8745                                    ValueType AccumType, ValueType InputType,
8746                                    SDPatternOperator OpNode> :
8747        BaseSIMDIndexedTied<Q, U, 0b0, size, opc, RegType, RegType, V128,
8748                            VectorIndexS, asm, "", dst_kind, lhs_kind, rhs_kind,
8749        [(set (AccumType RegType:$dst),
8750              (AccumType (OpNode (AccumType RegType:$Rd),
8751                                 (InputType RegType:$Rn),
8752                                 (InputType (bitconvert (AccumType
8753                                    (AArch64duplane32 (v4i32 V128:$Rm),
8754                                        VectorIndexS:$idx)))))))]> {
8755  bits<2> idx;
8756  let Inst{21}    = idx{0};  // L
8757  let Inst{11}    = idx{1};  // H
8758}
8759
8760multiclass SIMDThreeSameVectorDotIndex<bit U, bit Mixed, bits<2> size, string asm,
8761                                       SDPatternOperator OpNode> {
8762  def v8i8  : BaseSIMDThreeSameVectorIndexS<0, U, size, {0b111, Mixed}, asm, ".2s", ".8b", ".4b",
8763                                              V64, v2i32, v8i8, OpNode>;
8764  def v16i8 : BaseSIMDThreeSameVectorIndexS<1, U, size, {0b111, Mixed}, asm, ".4s", ".16b", ".4b",
8765                                              V128, v4i32, v16i8, OpNode>;
8766}
8767
8768// TODO: The vectors v8i8 and v16i8 should be v8f8 and v16f8
8769multiclass SIMDThreeSameVectorFP8DOT4Index<string asm> {
8770  def v8f8 : BaseSIMDThreeSameVectorIndexS<0b0, 0b0, 0b00, 0b0000, asm, ".2s", ".8b", ".4b",
8771                                           V64, v2f32, v8i8, null_frag>;
8772  def v16f8 : BaseSIMDThreeSameVectorIndexS<0b1, 0b0, 0b00, 0b0000, asm, ".4s", ".16b",".4b",
8773                                            V128, v4f32, v16i8, null_frag>;
8774}
8775
8776// ARMv8.2-A Fused Multiply Add-Long Instructions (Indexed)
8777let mayRaiseFPException = 1, Uses = [FPCR] in
8778class BaseSIMDThreeSameVectorIndexH<bit Q, bit U, bits<2> sz, bits<4> opc, string asm,
8779                                      string dst_kind, string lhs_kind,
8780                                      string rhs_kind, RegisterOperand RegType,
8781                                      RegisterOperand RegType_lo, ValueType AccumType,
8782                                      ValueType InputType, SDPatternOperator OpNode> :
8783        BaseSIMDIndexedTied<Q, U, 0, sz, opc, RegType, RegType, RegType_lo,
8784                            VectorIndexH, asm, "", dst_kind, lhs_kind, rhs_kind,
8785          [(set (AccumType RegType:$dst),
8786                (AccumType (OpNode (AccumType RegType:$Rd),
8787                                   (InputType RegType:$Rn),
8788                                   (InputType (AArch64duplane16 (v8f16 V128_lo:$Rm),
8789                                                VectorIndexH:$idx)))))]> {
8790  // idx = H:L:M
8791  bits<3> idx;
8792  let Inst{11} = idx{2}; // H
8793  let Inst{21} = idx{1}; // L
8794  let Inst{20} = idx{0}; // M
8795}
8796
8797multiclass SIMDThreeSameVectorFMLIndex<bit U, bits<4> opc, string asm,
8798                                       SDPatternOperator OpNode> {
8799  def v4f16 : BaseSIMDThreeSameVectorIndexH<0, U, 0b10, opc, asm, ".2s", ".2h", ".h",
8800                                              V64, V128_lo, v2f32, v4f16, OpNode>;
8801  def v8f16 : BaseSIMDThreeSameVectorIndexH<1, U, 0b10, opc, asm, ".4s", ".4h", ".h",
8802                                              V128, V128_lo, v4f32, v8f16, OpNode>;
8803}
8804
8805//----------------------------------------------------------------------------
8806// FP8 Advanced SIMD vector x indexed element
8807// TODO: Replace value types v8i8 and v16i8 by v8f8 and v16f8
8808multiclass SIMDThreeSameVectorFP8DOT2Index<string asm> {
8809  def v4f16 : BaseSIMDThreeSameVectorIndexH<0b0, 0b0, 0b01, 0b0000, asm, ".4h", ".8b", ".2b",
8810                                            V64, V128_lo, v4f16, v8i8, null_frag>;
8811  def v8f16 : BaseSIMDThreeSameVectorIndexH<0b1, 0b0, 0b01, 0b0000, asm, ".8h", ".16b", ".2b",
8812                                            V128, V128_lo, v8f16, v8i16, null_frag>;
8813}
8814
8815multiclass SIMDFPIndexed<bit U, bits<4> opc, string asm,
8816                         SDPatternOperator OpNode> {
8817  let mayRaiseFPException = 1, Uses = [FPCR] in {
8818  let Predicates = [HasNEON, HasFullFP16] in {
8819  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b00, opc,
8820                                      V64, V64,
8821                                      V128_lo, VectorIndexH,
8822                                      asm, ".4h", ".4h", ".4h", ".h",
8823    [(set (v4f16 V64:$Rd),
8824        (OpNode (v4f16 V64:$Rn),
8825         (dup_v8f16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
8826    bits<3> idx;
8827    let Inst{11} = idx{2};
8828    let Inst{21} = idx{1};
8829    let Inst{20} = idx{0};
8830  }
8831
8832  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b00, opc,
8833                                      V128, V128,
8834                                      V128_lo, VectorIndexH,
8835                                      asm, ".8h", ".8h", ".8h", ".h",
8836    [(set (v8f16 V128:$Rd),
8837        (OpNode (v8f16 V128:$Rn),
8838         (v8f16 (AArch64duplane16 (v8f16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
8839    bits<3> idx;
8840    let Inst{11} = idx{2};
8841    let Inst{21} = idx{1};
8842    let Inst{20} = idx{0};
8843  }
8844  } // Predicates = [HasNEON, HasFullFP16]
8845
8846  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
8847                                      V64, V64,
8848                                      V128, VectorIndexS,
8849                                      asm, ".2s", ".2s", ".2s", ".s",
8850    [(set (v2f32 V64:$Rd),
8851        (OpNode (v2f32 V64:$Rn),
8852         (dup_v4f32 (v4f32 V128:$Rm), VectorIndexS:$idx)))]> {
8853    bits<2> idx;
8854    let Inst{11} = idx{1};
8855    let Inst{21} = idx{0};
8856  }
8857
8858  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
8859                                      V128, V128,
8860                                      V128, VectorIndexS,
8861                                      asm, ".4s", ".4s", ".4s", ".s",
8862    [(set (v4f32 V128:$Rd),
8863        (OpNode (v4f32 V128:$Rn),
8864         (v4f32 (AArch64duplane32 (v4f32 V128:$Rm), VectorIndexS:$idx))))]> {
8865    bits<2> idx;
8866    let Inst{11} = idx{1};
8867    let Inst{21} = idx{0};
8868  }
8869
8870  def v2i64_indexed : BaseSIMDIndexed<1, U, 0, 0b11, opc,
8871                                      V128, V128,
8872                                      V128, VectorIndexD,
8873                                      asm, ".2d", ".2d", ".2d", ".d",
8874    [(set (v2f64 V128:$Rd),
8875        (OpNode (v2f64 V128:$Rn),
8876         (v2f64 (AArch64duplane64 (v2f64 V128:$Rm), VectorIndexD:$idx))))]> {
8877    bits<1> idx;
8878    let Inst{11} = idx{0};
8879    let Inst{21} = 0;
8880  }
8881
8882  let Predicates = [HasNEON, HasFullFP16] in {
8883  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b00, opc,
8884                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
8885                                      asm, ".h", "", "", ".h",
8886    [(set (f16 FPR16Op:$Rd),
8887          (OpNode (f16 FPR16Op:$Rn),
8888                  (f16 (vector_extract (v8f16 V128_lo:$Rm),
8889                                       VectorIndexH:$idx))))]> {
8890    bits<3> idx;
8891    let Inst{11} = idx{2};
8892    let Inst{21} = idx{1};
8893    let Inst{20} = idx{0};
8894  }
8895  } // Predicates = [HasNEON, HasFullFP16]
8896
8897  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
8898                                      FPR32Op, FPR32Op, V128, VectorIndexS,
8899                                      asm, ".s", "", "", ".s",
8900    [(set (f32 FPR32Op:$Rd),
8901          (OpNode (f32 FPR32Op:$Rn),
8902                  (f32 (vector_extract (v4f32 V128:$Rm),
8903                                       VectorIndexS:$idx))))]> {
8904    bits<2> idx;
8905    let Inst{11} = idx{1};
8906    let Inst{21} = idx{0};
8907  }
8908
8909  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b11, opc,
8910                                      FPR64Op, FPR64Op, V128, VectorIndexD,
8911                                      asm, ".d", "", "", ".d",
8912    [(set (f64 FPR64Op:$Rd),
8913          (OpNode (f64 FPR64Op:$Rn),
8914                  (f64 (vector_extract (v2f64 V128:$Rm),
8915                                       VectorIndexD:$idx))))]> {
8916    bits<1> idx;
8917    let Inst{11} = idx{0};
8918    let Inst{21} = 0;
8919  }
8920  } // mayRaiseFPException = 1, Uses = [FPCR]
8921
8922  let Predicates = [HasNEON, HasFullFP16] in {
8923  def : Pat<(f16 (OpNode
8924                   (f16 (vector_extract (v8f16 V128:$Rn), (i64 0))),
8925                   (f16 (vector_extract (v8f16 V128:$Rm), VectorIndexH:$idx)))),
8926            (!cast<Instruction>(NAME # v1i16_indexed)
8927              (f16 (EXTRACT_SUBREG V128:$Rn, hsub)), V128:$Rm, VectorIndexH:$idx)>;
8928  }
8929
8930  let Predicates = [HasNEON] in {
8931  def : Pat<(f32 (OpNode
8932                   (f32 (vector_extract (v4f32 V128:$Rn), (i64 0))),
8933                   (f32 (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx)))),
8934            (!cast<Instruction>(NAME # v1i32_indexed)
8935              (EXTRACT_SUBREG V128:$Rn, ssub), V128:$Rm, VectorIndexS:$idx)>;
8936
8937  def : Pat<(f64 (OpNode
8938                   (f64 (vector_extract (v2f64 V128:$Rn), (i64 0))),
8939                   (f64 (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx)))),
8940            (!cast<Instruction>(NAME # v1i64_indexed)
8941              (EXTRACT_SUBREG V128:$Rn, dsub), V128:$Rm, VectorIndexD:$idx)>;
8942  }
8943}
8944
8945multiclass SIMDFPIndexedTiedPatterns<string INST, SDPatternOperator OpNode> {
8946  let Predicates = [HasNEON, HasFullFP16] in {
8947  // Patterns for f16: DUPLANE, DUP scalar and vector_extract.
8948  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8949                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8950                                           VectorIndexH:$idx))),
8951            (!cast<Instruction>(INST # "v8i16_indexed")
8952                V128:$Rd, V128:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8953  def : Pat<(v8f16 (OpNode (v8f16 V128:$Rd), (v8f16 V128:$Rn),
8954                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8955            (!cast<Instruction>(INST # "v8i16_indexed") V128:$Rd, V128:$Rn,
8956                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8957
8958  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8959                           (AArch64duplane16 (v8f16 V128_lo:$Rm),
8960                                           VectorIndexH:$idx))),
8961            (!cast<Instruction>(INST # "v4i16_indexed")
8962                V64:$Rd, V64:$Rn, V128_lo:$Rm, VectorIndexH:$idx)>;
8963  def : Pat<(v4f16 (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn),
8964                           (AArch64dup (f16 FPR16Op_lo:$Rm)))),
8965            (!cast<Instruction>(INST # "v4i16_indexed") V64:$Rd, V64:$Rn,
8966                (SUBREG_TO_REG (i32 0), (f16 FPR16Op_lo:$Rm), hsub), (i64 0))>;
8967
8968  def : Pat<(f16 (OpNode (f16 FPR16:$Rd), (f16 FPR16:$Rn),
8969                         (vector_extract (v8f16 V128_lo:$Rm), VectorIndexH:$idx))),
8970            (!cast<Instruction>(INST # "v1i16_indexed") FPR16:$Rd, FPR16:$Rn,
8971                V128_lo:$Rm, VectorIndexH:$idx)>;
8972  } // Predicates = [HasNEON, HasFullFP16]
8973
8974  // 2 variants for the .2s version: DUPLANE from 128-bit and DUP scalar.
8975  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8976                           (AArch64duplane32 (v4f32 V128:$Rm),
8977                                           VectorIndexS:$idx))),
8978            (!cast<Instruction>(INST # v2i32_indexed)
8979                V64:$Rd, V64:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8980  def : Pat<(v2f32 (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn),
8981                           (AArch64dup (f32 FPR32Op:$Rm)))),
8982            (!cast<Instruction>(INST # "v2i32_indexed") V64:$Rd, V64:$Rn,
8983                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8984
8985
8986  // 2 variants for the .4s version: DUPLANE from 128-bit and DUP scalar.
8987  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8988                           (AArch64duplane32 (v4f32 V128:$Rm),
8989                                           VectorIndexS:$idx))),
8990            (!cast<Instruction>(INST # "v4i32_indexed")
8991                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
8992  def : Pat<(v4f32 (OpNode (v4f32 V128:$Rd), (v4f32 V128:$Rn),
8993                           (AArch64dup (f32 FPR32Op:$Rm)))),
8994            (!cast<Instruction>(INST # "v4i32_indexed") V128:$Rd, V128:$Rn,
8995                (SUBREG_TO_REG (i32 0), FPR32Op:$Rm, ssub), (i64 0))>;
8996
8997  // 2 variants for the .2d version: DUPLANE from 128-bit and DUP scalar.
8998  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
8999                           (AArch64duplane64 (v2f64 V128:$Rm),
9000                                           VectorIndexD:$idx))),
9001            (!cast<Instruction>(INST # "v2i64_indexed")
9002                V128:$Rd, V128:$Rn, V128:$Rm, VectorIndexS:$idx)>;
9003  def : Pat<(v2f64 (OpNode (v2f64 V128:$Rd), (v2f64 V128:$Rn),
9004                           (AArch64dup (f64 FPR64Op:$Rm)))),
9005            (!cast<Instruction>(INST # "v2i64_indexed") V128:$Rd, V128:$Rn,
9006                (SUBREG_TO_REG (i32 0), FPR64Op:$Rm, dsub), (i64 0))>;
9007
9008  // Covers 2 variants for 32-bit scalar version: extract from .2s or from .4s
9009  def : Pat<(f32 (OpNode (f32 FPR32:$Rd), (f32 FPR32:$Rn),
9010                         (vector_extract (v4f32 V128:$Rm), VectorIndexS:$idx))),
9011            (!cast<Instruction>(INST # "v1i32_indexed") FPR32:$Rd, FPR32:$Rn,
9012                V128:$Rm, VectorIndexS:$idx)>;
9013
9014  // 1 variant for 64-bit scalar version: extract from .1d or from .2d
9015  def : Pat<(f64 (OpNode (f64 FPR64:$Rd), (f64 FPR64:$Rn),
9016                         (vector_extract (v2f64 V128:$Rm), VectorIndexD:$idx))),
9017            (!cast<Instruction>(INST # "v1i64_indexed") FPR64:$Rd, FPR64:$Rn,
9018                V128:$Rm, VectorIndexD:$idx)>;
9019}
9020
9021let mayRaiseFPException = 1, Uses = [FPCR] in
9022multiclass SIMDFPIndexedTied<bit U, bits<4> opc, string asm> {
9023  let Predicates = [HasNEON, HasFullFP16] in {
9024  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b00, opc, V64, V64,
9025                                          V128_lo, VectorIndexH,
9026                                          asm, ".4h", ".4h", ".4h", ".h", []> {
9027    bits<3> idx;
9028    let Inst{11} = idx{2};
9029    let Inst{21} = idx{1};
9030    let Inst{20} = idx{0};
9031  }
9032
9033  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b00, opc,
9034                                          V128, V128,
9035                                          V128_lo, VectorIndexH,
9036                                          asm, ".8h", ".8h", ".8h", ".h", []> {
9037    bits<3> idx;
9038    let Inst{11} = idx{2};
9039    let Inst{21} = idx{1};
9040    let Inst{20} = idx{0};
9041  }
9042  } // Predicates = [HasNEON, HasFullFP16]
9043
9044  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc, V64, V64,
9045                                          V128, VectorIndexS,
9046                                          asm, ".2s", ".2s", ".2s", ".s", []> {
9047    bits<2> idx;
9048    let Inst{11} = idx{1};
9049    let Inst{21} = idx{0};
9050  }
9051
9052  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9053                                      V128, V128,
9054                                      V128, VectorIndexS,
9055                                      asm, ".4s", ".4s", ".4s", ".s", []> {
9056    bits<2> idx;
9057    let Inst{11} = idx{1};
9058    let Inst{21} = idx{0};
9059  }
9060
9061  def v2i64_indexed : BaseSIMDIndexedTied<1, U, 0, 0b11, opc,
9062                                      V128, V128,
9063                                      V128, VectorIndexD,
9064                                      asm, ".2d", ".2d", ".2d", ".d", []> {
9065    bits<1> idx;
9066    let Inst{11} = idx{0};
9067    let Inst{21} = 0;
9068  }
9069
9070  let Predicates = [HasNEON, HasFullFP16] in {
9071  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b00, opc,
9072                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
9073                                      asm, ".h", "", "", ".h", []> {
9074    bits<3> idx;
9075    let Inst{11} = idx{2};
9076    let Inst{21} = idx{1};
9077    let Inst{20} = idx{0};
9078  }
9079  } // Predicates = [HasNEON, HasFullFP16]
9080
9081  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9082                                      FPR32Op, FPR32Op, V128, VectorIndexS,
9083                                      asm, ".s", "", "", ".s", []> {
9084    bits<2> idx;
9085    let Inst{11} = idx{1};
9086    let Inst{21} = idx{0};
9087  }
9088
9089  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b11, opc,
9090                                      FPR64Op, FPR64Op, V128, VectorIndexD,
9091                                      asm, ".d", "", "", ".d", []> {
9092    bits<1> idx;
9093    let Inst{11} = idx{0};
9094    let Inst{21} = 0;
9095  }
9096}
9097
9098multiclass SIMDIndexedHSPatterns<SDPatternOperator OpNodeLane,
9099                                 SDPatternOperator OpNodeLaneQ> {
9100
9101  def : Pat<(v4i16 (OpNodeLane
9102                     (v4i16 V64:$Rn), (v4i16 V64_lo:$Rm),
9103                     VectorIndexS32b:$idx)),
9104            (!cast<Instruction>(NAME # v4i16_indexed) $Rn,
9105              (SUBREG_TO_REG (i32 0), (v4i16 V64_lo:$Rm), dsub),
9106              (UImmS1XForm $idx))>;
9107
9108  def : Pat<(v4i16 (OpNodeLaneQ
9109                     (v4i16 V64:$Rn), (v8i16 V128_lo:$Rm),
9110                     VectorIndexH32b:$idx)),
9111            (!cast<Instruction>(NAME # v4i16_indexed) $Rn, $Rm,
9112              (UImmS1XForm $idx))>;
9113
9114  def : Pat<(v8i16 (OpNodeLane
9115                     (v8i16 V128:$Rn), (v4i16 V64_lo:$Rm),
9116                     VectorIndexS32b:$idx)),
9117            (!cast<Instruction>(NAME # v8i16_indexed) $Rn,
9118              (SUBREG_TO_REG (i32 0), $Rm, dsub),
9119              (UImmS1XForm $idx))>;
9120
9121  def : Pat<(v8i16 (OpNodeLaneQ
9122                     (v8i16 V128:$Rn), (v8i16 V128_lo:$Rm),
9123                     VectorIndexH32b:$idx)),
9124            (!cast<Instruction>(NAME # v8i16_indexed) $Rn, $Rm,
9125              (UImmS1XForm $idx))>;
9126
9127  def : Pat<(v2i32 (OpNodeLane
9128                     (v2i32 V64:$Rn), (v2i32 V64:$Rm),
9129                     VectorIndexD32b:$idx)),
9130            (!cast<Instruction>(NAME # v2i32_indexed) $Rn,
9131              (SUBREG_TO_REG (i32 0), (v2i32 V64_lo:$Rm), dsub),
9132              (UImmS1XForm $idx))>;
9133
9134  def : Pat<(v2i32 (OpNodeLaneQ
9135                     (v2i32 V64:$Rn), (v4i32 V128:$Rm),
9136                     VectorIndexS32b:$idx)),
9137            (!cast<Instruction>(NAME # v2i32_indexed) $Rn, $Rm,
9138              (UImmS1XForm $idx))>;
9139
9140  def : Pat<(v4i32 (OpNodeLane
9141                     (v4i32 V128:$Rn), (v2i32 V64:$Rm),
9142                     VectorIndexD32b:$idx)),
9143            (!cast<Instruction>(NAME # v4i32_indexed) $Rn,
9144              (SUBREG_TO_REG (i32 0), $Rm, dsub),
9145              (UImmS1XForm $idx))>;
9146
9147  def : Pat<(v4i32 (OpNodeLaneQ
9148                     (v4i32 V128:$Rn),
9149                     (v4i32 V128:$Rm),
9150                     VectorIndexS32b:$idx)),
9151            (!cast<Instruction>(NAME # v4i32_indexed) $Rn, $Rm,
9152              (UImmS1XForm $idx))>;
9153
9154}
9155
9156multiclass SIMDIndexedHS<bit U, bits<4> opc, string asm,
9157                         SDPatternOperator OpNode> {
9158  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc, V64, V64,
9159                                      V128_lo, VectorIndexH,
9160                                      asm, ".4h", ".4h", ".4h", ".h",
9161    [(set (v4i16 V64:$Rd),
9162        (OpNode (v4i16 V64:$Rn),
9163         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9164    bits<3> idx;
9165    let Inst{11} = idx{2};
9166    let Inst{21} = idx{1};
9167    let Inst{20} = idx{0};
9168  }
9169
9170  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9171                                      V128, V128,
9172                                      V128_lo, VectorIndexH,
9173                                      asm, ".8h", ".8h", ".8h", ".h",
9174    [(set (v8i16 V128:$Rd),
9175       (OpNode (v8i16 V128:$Rn),
9176         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9177    bits<3> idx;
9178    let Inst{11} = idx{2};
9179    let Inst{21} = idx{1};
9180    let Inst{20} = idx{0};
9181  }
9182
9183  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9184                                      V64, V64,
9185                                      V128, VectorIndexS,
9186                                      asm, ".2s", ".2s", ".2s",  ".s",
9187    [(set (v2i32 V64:$Rd),
9188       (OpNode (v2i32 V64:$Rn),
9189          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9190    bits<2> idx;
9191    let Inst{11} = idx{1};
9192    let Inst{21} = idx{0};
9193  }
9194
9195  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9196                                      V128, V128,
9197                                      V128, VectorIndexS,
9198                                      asm, ".4s", ".4s", ".4s", ".s",
9199    [(set (v4i32 V128:$Rd),
9200       (OpNode (v4i32 V128:$Rn),
9201          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9202    bits<2> idx;
9203    let Inst{11} = idx{1};
9204    let Inst{21} = idx{0};
9205  }
9206
9207  def v1i16_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
9208                                      FPR16Op, FPR16Op, V128_lo, VectorIndexH,
9209                                      asm, ".h", "", "", ".h", []> {
9210    bits<3> idx;
9211    let Inst{11} = idx{2};
9212    let Inst{21} = idx{1};
9213    let Inst{20} = idx{0};
9214  }
9215
9216  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9217                                      FPR32Op, FPR32Op, V128, VectorIndexS,
9218                                      asm, ".s", "", "", ".s",
9219      [(set (i32 FPR32Op:$Rd),
9220            (OpNode FPR32Op:$Rn,
9221                    (i32 (vector_extract (v4i32 V128:$Rm),
9222                                         VectorIndexS:$idx))))]> {
9223    bits<2> idx;
9224    let Inst{11} = idx{1};
9225    let Inst{21} = idx{0};
9226  }
9227}
9228
9229multiclass SIMDVectorIndexedHS<bit U, bits<4> opc, string asm,
9230                               SDPatternOperator OpNode> {
9231  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9232                                      V64, V64,
9233                                      V128_lo, VectorIndexH,
9234                                      asm, ".4h", ".4h", ".4h", ".h",
9235    [(set (v4i16 V64:$Rd),
9236        (OpNode (v4i16 V64:$Rn),
9237         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9238    bits<3> idx;
9239    let Inst{11} = idx{2};
9240    let Inst{21} = idx{1};
9241    let Inst{20} = idx{0};
9242  }
9243
9244  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9245                                      V128, V128,
9246                                      V128_lo, VectorIndexH,
9247                                      asm, ".8h", ".8h", ".8h", ".h",
9248    [(set (v8i16 V128:$Rd),
9249       (OpNode (v8i16 V128:$Rn),
9250         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9251    bits<3> idx;
9252    let Inst{11} = idx{2};
9253    let Inst{21} = idx{1};
9254    let Inst{20} = idx{0};
9255  }
9256
9257  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9258                                      V64, V64,
9259                                      V128, VectorIndexS,
9260                                      asm, ".2s", ".2s", ".2s", ".s",
9261    [(set (v2i32 V64:$Rd),
9262       (OpNode (v2i32 V64:$Rn),
9263          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9264    bits<2> idx;
9265    let Inst{11} = idx{1};
9266    let Inst{21} = idx{0};
9267  }
9268
9269  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9270                                      V128, V128,
9271                                      V128, VectorIndexS,
9272                                      asm, ".4s", ".4s", ".4s", ".s",
9273    [(set (v4i32 V128:$Rd),
9274       (OpNode (v4i32 V128:$Rn),
9275          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9276    bits<2> idx;
9277    let Inst{11} = idx{1};
9278    let Inst{21} = idx{0};
9279  }
9280}
9281
9282multiclass SIMDVectorIndexedHSTied<bit U, bits<4> opc, string asm,
9283                                   SDPatternOperator OpNode> {
9284  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc, V64, V64,
9285                                          V128_lo, VectorIndexH,
9286                                          asm, ".4h", ".4h", ".4h", ".h",
9287    [(set (v4i16 V64:$dst),
9288        (OpNode (v4i16 V64:$Rd),(v4i16 V64:$Rn),
9289         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9290    bits<3> idx;
9291    let Inst{11} = idx{2};
9292    let Inst{21} = idx{1};
9293    let Inst{20} = idx{0};
9294  }
9295
9296  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9297                                      V128, V128,
9298                                      V128_lo, VectorIndexH,
9299                                      asm, ".8h", ".8h", ".8h", ".h",
9300    [(set (v8i16 V128:$dst),
9301       (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
9302         (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx))))]> {
9303    bits<3> idx;
9304    let Inst{11} = idx{2};
9305    let Inst{21} = idx{1};
9306    let Inst{20} = idx{0};
9307  }
9308
9309  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9310                                      V64, V64,
9311                                      V128, VectorIndexS,
9312                                      asm, ".2s", ".2s", ".2s", ".s",
9313    [(set (v2i32 V64:$dst),
9314       (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
9315          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9316    bits<2> idx;
9317    let Inst{11} = idx{1};
9318    let Inst{21} = idx{0};
9319  }
9320
9321  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9322                                      V128, V128,
9323                                      V128, VectorIndexS,
9324                                      asm, ".4s", ".4s", ".4s", ".s",
9325    [(set (v4i32 V128:$dst),
9326       (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
9327          (v4i32 (AArch64duplane32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
9328    bits<2> idx;
9329    let Inst{11} = idx{1};
9330    let Inst{21} = idx{0};
9331  }
9332}
9333
9334multiclass SIMDIndexedLongSD<bit U, bits<4> opc, string asm,
9335                             SDPatternOperator OpNode> {
9336  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9337                                      V128, V64,
9338                                      V128_lo, VectorIndexH,
9339                                      asm, ".4s", ".4s", ".4h", ".h",
9340    [(set (v4i32 V128:$Rd),
9341        (OpNode (v4i16 V64:$Rn),
9342         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9343    bits<3> idx;
9344    let Inst{11} = idx{2};
9345    let Inst{21} = idx{1};
9346    let Inst{20} = idx{0};
9347  }
9348
9349  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9350                                      V128, V128,
9351                                      V128_lo, VectorIndexH,
9352                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9353    [(set (v4i32 V128:$Rd),
9354          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9355                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9356
9357    bits<3> idx;
9358    let Inst{11} = idx{2};
9359    let Inst{21} = idx{1};
9360    let Inst{20} = idx{0};
9361  }
9362
9363  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9364                                      V128, V64,
9365                                      V128, VectorIndexS,
9366                                      asm, ".2d", ".2d", ".2s", ".s",
9367    [(set (v2i64 V128:$Rd),
9368        (OpNode (v2i32 V64:$Rn),
9369         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9370    bits<2> idx;
9371    let Inst{11} = idx{1};
9372    let Inst{21} = idx{0};
9373  }
9374
9375  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9376                                      V128, V128,
9377                                      V128, VectorIndexS,
9378                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9379    [(set (v2i64 V128:$Rd),
9380          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9381                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9382    bits<2> idx;
9383    let Inst{11} = idx{1};
9384    let Inst{21} = idx{0};
9385  }
9386
9387  def v1i32_indexed : BaseSIMDIndexed<1, U, 1, 0b01, opc,
9388                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9389                                      asm, ".h", "", "", ".h", []> {
9390    bits<3> idx;
9391    let Inst{11} = idx{2};
9392    let Inst{21} = idx{1};
9393    let Inst{20} = idx{0};
9394  }
9395
9396  def v1i64_indexed : BaseSIMDIndexed<1, U, 1, 0b10, opc,
9397                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9398                                      asm, ".s", "", "", ".s", []> {
9399    bits<2> idx;
9400    let Inst{11} = idx{1};
9401    let Inst{21} = idx{0};
9402  }
9403}
9404
9405multiclass SIMDIndexedLongSQDMLXSDTied<bit U, bits<4> opc, string asm,
9406                                       SDPatternOperator Accum> {
9407  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9408                                      V128, V64,
9409                                      V128_lo, VectorIndexH,
9410                                      asm, ".4s", ".4s", ".4h", ".h",
9411    [(set (v4i32 V128:$dst),
9412          (Accum (v4i32 V128:$Rd),
9413                 (v4i32 (int_aarch64_neon_sqdmull
9414                             (v4i16 V64:$Rn),
9415                             (dup_v8i16 (v8i16 V128_lo:$Rm),
9416                                         VectorIndexH:$idx)))))]> {
9417    bits<3> idx;
9418    let Inst{11} = idx{2};
9419    let Inst{21} = idx{1};
9420    let Inst{20} = idx{0};
9421  }
9422
9423  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9424                                      V128, V128,
9425                                      V128_lo, VectorIndexH,
9426                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9427    [(set (v4i32 V128:$dst),
9428          (Accum (v4i32 V128:$Rd),
9429                 (v4i32 (int_aarch64_neon_sqdmull
9430                            (extract_high_v8i16 (v8i16 V128:$Rn)),
9431                            (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))))]> {
9432    bits<3> idx;
9433    let Inst{11} = idx{2};
9434    let Inst{21} = idx{1};
9435    let Inst{20} = idx{0};
9436  }
9437
9438  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9439                                      V128, V64,
9440                                      V128, VectorIndexS,
9441                                      asm, ".2d", ".2d", ".2s", ".s",
9442    [(set (v2i64 V128:$dst),
9443        (Accum (v2i64 V128:$Rd),
9444               (v2i64 (int_aarch64_neon_sqdmull
9445                          (v2i32 V64:$Rn),
9446                          (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9447    bits<2> idx;
9448    let Inst{11} = idx{1};
9449    let Inst{21} = idx{0};
9450  }
9451
9452  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9453                                      V128, V128,
9454                                      V128, VectorIndexS,
9455                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9456    [(set (v2i64 V128:$dst),
9457          (Accum (v2i64 V128:$Rd),
9458                 (v2i64 (int_aarch64_neon_sqdmull
9459                            (extract_high_v4i32 (v4i32 V128:$Rn)),
9460                            (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))))]> {
9461    bits<2> idx;
9462    let Inst{11} = idx{1};
9463    let Inst{21} = idx{0};
9464  }
9465
9466  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
9467                                      FPR32Op, FPR16Op, V128_lo, VectorIndexH,
9468                                      asm, ".h", "", "", ".h", []> {
9469    bits<3> idx;
9470    let Inst{11} = idx{2};
9471    let Inst{21} = idx{1};
9472    let Inst{20} = idx{0};
9473  }
9474
9475  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9476                        (i32 (vector_extract
9477                                    (v4i32 (int_aarch64_neon_sqdmull
9478                                                (v4i16 V64:$Rn),
9479                                                (v4i16 V64:$Rm))),
9480                                    (i64 0))))),
9481            (!cast<Instruction>(NAME # v1i32_indexed)
9482                        FPR32Op:$Rd,
9483                        (f16 (EXTRACT_SUBREG V64:$Rn, hsub)),
9484                        (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rm, dsub),
9485                        (i64 0))>;
9486
9487  def : Pat<(i32 (Accum (i32 FPR32Op:$Rd),
9488                        (i32 (vector_extract
9489                                    (v4i32 (int_aarch64_neon_sqdmull
9490                                                (v4i16 V64:$Rn),
9491                                                (dup_v8i16 (v8i16 V128_lo:$Rm),
9492                                                            VectorIndexH:$idx))),
9493                                    (i64 0))))),
9494            (!cast<Instruction>(NAME # v1i32_indexed)
9495                        FPR32Op:$Rd,
9496                        (f16 (EXTRACT_SUBREG V64:$Rn, hsub)),
9497                        V128_lo:$Rm,
9498                        VectorIndexH:$idx)>;
9499
9500  def v1i64_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
9501                                      FPR64Op, FPR32Op, V128, VectorIndexS,
9502                                      asm, ".s", "", "", ".s",
9503    [(set (i64 FPR64Op:$dst),
9504          (Accum (i64 FPR64Op:$Rd),
9505                 (i64 (int_aarch64_neon_sqdmulls_scalar
9506                            (i32 FPR32Op:$Rn),
9507                            (i32 (vector_extract (v4i32 V128:$Rm),
9508                                                 VectorIndexS:$idx))))))]> {
9509
9510    bits<2> idx;
9511    let Inst{11} = idx{1};
9512    let Inst{21} = idx{0};
9513  }
9514}
9515
9516multiclass SIMDVectorIndexedLongSD<bit U, bits<4> opc, string asm,
9517                                   SDPatternOperator OpNode> {
9518  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9519  def v4i16_indexed : BaseSIMDIndexed<0, U, 0, 0b01, opc,
9520                                      V128, V64,
9521                                      V128_lo, VectorIndexH,
9522                                      asm, ".4s", ".4s", ".4h", ".h",
9523    [(set (v4i32 V128:$Rd),
9524        (OpNode (v4i16 V64:$Rn),
9525         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9526    bits<3> idx;
9527    let Inst{11} = idx{2};
9528    let Inst{21} = idx{1};
9529    let Inst{20} = idx{0};
9530  }
9531
9532  def v8i16_indexed : BaseSIMDIndexed<1, U, 0, 0b01, opc,
9533                                      V128, V128,
9534                                      V128_lo, VectorIndexH,
9535                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9536    [(set (v4i32 V128:$Rd),
9537          (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)),
9538                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9539
9540    bits<3> idx;
9541    let Inst{11} = idx{2};
9542    let Inst{21} = idx{1};
9543    let Inst{20} = idx{0};
9544  }
9545
9546  def v2i32_indexed : BaseSIMDIndexed<0, U, 0, 0b10, opc,
9547                                      V128, V64,
9548                                      V128, VectorIndexS,
9549                                      asm, ".2d", ".2d", ".2s", ".s",
9550    [(set (v2i64 V128:$Rd),
9551        (OpNode (v2i32 V64:$Rn),
9552         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9553    bits<2> idx;
9554    let Inst{11} = idx{1};
9555    let Inst{21} = idx{0};
9556  }
9557
9558  def v4i32_indexed : BaseSIMDIndexed<1, U, 0, 0b10, opc,
9559                                      V128, V128,
9560                                      V128, VectorIndexS,
9561                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9562    [(set (v2i64 V128:$Rd),
9563          (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)),
9564                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9565    bits<2> idx;
9566    let Inst{11} = idx{1};
9567    let Inst{21} = idx{0};
9568  }
9569  }
9570}
9571
9572multiclass SIMDVectorIndexedLongSDTied<bit U, bits<4> opc, string asm,
9573                                       SDPatternOperator OpNode> {
9574  let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in {
9575  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
9576                                      V128, V64,
9577                                      V128_lo, VectorIndexH,
9578                                      asm, ".4s", ".4s", ".4h", ".h",
9579    [(set (v4i32 V128:$dst),
9580        (OpNode (v4i32 V128:$Rd), (v4i16 V64:$Rn),
9581         (dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9582    bits<3> idx;
9583    let Inst{11} = idx{2};
9584    let Inst{21} = idx{1};
9585    let Inst{20} = idx{0};
9586  }
9587
9588  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
9589                                      V128, V128,
9590                                      V128_lo, VectorIndexH,
9591                                      asm#"2", ".4s", ".4s", ".8h", ".h",
9592    [(set (v4i32 V128:$dst),
9593          (OpNode (v4i32 V128:$Rd),
9594                  (extract_high_v8i16 (v8i16 V128:$Rn)),
9595                  (extract_high_dup_v8i16 (v8i16 V128_lo:$Rm), VectorIndexH:$idx)))]> {
9596    bits<3> idx;
9597    let Inst{11} = idx{2};
9598    let Inst{21} = idx{1};
9599    let Inst{20} = idx{0};
9600  }
9601
9602  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
9603                                      V128, V64,
9604                                      V128, VectorIndexS,
9605                                      asm, ".2d", ".2d", ".2s", ".s",
9606    [(set (v2i64 V128:$dst),
9607        (OpNode (v2i64 V128:$Rd), (v2i32 V64:$Rn),
9608         (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9609    bits<2> idx;
9610    let Inst{11} = idx{1};
9611    let Inst{21} = idx{0};
9612  }
9613
9614  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
9615                                      V128, V128,
9616                                      V128, VectorIndexS,
9617                                      asm#"2", ".2d", ".2d", ".4s", ".s",
9618    [(set (v2i64 V128:$dst),
9619          (OpNode (v2i64 V128:$Rd),
9620                  (extract_high_v4i32 (v4i32 V128:$Rn)),
9621                  (extract_high_dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx)))]> {
9622    bits<2> idx;
9623    let Inst{11} = idx{1};
9624    let Inst{21} = idx{0};
9625  }
9626  }
9627}
9628
9629//----------------------------------------------------------------------------
9630// AdvSIMD scalar shift by immediate
9631//----------------------------------------------------------------------------
9632
9633let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9634class BaseSIMDScalarShift<bit U, bits<5> opc, bits<7> fixed_imm,
9635                     RegisterClass regtype1, RegisterClass regtype2,
9636                     Operand immtype, string asm, list<dag> pattern>
9637  : I<(outs regtype1:$Rd), (ins regtype2:$Rn, immtype:$imm),
9638      asm, "\t$Rd, $Rn, $imm", "", pattern>,
9639    Sched<[WriteVd]> {
9640  bits<5> Rd;
9641  bits<5> Rn;
9642  bits<7> imm;
9643  let Inst{31-30} = 0b01;
9644  let Inst{29}    = U;
9645  let Inst{28-23} = 0b111110;
9646  let Inst{22-16} = fixed_imm;
9647  let Inst{15-11} = opc;
9648  let Inst{10}    = 1;
9649  let Inst{9-5} = Rn;
9650  let Inst{4-0} = Rd;
9651}
9652
9653let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9654class BaseSIMDScalarShiftTied<bit U, bits<5> opc, bits<7> fixed_imm,
9655                     RegisterClass regtype1, RegisterClass regtype2,
9656                     Operand immtype, string asm, list<dag> pattern>
9657  : I<(outs regtype1:$dst), (ins regtype1:$Rd, regtype2:$Rn, immtype:$imm),
9658      asm, "\t$Rd, $Rn, $imm", "$Rd = $dst", pattern>,
9659    Sched<[WriteVd]> {
9660  bits<5> Rd;
9661  bits<5> Rn;
9662  bits<7> imm;
9663  let Inst{31-30} = 0b01;
9664  let Inst{29}    = U;
9665  let Inst{28-23} = 0b111110;
9666  let Inst{22-16} = fixed_imm;
9667  let Inst{15-11} = opc;
9668  let Inst{10}    = 1;
9669  let Inst{9-5} = Rn;
9670  let Inst{4-0} = Rd;
9671}
9672
9673
9674multiclass SIMDFPScalarRShift<bit U, bits<5> opc, string asm> {
9675  let Predicates = [HasNEON, HasFullFP16] in {
9676  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9677                              FPR16, FPR16, vecshiftR16, asm, []> {
9678    let Inst{19-16} = imm{3-0};
9679  }
9680  } // Predicates = [HasNEON, HasFullFP16]
9681  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9682                              FPR32, FPR32, vecshiftR32, asm, []> {
9683    let Inst{20-16} = imm{4-0};
9684  }
9685  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9686                              FPR64, FPR64, vecshiftR64, asm, []> {
9687    let Inst{21-16} = imm{5-0};
9688  }
9689}
9690
9691multiclass SIMDScalarRShiftD<bit U, bits<5> opc, string asm,
9692                             SDPatternOperator OpNode> {
9693  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9694                              FPR64, FPR64, vecshiftR64, asm,
9695  [(set (i64 FPR64:$Rd),
9696     (OpNode (i64 FPR64:$Rn), (i32 vecshiftR64:$imm)))]> {
9697    let Inst{21-16} = imm{5-0};
9698  }
9699
9700  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftR64:$imm))),
9701            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftR64:$imm)>;
9702}
9703
9704multiclass SIMDScalarRShiftDTied<bit U, bits<5> opc, string asm,
9705                                 SDPatternOperator OpNode = null_frag> {
9706  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9707                              FPR64, FPR64, vecshiftR64, asm,
9708  [(set (i64 FPR64:$dst), (OpNode (i64 FPR64:$Rd), (i64 FPR64:$Rn),
9709                                                   (i32 vecshiftR64:$imm)))]> {
9710    let Inst{21-16} = imm{5-0};
9711  }
9712
9713  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rd), (v1i64 FPR64:$Rn),
9714                           (i32 vecshiftR64:$imm))),
9715            (!cast<Instruction>(NAME # "d") FPR64:$Rd, FPR64:$Rn,
9716                                            vecshiftR64:$imm)>;
9717}
9718
9719multiclass SIMDScalarLShiftD<bit U, bits<5> opc, string asm,
9720                             SDPatternOperator OpNode> {
9721  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9722                              FPR64, FPR64, vecshiftL64, asm,
9723    [(set (i64 FPR64:$Rd),
9724       (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9725    let Inst{21-16} = imm{5-0};
9726  }
9727
9728  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9729            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9730}
9731
9732let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9733multiclass SIMDScalarLShiftDTied<bit U, bits<5> opc, string asm> {
9734  def d : BaseSIMDScalarShiftTied<U, opc, {1,?,?,?,?,?,?},
9735                              FPR64, FPR64, vecshiftL64, asm, []> {
9736    let Inst{21-16} = imm{5-0};
9737  }
9738}
9739
9740let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9741multiclass SIMDScalarRShiftBHS<bit U, bits<5> opc, string asm,
9742                               SDPatternOperator OpNode = null_frag> {
9743  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9744                              FPR8, FPR16, vecshiftR8, asm, []> {
9745    let Inst{18-16} = imm{2-0};
9746  }
9747
9748  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9749                              FPR16, FPR32, vecshiftR16, asm, []> {
9750    let Inst{19-16} = imm{3-0};
9751  }
9752
9753  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9754                              FPR32, FPR64, vecshiftR32, asm,
9755    [(set (i32 FPR32:$Rd), (OpNode (i64 FPR64:$Rn), vecshiftR32:$imm))]> {
9756    let Inst{20-16} = imm{4-0};
9757  }
9758}
9759
9760multiclass SIMDScalarLShiftBHSD<bit U, bits<5> opc, string asm,
9761                                SDPatternOperator OpNode> {
9762  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9763                              FPR8, FPR8, vecshiftL8, asm, []> {
9764    let Inst{18-16} = imm{2-0};
9765  }
9766
9767  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9768                              FPR16, FPR16, vecshiftL16, asm, []> {
9769    let Inst{19-16} = imm{3-0};
9770  }
9771
9772  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9773                              FPR32, FPR32, vecshiftL32, asm,
9774    [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn), (i32 vecshiftL32:$imm)))]> {
9775    let Inst{20-16} = imm{4-0};
9776  }
9777
9778  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9779                              FPR64, FPR64, vecshiftL64, asm,
9780    [(set (i64 FPR64:$Rd), (OpNode (i64 FPR64:$Rn), (i32 vecshiftL64:$imm)))]> {
9781    let Inst{21-16} = imm{5-0};
9782  }
9783
9784  def : Pat<(v1i64 (OpNode (v1i64 FPR64:$Rn), (i32 vecshiftL64:$imm))),
9785            (!cast<Instruction>(NAME # "d") FPR64:$Rn, vecshiftL64:$imm)>;
9786}
9787
9788multiclass SIMDScalarRShiftBHSD<bit U, bits<5> opc, string asm> {
9789  def b : BaseSIMDScalarShift<U, opc, {0,0,0,1,?,?,?},
9790                              FPR8, FPR8, vecshiftR8, asm, []> {
9791    let Inst{18-16} = imm{2-0};
9792  }
9793
9794  def h : BaseSIMDScalarShift<U, opc, {0,0,1,?,?,?,?},
9795                              FPR16, FPR16, vecshiftR16, asm, []> {
9796    let Inst{19-16} = imm{3-0};
9797  }
9798
9799  def s : BaseSIMDScalarShift<U, opc, {0,1,?,?,?,?,?},
9800                              FPR32, FPR32, vecshiftR32, asm, []> {
9801    let Inst{20-16} = imm{4-0};
9802  }
9803
9804  def d : BaseSIMDScalarShift<U, opc, {1,?,?,?,?,?,?},
9805                              FPR64, FPR64, vecshiftR64, asm, []> {
9806    let Inst{21-16} = imm{5-0};
9807  }
9808}
9809
9810//----------------------------------------------------------------------------
9811// AdvSIMD vector x indexed element
9812//----------------------------------------------------------------------------
9813
9814let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9815class BaseSIMDVectorShift<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9816                     RegisterOperand dst_reg, RegisterOperand src_reg,
9817                     Operand immtype,
9818                     string asm, string dst_kind, string src_kind,
9819                     list<dag> pattern>
9820  : I<(outs dst_reg:$Rd), (ins src_reg:$Rn, immtype:$imm),
9821      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9822           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "", pattern>,
9823    Sched<[!if(Q, WriteVq, WriteVd)]> {
9824  bits<5> Rd;
9825  bits<5> Rn;
9826  let Inst{31}    = 0;
9827  let Inst{30}    = Q;
9828  let Inst{29}    = U;
9829  let Inst{28-23} = 0b011110;
9830  let Inst{22-16} = fixed_imm;
9831  let Inst{15-11} = opc;
9832  let Inst{10}    = 1;
9833  let Inst{9-5}   = Rn;
9834  let Inst{4-0}   = Rd;
9835}
9836
9837let mayStore = 0, mayLoad = 0, hasSideEffects = 0 in
9838class BaseSIMDVectorShiftTied<bit Q, bit U, bits<5> opc, bits<7> fixed_imm,
9839                     RegisterOperand vectype1, RegisterOperand vectype2,
9840                     Operand immtype,
9841                     string asm, string dst_kind, string src_kind,
9842                     list<dag> pattern>
9843  : I<(outs vectype1:$dst), (ins vectype1:$Rd, vectype2:$Rn, immtype:$imm),
9844      asm, "{\t$Rd" # dst_kind # ", $Rn" # src_kind # ", $imm" #
9845           "|" # dst_kind # "\t$Rd, $Rn, $imm}", "$Rd = $dst", pattern>,
9846    Sched<[!if(Q, WriteVq, WriteVd)]> {
9847  bits<5> Rd;
9848  bits<5> Rn;
9849  let Inst{31}    = 0;
9850  let Inst{30}    = Q;
9851  let Inst{29}    = U;
9852  let Inst{28-23} = 0b011110;
9853  let Inst{22-16} = fixed_imm;
9854  let Inst{15-11} = opc;
9855  let Inst{10}    = 1;
9856  let Inst{9-5}   = Rn;
9857  let Inst{4-0}   = Rd;
9858}
9859
9860multiclass SIMDVectorRShiftSD<bit U, bits<5> opc, string asm,
9861                              Intrinsic OpNode> {
9862  let Predicates = [HasNEON, HasFullFP16] in {
9863  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9864                                  V64, V64, vecshiftR16,
9865                                  asm, ".4h", ".4h",
9866      [(set (v4i16 V64:$Rd), (OpNode (v4f16 V64:$Rn), (i32 imm:$imm)))]> {
9867    bits<4> imm;
9868    let Inst{19-16} = imm;
9869  }
9870
9871  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9872                                  V128, V128, vecshiftR16,
9873                                  asm, ".8h", ".8h",
9874      [(set (v8i16 V128:$Rd), (OpNode (v8f16 V128:$Rn), (i32 imm:$imm)))]> {
9875    bits<4> imm;
9876    let Inst{19-16} = imm;
9877  }
9878  } // Predicates = [HasNEON, HasFullFP16]
9879  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9880                                  V64, V64, vecshiftR32,
9881                                  asm, ".2s", ".2s",
9882      [(set (v2i32 V64:$Rd), (OpNode (v2f32 V64:$Rn), (i32 imm:$imm)))]> {
9883    bits<5> imm;
9884    let Inst{20-16} = imm;
9885  }
9886
9887  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9888                                  V128, V128, vecshiftR32,
9889                                  asm, ".4s", ".4s",
9890      [(set (v4i32 V128:$Rd), (OpNode (v4f32 V128:$Rn), (i32 imm:$imm)))]> {
9891    bits<5> imm;
9892    let Inst{20-16} = imm;
9893  }
9894
9895  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9896                                  V128, V128, vecshiftR64,
9897                                  asm, ".2d", ".2d",
9898      [(set (v2i64 V128:$Rd), (OpNode (v2f64 V128:$Rn), (i32 imm:$imm)))]> {
9899    bits<6> imm;
9900    let Inst{21-16} = imm;
9901  }
9902}
9903
9904multiclass SIMDVectorRShiftToFP<bit U, bits<5> opc, string asm,
9905                                  Intrinsic OpNode> {
9906  let Predicates = [HasNEON, HasFullFP16] in {
9907  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9908                                  V64, V64, vecshiftR16,
9909                                  asm, ".4h", ".4h",
9910      [(set (v4f16 V64:$Rd), (OpNode (v4i16 V64:$Rn), (i32 imm:$imm)))]> {
9911    bits<4> imm;
9912    let Inst{19-16} = imm;
9913  }
9914
9915  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
9916                                  V128, V128, vecshiftR16,
9917                                  asm, ".8h", ".8h",
9918      [(set (v8f16 V128:$Rd), (OpNode (v8i16 V128:$Rn), (i32 imm:$imm)))]> {
9919    bits<4> imm;
9920    let Inst{19-16} = imm;
9921  }
9922  } // Predicates = [HasNEON, HasFullFP16]
9923
9924  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9925                                  V64, V64, vecshiftR32,
9926                                  asm, ".2s", ".2s",
9927      [(set (v2f32 V64:$Rd), (OpNode (v2i32 V64:$Rn), (i32 imm:$imm)))]> {
9928    bits<5> imm;
9929    let Inst{20-16} = imm;
9930  }
9931
9932  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
9933                                  V128, V128, vecshiftR32,
9934                                  asm, ".4s", ".4s",
9935      [(set (v4f32 V128:$Rd), (OpNode (v4i32 V128:$Rn), (i32 imm:$imm)))]> {
9936    bits<5> imm;
9937    let Inst{20-16} = imm;
9938  }
9939
9940  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
9941                                  V128, V128, vecshiftR64,
9942                                  asm, ".2d", ".2d",
9943      [(set (v2f64 V128:$Rd), (OpNode (v2i64 V128:$Rn), (i32 imm:$imm)))]> {
9944    bits<6> imm;
9945    let Inst{21-16} = imm;
9946  }
9947}
9948
9949multiclass SIMDVectorRShiftNarrowBHS<bit U, bits<5> opc, string asm,
9950                                     SDPatternOperator OpNode> {
9951  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
9952                                  V64, V128, vecshiftR16Narrow,
9953                                  asm, ".8b", ".8h",
9954      [(set (v8i8 V64:$Rd), (OpNode (v8i16 V128:$Rn), vecshiftR16Narrow:$imm))]> {
9955    bits<3> imm;
9956    let Inst{18-16} = imm;
9957  }
9958
9959  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
9960                                  V128, V128, vecshiftR16Narrow,
9961                                  asm#"2", ".16b", ".8h", []> {
9962    bits<3> imm;
9963    let Inst{18-16} = imm;
9964    let hasSideEffects = 0;
9965  }
9966
9967  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
9968                                  V64, V128, vecshiftR32Narrow,
9969                                  asm, ".4h", ".4s",
9970      [(set (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn), vecshiftR32Narrow:$imm))]> {
9971    bits<4> imm;
9972    let Inst{19-16} = imm;
9973  }
9974
9975  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
9976                                  V128, V128, vecshiftR32Narrow,
9977                                  asm#"2", ".8h", ".4s", []> {
9978    bits<4> imm;
9979    let Inst{19-16} = imm;
9980    let hasSideEffects = 0;
9981  }
9982
9983  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
9984                                  V64, V128, vecshiftR64Narrow,
9985                                  asm, ".2s", ".2d",
9986      [(set (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn), vecshiftR64Narrow:$imm))]> {
9987    bits<5> imm;
9988    let Inst{20-16} = imm;
9989  }
9990
9991  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
9992                                  V128, V128, vecshiftR64Narrow,
9993                                  asm#"2", ".4s", ".2d", []> {
9994    bits<5> imm;
9995    let Inst{20-16} = imm;
9996    let hasSideEffects = 0;
9997  }
9998
9999  // TableGen doesn't like patters w/ INSERT_SUBREG on the instructions
10000  // themselves, so put them here instead.
10001
10002  // Patterns involving what's effectively an insert high and a normal
10003  // intrinsic, represented by CONCAT_VECTORS.
10004  def : Pat<(concat_vectors (v8i8 V64:$Rd),(OpNode (v8i16 V128:$Rn),
10005                                                   vecshiftR16Narrow:$imm)),
10006            (!cast<Instruction>(NAME # "v16i8_shift")
10007                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
10008                V128:$Rn, vecshiftR16Narrow:$imm)>;
10009  def : Pat<(concat_vectors (v4i16 V64:$Rd), (OpNode (v4i32 V128:$Rn),
10010                                                     vecshiftR32Narrow:$imm)),
10011            (!cast<Instruction>(NAME # "v8i16_shift")
10012                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
10013                V128:$Rn, vecshiftR32Narrow:$imm)>;
10014  def : Pat<(concat_vectors (v2i32 V64:$Rd), (OpNode (v2i64 V128:$Rn),
10015                                                     vecshiftR64Narrow:$imm)),
10016            (!cast<Instruction>(NAME # "v4i32_shift")
10017                (INSERT_SUBREG (IMPLICIT_DEF), V64:$Rd, dsub),
10018                V128:$Rn, vecshiftR64Narrow:$imm)>;
10019}
10020
10021multiclass SIMDVectorLShiftBHSD<bit U, bits<5> opc, string asm,
10022                                SDPatternOperator OpNode> {
10023  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10024                                  V64, V64, vecshiftL8,
10025                                  asm, ".8b", ".8b",
10026                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
10027                       (i32 vecshiftL8:$imm)))]> {
10028    bits<3> imm;
10029    let Inst{18-16} = imm;
10030  }
10031
10032  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10033                                  V128, V128, vecshiftL8,
10034                                  asm, ".16b", ".16b",
10035             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
10036                   (i32 vecshiftL8:$imm)))]> {
10037    bits<3> imm;
10038    let Inst{18-16} = imm;
10039  }
10040
10041  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10042                                  V64, V64, vecshiftL16,
10043                                  asm, ".4h", ".4h",
10044              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
10045                    (i32 vecshiftL16:$imm)))]> {
10046    bits<4> imm;
10047    let Inst{19-16} = imm;
10048  }
10049
10050  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10051                                  V128, V128, vecshiftL16,
10052                                  asm, ".8h", ".8h",
10053            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
10054                  (i32 vecshiftL16:$imm)))]> {
10055    bits<4> imm;
10056    let Inst{19-16} = imm;
10057  }
10058
10059  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10060                                  V64, V64, vecshiftL32,
10061                                  asm, ".2s", ".2s",
10062              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
10063                    (i32 vecshiftL32:$imm)))]> {
10064    bits<5> imm;
10065    let Inst{20-16} = imm;
10066  }
10067
10068  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10069                                  V128, V128, vecshiftL32,
10070                                  asm, ".4s", ".4s",
10071            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
10072                  (i32 vecshiftL32:$imm)))]> {
10073    bits<5> imm;
10074    let Inst{20-16} = imm;
10075  }
10076
10077  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10078                                  V128, V128, vecshiftL64,
10079                                  asm, ".2d", ".2d",
10080            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
10081                  (i32 vecshiftL64:$imm)))]> {
10082    bits<6> imm;
10083    let Inst{21-16} = imm;
10084  }
10085}
10086
10087multiclass SIMDVectorRShiftBHSD<bit U, bits<5> opc, string asm,
10088                                SDPatternOperator OpNode> {
10089  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10090                                  V64, V64, vecshiftR8,
10091                                  asm, ".8b", ".8b",
10092                 [(set (v8i8 V64:$Rd), (OpNode (v8i8 V64:$Rn),
10093                       (i32 vecshiftR8:$imm)))]> {
10094    bits<3> imm;
10095    let Inst{18-16} = imm;
10096  }
10097
10098  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10099                                  V128, V128, vecshiftR8,
10100                                  asm, ".16b", ".16b",
10101             [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn),
10102                   (i32 vecshiftR8:$imm)))]> {
10103    bits<3> imm;
10104    let Inst{18-16} = imm;
10105  }
10106
10107  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10108                                  V64, V64, vecshiftR16,
10109                                  asm, ".4h", ".4h",
10110              [(set (v4i16 V64:$Rd), (OpNode (v4i16 V64:$Rn),
10111                    (i32 vecshiftR16:$imm)))]> {
10112    bits<4> imm;
10113    let Inst{19-16} = imm;
10114  }
10115
10116  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10117                                  V128, V128, vecshiftR16,
10118                                  asm, ".8h", ".8h",
10119            [(set (v8i16 V128:$Rd), (OpNode (v8i16 V128:$Rn),
10120                  (i32 vecshiftR16:$imm)))]> {
10121    bits<4> imm;
10122    let Inst{19-16} = imm;
10123  }
10124
10125  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10126                                  V64, V64, vecshiftR32,
10127                                  asm, ".2s", ".2s",
10128              [(set (v2i32 V64:$Rd), (OpNode (v2i32 V64:$Rn),
10129                    (i32 vecshiftR32:$imm)))]> {
10130    bits<5> imm;
10131    let Inst{20-16} = imm;
10132  }
10133
10134  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10135                                  V128, V128, vecshiftR32,
10136                                  asm, ".4s", ".4s",
10137            [(set (v4i32 V128:$Rd), (OpNode (v4i32 V128:$Rn),
10138                  (i32 vecshiftR32:$imm)))]> {
10139    bits<5> imm;
10140    let Inst{20-16} = imm;
10141  }
10142
10143  def v2i64_shift : BaseSIMDVectorShift<1, U, opc, {1,?,?,?,?,?,?},
10144                                  V128, V128, vecshiftR64,
10145                                  asm, ".2d", ".2d",
10146            [(set (v2i64 V128:$Rd), (OpNode (v2i64 V128:$Rn),
10147                  (i32 vecshiftR64:$imm)))]> {
10148    bits<6> imm;
10149    let Inst{21-16} = imm;
10150  }
10151}
10152
10153let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
10154multiclass SIMDVectorRShiftBHSDTied<bit U, bits<5> opc, string asm,
10155                                    SDPatternOperator OpNode = null_frag> {
10156  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
10157                                  V64, V64, vecshiftR8, asm, ".8b", ".8b",
10158                 [(set (v8i8 V64:$dst),
10159                   (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
10160                           (i32 vecshiftR8:$imm)))]> {
10161    bits<3> imm;
10162    let Inst{18-16} = imm;
10163  }
10164
10165  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
10166                                  V128, V128, vecshiftR8, asm, ".16b", ".16b",
10167             [(set (v16i8 V128:$dst),
10168               (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
10169                       (i32 vecshiftR8:$imm)))]> {
10170    bits<3> imm;
10171    let Inst{18-16} = imm;
10172  }
10173
10174  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
10175                                  V64, V64, vecshiftR16, asm, ".4h", ".4h",
10176              [(set (v4i16 V64:$dst),
10177                (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10178                        (i32 vecshiftR16:$imm)))]> {
10179    bits<4> imm;
10180    let Inst{19-16} = imm;
10181  }
10182
10183  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
10184                                  V128, V128, vecshiftR16, asm, ".8h", ".8h",
10185            [(set (v8i16 V128:$dst),
10186              (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10187                      (i32 vecshiftR16:$imm)))]> {
10188    bits<4> imm;
10189    let Inst{19-16} = imm;
10190  }
10191
10192  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
10193                                  V64, V64, vecshiftR32, asm, ".2s", ".2s",
10194              [(set (v2i32 V64:$dst),
10195                (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10196                        (i32 vecshiftR32:$imm)))]> {
10197    bits<5> imm;
10198    let Inst{20-16} = imm;
10199  }
10200
10201  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
10202                                  V128, V128, vecshiftR32, asm, ".4s", ".4s",
10203            [(set (v4i32 V128:$dst),
10204              (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10205                      (i32 vecshiftR32:$imm)))]> {
10206    bits<5> imm;
10207    let Inst{20-16} = imm;
10208  }
10209
10210  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
10211                                  V128, V128, vecshiftR64,
10212                                  asm, ".2d", ".2d", [(set (v2i64 V128:$dst),
10213              (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
10214                      (i32 vecshiftR64:$imm)))]> {
10215    bits<6> imm;
10216    let Inst{21-16} = imm;
10217  }
10218}
10219
10220multiclass SIMDVectorLShiftBHSDTied<bit U, bits<5> opc, string asm,
10221                                    SDPatternOperator OpNode = null_frag> {
10222  def v8i8_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,0,1,?,?,?},
10223                                  V64, V64, vecshiftL8,
10224                                  asm, ".8b", ".8b",
10225                    [(set (v8i8 V64:$dst),
10226                          (OpNode (v8i8 V64:$Rd), (v8i8 V64:$Rn),
10227                                  (i32 vecshiftL8:$imm)))]> {
10228    bits<3> imm;
10229    let Inst{18-16} = imm;
10230  }
10231
10232  def v16i8_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,0,1,?,?,?},
10233                                  V128, V128, vecshiftL8,
10234                                  asm, ".16b", ".16b",
10235                    [(set (v16i8 V128:$dst),
10236                          (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn),
10237                                  (i32 vecshiftL8:$imm)))]> {
10238    bits<3> imm;
10239    let Inst{18-16} = imm;
10240  }
10241
10242  def v4i16_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,0,1,?,?,?,?},
10243                                  V64, V64, vecshiftL16,
10244                                  asm, ".4h", ".4h",
10245                    [(set (v4i16 V64:$dst),
10246                           (OpNode (v4i16 V64:$Rd), (v4i16 V64:$Rn),
10247                                   (i32 vecshiftL16:$imm)))]> {
10248    bits<4> imm;
10249    let Inst{19-16} = imm;
10250  }
10251
10252  def v8i16_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,0,1,?,?,?,?},
10253                                  V128, V128, vecshiftL16,
10254                                  asm, ".8h", ".8h",
10255                    [(set (v8i16 V128:$dst),
10256                          (OpNode (v8i16 V128:$Rd), (v8i16 V128:$Rn),
10257                                  (i32 vecshiftL16:$imm)))]> {
10258    bits<4> imm;
10259    let Inst{19-16} = imm;
10260  }
10261
10262  def v2i32_shift : BaseSIMDVectorShiftTied<0, U, opc, {0,1,?,?,?,?,?},
10263                                  V64, V64, vecshiftL32,
10264                                  asm, ".2s", ".2s",
10265                    [(set (v2i32 V64:$dst),
10266                          (OpNode (v2i32 V64:$Rd), (v2i32 V64:$Rn),
10267                                  (i32 vecshiftL32:$imm)))]> {
10268    bits<5> imm;
10269    let Inst{20-16} = imm;
10270  }
10271
10272  def v4i32_shift : BaseSIMDVectorShiftTied<1, U, opc, {0,1,?,?,?,?,?},
10273                                  V128, V128, vecshiftL32,
10274                                  asm, ".4s", ".4s",
10275                    [(set (v4i32 V128:$dst),
10276                          (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
10277                                  (i32 vecshiftL32:$imm)))]> {
10278    bits<5> imm;
10279    let Inst{20-16} = imm;
10280  }
10281
10282  def v2i64_shift : BaseSIMDVectorShiftTied<1, U, opc, {1,?,?,?,?,?,?},
10283                                  V128, V128, vecshiftL64,
10284                                  asm, ".2d", ".2d",
10285                    [(set (v2i64 V128:$dst),
10286                          (OpNode (v2i64 V128:$Rd), (v2i64 V128:$Rn),
10287                                  (i32 vecshiftL64:$imm)))]> {
10288    bits<6> imm;
10289    let Inst{21-16} = imm;
10290  }
10291}
10292
10293multiclass SIMDVectorLShiftLongBHSD<bit U, bits<5> opc, string asm,
10294                                   SDPatternOperator OpNode> {
10295  def v8i8_shift : BaseSIMDVectorShift<0, U, opc, {0,0,0,1,?,?,?},
10296                                  V128, V64, vecshiftL8, asm, ".8h", ".8b",
10297      [(set (v8i16 V128:$Rd), (OpNode (v8i8 V64:$Rn), vecshiftL8:$imm))]> {
10298    bits<3> imm;
10299    let Inst{18-16} = imm;
10300  }
10301
10302  def v16i8_shift : BaseSIMDVectorShift<1, U, opc, {0,0,0,1,?,?,?},
10303                                  V128, V128, vecshiftL8,
10304                                  asm#"2", ".8h", ".16b",
10305      [(set (v8i16 V128:$Rd),
10306            (OpNode (extract_high_v16i8 (v16i8 V128:$Rn)), vecshiftL8:$imm))]> {
10307    bits<3> imm;
10308    let Inst{18-16} = imm;
10309  }
10310
10311  def v4i16_shift : BaseSIMDVectorShift<0, U, opc, {0,0,1,?,?,?,?},
10312                                  V128, V64, vecshiftL16, asm, ".4s", ".4h",
10313      [(set (v4i32 V128:$Rd), (OpNode (v4i16 V64:$Rn), vecshiftL16:$imm))]> {
10314    bits<4> imm;
10315    let Inst{19-16} = imm;
10316  }
10317
10318  def v8i16_shift : BaseSIMDVectorShift<1, U, opc, {0,0,1,?,?,?,?},
10319                                  V128, V128, vecshiftL16,
10320                                  asm#"2", ".4s", ".8h",
10321      [(set (v4i32 V128:$Rd),
10322            (OpNode (extract_high_v8i16 (v8i16 V128:$Rn)), vecshiftL16:$imm))]> {
10323
10324    bits<4> imm;
10325    let Inst{19-16} = imm;
10326  }
10327
10328  def v2i32_shift : BaseSIMDVectorShift<0, U, opc, {0,1,?,?,?,?,?},
10329                                  V128, V64, vecshiftL32, asm, ".2d", ".2s",
10330      [(set (v2i64 V128:$Rd), (OpNode (v2i32 V64:$Rn), vecshiftL32:$imm))]> {
10331    bits<5> imm;
10332    let Inst{20-16} = imm;
10333  }
10334
10335  def v4i32_shift : BaseSIMDVectorShift<1, U, opc, {0,1,?,?,?,?,?},
10336                                  V128, V128, vecshiftL32,
10337                                  asm#"2", ".2d", ".4s",
10338      [(set (v2i64 V128:$Rd),
10339            (OpNode (extract_high_v4i32 (v4i32 V128:$Rn)), vecshiftL32:$imm))]> {
10340    bits<5> imm;
10341    let Inst{20-16} = imm;
10342  }
10343}
10344
10345
10346//---
10347// Vector load/store
10348//---
10349// SIMD ldX/stX no-index memory references don't allow the optional
10350// ", #0" constant and handle post-indexing explicitly, so we use
10351// a more specialized parse method for them. Otherwise, it's the same as
10352// the general GPR64sp handling.
10353
10354class BaseSIMDLdSt<bit Q, bit L, bits<4> opcode, bits<2> size,
10355                   string asm, dag oops, dag iops, list<dag> pattern>
10356  : I<oops, iops, asm, "\t$Vt, [$Rn]", "", pattern> {
10357  bits<5> Vt;
10358  bits<5> Rn;
10359  let Inst{31} = 0;
10360  let Inst{30} = Q;
10361  let Inst{29-23} = 0b0011000;
10362  let Inst{22} = L;
10363  let Inst{21-16} = 0b000000;
10364  let Inst{15-12} = opcode;
10365  let Inst{11-10} = size;
10366  let Inst{9-5} = Rn;
10367  let Inst{4-0} = Vt;
10368}
10369
10370class BaseSIMDLdStPost<bit Q, bit L, bits<4> opcode, bits<2> size,
10371                       string asm, dag oops, dag iops>
10372  : I<oops, iops, asm, "\t$Vt, [$Rn], $Xm", "$Rn = $wback", []> {
10373  bits<5> Vt;
10374  bits<5> Rn;
10375  bits<5> Xm;
10376  let Inst{31} = 0;
10377  let Inst{30} = Q;
10378  let Inst{29-23} = 0b0011001;
10379  let Inst{22} = L;
10380  let Inst{21} = 0;
10381  let Inst{20-16} = Xm;
10382  let Inst{15-12} = opcode;
10383  let Inst{11-10} = size;
10384  let Inst{9-5} = Rn;
10385  let Inst{4-0} = Vt;
10386}
10387
10388// The immediate form of AdvSIMD post-indexed addressing is encoded with
10389// register post-index addressing from the zero register.
10390multiclass SIMDLdStAliases<string BaseName, string asm, string layout, string Count,
10391                           int Offset, int Size> {
10392  // E.g. "ld1 { v0.8b, v1.8b }, [x1], #16"
10393  //      "ld1\t$Vt, [$Rn], #16"
10394  // may get mapped to
10395  //      (LD1Twov8b_POST VecListTwo8b:$Vt, GPR64sp:$Rn, XZR)
10396  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10397                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10398                      GPR64sp:$Rn,
10399                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10400                      XZR), 1>;
10401
10402  // E.g. "ld1.8b { v0, v1 }, [x1], #16"
10403  //      "ld1.8b\t$Vt, [$Rn], #16"
10404  // may get mapped to
10405  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, XZR)
10406  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10407                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10408                      GPR64sp:$Rn,
10409                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10410                      XZR), 0>;
10411
10412  // E.g. "ld1.8b { v0, v1 }, [x1]"
10413  //      "ld1\t$Vt, [$Rn]"
10414  // may get mapped to
10415  //      (LD1Twov8b VecListTwo64:$Vt, GPR64sp:$Rn)
10416  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10417                  (!cast<Instruction>(BaseName # Count # "v" # layout)
10418                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10419                      GPR64sp:$Rn), 0>;
10420
10421  // E.g. "ld1.8b { v0, v1 }, [x1], x2"
10422  //      "ld1\t$Vt, [$Rn], $Xm"
10423  // may get mapped to
10424  //      (LD1Twov8b_POST VecListTwo64:$Vt, GPR64sp:$Rn, GPR64pi8:$Xm)
10425  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10426                  (!cast<Instruction>(BaseName # Count # "v" # layout # "_POST")
10427                      GPR64sp:$Rn,
10428                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10429                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10430}
10431
10432multiclass BaseSIMDLdN<string BaseName, string Count, string asm, string veclist,
10433                       int Offset128, int Offset64, bits<4> opcode> {
10434  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10435    def v16b: BaseSIMDLdSt<1, 1, opcode, 0b00, asm,
10436                           (outs !cast<RegisterOperand>(veclist # "16b"):$Vt),
10437                           (ins GPR64sp:$Rn), []>;
10438    def v8h : BaseSIMDLdSt<1, 1, opcode, 0b01, asm,
10439                           (outs !cast<RegisterOperand>(veclist # "8h"):$Vt),
10440                           (ins GPR64sp:$Rn), []>;
10441    def v4s : BaseSIMDLdSt<1, 1, opcode, 0b10, asm,
10442                           (outs !cast<RegisterOperand>(veclist # "4s"):$Vt),
10443                           (ins GPR64sp:$Rn), []>;
10444    def v2d : BaseSIMDLdSt<1, 1, opcode, 0b11, asm,
10445                           (outs !cast<RegisterOperand>(veclist # "2d"):$Vt),
10446                           (ins GPR64sp:$Rn), []>;
10447    def v8b : BaseSIMDLdSt<0, 1, opcode, 0b00, asm,
10448                           (outs !cast<RegisterOperand>(veclist # "8b"):$Vt),
10449                           (ins GPR64sp:$Rn), []>;
10450    def v4h : BaseSIMDLdSt<0, 1, opcode, 0b01, asm,
10451                           (outs !cast<RegisterOperand>(veclist # "4h"):$Vt),
10452                           (ins GPR64sp:$Rn), []>;
10453    def v2s : BaseSIMDLdSt<0, 1, opcode, 0b10, asm,
10454                           (outs !cast<RegisterOperand>(veclist # "2s"):$Vt),
10455                           (ins GPR64sp:$Rn), []>;
10456
10457
10458    def v16b_POST: BaseSIMDLdStPost<1, 1, opcode, 0b00, asm,
10459                       (outs GPR64sp:$wback,
10460                             !cast<RegisterOperand>(veclist # "16b"):$Vt),
10461                       (ins GPR64sp:$Rn,
10462                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10463    def v8h_POST : BaseSIMDLdStPost<1, 1, opcode, 0b01, asm,
10464                       (outs GPR64sp:$wback,
10465                             !cast<RegisterOperand>(veclist # "8h"):$Vt),
10466                       (ins GPR64sp:$Rn,
10467                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10468    def v4s_POST : BaseSIMDLdStPost<1, 1, opcode, 0b10, asm,
10469                       (outs GPR64sp:$wback,
10470                             !cast<RegisterOperand>(veclist # "4s"):$Vt),
10471                       (ins GPR64sp:$Rn,
10472                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10473    def v2d_POST : BaseSIMDLdStPost<1, 1, opcode, 0b11, asm,
10474                       (outs GPR64sp:$wback,
10475                             !cast<RegisterOperand>(veclist # "2d"):$Vt),
10476                       (ins GPR64sp:$Rn,
10477                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10478    def v8b_POST : BaseSIMDLdStPost<0, 1, opcode, 0b00, asm,
10479                       (outs GPR64sp:$wback,
10480                             !cast<RegisterOperand>(veclist # "8b"):$Vt),
10481                       (ins GPR64sp:$Rn,
10482                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10483    def v4h_POST : BaseSIMDLdStPost<0, 1, opcode, 0b01, asm,
10484                       (outs GPR64sp:$wback,
10485                             !cast<RegisterOperand>(veclist # "4h"):$Vt),
10486                       (ins GPR64sp:$Rn,
10487                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10488    def v2s_POST : BaseSIMDLdStPost<0, 1, opcode, 0b10, asm,
10489                       (outs GPR64sp:$wback,
10490                             !cast<RegisterOperand>(veclist # "2s"):$Vt),
10491                       (ins GPR64sp:$Rn,
10492                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10493  }
10494
10495  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10496  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10497  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10498  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10499  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10500  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10501  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10502}
10503
10504// Only ld1/st1 has a v1d version.
10505multiclass BaseSIMDStN<string BaseName, string Count, string asm, string veclist,
10506                       int Offset128, int Offset64, bits<4> opcode> {
10507  let hasSideEffects = 0, mayStore = 1, mayLoad = 0 in {
10508    def v16b : BaseSIMDLdSt<1, 0, opcode, 0b00, asm, (outs),
10509                            (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10510                                 GPR64sp:$Rn), []>;
10511    def v8h : BaseSIMDLdSt<1, 0, opcode, 0b01, asm, (outs),
10512                           (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10513                                GPR64sp:$Rn), []>;
10514    def v4s : BaseSIMDLdSt<1, 0, opcode, 0b10, asm, (outs),
10515                           (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10516                                GPR64sp:$Rn), []>;
10517    def v2d : BaseSIMDLdSt<1, 0, opcode, 0b11, asm, (outs),
10518                           (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10519                                GPR64sp:$Rn), []>;
10520    def v8b : BaseSIMDLdSt<0, 0, opcode, 0b00, asm, (outs),
10521                           (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10522                                GPR64sp:$Rn), []>;
10523    def v4h : BaseSIMDLdSt<0, 0, opcode, 0b01, asm, (outs),
10524                           (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10525                                GPR64sp:$Rn), []>;
10526    def v2s : BaseSIMDLdSt<0, 0, opcode, 0b10, asm, (outs),
10527                           (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10528                                GPR64sp:$Rn), []>;
10529
10530    def v16b_POST : BaseSIMDLdStPost<1, 0, opcode, 0b00, asm,
10531                       (outs GPR64sp:$wback),
10532                       (ins !cast<RegisterOperand>(veclist # "16b"):$Vt,
10533                            GPR64sp:$Rn,
10534                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10535    def v8h_POST : BaseSIMDLdStPost<1, 0, opcode, 0b01, asm,
10536                       (outs GPR64sp:$wback),
10537                       (ins !cast<RegisterOperand>(veclist # "8h"):$Vt,
10538                            GPR64sp:$Rn,
10539                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10540    def v4s_POST : BaseSIMDLdStPost<1, 0, opcode, 0b10, asm,
10541                       (outs GPR64sp:$wback),
10542                       (ins !cast<RegisterOperand>(veclist # "4s"):$Vt,
10543                            GPR64sp:$Rn,
10544                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10545    def v2d_POST : BaseSIMDLdStPost<1, 0, opcode, 0b11, asm,
10546                       (outs GPR64sp:$wback),
10547                       (ins !cast<RegisterOperand>(veclist # "2d"):$Vt,
10548                            GPR64sp:$Rn,
10549                            !cast<RegisterOperand>("GPR64pi" # Offset128):$Xm)>;
10550    def v8b_POST : BaseSIMDLdStPost<0, 0, opcode, 0b00, asm,
10551                       (outs GPR64sp:$wback),
10552                       (ins !cast<RegisterOperand>(veclist # "8b"):$Vt,
10553                            GPR64sp:$Rn,
10554                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10555    def v4h_POST : BaseSIMDLdStPost<0, 0, opcode, 0b01, asm,
10556                       (outs GPR64sp:$wback),
10557                       (ins !cast<RegisterOperand>(veclist # "4h"):$Vt,
10558                            GPR64sp:$Rn,
10559                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10560    def v2s_POST : BaseSIMDLdStPost<0, 0, opcode, 0b10, asm,
10561                       (outs GPR64sp:$wback),
10562                       (ins !cast<RegisterOperand>(veclist # "2s"):$Vt,
10563                            GPR64sp:$Rn,
10564                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10565  }
10566
10567  defm : SIMDLdStAliases<BaseName, asm, "16b", Count, Offset128, 128>;
10568  defm : SIMDLdStAliases<BaseName, asm, "8h", Count, Offset128, 128>;
10569  defm : SIMDLdStAliases<BaseName, asm, "4s", Count, Offset128, 128>;
10570  defm : SIMDLdStAliases<BaseName, asm, "2d", Count, Offset128, 128>;
10571  defm : SIMDLdStAliases<BaseName, asm, "8b", Count, Offset64, 64>;
10572  defm : SIMDLdStAliases<BaseName, asm, "4h", Count, Offset64, 64>;
10573  defm : SIMDLdStAliases<BaseName, asm, "2s", Count, Offset64, 64>;
10574}
10575
10576multiclass BaseSIMDLd1<string BaseName, string Count, string asm, string veclist,
10577                       int Offset128, int Offset64, bits<4> opcode>
10578  : BaseSIMDLdN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10579
10580  // LD1 instructions have extra "1d" variants.
10581  let hasSideEffects = 0, mayLoad = 1, mayStore = 0 in {
10582    def v1d : BaseSIMDLdSt<0, 1, opcode, 0b11, asm,
10583                           (outs !cast<RegisterOperand>(veclist # "1d"):$Vt),
10584                           (ins GPR64sp:$Rn), []>;
10585
10586    def v1d_POST : BaseSIMDLdStPost<0, 1, opcode, 0b11, asm,
10587                       (outs GPR64sp:$wback,
10588                             !cast<RegisterOperand>(veclist # "1d"):$Vt),
10589                       (ins GPR64sp:$Rn,
10590                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10591  }
10592
10593  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10594}
10595
10596multiclass BaseSIMDSt1<string BaseName, string Count, string asm, string veclist,
10597                       int Offset128, int Offset64, bits<4> opcode>
10598  : BaseSIMDStN<BaseName, Count, asm, veclist, Offset128, Offset64, opcode> {
10599
10600  // ST1 instructions have extra "1d" variants.
10601  let hasSideEffects = 0, mayLoad = 0, mayStore = 1 in {
10602    def v1d : BaseSIMDLdSt<0, 0, opcode, 0b11, asm, (outs),
10603                           (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10604                                GPR64sp:$Rn), []>;
10605
10606    def v1d_POST : BaseSIMDLdStPost<0, 0, opcode, 0b11, asm,
10607                       (outs GPR64sp:$wback),
10608                       (ins !cast<RegisterOperand>(veclist # "1d"):$Vt,
10609                            GPR64sp:$Rn,
10610                            !cast<RegisterOperand>("GPR64pi" # Offset64):$Xm)>;
10611  }
10612
10613  defm : SIMDLdStAliases<BaseName, asm, "1d", Count, Offset64, 64>;
10614}
10615
10616multiclass SIMDLd1Multiple<string asm> {
10617  defm One   : BaseSIMDLd1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10618  defm Two   : BaseSIMDLd1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10619  defm Three : BaseSIMDLd1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10620  defm Four  : BaseSIMDLd1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10621}
10622
10623multiclass SIMDSt1Multiple<string asm> {
10624  defm One   : BaseSIMDSt1<NAME, "One", asm, "VecListOne", 16, 8,  0b0111>;
10625  defm Two   : BaseSIMDSt1<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1010>;
10626  defm Three : BaseSIMDSt1<NAME, "Three", asm, "VecListThree", 48, 24, 0b0110>;
10627  defm Four  : BaseSIMDSt1<NAME, "Four", asm, "VecListFour", 64, 32, 0b0010>;
10628}
10629
10630multiclass SIMDLd2Multiple<string asm> {
10631  defm Two : BaseSIMDLdN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10632}
10633
10634multiclass SIMDSt2Multiple<string asm> {
10635  defm Two : BaseSIMDStN<NAME, "Two", asm, "VecListTwo", 32, 16, 0b1000>;
10636}
10637
10638multiclass SIMDLd3Multiple<string asm> {
10639  defm Three : BaseSIMDLdN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10640}
10641
10642multiclass SIMDSt3Multiple<string asm> {
10643  defm Three : BaseSIMDStN<NAME, "Three", asm, "VecListThree", 48, 24, 0b0100>;
10644}
10645
10646multiclass SIMDLd4Multiple<string asm> {
10647  defm Four : BaseSIMDLdN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10648}
10649
10650multiclass SIMDSt4Multiple<string asm> {
10651  defm Four : BaseSIMDStN<NAME, "Four", asm, "VecListFour", 64, 32, 0b0000>;
10652}
10653
10654//---
10655// AdvSIMD Load/store single-element
10656//---
10657
10658class BaseSIMDLdStSingle<bit L, bit R, bits<3> opcode,
10659                         string asm, string operands, string cst,
10660                         dag oops, dag iops, list<dag> pattern>
10661  : I<oops, iops, asm, operands, cst, pattern> {
10662  bits<5> Vt;
10663  bits<5> Rn;
10664  let Inst{31} = 0;
10665  let Inst{29-24} = 0b001101;
10666  let Inst{22} = L;
10667  let Inst{21} = R;
10668  let Inst{15-13} = opcode;
10669  let Inst{9-5} = Rn;
10670  let Inst{4-0} = Vt;
10671}
10672
10673class BaseSIMDLdStSingleTied<bit L, bit R, bits<3> opcode,
10674                         string asm, string operands, string cst,
10675                         dag oops, dag iops, list<dag> pattern>
10676  : I<oops, iops, asm, operands, "$Vt = $dst," # cst, pattern> {
10677  bits<5> Vt;
10678  bits<5> Rn;
10679  let Inst{31} = 0;
10680  let Inst{29-24} = 0b001101;
10681  let Inst{22} = L;
10682  let Inst{21} = R;
10683  let Inst{15-13} = opcode;
10684  let Inst{9-5} = Rn;
10685  let Inst{4-0} = Vt;
10686}
10687
10688
10689let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10690class BaseSIMDLdR<bit Q, bit R, bits<3> opcode, bit S, bits<2> size, string asm,
10691                  DAGOperand listtype>
10692  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn]", "",
10693                       (outs listtype:$Vt), (ins GPR64sp:$Rn),
10694                       []> {
10695  let Inst{30} = Q;
10696  let Inst{23} = 0;
10697  let Inst{20-16} = 0b00000;
10698  let Inst{12} = S;
10699  let Inst{11-10} = size;
10700}
10701let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
10702class BaseSIMDLdRPost<bit Q, bit R, bits<3> opcode, bit S, bits<2> size,
10703                      string asm, DAGOperand listtype, DAGOperand GPR64pi>
10704  : BaseSIMDLdStSingle<1, R, opcode, asm, "\t$Vt, [$Rn], $Xm",
10705                       "$Rn = $wback",
10706                       (outs GPR64sp:$wback, listtype:$Vt),
10707                       (ins GPR64sp:$Rn, GPR64pi:$Xm), []> {
10708  bits<5> Xm;
10709  let Inst{30} = Q;
10710  let Inst{23} = 1;
10711  let Inst{20-16} = Xm;
10712  let Inst{12} = S;
10713  let Inst{11-10} = size;
10714}
10715
10716multiclass SIMDLdrAliases<string BaseName, string asm, string layout, string Count,
10717                          int Offset, int Size> {
10718  // E.g. "ld1r { v0.8b }, [x1], #1"
10719  //      "ld1r.8b\t$Vt, [$Rn], #1"
10720  // may get mapped to
10721  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
10722  def : InstAlias<asm # "\t$Vt, [$Rn], #" # Offset,
10723                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10724                      GPR64sp:$Rn,
10725                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
10726                      XZR), 1>;
10727
10728  // E.g. "ld1r.8b { v0 }, [x1], #1"
10729  //      "ld1r.8b\t$Vt, [$Rn], #1"
10730  // may get mapped to
10731  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
10732  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], #" # Offset,
10733                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10734                      GPR64sp:$Rn,
10735                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10736                      XZR), 0>;
10737
10738  // E.g. "ld1r.8b { v0 }, [x1]"
10739  //      "ld1r.8b\t$Vt, [$Rn]"
10740  // may get mapped to
10741  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
10742  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn]",
10743                  (!cast<Instruction>(BaseName # "v" # layout)
10744                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10745                      GPR64sp:$Rn), 0>;
10746
10747  // E.g. "ld1r.8b { v0 }, [x1], x2"
10748  //      "ld1r.8b\t$Vt, [$Rn], $Xm"
10749  // may get mapped to
10750  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
10751  def : InstAlias<asm # "." # layout # "\t$Vt, [$Rn], $Xm",
10752                  (!cast<Instruction>(BaseName # "v" # layout # "_POST")
10753                      GPR64sp:$Rn,
10754                      !cast<RegisterOperand>("VecList" # Count # Size):$Vt,
10755                      !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
10756}
10757
10758multiclass SIMDLdR<bit R, bits<3> opcode, bit S, string asm, string Count,
10759  int Offset1, int Offset2, int Offset4, int Offset8> {
10760  def v8b : BaseSIMDLdR<0, R, opcode, S, 0b00, asm,
10761                        !cast<DAGOperand>("VecList" # Count # "8b")>;
10762  def v16b: BaseSIMDLdR<1, R, opcode, S, 0b00, asm,
10763                        !cast<DAGOperand>("VecList" # Count #"16b")>;
10764  def v4h : BaseSIMDLdR<0, R, opcode, S, 0b01, asm,
10765                        !cast<DAGOperand>("VecList" # Count #"4h")>;
10766  def v8h : BaseSIMDLdR<1, R, opcode, S, 0b01, asm,
10767                        !cast<DAGOperand>("VecList" # Count #"8h")>;
10768  def v2s : BaseSIMDLdR<0, R, opcode, S, 0b10, asm,
10769                        !cast<DAGOperand>("VecList" # Count #"2s")>;
10770  def v4s : BaseSIMDLdR<1, R, opcode, S, 0b10, asm,
10771                        !cast<DAGOperand>("VecList" # Count #"4s")>;
10772  def v1d : BaseSIMDLdR<0, R, opcode, S, 0b11, asm,
10773                        !cast<DAGOperand>("VecList" # Count #"1d")>;
10774  def v2d : BaseSIMDLdR<1, R, opcode, S, 0b11, asm,
10775                        !cast<DAGOperand>("VecList" # Count #"2d")>;
10776
10777  def v8b_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b00, asm,
10778                                 !cast<DAGOperand>("VecList" # Count # "8b"),
10779                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10780  def v16b_POST: BaseSIMDLdRPost<1, R, opcode, S, 0b00, asm,
10781                                 !cast<DAGOperand>("VecList" # Count # "16b"),
10782                                 !cast<DAGOperand>("GPR64pi" # Offset1)>;
10783  def v4h_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b01, asm,
10784                                 !cast<DAGOperand>("VecList" # Count # "4h"),
10785                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10786  def v8h_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b01, asm,
10787                                 !cast<DAGOperand>("VecList" # Count # "8h"),
10788                                 !cast<DAGOperand>("GPR64pi" # Offset2)>;
10789  def v2s_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b10, asm,
10790                                 !cast<DAGOperand>("VecList" # Count # "2s"),
10791                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10792  def v4s_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b10, asm,
10793                                 !cast<DAGOperand>("VecList" # Count # "4s"),
10794                                 !cast<DAGOperand>("GPR64pi" # Offset4)>;
10795  def v1d_POST : BaseSIMDLdRPost<0, R, opcode, S, 0b11, asm,
10796                                 !cast<DAGOperand>("VecList" # Count # "1d"),
10797                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10798  def v2d_POST : BaseSIMDLdRPost<1, R, opcode, S, 0b11, asm,
10799                                 !cast<DAGOperand>("VecList" # Count # "2d"),
10800                                 !cast<DAGOperand>("GPR64pi" # Offset8)>;
10801
10802  defm : SIMDLdrAliases<NAME, asm, "8b",  Count, Offset1,  64>;
10803  defm : SIMDLdrAliases<NAME, asm, "16b", Count, Offset1, 128>;
10804  defm : SIMDLdrAliases<NAME, asm, "4h",  Count, Offset2,  64>;
10805  defm : SIMDLdrAliases<NAME, asm, "8h",  Count, Offset2, 128>;
10806  defm : SIMDLdrAliases<NAME, asm, "2s",  Count, Offset4,  64>;
10807  defm : SIMDLdrAliases<NAME, asm, "4s",  Count, Offset4, 128>;
10808  defm : SIMDLdrAliases<NAME, asm, "1d",  Count, Offset8,  64>;
10809  defm : SIMDLdrAliases<NAME, asm, "2d",  Count, Offset8, 128>;
10810}
10811
10812class SIMDLdStSingleB<bit L, bit R, bits<3> opcode, string asm,
10813                      dag oops, dag iops, list<dag> pattern>
10814  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10815                       pattern> {
10816  // idx encoded in Q:S:size fields.
10817  bits<4> idx;
10818  let Inst{30} = idx{3};
10819  let Inst{23} = 0;
10820  let Inst{20-16} = 0b00000;
10821  let Inst{12} = idx{2};
10822  let Inst{11-10} = idx{1-0};
10823}
10824class SIMDLdStSingleBTied<bit L, bit R, bits<3> opcode, string asm,
10825                      dag oops, dag iops, list<dag> pattern>
10826  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10827                           oops, iops, pattern> {
10828  // idx encoded in Q:S:size fields.
10829  bits<4> idx;
10830  let Inst{30} = idx{3};
10831  let Inst{23} = 0;
10832  let Inst{20-16} = 0b00000;
10833  let Inst{12} = idx{2};
10834  let Inst{11-10} = idx{1-0};
10835}
10836class SIMDLdStSingleBPost<bit L, bit R, bits<3> opcode, string asm,
10837                          dag oops, dag iops>
10838  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10839                       "$Rn = $wback", oops, iops, []> {
10840  // idx encoded in Q:S:size fields.
10841  bits<4> idx;
10842  bits<5> Xm;
10843  let Inst{30} = idx{3};
10844  let Inst{23} = 1;
10845  let Inst{20-16} = Xm;
10846  let Inst{12} = idx{2};
10847  let Inst{11-10} = idx{1-0};
10848}
10849class SIMDLdStSingleBTiedPost<bit L, bit R, bits<3> opcode, string asm,
10850                          dag oops, dag iops>
10851  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10852                           "$Rn = $wback", oops, iops, []> {
10853  // idx encoded in Q:S:size fields.
10854  bits<4> idx;
10855  bits<5> Xm;
10856  let Inst{30} = idx{3};
10857  let Inst{23} = 1;
10858  let Inst{20-16} = Xm;
10859  let Inst{12} = idx{2};
10860  let Inst{11-10} = idx{1-0};
10861}
10862
10863class SIMDLdStSingleH<bit L, bit R, bits<3> opcode, bit size, string asm,
10864                      dag oops, dag iops, list<dag> pattern>
10865  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10866                       pattern> {
10867  // idx encoded in Q:S:size<1> fields.
10868  bits<3> idx;
10869  let Inst{30} = idx{2};
10870  let Inst{23} = 0;
10871  let Inst{20-16} = 0b00000;
10872  let Inst{12} = idx{1};
10873  let Inst{11} = idx{0};
10874  let Inst{10} = size;
10875}
10876class SIMDLdStSingleHTied<bit L, bit R, bits<3> opcode, bit size, string asm,
10877                      dag oops, dag iops, list<dag> pattern>
10878  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10879                           oops, iops, pattern> {
10880  // idx encoded in Q:S:size<1> fields.
10881  bits<3> idx;
10882  let Inst{30} = idx{2};
10883  let Inst{23} = 0;
10884  let Inst{20-16} = 0b00000;
10885  let Inst{12} = idx{1};
10886  let Inst{11} = idx{0};
10887  let Inst{10} = size;
10888}
10889
10890class SIMDLdStSingleHPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10891                          dag oops, dag iops>
10892  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10893                       "$Rn = $wback", oops, iops, []> {
10894  // idx encoded in Q:S:size<1> fields.
10895  bits<3> idx;
10896  bits<5> Xm;
10897  let Inst{30} = idx{2};
10898  let Inst{23} = 1;
10899  let Inst{20-16} = Xm;
10900  let Inst{12} = idx{1};
10901  let Inst{11} = idx{0};
10902  let Inst{10} = size;
10903}
10904class SIMDLdStSingleHTiedPost<bit L, bit R, bits<3> opcode, bit size, string asm,
10905                          dag oops, dag iops>
10906  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10907                           "$Rn = $wback", oops, iops, []> {
10908  // idx encoded in Q:S:size<1> fields.
10909  bits<3> idx;
10910  bits<5> Xm;
10911  let Inst{30} = idx{2};
10912  let Inst{23} = 1;
10913  let Inst{20-16} = Xm;
10914  let Inst{12} = idx{1};
10915  let Inst{11} = idx{0};
10916  let Inst{10} = size;
10917}
10918class SIMDLdStSingleS<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10919                      dag oops, dag iops, list<dag> pattern>
10920  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10921                       pattern> {
10922  // idx encoded in Q:S fields.
10923  bits<2> idx;
10924  let Inst{30} = idx{1};
10925  let Inst{23} = 0;
10926  let Inst{20-16} = 0b00000;
10927  let Inst{12} = idx{0};
10928  let Inst{11-10} = size;
10929}
10930class SIMDLdStSingleSTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10931                      dag oops, dag iops, list<dag> pattern>
10932  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10933                           oops, iops, pattern> {
10934  // idx encoded in Q:S fields.
10935  bits<2> idx;
10936  let Inst{30} = idx{1};
10937  let Inst{23} = 0;
10938  let Inst{20-16} = 0b00000;
10939  let Inst{12} = idx{0};
10940  let Inst{11-10} = size;
10941}
10942class SIMDLdStSingleSPost<bit L, bit R, bits<3> opcode, bits<2> size,
10943                          string asm, dag oops, dag iops>
10944  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10945                       "$Rn = $wback", oops, iops, []> {
10946  // idx encoded in Q:S fields.
10947  bits<2> idx;
10948  bits<5> Xm;
10949  let Inst{30} = idx{1};
10950  let Inst{23} = 1;
10951  let Inst{20-16} = Xm;
10952  let Inst{12} = idx{0};
10953  let Inst{11-10} = size;
10954}
10955class SIMDLdStSingleSTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
10956                          string asm, dag oops, dag iops>
10957  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10958                           "$Rn = $wback", oops, iops, []> {
10959  // idx encoded in Q:S fields.
10960  bits<2> idx;
10961  bits<5> Xm;
10962  let Inst{30} = idx{1};
10963  let Inst{23} = 1;
10964  let Inst{20-16} = Xm;
10965  let Inst{12} = idx{0};
10966  let Inst{11-10} = size;
10967}
10968class SIMDLdStSingleD<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10969                      dag oops, dag iops, list<dag> pattern>
10970  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "", oops, iops,
10971                       pattern> {
10972  // idx encoded in Q field.
10973  bits<1> idx;
10974  let Inst{30} = idx;
10975  let Inst{23} = 0;
10976  let Inst{20-16} = 0b00000;
10977  let Inst{12} = 0;
10978  let Inst{11-10} = size;
10979}
10980class SIMDLdStSingleDTied<bit L, bit R, bits<3> opcode, bits<2> size, string asm,
10981                      dag oops, dag iops, list<dag> pattern>
10982  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn]", "",
10983                           oops, iops, pattern> {
10984  // idx encoded in Q field.
10985  bits<1> idx;
10986  let Inst{30} = idx;
10987  let Inst{23} = 0;
10988  let Inst{20-16} = 0b00000;
10989  let Inst{12} = 0;
10990  let Inst{11-10} = size;
10991}
10992class SIMDLdStSingleDPost<bit L, bit R, bits<3> opcode, bits<2> size,
10993                          string asm, dag oops, dag iops>
10994  : BaseSIMDLdStSingle<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
10995                       "$Rn = $wback", oops, iops, []> {
10996  // idx encoded in Q field.
10997  bits<1> idx;
10998  bits<5> Xm;
10999  let Inst{30} = idx;
11000  let Inst{23} = 1;
11001  let Inst{20-16} = Xm;
11002  let Inst{12} = 0;
11003  let Inst{11-10} = size;
11004}
11005class SIMDLdStSingleDTiedPost<bit L, bit R, bits<3> opcode, bits<2> size,
11006                          string asm, dag oops, dag iops>
11007  : BaseSIMDLdStSingleTied<L, R, opcode, asm, "\t$Vt$idx, [$Rn], $Xm",
11008                           "$Rn = $wback", oops, iops, []> {
11009  // idx encoded in Q field.
11010  bits<1> idx;
11011  bits<5> Xm;
11012  let Inst{30} = idx;
11013  let Inst{23} = 1;
11014  let Inst{20-16} = Xm;
11015  let Inst{12} = 0;
11016  let Inst{11-10} = size;
11017}
11018
11019let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11020multiclass SIMDLdSingleBTied<bit R, bits<3> opcode, string asm,
11021                         RegisterOperand listtype,
11022                         RegisterOperand GPR64pi> {
11023  def i8 : SIMDLdStSingleBTied<1, R, opcode, asm,
11024                           (outs listtype:$dst),
11025                           (ins listtype:$Vt, VectorIndexB:$idx,
11026                                GPR64sp:$Rn), []>;
11027
11028  def i8_POST : SIMDLdStSingleBTiedPost<1, R, opcode, asm,
11029                            (outs GPR64sp:$wback, listtype:$dst),
11030                            (ins listtype:$Vt, VectorIndexB:$idx,
11031                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11032}
11033let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11034multiclass SIMDLdSingleHTied<bit R, bits<3> opcode, bit size, string asm,
11035                         RegisterOperand listtype,
11036                         RegisterOperand GPR64pi> {
11037  def i16 : SIMDLdStSingleHTied<1, R, opcode, size, asm,
11038                            (outs listtype:$dst),
11039                            (ins listtype:$Vt, VectorIndexH:$idx,
11040                                 GPR64sp:$Rn), []>;
11041
11042  def i16_POST : SIMDLdStSingleHTiedPost<1, R, opcode, size, asm,
11043                            (outs GPR64sp:$wback, listtype:$dst),
11044                            (ins listtype:$Vt, VectorIndexH:$idx,
11045                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11046}
11047let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11048multiclass SIMDLdSingleSTied<bit R, bits<3> opcode, bits<2> size,string asm,
11049                         RegisterOperand listtype,
11050                         RegisterOperand GPR64pi> {
11051  def i32 : SIMDLdStSingleSTied<1, R, opcode, size, asm,
11052                            (outs listtype:$dst),
11053                            (ins listtype:$Vt, VectorIndexS:$idx,
11054                                 GPR64sp:$Rn), []>;
11055
11056  def i32_POST : SIMDLdStSingleSTiedPost<1, R, opcode, size, asm,
11057                            (outs GPR64sp:$wback, listtype:$dst),
11058                            (ins listtype:$Vt, VectorIndexS:$idx,
11059                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11060}
11061let mayLoad = 1, mayStore = 0, hasSideEffects = 0 in
11062multiclass SIMDLdSingleDTied<bit R, bits<3> opcode, bits<2> size, string asm,
11063                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11064  def i64 : SIMDLdStSingleDTied<1, R, opcode, size, asm,
11065                            (outs listtype:$dst),
11066                            (ins listtype:$Vt, VectorIndexD:$idx,
11067                                 GPR64sp:$Rn), []>;
11068
11069  def i64_POST : SIMDLdStSingleDTiedPost<1, R, opcode, size, asm,
11070                            (outs GPR64sp:$wback, listtype:$dst),
11071                            (ins listtype:$Vt, VectorIndexD:$idx,
11072                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11073}
11074let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11075multiclass SIMDStSingleB<bit R, bits<3> opcode, string asm,
11076                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11077  def i8 : SIMDLdStSingleB<0, R, opcode, asm,
11078                           (outs), (ins listtype:$Vt, VectorIndexB:$idx,
11079                                        GPR64sp:$Rn), []>;
11080
11081  def i8_POST : SIMDLdStSingleBPost<0, R, opcode, asm,
11082                                    (outs GPR64sp:$wback),
11083                                    (ins listtype:$Vt, VectorIndexB:$idx,
11084                                         GPR64sp:$Rn, GPR64pi:$Xm)>;
11085}
11086let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11087multiclass SIMDStSingleH<bit R, bits<3> opcode, bit size, string asm,
11088                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11089  def i16 : SIMDLdStSingleH<0, R, opcode, size, asm,
11090                            (outs), (ins listtype:$Vt, VectorIndexH:$idx,
11091                                         GPR64sp:$Rn), []>;
11092
11093  def i16_POST : SIMDLdStSingleHPost<0, R, opcode, size, asm,
11094                            (outs GPR64sp:$wback),
11095                            (ins listtype:$Vt, VectorIndexH:$idx,
11096                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11097}
11098let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11099multiclass SIMDStSingleS<bit R, bits<3> opcode, bits<2> size,string asm,
11100                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11101  def i32 : SIMDLdStSingleS<0, R, opcode, size, asm,
11102                            (outs), (ins listtype:$Vt, VectorIndexS:$idx,
11103                                         GPR64sp:$Rn), []>;
11104
11105  def i32_POST : SIMDLdStSingleSPost<0, R, opcode, size, asm,
11106                            (outs GPR64sp:$wback),
11107                            (ins listtype:$Vt, VectorIndexS:$idx,
11108                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11109}
11110let mayLoad = 0, mayStore = 1, hasSideEffects = 0 in
11111multiclass SIMDStSingleD<bit R, bits<3> opcode, bits<2> size, string asm,
11112                         RegisterOperand listtype, RegisterOperand GPR64pi> {
11113  def i64 : SIMDLdStSingleD<0, R, opcode, size, asm,
11114                            (outs), (ins listtype:$Vt, VectorIndexD:$idx,
11115                                         GPR64sp:$Rn), []>;
11116
11117  def i64_POST : SIMDLdStSingleDPost<0, R, opcode, size, asm,
11118                            (outs GPR64sp:$wback),
11119                            (ins listtype:$Vt, VectorIndexD:$idx,
11120                                 GPR64sp:$Rn, GPR64pi:$Xm)>;
11121}
11122
11123multiclass SIMDLdStSingleAliases<string asm, string layout, string Type,
11124                                 string Count, int Offset, Operand idxtype> {
11125  // E.g. "ld1 { v0.8b }[0], [x1], #1"
11126  //      "ld1\t$Vt, [$Rn], #1"
11127  // may get mapped to
11128  //      (LD1Rv8b_POST VecListOne8b:$Vt, GPR64sp:$Rn, XZR)
11129  def : InstAlias<asm # "\t$Vt$idx, [$Rn], #" # Offset,
11130                  (!cast<Instruction>(NAME # Type  # "_POST")
11131                      GPR64sp:$Rn,
11132                      !cast<RegisterOperand>("VecList" # Count # layout):$Vt,
11133                      idxtype:$idx, XZR), 1>;
11134
11135  // E.g. "ld1.8b { v0 }[0], [x1], #1"
11136  //      "ld1.8b\t$Vt, [$Rn], #1"
11137  // may get mapped to
11138  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, XZR)
11139  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], #" # Offset,
11140                  (!cast<Instruction>(NAME # Type # "_POST")
11141                      GPR64sp:$Rn,
11142                      !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11143                      idxtype:$idx, XZR), 0>;
11144
11145  // E.g. "ld1.8b { v0 }[0], [x1]"
11146  //      "ld1.8b\t$Vt, [$Rn]"
11147  // may get mapped to
11148  //      (LD1Rv8b VecListOne64:$Vt, GPR64sp:$Rn)
11149  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn]",
11150                      (!cast<Instruction>(NAME # Type)
11151                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11152                         idxtype:$idx, GPR64sp:$Rn), 0>;
11153
11154  // E.g. "ld1.8b { v0 }[0], [x1], x2"
11155  //      "ld1.8b\t$Vt, [$Rn], $Xm"
11156  // may get mapped to
11157  //      (LD1Rv8b_POST VecListOne64:$Vt, GPR64sp:$Rn, GPR64pi1:$Xm)
11158  def : InstAlias<asm # "." # layout # "\t$Vt$idx, [$Rn], $Xm",
11159                      (!cast<Instruction>(NAME # Type # "_POST")
11160                         GPR64sp:$Rn,
11161                         !cast<RegisterOperand>("VecList" # Count # "128"):$Vt,
11162                         idxtype:$idx,
11163                         !cast<RegisterOperand>("GPR64pi" # Offset):$Xm), 0>;
11164}
11165
11166multiclass SIMDLdSt1SingleAliases<string asm> {
11167  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "One", 1, VectorIndexB>;
11168  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "One", 2, VectorIndexH>;
11169  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "One", 4, VectorIndexS>;
11170  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "One", 8, VectorIndexD>;
11171}
11172
11173multiclass SIMDLdSt2SingleAliases<string asm> {
11174  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Two", 2,  VectorIndexB>;
11175  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Two", 4,  VectorIndexH>;
11176  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Two", 8,  VectorIndexS>;
11177  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Two", 16, VectorIndexD>;
11178}
11179
11180multiclass SIMDLdSt3SingleAliases<string asm> {
11181  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Three", 3,  VectorIndexB>;
11182  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Three", 6,  VectorIndexH>;
11183  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Three", 12, VectorIndexS>;
11184  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Three", 24, VectorIndexD>;
11185}
11186
11187multiclass SIMDLdSt4SingleAliases<string asm> {
11188  defm "" : SIMDLdStSingleAliases<asm, "b", "i8",  "Four", 4,  VectorIndexB>;
11189  defm "" : SIMDLdStSingleAliases<asm, "h", "i16", "Four", 8,  VectorIndexH>;
11190  defm "" : SIMDLdStSingleAliases<asm, "s", "i32", "Four", 16, VectorIndexS>;
11191  defm "" : SIMDLdStSingleAliases<asm, "d", "i64", "Four", 32, VectorIndexD>;
11192}
11193} // end of 'let Predicates = [HasNEON]'
11194
11195//----------------------------------------------------------------------------
11196// AdvSIMD v8.1 Rounding Double Multiply Add/Subtract
11197//----------------------------------------------------------------------------
11198
11199let Predicates = [HasNEON, HasRDM] in {
11200
11201class BaseSIMDThreeSameVectorTiedR0<bit Q, bit U, bits<2> size, bits<5> opcode,
11202                                    RegisterOperand regtype, string asm,
11203                                    string kind, list<dag> pattern>
11204  : BaseSIMDThreeSameVectorTied<Q, U, {size,0}, opcode, regtype, asm, kind,
11205                                pattern> {
11206}
11207multiclass SIMDThreeSameVectorSQRDMLxHTiedHS<bit U, bits<5> opc, string asm,
11208                                             SDPatternOperator op> {
11209  def v4i16 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b01, opc, V64, asm, ".4h",
11210    [(set (v4i16 V64:$dst),
11211          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn), (v4i16 V64:$Rm))))]>;
11212  def v8i16 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b01, opc, V128, asm, ".8h",
11213    [(set (v8i16 V128:$dst),
11214          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn), (v8i16 V128:$Rm))))]>;
11215  def v2i32 : BaseSIMDThreeSameVectorTiedR0<0, U, 0b10, opc, V64, asm, ".2s",
11216    [(set (v2i32 V64:$dst),
11217          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn), (v2i32 V64:$Rm))))]>;
11218  def v4i32 : BaseSIMDThreeSameVectorTiedR0<1, U, 0b10, opc, V128, asm, ".4s",
11219    [(set (v4i32 V128:$dst),
11220          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn), (v4i32 V128:$Rm))))]>;
11221}
11222
11223multiclass SIMDIndexedSQRDMLxHSDTied<bit U, bits<4> opc, string asm,
11224                                     SDPatternOperator op> {
11225  def v4i16_indexed : BaseSIMDIndexedTied<0, U, 0, 0b01, opc,
11226                                          V64, V64, V128_lo, VectorIndexH,
11227                                          asm, ".4h", ".4h", ".4h", ".h",
11228    [(set (v4i16 V64:$dst),
11229          (v4i16 (op (v4i16 V64:$Rd), (v4i16 V64:$Rn),
11230                     (dup_v8i16 (v8i16 V128_lo:$Rm),
11231                                 VectorIndexH:$idx))))]> {
11232    bits<3> idx;
11233    let Inst{11} = idx{2};
11234    let Inst{21} = idx{1};
11235    let Inst{20} = idx{0};
11236  }
11237
11238  def v8i16_indexed : BaseSIMDIndexedTied<1, U, 0, 0b01, opc,
11239                                          V128, V128, V128_lo, VectorIndexH,
11240                                          asm, ".8h", ".8h", ".8h", ".h",
11241    [(set (v8i16 V128:$dst),
11242          (v8i16 (op (v8i16 V128:$Rd), (v8i16 V128:$Rn),
11243                     (v8i16 (AArch64duplane16 (v8i16 V128_lo:$Rm),
11244                                              VectorIndexH:$idx)))))]> {
11245    bits<3> idx;
11246    let Inst{11} = idx{2};
11247    let Inst{21} = idx{1};
11248    let Inst{20} = idx{0};
11249  }
11250
11251  def v2i32_indexed : BaseSIMDIndexedTied<0, U, 0, 0b10, opc,
11252                                          V64, V64, V128, VectorIndexS,
11253                                          asm, ".2s", ".2s", ".2s", ".s",
11254    [(set (v2i32 V64:$dst),
11255          (v2i32 (op (v2i32 V64:$Rd), (v2i32 V64:$Rn),
11256                     (dup_v4i32 (v4i32 V128:$Rm), VectorIndexS:$idx))))]> {
11257    bits<2> idx;
11258    let Inst{11} = idx{1};
11259    let Inst{21} = idx{0};
11260  }
11261
11262  def v4i32_indexed : BaseSIMDIndexedTied<1, U, 0, 0b10, opc,
11263                                          V128, V128, V128, VectorIndexS,
11264                                          asm, ".4s", ".4s", ".4s", ".s",
11265    [(set (v4i32 V128:$dst),
11266          (v4i32 (op (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11267                     (v4i32 (AArch64duplane32 (v4i32 V128:$Rm),
11268                                              VectorIndexS:$idx)))))]> {
11269    bits<2> idx;
11270    let Inst{11} = idx{1};
11271    let Inst{21} = idx{0};
11272  }
11273
11274  def v1i16_indexed : BaseSIMDIndexedTied<1, U, 1, 0b01, opc,
11275                                          FPR16Op, FPR16Op, V128_lo,
11276                                          VectorIndexH, asm, ".h", "", "", ".h",
11277                                          []> {
11278    bits<3> idx;
11279    let Inst{11} = idx{2};
11280    let Inst{21} = idx{1};
11281    let Inst{20} = idx{0};
11282  }
11283
11284  def v1i32_indexed : BaseSIMDIndexedTied<1, U, 1, 0b10, opc,
11285                                          FPR32Op, FPR32Op, V128, VectorIndexS,
11286                                          asm, ".s", "", "", ".s",
11287    [(set (i32 FPR32Op:$dst),
11288          (i32 (op (i32 FPR32Op:$Rd), (i32 FPR32Op:$Rn),
11289                   (i32 (vector_extract (v4i32 V128:$Rm),
11290                                        VectorIndexS:$idx)))))]> {
11291    bits<2> idx;
11292    let Inst{11} = idx{1};
11293    let Inst{21} = idx{0};
11294  }
11295}
11296} // let Predicates = [HasNeon, HasRDM]
11297
11298//----------------------------------------------------------------------------
11299// ARMv8.3 Complex ADD/MLA instructions
11300//----------------------------------------------------------------------------
11301
11302class ComplexRotationOperand<int Angle, int Remainder, string Type>
11303  : AsmOperandClass {
11304  let PredicateMethod = "isComplexRotation<" # Angle # ", " # Remainder # ">";
11305  let DiagnosticType = "InvalidComplexRotation" # Type;
11306  let Name = "ComplexRotation" # Type;
11307}
11308def complexrotateop : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
11309                                                  SDNodeXForm<imm, [{
11310  return CurDAG->getTargetConstant((N->getSExtValue() / 90), SDLoc(N), MVT::i32);
11311}]>> {
11312  let ParserMatchClass = ComplexRotationOperand<90, 0, "Even">;
11313  let PrintMethod = "printComplexRotationOp<90, 0>";
11314}
11315def complexrotateopodd : Operand<i32>, TImmLeaf<i32, [{ return Imm >= 0 && Imm <= 270;  }],
11316                                                  SDNodeXForm<imm, [{
11317  return CurDAG->getTargetConstant(((N->getSExtValue() - 90) / 180), SDLoc(N), MVT::i32);
11318}]>> {
11319  let ParserMatchClass = ComplexRotationOperand<180, 90, "Odd">;
11320  let PrintMethod = "printComplexRotationOp<180, 90>";
11321}
11322let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11323class BaseSIMDThreeSameVectorComplex<bit Q, bit U, bits<2> size, bits<3> opcode,
11324                                     RegisterOperand regtype, Operand rottype,
11325                                     string asm, string kind, list<dag> pattern>
11326  : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
11327      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
11328      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>,
11329    Sched<[!if(Q, WriteVq, WriteVd)]> {
11330  bits<5> Rd;
11331  bits<5> Rn;
11332  bits<5> Rm;
11333  bits<1> rot;
11334  let Inst{31}    = 0;
11335  let Inst{30}    = Q;
11336  let Inst{29}    = U;
11337  let Inst{28-24} = 0b01110;
11338  let Inst{23-22} = size;
11339  let Inst{21}    = 0;
11340  let Inst{20-16} = Rm;
11341  let Inst{15-13} = opcode;
11342  // Non-tied version (FCADD) only has one rotation bit
11343  let Inst{12}    = rot;
11344  let Inst{11}    = 0;
11345  let Inst{10}    = 1;
11346  let Inst{9-5}   = Rn;
11347  let Inst{4-0}   = Rd;
11348}
11349
11350//8.3 CompNum - Floating-point complex number support
11351multiclass SIMDThreeSameVectorComplexHSD<bit U, bits<3> opcode, Operand rottype,
11352                                          string asm, SDPatternOperator OpNode>{
11353  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11354  def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype,
11355              asm, ".4h",
11356              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11357                                              (v4f16 V64:$Rn),
11358                                              (v4f16 V64:$Rm),
11359                                              (i32 rottype:$rot)))]>;
11360
11361  def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype,
11362              asm, ".8h",
11363              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11364                                               (v8f16 V128:$Rn),
11365                                               (v8f16 V128:$Rm),
11366                                               (i32 rottype:$rot)))]>;
11367  }
11368
11369  let Predicates = [HasComplxNum, HasNEON] in {
11370  def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype,
11371              asm, ".2s",
11372              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11373                                              (v2f32 V64:$Rn),
11374                                              (v2f32 V64:$Rm),
11375                                              (i32 rottype:$rot)))]>;
11376
11377  def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype,
11378              asm, ".4s",
11379              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11380                                               (v4f32 V128:$Rn),
11381                                               (v4f32 V128:$Rm),
11382                                               (i32 rottype:$rot)))]>;
11383
11384  def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype,
11385              asm, ".2d",
11386              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11387                                               (v2f64 V128:$Rn),
11388                                               (v2f64 V128:$Rm),
11389                                               (i32 rottype:$rot)))]>;
11390  }
11391}
11392
11393let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11394class BaseSIMDThreeSameVectorTiedComplex<bit Q, bit U, bits<2> size,
11395                                         bits<3> opcode,
11396                                         RegisterOperand regtype,
11397                                         Operand rottype, string asm,
11398                                         string kind, list<dag> pattern>
11399  : I<(outs regtype:$dst),
11400      (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm,
11401      "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot"
11402      "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>,
11403    Sched<[!if(Q, WriteVq, WriteVd)]> {
11404  bits<5> Rd;
11405  bits<5> Rn;
11406  bits<5> Rm;
11407  bits<2> rot;
11408  let Inst{31}    = 0;
11409  let Inst{30}    = Q;
11410  let Inst{29}    = U;
11411  let Inst{28-24} = 0b01110;
11412  let Inst{23-22} = size;
11413  let Inst{21}    = 0;
11414  let Inst{20-16} = Rm;
11415  let Inst{15-13} = opcode;
11416  let Inst{12-11} = rot;
11417  let Inst{10}    = 1;
11418  let Inst{9-5}   = Rn;
11419  let Inst{4-0}   = Rd;
11420}
11421
11422multiclass SIMDThreeSameVectorTiedComplexHSD<bit U, bits<3> opcode,
11423                                             Operand rottype, string asm,
11424                                             SDPatternOperator OpNode> {
11425  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11426  def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64,
11427              rottype, asm, ".4h",
11428              [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd),
11429                                              (v4f16 V64:$Rn),
11430                                              (v4f16 V64:$Rm),
11431                                              (i32 rottype:$rot)))]>;
11432
11433  def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128,
11434              rottype, asm, ".8h",
11435              [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd),
11436                                               (v8f16 V128:$Rn),
11437                                               (v8f16 V128:$Rm),
11438                                               (i32 rottype:$rot)))]>;
11439  }
11440
11441  let Predicates = [HasComplxNum, HasNEON] in {
11442  def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64,
11443              rottype, asm, ".2s",
11444              [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd),
11445                                              (v2f32 V64:$Rn),
11446                                              (v2f32 V64:$Rm),
11447                                              (i32 rottype:$rot)))]>;
11448
11449  def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128,
11450              rottype, asm, ".4s",
11451              [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd),
11452                                               (v4f32 V128:$Rn),
11453                                               (v4f32 V128:$Rm),
11454                                               (i32 rottype:$rot)))]>;
11455
11456  def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128,
11457              rottype, asm, ".2d",
11458              [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd),
11459                                               (v2f64 V128:$Rn),
11460                                               (v2f64 V128:$Rm),
11461                                               (i32 rottype:$rot)))]>;
11462  }
11463}
11464
11465let mayLoad = 0, mayStore = 0, hasSideEffects = 0, mayRaiseFPException = 1, Uses = [FPCR] in
11466class BaseSIMDIndexedTiedComplex<bit Q, bit U, bit Scalar, bits<2> size,
11467                                 bit opc1, bit opc2, RegisterOperand dst_reg,
11468                                 RegisterOperand lhs_reg,
11469                                 RegisterOperand rhs_reg, Operand vec_idx,
11470                                 Operand rottype, string asm, string apple_kind,
11471                                 string dst_kind, string lhs_kind,
11472                                 string rhs_kind, list<dag> pattern>
11473  : I<(outs dst_reg:$dst),
11474      (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot),
11475      asm,
11476      "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind #
11477      "$idx, $rot" # "|" # apple_kind #
11478      "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>,
11479    Sched<[!if(Q, WriteVq, WriteVd)]> {
11480  bits<5> Rd;
11481  bits<5> Rn;
11482  bits<5> Rm;
11483  bits<2> rot;
11484
11485  let Inst{31}    = 0;
11486  let Inst{30}    = Q;
11487  let Inst{29}    = U;
11488  let Inst{28}    = Scalar;
11489  let Inst{27-24} = 0b1111;
11490  let Inst{23-22} = size;
11491  // Bit 21 must be set by the derived class.
11492  let Inst{20-16} = Rm;
11493  let Inst{15}    = opc1;
11494  let Inst{14-13} = rot;
11495  let Inst{12}    = opc2;
11496  // Bit 11 must be set by the derived class.
11497  let Inst{10}    = 0;
11498  let Inst{9-5}   = Rn;
11499  let Inst{4-0}   = Rd;
11500}
11501
11502// The complex instructions index by pairs of elements, so the VectorIndexes
11503// don't match the lane types, and the index bits are different to the other
11504// classes.
11505multiclass SIMDIndexedTiedComplexHSD<bit opc1, bit opc2, Operand rottype,
11506                                     string asm> {
11507  let Predicates = [HasComplxNum, HasNEON, HasFullFP16] in {
11508  def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64,
11509                      V64, V128, VectorIndexD, rottype, asm, ".4h", ".4h",
11510                      ".4h", ".h", []> {
11511    bits<1> idx;
11512    let Inst{11} = 0;
11513    let Inst{21} = idx{0};
11514  }
11515
11516  def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2,
11517                      V128, V128, V128, VectorIndexS, rottype, asm, ".8h",
11518                      ".8h", ".8h", ".h", []> {
11519    bits<2> idx;
11520    let Inst{11} = idx{1};
11521    let Inst{21} = idx{0};
11522  }
11523  } // Predicates = HasComplxNum, HasNEON, HasFullFP16]
11524
11525  let Predicates = [HasComplxNum, HasNEON] in {
11526  def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2,
11527                      V128, V128, V128, VectorIndexD, rottype, asm, ".4s",
11528                      ".4s", ".4s", ".s", []> {
11529    bits<1> idx;
11530    let Inst{11} = idx{0};
11531    let Inst{21} = 0;
11532  }
11533  } // Predicates = [HasComplxNum, HasNEON]
11534}
11535
11536//----------------------------------------------------------------------------
11537// Crypto extensions
11538//----------------------------------------------------------------------------
11539
11540let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11541class AESBase<bits<4> opc, string asm, dag outs, dag ins, string cstr,
11542              list<dag> pat>
11543  : I<outs, ins, asm, "{\t$Rd.16b, $Rn.16b|.16b\t$Rd, $Rn}", cstr, pat>,
11544    Sched<[WriteVq]>{
11545  bits<5> Rd;
11546  bits<5> Rn;
11547  let Inst{31-16} = 0b0100111000101000;
11548  let Inst{15-12} = opc;
11549  let Inst{11-10} = 0b10;
11550  let Inst{9-5}   = Rn;
11551  let Inst{4-0}   = Rd;
11552}
11553
11554class AESInst<bits<4> opc, string asm, Intrinsic OpNode>
11555  : AESBase<opc, asm, (outs V128:$Rd), (ins V128:$Rn), "",
11556            [(set (v16i8 V128:$Rd), (OpNode (v16i8 V128:$Rn)))]>;
11557
11558class AESTiedInst<bits<4> opc, string asm, Intrinsic OpNode>
11559  : AESBase<opc, asm, (outs V128:$dst), (ins V128:$Rd, V128:$Rn),
11560            "$Rd = $dst",
11561            [(set (v16i8 V128:$dst),
11562                  (OpNode (v16i8 V128:$Rd), (v16i8 V128:$Rn)))]>;
11563
11564let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11565class SHA3OpTiedInst<bits<3> opc, string asm, string dst_lhs_kind,
11566                     dag oops, dag iops, list<dag> pat>
11567  : I<oops, iops, asm,
11568      "{\t$Rd" # dst_lhs_kind # ", $Rn" # dst_lhs_kind # ", $Rm.4s" #
11569      "|.4s\t$Rd, $Rn, $Rm}", "$Rd = $dst", pat>,
11570    Sched<[WriteVq]>{
11571  bits<5> Rd;
11572  bits<5> Rn;
11573  bits<5> Rm;
11574  let Inst{31-21} = 0b01011110000;
11575  let Inst{20-16} = Rm;
11576  let Inst{15}    = 0;
11577  let Inst{14-12} = opc;
11578  let Inst{11-10} = 0b00;
11579  let Inst{9-5}   = Rn;
11580  let Inst{4-0}   = Rd;
11581}
11582
11583class SHATiedInstQSV<bits<3> opc, string asm, Intrinsic OpNode>
11584  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11585                   (ins FPR128:$Rd, FPR32:$Rn, V128:$Rm),
11586                   [(set (v4i32 FPR128:$dst),
11587                         (OpNode (v4i32 FPR128:$Rd), (i32 FPR32:$Rn),
11588                                 (v4i32 V128:$Rm)))]>;
11589
11590class SHATiedInstVVV<bits<3> opc, string asm, Intrinsic OpNode>
11591  : SHA3OpTiedInst<opc, asm, ".4s", (outs V128:$dst),
11592                   (ins V128:$Rd, V128:$Rn, V128:$Rm),
11593                   [(set (v4i32 V128:$dst),
11594                         (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn),
11595                                 (v4i32 V128:$Rm)))]>;
11596
11597class SHATiedInstQQV<bits<3> opc, string asm, Intrinsic OpNode>
11598  : SHA3OpTiedInst<opc, asm, "", (outs FPR128:$dst),
11599                   (ins FPR128:$Rd, FPR128:$Rn, V128:$Rm),
11600                   [(set (v4i32 FPR128:$dst),
11601                         (OpNode (v4i32 FPR128:$Rd), (v4i32 FPR128:$Rn),
11602                                 (v4i32 V128:$Rm)))]>;
11603
11604let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in
11605class SHA2OpInst<bits<4> opc, string asm, string kind,
11606                 string cstr, dag oops, dag iops,
11607                 list<dag> pat>
11608  : I<oops, iops, asm, "{\t$Rd" # kind # ", $Rn" # kind #
11609                       "|" # kind # "\t$Rd, $Rn}", cstr, pat>,
11610    Sched<[WriteVq]>{
11611  bits<5> Rd;
11612  bits<5> Rn;
11613  let Inst{31-16} = 0b0101111000101000;
11614  let Inst{15-12} = opc;
11615  let Inst{11-10} = 0b10;
11616  let Inst{9-5}   = Rn;
11617  let Inst{4-0}   = Rd;
11618}
11619
11620class SHATiedInstVV<bits<4> opc, string asm, Intrinsic OpNode>
11621  : SHA2OpInst<opc, asm, ".4s", "$Rd = $dst", (outs V128:$dst),
11622               (ins V128:$Rd, V128:$Rn),
11623               [(set (v4i32 V128:$dst),
11624                     (OpNode (v4i32 V128:$Rd), (v4i32 V128:$Rn)))]>;
11625
11626class SHAInstSS<bits<4> opc, string asm, Intrinsic OpNode>
11627  : SHA2OpInst<opc, asm, "", "", (outs FPR32:$Rd), (ins FPR32:$Rn),
11628               [(set (i32 FPR32:$Rd), (OpNode (i32 FPR32:$Rn)))]>;
11629
11630// Armv8.2-A Crypto extensions
11631class BaseCryptoV82<dag oops, dag iops, string asm, string asmops, string cst,
11632                    list<dag> pattern>
11633  : I <oops, iops, asm, asmops, cst, pattern>, Sched<[WriteVq]> {
11634  bits<5> Vd;
11635  bits<5> Vn;
11636  let Inst{31-25} = 0b1100111;
11637  let Inst{9-5}   = Vn;
11638  let Inst{4-0}   = Vd;
11639}
11640
11641class CryptoRRTied<bits<1>op0, bits<2>op1, string asm, string asmops>
11642  : BaseCryptoV82<(outs V128:$Vdst), (ins V128:$Vd, V128:$Vn), asm, asmops,
11643                  "$Vd = $Vdst", []> {
11644  let Inst{31-25} = 0b1100111;
11645  let Inst{24-21} = 0b0110;
11646  let Inst{20-15} = 0b000001;
11647  let Inst{14}    = op0;
11648  let Inst{13-12} = 0b00;
11649  let Inst{11-10} = op1;
11650}
11651class CryptoRRTied_2D<bits<1>op0, bits<2>op1, string asm>
11652  : CryptoRRTied<op0, op1, asm, "{\t$Vd.2d, $Vn.2d|.2d\t$Vd, $Vn}">;
11653class CryptoRRTied_4S<bits<1>op0, bits<2>op1, string asm>
11654  : CryptoRRTied<op0, op1, asm, "{\t$Vd.4s, $Vn.4s|.4s\t$Vd, $Vn}">;
11655
11656class CryptoRRR<bits<1> op0, bits<2>op1, dag oops, dag iops, string asm,
11657                string asmops, string cst>
11658  : BaseCryptoV82<oops, iops, asm , asmops, cst, []> {
11659  bits<5> Vm;
11660  let Inst{24-21} = 0b0011;
11661  let Inst{20-16} = Vm;
11662  let Inst{15}    = 0b1;
11663  let Inst{14}    = op0;
11664  let Inst{13-12} = 0b00;
11665  let Inst{11-10} = op1;
11666}
11667class CryptoRRR_2D<bits<1> op0, bits<2>op1, string asm>
11668  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11669              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "">;
11670class CryptoRRRTied_2D<bits<1> op0, bits<2>op1, string asm>
11671  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11672              "{\t$Vd.2d, $Vn.2d, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11673class CryptoRRR_4S<bits<1> op0, bits<2>op1, string asm>
11674  : CryptoRRR<op0, op1, (outs V128:$Vd), (ins V128:$Vn, V128:$Vm), asm,
11675              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "">;
11676class CryptoRRRTied_4S<bits<1> op0, bits<2>op1, string asm>
11677  : CryptoRRR<op0, op1, (outs V128:$Vdst), (ins V128:$Vd, V128:$Vn, V128:$Vm), asm,
11678              "{\t$Vd.4s, $Vn.4s, $Vm.4s|.4s\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11679class CryptoRRRTied<bits<1> op0, bits<2>op1, string asm>
11680  : CryptoRRR<op0, op1, (outs FPR128:$Vdst), (ins FPR128:$Vd, FPR128:$Vn, V128:$Vm),
11681              asm, "{\t$Vd, $Vn, $Vm.2d|.2d\t$Vd, $Vn, $Vm}", "$Vd = $Vdst">;
11682
11683class CryptoRRRR<bits<2>op0, string asm, string asmops>
11684  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, V128:$Va), asm,
11685                  asmops, "", []> {
11686  bits<5> Vm;
11687  bits<5> Va;
11688  let Inst{24-23} = 0b00;
11689  let Inst{22-21} = op0;
11690  let Inst{20-16} = Vm;
11691  let Inst{15}    = 0b0;
11692  let Inst{14-10} = Va;
11693}
11694class CryptoRRRR_16B<bits<2>op0, string asm>
11695 : CryptoRRRR<op0, asm, "{\t$Vd.16b, $Vn.16b, $Vm.16b, $Va.16b" #
11696                        "|.16b\t$Vd, $Vn, $Vm, $Va}"> {
11697}
11698class CryptoRRRR_4S<bits<2>op0, string asm>
11699 : CryptoRRRR<op0, asm, "{\t$Vd.4s, $Vn.4s, $Vm.4s, $Va.4s" #
11700                         "|.4s\t$Vd, $Vn, $Vm, $Va}"> {
11701}
11702
11703class CryptoRRRi6<string asm>
11704  : BaseCryptoV82<(outs V128:$Vd), (ins V128:$Vn, V128:$Vm, uimm6:$imm), asm,
11705                  "{\t$Vd.2d, $Vn.2d, $Vm.2d, $imm" #
11706                  "|.2d\t$Vd, $Vn, $Vm, $imm}", "", []> {
11707  bits<6> imm;
11708  bits<5> Vm;
11709  let Inst{24-21} = 0b0100;
11710  let Inst{20-16} = Vm;
11711  let Inst{15-10} = imm;
11712  let Inst{9-5}   = Vn;
11713  let Inst{4-0}   = Vd;
11714}
11715
11716class CryptoRRRi2Tied<bits<1>op0, bits<2>op1, string asm>
11717  : BaseCryptoV82<(outs V128:$Vdst),
11718                  (ins V128:$Vd, V128:$Vn, V128:$Vm, VectorIndexS:$imm),
11719                  asm, "{\t$Vd.4s, $Vn.4s, $Vm.s$imm" #
11720                       "|.4s\t$Vd, $Vn, $Vm$imm}", "$Vd = $Vdst", []> {
11721  bits<2> imm;
11722  bits<5> Vm;
11723  let Inst{24-21} = 0b0010;
11724  let Inst{20-16} = Vm;
11725  let Inst{15}    = 0b1;
11726  let Inst{14}    = op0;
11727  let Inst{13-12} = imm;
11728  let Inst{11-10} = op1;
11729}
11730
11731//----------------------------------------------------------------------------
11732// v8.1 atomic instructions extension:
11733// * CAS
11734// * CASP
11735// * SWP
11736// * LDOPregister<OP>, and aliases STOPregister<OP>
11737
11738// Instruction encodings:
11739//
11740//      31 30|29  24|23|22|21|20 16|15|14  10|9 5|4 0
11741// CAS  SZ   |001000|1 |A |1 |Rs   |R |11111 |Rn |Rt
11742// CASP  0|SZ|001000|0 |A |1 |Rs   |R |11111 |Rn |Rt
11743// SWP  SZ   |111000|A |R |1 |Rs   |1 |OPC|00|Rn |Rt
11744// LD   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |Rt
11745// ST   SZ   |111000|A |R |1 |Rs   |0 |OPC|00|Rn |11111
11746
11747// Instruction syntax:
11748//
11749// CAS{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11750// CAS{<order>} <Xs>, <Xt>, [<Xn|SP>]
11751// CASP{<order>} <Ws>, <W(s+1)>, <Wt>, <W(t+1)>, [<Xn|SP>]
11752// CASP{<order>} <Xs>, <X(s+1)>, <Xt>, <X(t+1)>, [<Xn|SP>]
11753// SWP{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11754// SWP{<order>} <Xs>, <Xt>, [<Xn|SP>]
11755// LD<OP>{<order>}[<size>] <Ws>, <Wt>, [<Xn|SP>]
11756// LD<OP>{<order>} <Xs>, <Xt>, [<Xn|SP>]
11757// ST<OP>{<order>}[<size>] <Ws>, [<Xn|SP>]
11758// ST<OP>{<order>} <Xs>, [<Xn|SP>]
11759
11760let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11761class BaseCASEncoding<dag oops, dag iops, string asm, string operands,
11762                      string cstr, list<dag> pattern>
11763      : I<oops, iops, asm, operands, cstr, pattern> {
11764  bits<2> Sz;
11765  bit NP;
11766  bit Acq;
11767  bit Rel;
11768  bits<5> Rs;
11769  bits<5> Rn;
11770  bits<5> Rt;
11771  let Inst{31-30} = Sz;
11772  let Inst{29-24} = 0b001000;
11773  let Inst{23} = NP;
11774  let Inst{22} = Acq;
11775  let Inst{21} = 0b1;
11776  let Inst{20-16} = Rs;
11777  let Inst{15} = Rel;
11778  let Inst{14-10} = 0b11111;
11779  let Inst{9-5} = Rn;
11780  let Inst{4-0} = Rt;
11781  let Predicates = [HasLSE];
11782}
11783
11784class BaseCAS<string order, string size, RegisterClass RC>
11785      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11786                        "cas" # order # size, "\t$Rs, $Rt, [$Rn]",
11787                        "$out = $Rs",[]>,
11788        Sched<[WriteAtomic]> {
11789  let NP = 1;
11790}
11791
11792multiclass CompareAndSwap<bits<1> Acq, bits<1> Rel, string order> {
11793  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseCAS<order, "b", GPR32>;
11794  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseCAS<order, "h", GPR32>;
11795  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseCAS<order, "", GPR32>;
11796  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseCAS<order, "", GPR64>;
11797}
11798
11799class BaseCASP<string order, string size, RegisterOperand RC>
11800      : BaseCASEncoding<(outs RC:$out),(ins RC:$Rs, RC:$Rt, GPR64sp:$Rn),
11801                        "casp" # order # size, "\t$Rs, $Rt, [$Rn]",
11802                        "$out = $Rs",[]>,
11803        Sched<[WriteAtomic]> {
11804  let NP = 0;
11805}
11806
11807multiclass CompareAndSwapPair<bits<1> Acq, bits<1> Rel, string order> {
11808  let Sz = 0b00, Acq = Acq, Rel = Rel in
11809    def W : BaseCASP<order, "", WSeqPairClassOperand>;
11810  let Sz = 0b01, Acq = Acq, Rel = Rel in
11811    def X : BaseCASP<order, "", XSeqPairClassOperand>;
11812}
11813
11814let Predicates = [HasLSE] in
11815class BaseSWP<string order, string size, RegisterClass RC>
11816      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "swp" # order # size,
11817          "\t$Rs, $Rt, [$Rn]","",[]>,
11818        Sched<[WriteAtomic]> {
11819  bits<2> Sz;
11820  bit Acq;
11821  bit Rel;
11822  bits<5> Rs;
11823  bits<3> opc = 0b000;
11824  bits<5> Rn;
11825  bits<5> Rt;
11826  let Inst{31-30} = Sz;
11827  let Inst{29-24} = 0b111000;
11828  let Inst{23} = Acq;
11829  let Inst{22} = Rel;
11830  let Inst{21} = 0b1;
11831  let Inst{20-16} = Rs;
11832  let Inst{15} = 0b1;
11833  let Inst{14-12} = opc;
11834  let Inst{11-10} = 0b00;
11835  let Inst{9-5} = Rn;
11836  let Inst{4-0} = Rt;
11837  let Predicates = [HasLSE];
11838}
11839
11840multiclass Swap<bits<1> Acq, bits<1> Rel, string order> {
11841  let Sz = 0b00, Acq = Acq, Rel = Rel in def B : BaseSWP<order, "b", GPR32>;
11842  let Sz = 0b01, Acq = Acq, Rel = Rel in def H : BaseSWP<order, "h", GPR32>;
11843  let Sz = 0b10, Acq = Acq, Rel = Rel in def W : BaseSWP<order, "", GPR32>;
11844  let Sz = 0b11, Acq = Acq, Rel = Rel in def X : BaseSWP<order, "", GPR64>;
11845}
11846
11847let Predicates = [HasLSE], mayLoad = 1, mayStore = 1, hasSideEffects = 1 in
11848class BaseLDOPregister<string op, string order, string size, RegisterClass RC>
11849      : I<(outs RC:$Rt),(ins RC:$Rs, GPR64sp:$Rn), "ld" # op # order # size,
11850          "\t$Rs, $Rt, [$Rn]","",[]>,
11851        Sched<[WriteAtomic]> {
11852  bits<2> Sz;
11853  bit Acq;
11854  bit Rel;
11855  bits<5> Rs;
11856  bits<3> opc;
11857  bits<5> Rn;
11858  bits<5> Rt;
11859  let Inst{31-30} = Sz;
11860  let Inst{29-24} = 0b111000;
11861  let Inst{23} = Acq;
11862  let Inst{22} = Rel;
11863  let Inst{21} = 0b1;
11864  let Inst{20-16} = Rs;
11865  let Inst{15} = 0b0;
11866  let Inst{14-12} = opc;
11867  let Inst{11-10} = 0b00;
11868  let Inst{9-5} = Rn;
11869  let Inst{4-0} = Rt;
11870  let Predicates = [HasLSE];
11871}
11872
11873multiclass LDOPregister<bits<3> opc, string op, bits<1> Acq, bits<1> Rel,
11874                        string order> {
11875  let Sz = 0b00, Acq = Acq, Rel = Rel, opc = opc in
11876    def B : BaseLDOPregister<op, order, "b", GPR32>;
11877  let Sz = 0b01, Acq = Acq, Rel = Rel, opc = opc in
11878    def H : BaseLDOPregister<op, order, "h", GPR32>;
11879  let Sz = 0b10, Acq = Acq, Rel = Rel, opc = opc in
11880    def W : BaseLDOPregister<op, order, "", GPR32>;
11881  let Sz = 0b11, Acq = Acq, Rel = Rel, opc = opc in
11882    def X : BaseLDOPregister<op, order, "", GPR64>;
11883}
11884
11885// Differing SrcRHS and DstRHS allow you to cover CLR & SUB by giving a more
11886// complex DAG for DstRHS.
11887let Predicates = [HasLSE] in
11888multiclass LDOPregister_patterns_ord_dag<string inst, string suffix, string op,
11889                                         string size, dag SrcRHS, dag DstRHS> {
11890  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, SrcRHS),
11891            (!cast<Instruction>(inst # suffix) DstRHS, GPR64sp:$Rn)>;
11892  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, SrcRHS),
11893            (!cast<Instruction>(inst # "A" # suffix) DstRHS, GPR64sp:$Rn)>;
11894  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, SrcRHS),
11895            (!cast<Instruction>(inst # "L" # suffix) DstRHS, GPR64sp:$Rn)>;
11896  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, SrcRHS),
11897            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11898  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, SrcRHS),
11899            (!cast<Instruction>(inst # "AL" # suffix) DstRHS, GPR64sp:$Rn)>;
11900}
11901
11902multiclass LDOPregister_patterns_ord<string inst, string suffix, string op,
11903                                     string size, dag RHS> {
11904  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, RHS, RHS>;
11905}
11906
11907multiclass LDOPregister_patterns_ord_mod<string inst, string suffix, string op,
11908                                         string size, dag LHS, dag RHS> {
11909  defm : LDOPregister_patterns_ord_dag<inst, suffix, op, size, LHS, RHS>;
11910}
11911
11912multiclass LDOPregister_patterns<string inst, string op> {
11913  defm : LDOPregister_patterns_ord<inst, "X", op, "64", (i64 GPR64:$Rm)>;
11914  defm : LDOPregister_patterns_ord<inst, "W", op, "32", (i32 GPR32:$Rm)>;
11915  defm : LDOPregister_patterns_ord<inst, "H", op, "16", (i32 GPR32:$Rm)>;
11916  defm : LDOPregister_patterns_ord<inst, "B", op, "8",  (i32 GPR32:$Rm)>;
11917}
11918
11919multiclass LDOPregister_patterns_mod<string inst, string op, string mod> {
11920  defm : LDOPregister_patterns_ord_mod<inst, "X", op, "64",
11921                        (i64 GPR64:$Rm),
11922                        (i64 (!cast<Instruction>(mod#Xrr) XZR, GPR64:$Rm))>;
11923  defm : LDOPregister_patterns_ord_mod<inst, "W", op, "32",
11924                        (i32 GPR32:$Rm),
11925                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11926  defm : LDOPregister_patterns_ord_mod<inst, "H", op, "16",
11927                        (i32 GPR32:$Rm),
11928                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11929  defm : LDOPregister_patterns_ord_mod<inst, "B", op, "8",
11930                        (i32 GPR32:$Rm),
11931                        (i32 (!cast<Instruction>(mod#Wrr) WZR, GPR32:$Rm))>;
11932}
11933
11934let Predicates = [HasLSE] in
11935multiclass CASregister_patterns_ord_dag<string inst, string suffix, string op,
11936                                        string size, dag OLD, dag NEW> {
11937  def : Pat<(!cast<PatFrag>(op#"_"#size#"_monotonic") GPR64sp:$Rn, OLD, NEW),
11938            (!cast<Instruction>(inst # suffix) OLD, NEW, GPR64sp:$Rn)>;
11939  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acquire") GPR64sp:$Rn, OLD, NEW),
11940            (!cast<Instruction>(inst # "A" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11941  def : Pat<(!cast<PatFrag>(op#"_"#size#"_release") GPR64sp:$Rn, OLD, NEW),
11942            (!cast<Instruction>(inst # "L" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11943  def : Pat<(!cast<PatFrag>(op#"_"#size#"_acq_rel") GPR64sp:$Rn, OLD, NEW),
11944            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11945  def : Pat<(!cast<PatFrag>(op#"_"#size#"_seq_cst") GPR64sp:$Rn, OLD, NEW),
11946            (!cast<Instruction>(inst # "AL" # suffix) OLD, NEW, GPR64sp:$Rn)>;
11947}
11948
11949multiclass CASregister_patterns_ord<string inst, string suffix, string op,
11950                                    string size, dag OLD, dag NEW> {
11951  defm : CASregister_patterns_ord_dag<inst, suffix, op, size, OLD, NEW>;
11952}
11953
11954multiclass CASregister_patterns<string inst, string op> {
11955  defm : CASregister_patterns_ord<inst, "X", op, "64",
11956                        (i64 GPR64:$Rold), (i64 GPR64:$Rnew)>;
11957  defm : CASregister_patterns_ord<inst, "W", op, "32",
11958                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11959  defm : CASregister_patterns_ord<inst, "H", op, "16",
11960                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11961  defm : CASregister_patterns_ord<inst, "B", op, "8",
11962                        (i32 GPR32:$Rold), (i32 GPR32:$Rnew)>;
11963}
11964
11965let Predicates = [HasLSE] in
11966class BaseSTOPregister<string asm, RegisterClass OP, Register Reg,
11967                        Instruction inst> :
11968      InstAlias<asm # "\t$Rs, [$Rn]", (inst Reg, OP:$Rs, GPR64sp:$Rn)>;
11969
11970multiclass STOPregister<string asm, string instr> {
11971  def : BaseSTOPregister<asm # "lb", GPR32, WZR,
11972                    !cast<Instruction>(instr # "LB")>;
11973  def : BaseSTOPregister<asm # "lh", GPR32, WZR,
11974                    !cast<Instruction>(instr # "LH")>;
11975  def : BaseSTOPregister<asm # "l",  GPR32, WZR,
11976                    !cast<Instruction>(instr # "LW")>;
11977  def : BaseSTOPregister<asm # "l",  GPR64, XZR,
11978                    !cast<Instruction>(instr # "LX")>;
11979  def : BaseSTOPregister<asm # "b",  GPR32, WZR,
11980                    !cast<Instruction>(instr # "B")>;
11981  def : BaseSTOPregister<asm # "h",  GPR32, WZR,
11982                    !cast<Instruction>(instr # "H")>;
11983  def : BaseSTOPregister<asm,        GPR32, WZR,
11984                    !cast<Instruction>(instr # "W")>;
11985  def : BaseSTOPregister<asm,        GPR64, XZR,
11986                    !cast<Instruction>(instr # "X")>;
11987}
11988
11989class LoadStore64B_base<bits<3> opc, string asm_inst, string asm_ops,
11990                        dag iops, dag oops, list<dag> pat>
11991    : I<oops, iops, asm_inst, asm_ops, "", pat>,
11992      Sched<[]> /* FIXME: fill in scheduling details once known */ {
11993  bits<5> Rt;
11994  bits<5> Rn;
11995  let Inst{31-21} = 0b11111000001;
11996  let Inst{15}    = 1;
11997  let Inst{14-12} = opc;
11998  let Inst{11-10} = 0b00;
11999  let Inst{9-5}   = Rn;
12000  let Inst{4-0}   = Rt;
12001
12002  let Predicates = [HasV8_7a];
12003}
12004
12005class LoadStore64B<bits<3> opc, string asm_inst, dag iops, dag oops,
12006                      list<dag> pat = []>
12007    : LoadStore64B_base<opc, asm_inst, "\t$Rt, [$Rn]", iops, oops, pat> {
12008  let Inst{20-16} = 0b11111;
12009}
12010
12011class Store64BV<bits<3> opc, string asm_inst, list<dag> pat = []>
12012    : LoadStore64B_base<opc, asm_inst, "\t$Rs, $Rt, [$Rn]",
12013                       (ins GPR64x8:$Rt, GPR64sp:$Rn), (outs GPR64:$Rs), pat> {
12014  bits<5> Rs;
12015  let Inst{20-16} = Rs;
12016}
12017
12018class MOPSMemoryCopyMoveBase<bit isMove, bits<2> opcode, bits<2> op1,
12019                             bits<2> op2, string asm>
12020  : I<(outs GPR64common:$Rd_wb, GPR64common:$Rs_wb, GPR64:$Rn_wb),
12021      (ins GPR64common:$Rd, GPR64common:$Rs, GPR64:$Rn),
12022      asm, "\t[$Rd]!, [$Rs]!, $Rn!",
12023      "$Rd = $Rd_wb,$Rs = $Rs_wb,$Rn = $Rn_wb", []>,
12024    Sched<[]> {
12025  bits<5> Rd;
12026  bits<5> Rs;
12027  bits<5> Rn;
12028  let Inst{31-27} = 0b00011;
12029  let Inst{26} = isMove;
12030  let Inst{25-24} = 0b01;
12031  let Inst{23-22} = opcode;
12032  let Inst{21} = 0b0;
12033  let Inst{20-16} = Rs;
12034  let Inst{15-14} = op2;
12035  let Inst{13-12} = op1;
12036  let Inst{11-10} = 0b01;
12037  let Inst{9-5} = Rn;
12038  let Inst{4-0} = Rd;
12039
12040  let DecoderMethod = "DecodeCPYMemOpInstruction";
12041  let mayLoad = 1;
12042  let mayStore = 1;
12043}
12044
12045class MOPSMemoryCopy<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
12046  : MOPSMemoryCopyMoveBase<0, opcode, op1, op2, asm>;
12047
12048class MOPSMemoryMove<bits<2> opcode, bits<2> op1, bits<2> op2, string asm>
12049  : MOPSMemoryCopyMoveBase<1, opcode, op1, op2, asm>;
12050
12051class MOPSMemorySetBase<bit isTagging, bits<2> opcode, bit op1, bit op2,
12052                        string asm>
12053  : I<(outs GPR64common:$Rd_wb, GPR64:$Rn_wb),
12054      (ins GPR64common:$Rd, GPR64:$Rn, GPR64:$Rm),
12055      asm, "\t[$Rd]!, $Rn!, $Rm",
12056      "$Rd = $Rd_wb,$Rn = $Rn_wb", []>,
12057    Sched<[]> {
12058  bits<5> Rd;
12059  bits<5> Rn;
12060  bits<5> Rm;
12061  let Inst{31-27} = 0b00011;
12062  let Inst{26} = isTagging;
12063  let Inst{25-21} = 0b01110;
12064  let Inst{20-16} = Rm;
12065  let Inst{15-14} = opcode;
12066  let Inst{13} = op2;
12067  let Inst{12} = op1;
12068  let Inst{11-10} = 0b01;
12069  let Inst{9-5} = Rn;
12070  let Inst{4-0} = Rd;
12071
12072  let DecoderMethod = "DecodeSETMemOpInstruction";
12073  let mayLoad = 0;
12074  let mayStore = 1;
12075}
12076
12077class MOPSMemorySet<bits<2> opcode, bit op1, bit op2, string asm>
12078  : MOPSMemorySetBase<0, opcode, op1, op2, asm>;
12079
12080class MOPSMemorySetTagging<bits<2> opcode, bit op1, bit op2, string asm>
12081  : MOPSMemorySetBase<1, opcode, op1, op2, asm>;
12082
12083multiclass MOPSMemoryCopyInsns<bits<2> opcode, string asm> {
12084  def ""   : MOPSMemoryCopy<opcode, 0b00, 0b00, asm>;
12085  def WN   : MOPSMemoryCopy<opcode, 0b00, 0b01, asm # "wn">;
12086  def RN   : MOPSMemoryCopy<opcode, 0b00, 0b10, asm # "rn">;
12087  def N    : MOPSMemoryCopy<opcode, 0b00, 0b11, asm # "n">;
12088  def WT   : MOPSMemoryCopy<opcode, 0b01, 0b00, asm # "wt">;
12089  def WTWN : MOPSMemoryCopy<opcode, 0b01, 0b01, asm # "wtwn">;
12090  def WTRN : MOPSMemoryCopy<opcode, 0b01, 0b10, asm # "wtrn">;
12091  def WTN  : MOPSMemoryCopy<opcode, 0b01, 0b11, asm # "wtn">;
12092  def RT   : MOPSMemoryCopy<opcode, 0b10, 0b00, asm # "rt">;
12093  def RTWN : MOPSMemoryCopy<opcode, 0b10, 0b01, asm # "rtwn">;
12094  def RTRN : MOPSMemoryCopy<opcode, 0b10, 0b10, asm # "rtrn">;
12095  def RTN  : MOPSMemoryCopy<opcode, 0b10, 0b11, asm # "rtn">;
12096  def T    : MOPSMemoryCopy<opcode, 0b11, 0b00, asm # "t">;
12097  def TWN  : MOPSMemoryCopy<opcode, 0b11, 0b01, asm # "twn">;
12098  def TRN  : MOPSMemoryCopy<opcode, 0b11, 0b10, asm # "trn">;
12099  def TN   : MOPSMemoryCopy<opcode, 0b11, 0b11, asm # "tn">;
12100}
12101
12102multiclass MOPSMemoryMoveInsns<bits<2> opcode, string asm> {
12103  def ""   : MOPSMemoryMove<opcode, 0b00, 0b00, asm>;
12104  def WN   : MOPSMemoryMove<opcode, 0b00, 0b01, asm # "wn">;
12105  def RN   : MOPSMemoryMove<opcode, 0b00, 0b10, asm # "rn">;
12106  def N    : MOPSMemoryMove<opcode, 0b00, 0b11, asm # "n">;
12107  def WT   : MOPSMemoryMove<opcode, 0b01, 0b00, asm # "wt">;
12108  def WTWN : MOPSMemoryMove<opcode, 0b01, 0b01, asm # "wtwn">;
12109  def WTRN : MOPSMemoryMove<opcode, 0b01, 0b10, asm # "wtrn">;
12110  def WTN  : MOPSMemoryMove<opcode, 0b01, 0b11, asm # "wtn">;
12111  def RT   : MOPSMemoryMove<opcode, 0b10, 0b00, asm # "rt">;
12112  def RTWN : MOPSMemoryMove<opcode, 0b10, 0b01, asm # "rtwn">;
12113  def RTRN : MOPSMemoryMove<opcode, 0b10, 0b10, asm # "rtrn">;
12114  def RTN  : MOPSMemoryMove<opcode, 0b10, 0b11, asm # "rtn">;
12115  def T    : MOPSMemoryMove<opcode, 0b11, 0b00, asm # "t">;
12116  def TWN  : MOPSMemoryMove<opcode, 0b11, 0b01, asm # "twn">;
12117  def TRN  : MOPSMemoryMove<opcode, 0b11, 0b10, asm # "trn">;
12118  def TN   : MOPSMemoryMove<opcode, 0b11, 0b11, asm # "tn">;
12119}
12120
12121multiclass MOPSMemorySetInsns<bits<2> opcode, string asm> {
12122  def "" : MOPSMemorySet<opcode, 0, 0, asm>;
12123  def T  : MOPSMemorySet<opcode, 1, 0, asm # "t">;
12124  def N  : MOPSMemorySet<opcode, 0, 1, asm # "n">;
12125  def TN : MOPSMemorySet<opcode, 1, 1, asm # "tn">;
12126}
12127
12128multiclass MOPSMemorySetTaggingInsns<bits<2> opcode, string asm> {
12129  def "" : MOPSMemorySetTagging<opcode, 0, 0, asm>;
12130  def T  : MOPSMemorySetTagging<opcode, 1, 0, asm # "t">;
12131  def N  : MOPSMemorySetTagging<opcode, 0, 1, asm # "n">;
12132  def TN : MOPSMemorySetTagging<opcode, 1, 1, asm # "tn">;
12133}
12134
12135//----------------------------------------------------------------------------
12136// 2022 Armv8.9/Armv9.4 Extensions
12137//----------------------------------------------------------------------------
12138
12139//---
12140// 2022 Architecture Extensions: General Data Processing (FEAT_CSSC)
12141//---
12142
12143class BaseTwoOperandRegImm<bit sf, bit Op, bit S, bits<4> opc,
12144                           RegisterClass regtype, ImmLeaf immtype, string asm,
12145                           SDPatternOperator OpNode>
12146    : I<(outs regtype:$Rd), (ins regtype:$Rn, immtype:$imm),
12147        asm, "\t$Rd, $Rn, $imm", "",
12148        [(set regtype:$Rd, (OpNode regtype:$Rn, immtype:$imm))]> {
12149  bits<5> Rd;
12150  bits<5> Rn;
12151  bits<8> imm;
12152
12153  let Inst{31}    = sf;
12154  let Inst{30}    = Op;
12155  let Inst{29}    = S;
12156  let Inst{28-22} = 0b1000111;
12157  let Inst{21-18} = opc;
12158  let Inst{17-10} = imm;
12159  let Inst{9-5}   = Rn;
12160  let Inst{4-0}   = Rd;
12161}
12162
12163class BaseComparisonOpReg<bit size, bit isUnsigned, bit isMin,
12164                          RegisterClass regtype, string asm,
12165                          SDPatternOperator OpNode>
12166    : BaseTwoOperandRegReg<size, 0b0, {0,1,1,0,?,?}, regtype, asm, OpNode>,
12167      Sched<[WriteI]> {
12168  let Inst{11} = isMin;
12169  let Inst{10} = isUnsigned;
12170  let mayLoad  = 0;
12171  let mayStore = 0;
12172  let hasSideEffects = 0;
12173}
12174
12175class BaseComparisonOpImm<bit size, bit isUnsigned, bit isMin,
12176                          RegisterClass regtype, ImmLeaf immtype, string asm,
12177                          SDPatternOperator OpNode>
12178    : BaseTwoOperandRegImm<size, 0b0, 0b0, {0,0,?,?}, regtype, immtype, asm,
12179                           OpNode>,
12180      Sched<[]> {
12181  let Inst{19} = isMin;
12182  let Inst{18} = isUnsigned;
12183  let mayLoad  = 0;
12184  let mayStore = 0;
12185  let hasSideEffects = 0;
12186}
12187
12188multiclass ComparisonOp<bit isUnsigned, bit isMin, string asm,
12189                        SDPatternOperator OpNode = null_frag> {
12190  def Wrr : BaseComparisonOpReg<0b0, isUnsigned, isMin, GPR32, asm, OpNode>;
12191
12192  def Wri : BaseComparisonOpImm<0b0, isUnsigned, isMin, GPR32,
12193                                !cond(isUnsigned : uimm8_32b,
12194                                      !not(isUnsigned) : simm8_32b), asm, OpNode>;
12195
12196  def Xrr : BaseComparisonOpReg<0b1, isUnsigned, isMin, GPR64, asm, OpNode>;
12197
12198  def Xri : BaseComparisonOpImm<0b1, isUnsigned, isMin, GPR64,
12199                                !cond(isUnsigned : uimm8_64b,
12200                                      !not(isUnsigned) : simm8_64b), asm, OpNode>;
12201}
12202
12203//---
12204// RCPC instructions (FEAT_LRCPC3)
12205//---
12206
12207class BaseLRCPC3<bits<2> size, bit V, bits<2> opc, dag oops, dag iops,
12208                 string asm, string operands, string cstr = "">
12209      : I<oops, iops, asm, operands, cstr, []>,
12210        Sched<[WriteAtomic]> {
12211  bits<5> Rt;
12212  bits<5> Rn;
12213  let Inst{31-30}    = size;
12214  let Inst{29-24}    = {0,1,1,V,0,1};
12215  let Inst{23-22}    = opc;
12216  let Inst{21}       = 0b0;
12217  //  Inst{20-12}
12218  let Inst{11-10}    = 0b10;
12219  let Inst{9-5}      = Rn;
12220  let Inst{4-0}      = Rt;
12221
12222  let mayLoad = Inst{22};
12223  let mayStore = !not(Inst{22});
12224  let hasSideEffects = 0;
12225}
12226
12227class BaseLRCPC3IntegerLoadStorePair<bits<2> size, bits<2> opc, bits<4> opc2,
12228                                     dag oops, dag iops, string asm,
12229                                     string operands, string cstr>
12230      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
12231  bits<5> Rt2;
12232  let Inst{20-16} = Rt2;
12233  let Inst{15-12} = opc2;
12234}
12235
12236class BaseLRCPC3IntegerLoadStore<bits<2> size, bits<2> opc, dag oops, dag iops,
12237                                 string asm, string operands, string cstr>
12238      : BaseLRCPC3<size, /*V*/0, opc, oops, iops, asm, operands, cstr> {
12239  let Inst{20-12} = 0b000000000; // imm9
12240}
12241
12242multiclass LRCPC3NEONLoadStoreUnscaledOffset<bits<2> size, bits<2> opc, RegisterClass regtype,
12243                                             dag oops, dag iops, string asm> {
12244  def i : BaseLRCPC3<size, /*V*/1, opc, oops, iops, asm, "\t$Rt, [$Rn{, $simm}]", /*cstr*/""> {
12245    bits<9> simm; // signed immediate encoded in imm9=Rt2:imm4
12246    let Inst{20-12} = simm;
12247  }
12248
12249  def a : InstAlias<asm # "\t$Rt, [$Rn]",
12250                  (!cast<Instruction>(NAME # "i") regtype:$Rt, GPR64sp:$Rn, 0)>;
12251}
12252
12253class LRCPC3NEONLdStSingle<bit L, dag oops, dag iops, string asm, string cst>
12254      : BaseSIMDLdStSingle<L, /*R*/0b0, /*opcode*/0b100, asm,
12255                           "\t$Vt$Q, [$Rn]", cst, oops, iops, []>,
12256        Sched<[]> {
12257  bit Q;
12258  let Inst{31}       = 0;
12259  let Inst{30}       = Q;
12260  let Inst{23}       = 0;
12261  let Inst{20-16}    = 0b00001;
12262  let Inst{12}       = 0; // S
12263  let Inst{11-10}    = 0b01; // size
12264
12265  let mayLoad = L;
12266  let mayStore = !not(L);
12267  let hasSideEffects = 1;
12268}
12269
12270//---
12271// Instrumentation Extension (FEAT_ITE)
12272//---
12273
12274let Predicates = [HasITE] in
12275def TRCIT : RtSystemI<0b0, (outs), (ins GPR64:$Rt), "trcit", "\t$Rt"> {
12276  let Inst{20-19} = 0b01;
12277  let Inst{18-16} = 0b011;
12278  let Inst{15-12} = 0b0111;
12279  let Inst{11-8}  = 0b0010;
12280  let Inst{7-5}   = 0b111;
12281}
12282
12283// * RCWCAS family
12284// * RCW<OP> family
12285
12286//--------------------------------------------------------------------
12287// Read-Check-Write Compare And Swap family (RCWCAS[S|P|PS]?[A|L|AL]?)
12288
12289// Instruction encoding:
12290//
12291//          31 30|29  24|23|22|21|20 16|15|14 13|12 11 10|9 5|4 0
12292// RCWCAS    0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
12293// RCWSCAS   0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  0| Rn| Rt
12294// RCWCASP   0  0|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
12295// RCWSCASP  0  1|011001| A| R| 1|   Rs| 0| 0  0| 0  1  1| Rn| Rt
12296
12297// Instruction syntax:
12298//
12299// RCW[S]CAS{<order>}   <Xs>,           <Xt>,          [<Xn|SP>]
12300// RCW[S]CASP{<order>}  <Xs>, <X(s+1)>, <Xt>, <X(t+1)> [<Xn|SP>]
12301
12302class BaseRCWCASEncoding<dag oops, dag iops, string asm>
12303      : I<oops, iops, asm, "\t$Rs, $Rt, [$Rn]", "$out = $Rs", []>,
12304        Sched<[]> {
12305  bit Acq;
12306  bit Rel;
12307  bit SC;
12308  bit Pair;
12309  bits<5> Rs;
12310  bits<5> Rn;
12311  bits<5> Rt;
12312  let Inst{31} = 0b0;
12313  let Inst{30} = SC;
12314  let Inst{29-24} = 0b011001;
12315  let Inst{23} = Acq;
12316  let Inst{22} = Rel;
12317  let Inst{21} = 0b1;
12318  let Inst{20-16} = Rs;
12319  let Inst{15-13} = 0b000;
12320  let Inst{12-11} = 0b01;
12321  let Inst{10} = Pair;
12322  let Inst{9-5} = Rn;
12323  let Inst{4-0} = Rt;
12324  let mayLoad = 1;
12325  let mayStore = 1;
12326  let hasSideEffects = 1;
12327  let Defs = [NZCV];
12328}
12329
12330multiclass BaseRCWCAS<dag oops, dag iops, string prefix> {
12331  let Acq = 0b0, Rel = 0b0 in
12332    def "" : BaseRCWCASEncoding<oops, iops, prefix # "">;
12333  let Acq = 0b1, Rel = 0b0 in
12334    def A  : BaseRCWCASEncoding<oops, iops, prefix # "a">;
12335  let Acq = 0b0, Rel = 0b1 in
12336    def L  : BaseRCWCASEncoding<oops, iops, prefix # "l">;
12337  let Acq = 0b1, Rel = 0b1 in
12338    def AL : BaseRCWCASEncoding<oops, iops, prefix # "al">;
12339}
12340
12341multiclass ReadCheckWriteCompareAndSwap {
12342  let SC = 0b0, Pair = 0b0, Predicates = [HasTHE] in
12343    defm CAS  : BaseRCWCAS<(outs GPR64:$out),
12344                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwcas" >;
12345  let SC = 0b1, Pair = 0b0, Predicates = [HasTHE] in
12346    defm SCAS : BaseRCWCAS<(outs GPR64:$out),
12347                           (ins GPR64:$Rs, GPR64:$Rt, GPR64sp:$Rn), "rcwscas">;
12348  let SC = 0b0, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12349    defm CASP : BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12350                           (ins XSeqPairClassOperand:$Rs,
12351                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12352                           "rcwcasp">;
12353  let SC = 0b1, Pair = 0b1, Predicates = [HasTHE, HasD128] in
12354    defm SCASP: BaseRCWCAS<(outs XSeqPairClassOperand:$out),
12355                           (ins XSeqPairClassOperand:$Rs,
12356                                XSeqPairClassOperand:$Rt, GPR64sp:$Rn),
12357                           "rcwscasp">;
12358}
12359
12360//------------------------------------------------------------------
12361// Read-Check-Write <OP> family (RCW[CLR|SET|SWP][S|P|PS]?[A|L|AL]?)
12362
12363// Instruction encoding:
12364//
12365//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12366// RCWCLR    0  0|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12367// RCWSCLR   0  1|111000| A| R| 1|   Rs| 1|  001| 0  0| Rn| Rt
12368// RCWSET    0  0|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12369// RCWSSET   0  1|111000| A| R| 1|   Rs| 1|  011| 0  0| Rn| Rt
12370// RCWSWP    0  0|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12371// RCWSSWP   0  1|111000| A| R| 1|   Rs| 1|  010| 0  0| Rn| Rt
12372
12373//          31 30|29  24|23|22|21|20 16|15|14 12|11 10|9 5|4 0
12374// RCWCLRP   0  0|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12375// RCWSCLRP  0  1|011001| A| R| 1|  Rt2| 1|  001| 0  0| Rn| Rt
12376// RCWSETP   0  0|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12377// RCWSSETP  0  1|011001| A| R| 1|  Rt2| 1|  011| 0  0| Rn| Rt
12378// RCWSWPP   0  0|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12379// RCWSSWPP  0  1|011001| A| R| 1|  Rt2| 1|  010| 0  0| Rn| Rt
12380
12381// Instruction syntax:
12382//
12383// RCW[S]<OP>{<order>}   <Xs>,  <Xt>, [<Xn|SP>]
12384// RCW[S]<OP>P{<order>}  <Xt1>, <Xt2>, [<Xn|SP>]
12385
12386class BaseRCWOPEncoding<string asm>
12387      : I<(outs GPR64:$Rt),(ins GPR64:$Rs, GPR64sp:$Rn), asm,
12388          "\t$Rs, $Rt, [$Rn]", "", []>,
12389        Sched<[]> {
12390  bit Acq;
12391  bit Rel;
12392  bit SC;
12393  bits<3> opc;
12394  bits<5> Rs;
12395  bits<5> Rn;
12396  bits<5> Rt;
12397  let Inst{31} = 0b0;
12398  let Inst{30} = SC;
12399  let Inst{29-24} = 0b111000;
12400  let Inst{23} = Acq;
12401  let Inst{22} = Rel;
12402  let Inst{21} = 0b1;
12403  let Inst{20-16} = Rs;
12404  let Inst{15} = 0b1;
12405  let Inst{14-12} = opc;
12406  let Inst{11-10} = 0b00;
12407  let Inst{9-5} = Rn;
12408  let Inst{4-0} = Rt;
12409  let mayLoad = 1;
12410  let mayStore = 1;
12411  let hasSideEffects = 1;
12412  let Defs = [NZCV];
12413  let Predicates = [HasTHE];
12414}
12415
12416class BaseRCWOPPEncoding<string asm>
12417      : I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12418          (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn), asm,
12419          "\t$Rt, $Rt2, [$Rn]", "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12420        Sched<[]> {
12421  bit Acq;
12422  bit Rel;
12423  bit SC;
12424  bits<3> opc;
12425  bits<5> Rt2;
12426  bits<5> Rn;
12427  bits<5> Rt;
12428  let Inst{31} = 0b0;
12429  let Inst{30} = SC;
12430  let Inst{29-24} = 0b011001;
12431  let Inst{23} = Acq;
12432  let Inst{22} = Rel;
12433  let Inst{21} = 0b1;
12434  let Inst{20-16} = Rt2;
12435  let Inst{15} = 0b1;
12436  let Inst{14-12} = opc;
12437  let Inst{11-10} = 0b00;
12438  let Inst{9-5} = Rn;
12439  let Inst{4-0} = Rt;
12440  let mayLoad = 1;
12441  let mayStore = 1;
12442  let hasSideEffects = 1;
12443  let Defs = [NZCV];
12444  let Predicates = [HasTHE, HasD128];
12445}
12446
12447multiclass BaseRCWOP<string prefix> {
12448  let Acq = 0b0, Rel = 0b0 in def "" : BaseRCWOPEncoding<prefix # "">;
12449  let Acq = 0b1, Rel = 0b0 in def A  : BaseRCWOPEncoding<prefix # "a">;
12450  let Acq = 0b0, Rel = 0b1 in def L  : BaseRCWOPEncoding<prefix # "l">;
12451  let Acq = 0b1, Rel = 0b1 in def AL : BaseRCWOPEncoding<prefix # "al">;
12452
12453  let Acq = 0b0, Rel = 0b0 in def P   : BaseRCWOPPEncoding<prefix # "p">;
12454  let Acq = 0b1, Rel = 0b0 in def PA  : BaseRCWOPPEncoding<prefix # "pa">;
12455  let Acq = 0b0, Rel = 0b1 in def PL  : BaseRCWOPPEncoding<prefix # "pl">;
12456  let Acq = 0b1, Rel = 0b1 in def PAL : BaseRCWOPPEncoding<prefix # "pal">;
12457}
12458
12459multiclass ReadCheckWriteOperation<bits<3> opc, string op> {
12460  let SC = 0b0, opc = opc in defm ""  : BaseRCWOP<"rcw" # ""  # op>;
12461  let SC = 0b1, opc = opc in defm S   : BaseRCWOP<"rcw" # "s" # op >;
12462}
12463
12464//---
12465// 128-bit atomic instructions (FEAT_LSE128)
12466//---
12467
12468let mayLoad = 1, mayStore = 1, hasSideEffects = 0 in
12469class LSE128Base<bits<3> op0, bits<2> AR, bit o3, string asm>
12470: I<(outs GPR64common:$Rt_wb, GPR64common:$Rt2_wb),
12471    (ins GPR64common:$Rt, GPR64common:$Rt2, GPR64sp:$Rn),
12472    asm, "\t$Rt, $Rt2, [$Rn]",
12473    "$Rt = $Rt_wb, $Rt2 = $Rt2_wb", []>,
12474  Sched<[]> {
12475  bits<5> Rt;
12476  bits<5> Rt2;
12477  bits<5> Rn;
12478  let Inst{31-24} = 0b00011001;
12479  let Inst{23-22} = AR;
12480  let Inst{21} = 0b1;
12481  let Inst{20-16} = Rt2;
12482  let Inst{15} = o3;
12483  let Inst{14-12} = op0;
12484  let Inst{11-10} = 0b00;
12485  let Inst{9-5} = Rn;
12486  let Inst{4-0} = Rt;
12487}
12488
12489//---
12490// 128-bit System Instructions (FEAT_SYSINSTR128)
12491//---
12492
12493// Instruction encoding:
12494//
12495//          31          19|18 16|15 12|11 8|7 5|4 0
12496// SYSP      1101010101001|  op1|   Cn|  Cm|op2| Rt
12497
12498// Instruction syntax:
12499//
12500// SYSP #<op1>, <Cn>, <Cm>, #<op2>{, <Xt>, <Xt+1>}
12501
12502class RtSystemI128<bit L, dag oops, dag iops, string asm, string operands, list<dag> pattern = []> :
12503  RtSystemI<L, oops, iops, asm, operands, pattern> {
12504  let Inst{22}    = 0b1; // override BaseSystemI
12505}
12506
12507class BaseSYSPEncoding<bit L, string asm, string operands, dag outputs, dag inputs>
12508  : RtSystemI128<L, outputs, inputs, asm, operands> {
12509  bits<3> op1;
12510  bits<4> Cn;
12511  bits<4> Cm;
12512  bits<3> op2;
12513  let Inst{20-19} = 0b01;
12514  let Inst{18-16} = op1;
12515  let Inst{15-12} = Cn;
12516  let Inst{11-8}  = Cm;
12517  let Inst{7-5}   = op2;
12518}
12519class SystemPXtI<bit L, string asm> :
12520  BaseSYSPEncoding<L, asm, "\t$op1, $Cn, $Cm, $op2, $Rt", (outs),
12521  (ins imm0_7:$op1, sys_cr_op:$Cn, sys_cr_op:$Cm, imm0_7:$op2, XSeqPairClassOperand:$Rt)>;
12522
12523//----------------------------------------------------------------------------
12524// 2023 Armv9.5 Extensions
12525//----------------------------------------------------------------------------
12526
12527//---
12528// Checked Pointer Arithmetic (FEAT_CPA)
12529//---
12530
12531def LSLImm3ShiftOperand : AsmOperandClass {
12532  let SuperClasses = [ExtendOperandLSL64];
12533  let Name = "LSLImm3Shift";
12534  let RenderMethod = "addLSLImm3ShifterOperands";
12535  let DiagnosticType = "AddSubLSLImm3ShiftLarge";
12536}
12537
12538def lsl_imm3_shift_operand : Operand<i32> {
12539  let PrintMethod = "printShifter";
12540  let ParserMatchClass = LSLImm3ShiftOperand;
12541}
12542
12543// Base CPA scalar add/subtract with lsl #imm3 shift
12544class BaseAddSubCPA<bit isSub, string asm> : I<(outs GPR64sp:$Rd),
12545    (ins GPR64sp:$Rn, GPR64:$Rm, lsl_imm3_shift_operand:$shift_imm),
12546    asm, "\t$Rd, $Rn, $Rm$shift_imm", "", []>, Sched<[]> {
12547  bits<5> Rd;
12548  bits<5> Rn;
12549  bits<5> Rm;
12550  bits<3> shift_imm;
12551  let Inst{31} = 0b1;
12552  let Inst{30} = isSub;
12553  let Inst{29-21} = 0b011010000;
12554  let Inst{20-16} = Rm;
12555  let Inst{15-13} = 0b001;
12556  let Inst{12-10} = shift_imm;
12557  let Inst{9-5} = Rn;
12558  let Inst{4-0} = Rd;
12559}
12560
12561// Alias for CPA scalar add/subtract with no shift
12562class AddSubCPAAlias<string asm, Instruction inst>
12563    : InstAlias<asm#"\t$Rd, $Rn, $Rm",
12564                (inst GPR64sp:$Rd, GPR64sp:$Rn, GPR64:$Rm, 0)>;
12565
12566multiclass AddSubCPA<bit isSub, string asm> {
12567  def _shift : BaseAddSubCPA<isSub, asm>;
12568  def _noshift : AddSubCPAAlias<asm, !cast<Instruction>(NAME#"_shift")>;
12569}
12570
12571class MulAccumCPA<bit isSub, string asm>
12572  : BaseMulAccum<isSub, 0b011, GPR64, GPR64, asm, []>, Sched<[]> {
12573  let Inst{31} = 0b1;
12574}
12575
12576//----------------------------------------------------------------------------
12577// Allow the size specifier tokens to be upper case, not just lower.
12578def : TokenAlias<".4B", ".4b">;  // Add dot product
12579def : TokenAlias<".8B", ".8b">;
12580def : TokenAlias<".4H", ".4h">;
12581def : TokenAlias<".2S", ".2s">;
12582def : TokenAlias<".1D", ".1d">;
12583def : TokenAlias<".16B", ".16b">;
12584def : TokenAlias<".8H", ".8h">;
12585def : TokenAlias<".4S", ".4s">;
12586def : TokenAlias<".2D", ".2d">;
12587def : TokenAlias<".1Q", ".1q">;
12588def : TokenAlias<".2H", ".2h">;
12589def : TokenAlias<".2B", ".2b">;
12590def : TokenAlias<".B", ".b">;
12591def : TokenAlias<".H", ".h">;
12592def : TokenAlias<".S", ".s">;
12593def : TokenAlias<".D", ".d">;
12594def : TokenAlias<".Q", ".q">;
12595